diff --git a/catalyst_voices_packages/catalyst_cardano_serialization/example/main.dart b/catalyst_voices_packages/catalyst_cardano_serialization/example/main.dart index 66a3e5a8a4..ac89d94ba2 100644 --- a/catalyst_voices_packages/catalyst_cardano_serialization/example/main.dart +++ b/catalyst_voices_packages/catalyst_cardano_serialization/example/main.dart @@ -57,7 +57,6 @@ void main() { final txBuilder = TransactionBuilder( config: txBuilderConfig, inputs: [utxo], - outputs: [], // fee can be left empty so that it's autocalculated or can be hardcoded // fee: const Coin(1000000), ttl: const SlotBigNum(410021), diff --git a/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/builders/transaction_builder.dart b/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/builders/transaction_builder.dart index c29f973721..9666cc7f72 100644 --- a/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/builders/transaction_builder.dart +++ b/catalyst_voices_packages/catalyst_cardano_serialization/lib/src/builders/transaction_builder.dart @@ -50,7 +50,7 @@ class TransactionBuilder { const TransactionBuilder({ required this.config, required this.inputs, - required this.outputs, + this.outputs = const [], this.fee, this.ttl, this.auxiliaryData, diff --git a/catalyst_voices_packages/catalyst_cardano_serialization/test/test_utils/test_data.dart b/catalyst_voices_packages/catalyst_cardano_serialization/test/test_utils/test_data.dart index ba0491dec5..88775f4482 100644 --- a/catalyst_voices_packages/catalyst_cardano_serialization/test/test_utils/test_data.dart +++ b/catalyst_voices_packages/catalyst_cardano_serialization/test/test_utils/test_data.dart @@ -29,15 +29,26 @@ final testTransactionHash = TransactionHash.fromHex( '4c1fbc5433ec764164945d736a09dc087d59ff30e64d26d462ff8570cd4be9a7', ); +TransactionUnspentOutput testUtxo() { + return TransactionUnspentOutput( + input: TransactionInput( + transactionId: testTransactionHash, + index: 0, + ), + output: TransactionOutput( + address: ShelleyAddress.fromBech32( + 'addr_test1qpu5vlrf4xkxv2qpwngf6cjhtw542ayty80v8dyr49rf5' + 'ewvxwdrt70qlcpeeagscasafhffqsxy36t90ldv06wqrk2qum8x5w', + ), + amount: const Coin(100000000), + ), + ); +} + Transaction minimalUnsignedTestTransaction() { return Transaction( body: TransactionBody( - inputs: { - TransactionInput( - transactionId: testTransactionHash, - index: 0, - ), - }, + inputs: {testUtxo().input}, outputs: [ TransactionOutput( address: testnetAddr, @@ -61,12 +72,7 @@ Transaction minimalUnsignedTestTransaction() { Transaction minimalSignedTestTransaction() { return Transaction( body: TransactionBody( - inputs: { - TransactionInput( - transactionId: testTransactionHash, - index: 0, - ), - }, + inputs: {testUtxo().input}, outputs: [ TransactionOutput( address: testnetAddr, @@ -103,31 +109,11 @@ Transaction minimalSignedTestTransaction() { } Transaction fullUnsignedTestTransaction() { - final auxiliaryData = AuxiliaryData( - map: { - const CborSmallInt(1): CborString('Test'), - const CborSmallInt(2): CborBytes(hex.decode('aabbccddeeff')), - const CborSmallInt(3): const CborSmallInt(997), - const CborSmallInt(4): cbor.decode( - hex.decode( - '82a50081825820afcf8497561065afe1ca623823508753cc580eb575ac8f1d6cfa' - 'a18c3ceeac010001818258390080f9e2c88e6c817008f3a812ed889b4a4da8e0bd' - '103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd6' - '9b42771a00df1560021a0002e63003182f075820bdc2b27e6869aa9a5fa23a1f1f' - 'd3a87025d8703df4fd7b120d058c839dc0415c82a10141aa80', - ), - ), - }, - ); + final auxiliaryData = testAuxiliaryData(); return Transaction( body: TransactionBody( - inputs: { - TransactionInput( - transactionId: testTransactionHash, - index: 0, - ), - }, + inputs: {testUtxo().input}, outputs: [ TransactionOutput( address: testnetAddr, @@ -153,31 +139,11 @@ Transaction fullUnsignedTestTransaction() { /// Returns a full transaction with all possible optional fields. Transaction fullSignedTestTransaction() { - final auxiliaryData = AuxiliaryData( - map: { - const CborSmallInt(1): CborString('Test'), - const CborSmallInt(2): CborBytes(hex.decode('aabbccddeeff')), - const CborSmallInt(3): const CborSmallInt(997), - const CborSmallInt(4): cbor.decode( - hex.decode( - '82a50081825820afcf8497561065afe1ca623823508753cc580eb575ac8f1d6cfa' - 'a18c3ceeac010001818258390080f9e2c88e6c817008f3a812ed889b4a4da8e0bd' - '103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd6' - '9b42771a00df1560021a0002e63003182f075820bdc2b27e6869aa9a5fa23a1f1f' - 'd3a87025d8703df4fd7b120d058c839dc0415c82a10141aa80', - ), - ), - }, - ); + final auxiliaryData = testAuxiliaryData(); return Transaction( body: TransactionBody( - inputs: { - TransactionInput( - transactionId: testTransactionHash, - index: 0, - ), - }, + inputs: {testUtxo().input}, outputs: [ TransactionOutput( address: testnetAddr, @@ -217,4 +183,23 @@ Transaction fullSignedTestTransaction() { ); } +AuxiliaryData testAuxiliaryData() { + return AuxiliaryData( + map: { + const CborSmallInt(1): CborString('Test'), + const CborSmallInt(2): CborBytes(hex.decode('aabbccddeeff')), + const CborSmallInt(3): const CborSmallInt(997), + const CborSmallInt(4): cbor.decode( + hex.decode( + '82a50081825820afcf8497561065afe1ca623823508753cc580eb575ac8f1d6cfa' + 'a18c3ceeac010001818258390080f9e2c88e6c817008f3a812ed889b4a4da8e0bd' + '103f86e7335422aa122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd6' + '9b42771a00df1560021a0002e63003182f075820bdc2b27e6869aa9a5fa23a1f1f' + 'd3a87025d8703df4fd7b120d058c839dc0415c82a10141aa80', + ), + ), + }, + ); +} + /* cSpell:enable */ diff --git a/catalyst_voices_packages/catalyst_cardano_serialization/test/transaction_test.dart b/catalyst_voices_packages/catalyst_cardano_serialization/test/transaction_test.dart index 52d8f88084..17217c3f3b 100644 --- a/catalyst_voices_packages/catalyst_cardano_serialization/test/transaction_test.dart +++ b/catalyst_voices_packages/catalyst_cardano_serialization/test/transaction_test.dart @@ -7,32 +7,111 @@ import 'test_utils/test_data.dart'; void main() { group(Transaction, () { - test('transaction with all supported fields serialized to bytes', () { - final bytes = cbor.encode(fullTestTransaction().toCbor()); - final hexString = hex.encode(bytes); - - expect( - hexString, - equals( - '84a40081825820583a3a5150bc7990656020ffb4e5a1be1589ce6f1a430aacb8e7e0' - '89b894d3d101018182581d609493315cd92eb5d8c4304e67b7e16ae36d61d3450269' - '4657811a2c8e1a004c4b40021a009896800319a029a0f5a1016454657374', - ), + test('full signed transaction serialized to cbor', () { + _testTransactionSerialization( + fullSignedTestTransaction(), + '84a600818258204c1fbc5433ec764164945d736a09dc087d59ff30e64d26d462ff' + '8570cd4be9a700018282581d6082e016828989cd9d809b50d6976d9efa9bc5b2c1' + 'a78d4b3bfa1bb83b1a000f424082583900c035332d2dcba35744e880729198459e' + '32c50eb3e179b1fa2247348c80b846ad416f120db94c1a401992950b11b9bc7d65' + 'dbb3424c0f8de41b0000000253fa14bb021a00028d050319a0e907582057b9d497' + '6bc8017e5b95c6996bac1749765e188c990b5c705a65c78f8349227d0f00a10081' + '8258203311ca404fcf22c91d607ace285d70e2263a1b81745c39673080329bd1a3' + 'f56e5840f5eb006f048fdfa9b81b0fe3abee1ce1f1a75789dc21088b23ebf95c76' + 'b050ad157a497999e083e1957c2a3d730a07a5b2aef4a755783c9ce778c02c4a08' + '970ff5a40164546573740246aabbccddeeff031903e50482a50081825820afcf84' + '97561065afe1ca623823508753cc580eb575ac8f1d6cfaa18c3ceeac0100018182' + '58390080f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a' + '946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b42771a00df1560021a' + '0002e63003182f075820bdc2b27e6869aa9a5fa23a1f1fd3a87025d8703df4fd7b' + '120d058c839dc0415c82a10141aa80', ); }); - test('transaction with required fields serialized to bytes', () { - final bytes = cbor.encode(minimalTestTransaction().toCbor()); - final hexString = hex.encode(bytes); + test('full signed transaction serialized to and from cbor', () { + _testTransactionSerializationRoundTrip(fullSignedTestTransaction()); + }); + + test('full unsigned transaction serialized to cbor', () { + _testTransactionSerialization( + fullUnsignedTestTransaction(), + '84a600818258204c1fbc5433ec764164945d736a09dc087d59ff30e64d26d462ff' + '8570cd4be9a700018282581d6082e016828989cd9d809b50d6976d9efa9bc5b2c1' + 'a78d4b3bfa1bb83b1a000f424082583900c035332d2dcba35744e880729198459e' + '32c50eb3e179b1fa2247348c80b846ad416f120db94c1a401992950b11b9bc7d65' + 'dbb3424c0f8de41b0000000253fa14bb021a00028d050319a0e907582057b9d497' + '6bc8017e5b95c6996bac1749765e188c990b5c705a65c78f8349227d0f00a0f5a4' + '0164546573740246aabbccddeeff031903e50482a50081825820afcf8497561065' + 'afe1ca623823508753cc580eb575ac8f1d6cfaa18c3ceeac010001818258390080' + 'f9e2c88e6c817008f3a812ed889b4a4da8e0bd103f86e7335422aa122a946b9ad3' + 'd2ddf029d3a828f0468aece76895f15c9efbd69b42771a00df1560021a0002e630' + '03182f075820bdc2b27e6869aa9a5fa23a1f1fd3a87025d8703df4fd7b120d058c' + '839dc0415c82a10141aa80', + ); + }); + + test('full unsigned transaction serialized to and from cbor', () { + _testTransactionSerializationRoundTrip(fullUnsignedTestTransaction()); + }); - expect( - hexString, - equals( - '84a30081825820583a3a5150bc7990656020ffb4e5a1be1589ce6f1a430aacb8e7e0' - '89b894d3d101018182581d609493315cd92eb5d8c4304e67b7e16ae36d61d3450269' - '4657811a2c8e1a004c4b40021a00989680a0f5d90103a0', - ), + test('minimal signed transaction serialized to cbor', () { + _testTransactionSerialization( + minimalSignedTestTransaction(), + '84a300818258204c1fbc5433ec764164945d736a09dc087d59ff30e64d26d462ff85' + '70cd4be9a700018282581d6082e016828989cd9d809b50d6976d9efa9bc5b2c1a78d' + '4b3bfa1bb83b1a000f424082583900c035332d2dcba35744e880729198459e32c50e' + 'b3e179b1fa2247348c80b846ad416f120db94c1a401992950b11b9bc7d65dbb3424c' + '0f8de41b0000000253fa156b021a00028c55a100818258203311ca404fcf22c91d60' + '7ace285d70e2263a1b81745c39673080329bd1a3f56e584085b3a67a0529c95a740f' + 'd643e2998f03f251268ca603a0778b6631966b9a43fd2e02fa907c610ecc985b375f' + 'a9852c14789dacd2ab7897b445efe4f4b0f60a06f5d90103a0', + ); + }); + + test('minimal signed transaction serialized to and from cbor', () { + _testTransactionSerializationRoundTrip( + minimalSignedTestTransaction(), + ); + }); + + test('minimal unsigned transaction serialized to and from cbor', () { + _testTransactionSerializationRoundTrip(fullUnsignedTestTransaction()); + }); + + test('minimal unsigned transaction serialized to cbor', () { + _testTransactionSerialization( + minimalUnsignedTestTransaction(), + '84a300818258204c1fbc5433ec764164945d736a09dc087d59ff30e64d26d4' + '62ff8570cd4be9a700018282581d6082e016828989cd9d809b50d6976d9efa' + '9bc5b2c1a78d4b3bfa1bb83b1a000f424082583900c035332d2dcba35744e8' + '80729198459e32c50eb3e179b1fa2247348c80b846ad416f120db94c1a4019' + '92950b11b9bc7d65dbb3424c0f8de41b0000000253fa156b021a00028c55a0' + 'f5d90103a0', + ); + }); + + test('minimal unsigned transaction serialized to and from cbor', () { + _testTransactionSerializationRoundTrip( + minimalUnsignedTestTransaction(), ); }); }); } + +void _testTransactionSerializationRoundTrip(Transaction transaction) { + final hex1 = hex.encode(cbor.encode(transaction.toCbor())); + final tx1 = Transaction.fromCbor(cbor.decode(hex.decode(hex1))); + final hex2 = hex.encode(cbor.encode(tx1.toCbor())); + + expect(hex1, equals(hex2)); +} + +void _testTransactionSerialization( + Transaction transaction, + String expectedHex, +) { + final bytes = cbor.encode(transaction.toCbor()); + final hexString = hex.encode(bytes); + + expect(hexString, equals(expectedHex)); +}