@@ -46,4 +46,78 @@ describe('Cardano API', () => {
4646 expect ( txCbor ) . toBe ( "84a300d9010281825820be6efd42a3d7b9a00d09d77a5d41e55ceaf0bd093a8aa8a893ce70d9caafd97800018182581d6082935e44937e8b530f32ce672b5d600d0a286b4e8a52c6555f659b871a0098968002192710a100d9010281825820adfc1c30385916da87db1ba3328f0690a57ebb2a6ac9f6f86b2d97f943adae0058400b19a00593e659ad0f10951f0f7d1e8a8b93112c60f67277529f91340581639e92ed4d0042ff92a0076cd69deb7e708acfdb73bb4ae79cf4bc06fd6d15efa208f5f6" ) ;
4747 } ) ;
4848
49+ // Delegation requires a witness from the stake credential, added with the stake key.
50+ it ( 'should build a delegation transaction signed with a payment key and a stake key' , async ( ) => {
51+ // Test constants
52+ const PREVIEW_MAGIC_NUMBER = 2 ;
53+ const paymentSecretKey = "addr_sk1648253w4tf6fv5fk28dc7crsjsaw7d9ymhztd4favg3cwkhz7x8sl5u3ms" ;
54+ const stakeSecretKey = "stake_sk10pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0puqawrffl" ;
55+ const poolId = "b" . repeat ( 56 ) ;
56+ const txInputHash = "be6efd42a3d7b9a00d09d77a5d41e55ceaf0bd093a8aa8a893ce70d9caafd978" ;
57+ const outputAddress = "addr_test1vzpfxhjyjdlgk5c0xt8xw26avqxs52rtf69993j4tajehpcue4v2v" ;
58+
59+ // Restore a stake wallet (holds both a payment and a stake key)
60+ const wallet = await api . wallet . testnet . restoreStakeWalletFromSigningKeyBech32 (
61+ PREVIEW_MAGIC_NUMBER , paymentSecretKey , stakeSecretKey ) ;
62+ const stakeKeyHash = await wallet . getBase16ForStakeVerificationKeyHash ( ) ;
63+
64+ // Delegate the stake credential to a pool
65+ const delegationCert = await api . certificate . mainnetEra
66+ . makeStakeAddressStakeDelegationCertificate ( stakeKeyHash , poolId ) ;
67+
68+ // Build a transaction that includes the delegation certificate
69+ const tx = ( await api . tx . newTx ( ) )
70+ . addTxInput ( txInputHash , 0 )
71+ . addSimpleTxOut ( outputAddress , 5_000_000n )
72+ . appendCertificateToTx ( delegationCert )
73+ . setFee ( 10_000n ) ;
74+
75+ // Sign with the payment key, then add a witness from the stake key
76+ const signedTx = ( await tx . signWithPaymentKey ( paymentSecretKey ) )
77+ . alsoSignWithStakeKey ( stakeSecretKey ) ;
78+ expect ( signedTx ) . toBeDefined ( ) ;
79+
80+ const txCbor = await signedTx . txToCbor ( ) ;
81+
82+ expect ( txCbor ) . toBe ( "84a400d9010281825820be6efd42a3d7b9a00d09d77a5d41e55ceaf0bd093a8aa8a893ce70d9caafd97800018182581d6082935e44937e8b530f32ce672b5d600d0a286b4e8a52c6555f659b871a004c4b400219271004d901028183028200581ca9461e687627cddc5f54ffc988bc44321189538c601f1ad1b7979d9b581cbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba100d9010282825820adfc1c30385916da87db1ba3328f0690a57ebb2a6ac9f6f86b2d97f943adae005840b5df44de4b1302d1b031363cfb9636be2f395561dcf083d1192656677506bfa401d988d745f2ee2d11ed9e563f35cc2dfbb605c7cd58a613e42377e5e2a8da01825820ee31f83c88a71219a6fcf9bee0da9bc22620588f5a15a6145553504df9649e5c58402a2a37f2391bdf3a1ff52a7ed2103473f35b43022ed101bddcb18a557f7e9f9eac75c3562b142cc15dc9ebd006da34f4076ff413914ec90e4359d757d73bfc06f5f6" ) ;
83+ } ) ;
84+
85+ // The stake key can also be the first signer, with the payment witness added afterwards.
86+ // Witnesses live in a set, so the resulting transaction is identical regardless of signing order.
87+ it ( 'should build a delegation transaction signed with a stake key and then a payment key' , async ( ) => {
88+ // Test constants
89+ const PREVIEW_MAGIC_NUMBER = 2 ;
90+ const paymentSecretKey = "addr_sk1648253w4tf6fv5fk28dc7crsjsaw7d9ymhztd4favg3cwkhz7x8sl5u3ms" ;
91+ const stakeSecretKey = "stake_sk10pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0pu8s7rc0puqawrffl" ;
92+ const poolId = "b" . repeat ( 56 ) ;
93+ const txInputHash = "be6efd42a3d7b9a00d09d77a5d41e55ceaf0bd093a8aa8a893ce70d9caafd978" ;
94+ const outputAddress = "addr_test1vzpfxhjyjdlgk5c0xt8xw26avqxs52rtf69993j4tajehpcue4v2v" ;
95+
96+ // Restore a stake wallet (holds both a payment and a stake key)
97+ const wallet = await api . wallet . testnet . restoreStakeWalletFromSigningKeyBech32 (
98+ PREVIEW_MAGIC_NUMBER , paymentSecretKey , stakeSecretKey ) ;
99+ const stakeKeyHash = await wallet . getBase16ForStakeVerificationKeyHash ( ) ;
100+
101+ // Delegate the stake credential to a pool
102+ const delegationCert = await api . certificate . mainnetEra
103+ . makeStakeAddressStakeDelegationCertificate ( stakeKeyHash , poolId ) ;
104+
105+ // Build a transaction that includes the delegation certificate
106+ const tx = ( await api . tx . newTx ( ) )
107+ . addTxInput ( txInputHash , 0 )
108+ . addSimpleTxOut ( outputAddress , 5_000_000n )
109+ . appendCertificateToTx ( delegationCert )
110+ . setFee ( 10_000n ) ;
111+
112+ // Sign with the stake key first, then add a witness from the payment key
113+ const signedTx = ( await tx . signWithStakeKey ( stakeSecretKey ) )
114+ . alsoSignWithPaymentKey ( paymentSecretKey ) ;
115+ expect ( signedTx ) . toBeDefined ( ) ;
116+
117+ const txCbor = await signedTx . txToCbor ( ) ;
118+
119+ // Identical to the payment-key-first delegation transaction above
120+ expect ( txCbor ) . toBe ( "84a400d9010281825820be6efd42a3d7b9a00d09d77a5d41e55ceaf0bd093a8aa8a893ce70d9caafd97800018182581d6082935e44937e8b530f32ce672b5d600d0a286b4e8a52c6555f659b871a004c4b400219271004d901028183028200581ca9461e687627cddc5f54ffc988bc44321189538c601f1ad1b7979d9b581cbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbba100d9010282825820adfc1c30385916da87db1ba3328f0690a57ebb2a6ac9f6f86b2d97f943adae005840b5df44de4b1302d1b031363cfb9636be2f395561dcf083d1192656677506bfa401d988d745f2ee2d11ed9e563f35cc2dfbb605c7cd58a613e42377e5e2a8da01825820ee31f83c88a71219a6fcf9bee0da9bc22620588f5a15a6145553504df9649e5c58402a2a37f2391bdf3a1ff52a7ed2103473f35b43022ed101bddcb18a557f7e9f9eac75c3562b142cc15dc9ebd006da34f4076ff413914ec90e4359d757d73bfc06f5f6" ) ;
121+ } ) ;
122+
49123} ) ;
0 commit comments