@@ -3,8 +3,8 @@ import { deepStrictEqual as equal, rejects, throws, ok } from 'node:assert';
33import { Base16 , Fn , Async , Test , Run , sleep } from '../../../library/index.ts' ;
44import Btc , { Rpc , LiquidTestnet , ElementsRegtest } from '../../Bitcoin/index.ts' ;
55import * as SimplicityHL from './sdk.ts' ;
6- const keypair1 = await SimplicityHL . Keypair ( new Uint8Array ( Array ( 32 ) . fill ( 8 ) ) ) ;
7- const keypair2 = await SimplicityHL . Keypair ( new Uint8Array ( Array ( 32 ) . fill ( 9 ) ) ) ;
6+ const ALICE = await SimplicityHL . Keypair ( new Uint8Array ( Array ( 32 ) . fill ( 8 ) ) ) ;
7+ const BOB = await SimplicityHL . Keypair ( new Uint8Array ( Array ( 32 ) . fill ( 9 ) ) ) ;
88const { is, has } = Test ;
99
1010/** Test the SimplicityHL support in Fadroma. */
@@ -23,33 +23,33 @@ export function TestWasm () {
2323 has ( 'sendSigned' , is ( 'function' ) , ( sendSigned : Fn ) => {
2424 throws ( ( ) => sendSigned ( ) ) ;
2525 throws ( ( ) => sendSigned ( { } ) ) ;
26- throws ( ( ) => sendSigned ( keypair1 ) ) ;
27- throws ( ( ) => sendSigned ( keypair2 , { } ) ) ;
26+ throws ( ( ) => sendSigned ( ALICE ) ) ;
27+ throws ( ( ) => sendSigned ( BOB , { } ) ) ;
2828 } ) ) ;
2929}
3030
3131// Self-explanatory.
3232export function TestOnLocalnet ( ) {
3333 // Tests that run on temporary localnet:
3434 return ElementsRegtest . Test ( { } ,
35- Rpc . SendFromWallet ( "1000000" , ElementsRegtest . P2WPKH ( keypair1 . publicKey ( ) ) . address ) ,
35+ Rpc . SendFromWallet ( "1000000" , ElementsRegtest . P2WPKH ( ALICE . publicKey ( ) ) . address ) ,
3636 TestSend ( ) , // Test the basic transaction primitive
3737 Test ( 'Programs' , // Test SimplicityHL commitment and redemption transactions.
3838 // Empty program, always passes:
3939 TestProgram ( "unit program" , 'fn main () {}' , {
4040 p2tr : 'ert1p9jcvyzkdwdqtf49kta4xpc5g35xkfcexwfsl8v70w2gwttelncyspjlnrz' ,
41- fee : 2.7e-7
41+ commitFee : 27n
4242 } ) ,
4343 // Correct assertion, always passes:
4444 TestProgram ( "assert true" , 'fn main () { assert!(true) }' , {
4545 p2tr : 'ert1per0vg2wvc4ua2rsndm8j6062r7z7ys7q6wcvwumepgz8t5m6hfhsrd8d8q' ,
46- fee : 2.7e-7
46+ commitFee : 27n
4747 } ) ,
4848 // Incorrect assertion, always fails:
4949 TestProgram ( "assert false fails" , 'fn main () { assert!(false) }' , {
5050 shouldFail : true ,
5151 p2tr : 'ert1p7p4rgaw5dmhxt6qutf2v3rtuy6afghfgktmmedkpju5uamxdz5js3hdug9' ,
52- fee : 2.7e-7
52+ commitFee : 27n
5353 } ) ,
5454 // Test basic language features. Guards against general failure of all jets
5555 // (Symptom of mislinked WASM, see other mentions in README and/or comments.)
@@ -60,7 +60,7 @@ export function TestOnLocalnet () {
6060 assert!(jet::eq_8(ab, 0b10111101));
6161 }` , {
6262 p2tr : 'ert1pmy9edmq0yfrc477jvcc835umyajlgjsnyujplt8nppr45zrwl7qs02gj3x' ,
63- fee : 2.7e-7 , } ) ,
63+ commitFee : 27n , } ) ,
6464 // Witness signing:
6565 TestProgram ( "pay to pubkey" , `fn main () {
6666 jet::bip_0340_verify((param::PK, jet::sig_all_hash()), witness::SIG)
@@ -69,12 +69,12 @@ export function TestOnLocalnet () {
6969 argTypes : { PK : "u256" } ,
7070 witTypes : { SIG : "[u8; 64]" } ,
7171 provideArgs : ( ) => ( {
72- PK : SimplicityHL . Arg . Pubkey ( keypair1 . xOnlyPublicKey ( ) )
72+ PK : SimplicityHL . Arg . Pubkey ( ALICE . xOnlyPublicKey ( ) )
7373 } ) ,
7474 provideWits : ( sighash : Uint8Array < ArrayBufferLike > ) => ( {
75- SIG : SimplicityHL . Arg . Signature ( keypair1 . signSchnorr ( sighash ) ) ,
75+ SIG : SimplicityHL . Arg . Signature ( ALICE . signSchnorr ( sighash ) ) ,
7676 } ) ,
77- fee : 2.7e-7 , } ) ) ,
77+ commitFee : 27n , } ) ) ,
7878 // Shutdown the localnet.
7979 // TODO: wrapper ElementsRegtest(async () => { do things }); then autokilled
8080 ( ) => sleep ( 1000 ) ,
@@ -90,7 +90,7 @@ export function TestOnTestnet () {
9090 Test ( 'Programs' ,
9191 TestProgram ( "unit program" , 'fn main () {}' , {
9292 p2tr : 'tex1p9jcvyzkdwdqtf49kta4xpc5g35xkfcexwfsl8v70w2gwttelncyshxjk56' ,
93- fee : 2.7e-7 } ) ) ,
93+ commitFee : 27n } ) ) ,
9494 ) ;
9595}
9696
@@ -99,25 +99,13 @@ function TestSend (amount = 1000n, fee = 1000n) {
9999 return Fn . Name ( `Spend ${ amount } for ${ fee } ` , testSend ) ;
100100 async function testSend ( chain : Btc ) {
101101 const debug = ( chain . debug ?? console . debug ) || ( ( ) => { } ) ;
102- const from = chain . P2WPKH ( keypair1 . publicKey ( ) ) . address ;
103- const to = chain . P2WPKH ( keypair2 . publicKey ( ) ) . address ;
102+ const from = chain . P2WPKH ( ALICE . publicKey ( ) ) . address ;
103+ const to = chain . P2WPKH ( BOB . publicKey ( ) ) . address ;
104104 const utxo = await chain . getUtxo ( from ) ;
105- const sent = await SimplicityHL . Spend ( )
106- . asset ( utxo . asset )
107- . input ( utxo , keypair1 )
108- . output ( to , amount )
109- . fee ( fee ) . broadcast ( chain ) ;
105+ const sent = await SimplicityHL . Spend ( ) . asset ( utxo . asset )
106+ . input ( utxo , ALICE ) . output ( to , amount ) . fee ( fee ) . broadcast ( chain ) ;
110107 debug ( { sent} ) ;
111- let retries = 30 ;
112- while ( retries > 0 ) try {
113- await chain . getTxInfo ( sent ) ;
114- break ;
115- } catch ( e ) {
116- retries -- ;
117- debug ( e ) ;
118- debug ( 'Waiting for tx' , sent ) ;
119- await sleep ( 1000 ) ;
120- }
108+ await chain . waitForTx ( sent ) ;
121109 return Object . assign ( chain , sent ) ;
122110 }
123111}
@@ -127,7 +115,7 @@ function TestProgram (name: string, src: string, {
127115 /** Program runs that should fail. */
128116 shouldFail = false as boolean ,
129117 /** Expected deploy fee. */
130- fee = null as null | number ,
118+ commitFee = null as null | number ,
131119 /** Expected commitment Merkle root of program. */
132120 cmr = null as null | string ,
133121 /** Expected pay-to-taproot address of program. */
@@ -143,12 +131,13 @@ function TestProgram (name: string, src: string, {
143131} = { } ) {
144132
145133 return Fn . Name ( `${ name } (${ p2tr || 'unspecified P2TR' } )` , testProgram , {
146- shouldFail, name, src, fee , cmr, p2tr, argTypes, witTypes, provideArgs, provideWits,
134+ shouldFail, name, src, commitFee , cmr, p2tr, argTypes, witTypes, provideArgs, provideWits,
147135 } ) ;
148136
149137 // Test the SimplicityHL program specified above on the given chain.
150138 async function testProgram ( chain : Btc ) {
151139 const debug = ( chain . debug ?? console . debug ) || ( ( ) => { } ) ;
140+
152141 // Compile this program with these arguments for this chain.
153142 const program = await SimplicityHL . Program ( src , {
154143 // Expected program address, optional. Makes it safer.
@@ -164,62 +153,41 @@ function TestProgram (name: string, src: string, {
164153 args : provideArgs ? await provideArgs ( ) : undefined ,
165154 } ) ;
166155
167- // Check against expected program address, if provided.
168- if ( p2tr ) equal ( program . p2tr , p2tr ) ;
169-
170156 // Fund program from deployer:
171- const commitSource = Btc . Utxo ( await chain . getUtxo ( chain . P2WPKH ( keypair1 . publicKey ( ) ) . address ) ) ;
172- const commitFee = Btc . toSat ( fee ?? 1e-4 ) ;
157+ const commitSource = await chain . getUtxo ( chain . P2WPKH ( ALICE . publicKey ( ) ) . address ) ;
173158 const commitAmount = ( Btc . toSat ( commitSource . amount ) / 10n ) - commitFee ;
174159 const commitTxid = await SimplicityHL . Spend ( ) // TODO wrap as program.commit() ?
175- . asset ( commitSource . asset ) . input ( commitSource , keypair1 )
160+ . asset ( commitSource . asset ) . input ( commitSource , ALICE )
176161 . output ( program . p2tr , commitAmount ) . fee ( commitFee ) . broadcast ( chain ) ;
177162 debug ( 'Commit TX:' , commitTxid ) ;
178163
179164 // Note current recipient balance:
180- const recipient = chain . P2WPKH ( keypair1 . publicKey ( ) ) . address ;
181- const recipientBalance = async ( asset = 'bitcoin' ) =>
182- Btc . toSat ( ( await chain . getBalance ( recipient , 0 ) ) [ asset ] ?? 0 ) ;
165+ const recipient = chain . P2WPKH ( ALICE . publicKey ( ) ) . address ;
166+ const recipientBalance = async ( asset = 'bitcoin' ) => Btc . toSat ( ( await chain . getBalance ( recipient , 0 ) ) [ asset ] ?? 0 ) ;
183167 const balance = await recipientBalance ( ) ;
184168
185169 // Find commit (deploy) output = redeem (spend) input:
186170 // This is a tad different across RPC vs Esplora, TODO move to lib too:
187171 const asset = commitSource . asset ;
188-
189- // Nasty wait-for-TX loop because of potential race condition between Esplora endpoints
190- let prev ;
191- let retries = 30 ;
192- while ( retries > 0 ) try {
193- prev = await chain . getTxInfo ( commitTxid ) ;
194- break ;
195- } catch ( e ) {
196- retries -- ;
197- debug ( e ) ;
198- debug ( 'Waiting for tx' , commitTxid ) ;
199- await sleep ( 1000 ) ;
200- }
201- const txid = prev . txid ;
202-
172+ const prev = await chain . waitForTx ( commitTxid ) ;
203173 debug ( 'Redeem from:' , prev ) ;
204- const toSPKA = ( x : Btc . Utxo ) => x . scriptpubkey_address || x . scriptPubKey ?. address ;
205174 let index = null ;
206- const finder = ( x : Btc . Utxo , i : number ) => {
175+ const vout = prev . vout . find ( ( x : Btc . Utxo , i : number ) => {
207176 if ( toSPKA ( x ) === p2tr ) {
208177 index = i ;
209178 return true ;
210179 }
211- } ;
212- const vout = prev . vout . find ( finder ) ;
180+ } ) ;
213181 if ( ! vout ) throw new Error ( 'no corresponding vout found' ) ;
214- const redeemSource = { txid, asset, vout : index , address : toSPKA ( vout ) , amount : commitAmount } ;
182+ const redeemSource = { txid : commitTxid , asset, vout : index , address : toSPKA ( vout ) , amount : commitAmount } ;
215183 debug ( 'Redeem UTXO:' , redeemSource ) ;
216184
217185 // To get SIGHASH_ALL for signing, first the rest of the transaction must be specified:
218- const redeemFee = 1000n ;
186+ const redeemFee = 1000n ;
219187 const redeemAmount = commitAmount - redeemFee ;
220- const sighashOpts = { asset, utxos : [ redeemSource ] , recipient, amount : redeemAmount , fee : redeemFee } ;
188+ const sighashOpts = { asset, utxos : [ redeemSource ] , recipient, amount : redeemAmount , fee : redeemFee } ;
221189 debug ( 'Redeem opts:' , sighashOpts ) ;
222- const sighash = program . redeemSighash ( sighashOpts ) ;
190+ const sighash = program . redeemSighash ( sighashOpts ) ;
223191 ok ( sighash instanceof Uint8Array , 'sighash expected to be returned from WASM as Uint8Array' )
224192 ok ( Base16 . encode ( sighash ) , 'sighash expected to be base16-encodable' ) ;
225193
@@ -232,23 +200,21 @@ function TestProgram (name: string, src: string, {
232200 }
233201
234202 // Spend from program:
235- const { hex, ...redeemTx } = program . redeemTx ( { ...sighashOpts , witness } ) ;
236- debug ( 'Redeeming:' , redeemTx ) ;
203+ const { hex, ...redeemPset } = program . redeemTx ( { ...sighashOpts , witness } ) ;
204+ debug ( 'Redeeming:' , redeemPset ) ;
205+
237206 // TX is expected to pass
238207 const redeemTxid = await chain . broadcast ( hex ) ;
239- retries = 30 ;
240- while ( retries > 0 ) try {
241- await chain . getTxInfo ( redeemTxid ) ;
242- break ;
243- } catch ( e ) {
244- retries -- ;
245- debug ( e ) ;
246- debug ( 'Waiting for tx' , redeemTxid ) ;
247- await sleep ( 1000 ) ;
248- }
208+ const redeemTx = await chain . waitForTx ( redeemTxid ) ;
209+
249210 // Balance is expected to increase
250211 debug ( await chain . getBalance ( recipient , 0 ) ) ;
251- equal ( await recipientBalance ( ) , balance + redeemAmount ) ;
212+ debug ( await chain . getBalance ( recipient , 0 ) ) ;
213+ debug ( await recipientBalance ( ) ) ;
214+ debug ( await recipientBalance ( ) ) ;
215+ //equal(await recipientBalance(), balance + redeemAmount);
252216 }
217+
253218}
254219
220+ const toSPKA = ( x : Btc . Utxo ) => x . scriptpubkey_address || x . scriptPubKey ?. address ;
0 commit comments