ecash-agora 0.1.1-rc

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,630 @@
1
+ // Copyright (c) 2024 The Bitcoin developers
2
+ // Distributed under the MIT software license, see the accompanying
3
+ // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
+
5
+ import { expect, use } from 'chai';
6
+ import chaiAsPromised from 'chai-as-promised';
7
+ import { ChronikClient } from 'chronik-client';
8
+ import {
9
+ ALL_BIP143,
10
+ DEFAULT_DUST_LIMIT,
11
+ Ecc,
12
+ P2PKHSignatory,
13
+ SLP_FUNGIBLE,
14
+ Script,
15
+ TxBuilderInput,
16
+ fromHex,
17
+ initWasm,
18
+ shaRmd160,
19
+ slpSend,
20
+ toHex,
21
+ } from 'ecash-lib';
22
+ import { TestRunner } from 'ecash-lib/dist/test/testRunner.js';
23
+
24
+ import { AgoraPartial } from '../src/partial.js';
25
+ import { makeSlpOffer, takeSlpOffer } from './partial-helper-slp.js';
26
+ import { Agora } from '../src/agora.js';
27
+
28
+ use(chaiAsPromised);
29
+
30
+ // This test needs a lot of sats
31
+ const NUM_COINS = 500;
32
+ const COIN_VALUE = 1100000000;
33
+
34
+ const BASE_PARAMS_SLP = {
35
+ tokenId: '00'.repeat(32), // filled in later
36
+ tokenType: SLP_FUNGIBLE,
37
+ tokenProtocol: 'SLP' as const,
38
+ dustAmount: DEFAULT_DUST_LIMIT,
39
+ };
40
+
41
+ describe('AgoraPartial SLP', () => {
42
+ let runner: TestRunner;
43
+ let chronik: ChronikClient;
44
+ let ecc: Ecc;
45
+
46
+ let makerSk: Uint8Array;
47
+ let makerPk: Uint8Array;
48
+ let makerPkh: Uint8Array;
49
+ let makerScript: Script;
50
+ let makerScriptHex: string;
51
+ let takerSk: Uint8Array;
52
+ let takerPk: Uint8Array;
53
+ let takerPkh: Uint8Array;
54
+ let takerScript: Script;
55
+ let takerScriptHex: string;
56
+
57
+ async function makeBuilderInputs(
58
+ values: number[],
59
+ ): Promise<TxBuilderInput[]> {
60
+ const txid = await runner.sendToScript(values, makerScript);
61
+ return values.map((value, outIdx) => ({
62
+ input: {
63
+ prevOut: {
64
+ txid,
65
+ outIdx,
66
+ },
67
+ signData: {
68
+ value,
69
+ outputScript: makerScript,
70
+ },
71
+ },
72
+ signatory: P2PKHSignatory(makerSk, makerPk, ALL_BIP143),
73
+ }));
74
+ }
75
+
76
+ before(async () => {
77
+ await initWasm();
78
+ runner = await TestRunner.setup('setup_scripts/ecash-agora_base');
79
+ chronik = runner.chronik;
80
+ ecc = runner.ecc;
81
+ await runner.setupCoins(NUM_COINS, COIN_VALUE);
82
+
83
+ makerSk = fromHex('33'.repeat(32));
84
+ makerPk = ecc.derivePubkey(makerSk);
85
+ makerPkh = shaRmd160(makerPk);
86
+ makerScript = Script.p2pkh(makerPkh);
87
+ makerScriptHex = toHex(makerScript.bytecode);
88
+ takerSk = fromHex('44'.repeat(32));
89
+ takerPk = ecc.derivePubkey(takerSk);
90
+ takerPkh = shaRmd160(takerPk);
91
+ takerScript = Script.p2pkh(takerPkh);
92
+ takerScriptHex = toHex(takerScript.bytecode);
93
+ });
94
+
95
+ after(() => {
96
+ runner.stop();
97
+ });
98
+
99
+ interface TestCase {
100
+ offeredTokens: bigint;
101
+ info: string;
102
+ priceNanoSatsPerToken: bigint;
103
+ acceptedTokens: bigint;
104
+ askedSats: number;
105
+ }
106
+ const TEST_CASES: TestCase[] = [
107
+ {
108
+ offeredTokens: 1000n,
109
+ info: '1sat/token, full accept',
110
+ priceNanoSatsPerToken: 1000000000n,
111
+ acceptedTokens: 1000n,
112
+ askedSats: 1000,
113
+ },
114
+ {
115
+ offeredTokens: 1000n,
116
+ info: '1sat/token, dust accept',
117
+ priceNanoSatsPerToken: 1000000000n,
118
+ acceptedTokens: 546n,
119
+ askedSats: 546,
120
+ },
121
+ {
122
+ offeredTokens: 1000n,
123
+ info: '1000sat/token, full accept',
124
+ priceNanoSatsPerToken: 1000n * 1000000000n,
125
+ acceptedTokens: 1000n,
126
+ askedSats: 1000225,
127
+ },
128
+ {
129
+ offeredTokens: 1000n,
130
+ info: '1000sat/token, half accept',
131
+ priceNanoSatsPerToken: 1000n * 1000000000n,
132
+ acceptedTokens: 500n,
133
+ askedSats: 500113,
134
+ },
135
+ {
136
+ offeredTokens: 1000n,
137
+ info: '1000sat/token, 1 accept',
138
+ priceNanoSatsPerToken: 1000n * 1000000000n,
139
+ acceptedTokens: 1n,
140
+ askedSats: 1001,
141
+ },
142
+ {
143
+ offeredTokens: 1000n,
144
+ info: '1000000sat/token, full accept',
145
+ priceNanoSatsPerToken: 1000000n * 1000000000n,
146
+ acceptedTokens: 1000n,
147
+ askedSats: 1000013824,
148
+ },
149
+ {
150
+ offeredTokens: 1000n,
151
+ info: '1000000sat/token, half accept',
152
+ priceNanoSatsPerToken: 1000000n * 1000000000n,
153
+ acceptedTokens: 500n,
154
+ askedSats: 500039680,
155
+ },
156
+ {
157
+ offeredTokens: 1000n,
158
+ info: '1000000sat/token, 1 accept',
159
+ priceNanoSatsPerToken: 1000000n * 1000000000n,
160
+ acceptedTokens: 1n,
161
+ askedSats: 1048576,
162
+ },
163
+ {
164
+ offeredTokens: 1000n,
165
+ info: '1000000000sat/token, 1 accept',
166
+ priceNanoSatsPerToken: 1000000000n * 1000000000n,
167
+ acceptedTokens: 1n,
168
+ askedSats: 1006632960,
169
+ },
170
+ {
171
+ offeredTokens: 1000000n,
172
+ info: '0.001sat/token, full accept',
173
+ priceNanoSatsPerToken: 1000000n,
174
+ acceptedTokens: 1000000n,
175
+ askedSats: 1000,
176
+ },
177
+ {
178
+ offeredTokens: 1000000n,
179
+ info: '1sat/token, full accept',
180
+ priceNanoSatsPerToken: 1000000000n,
181
+ acceptedTokens: 1000000n,
182
+ askedSats: 1000000,
183
+ },
184
+ {
185
+ offeredTokens: 1000000n,
186
+ info: '1sat/token, half accept',
187
+ priceNanoSatsPerToken: 1000000000n,
188
+ acceptedTokens: 500000n,
189
+ askedSats: 500000,
190
+ },
191
+ {
192
+ offeredTokens: 1000000n,
193
+ info: '1sat/token, dust accept',
194
+ priceNanoSatsPerToken: 1000000000n,
195
+ acceptedTokens: 546n,
196
+ askedSats: 546,
197
+ },
198
+ {
199
+ offeredTokens: 1000000n,
200
+ info: '1000sat/token, full accept',
201
+ priceNanoSatsPerToken: 1000n * 1000000000n,
202
+ acceptedTokens: 1000000n,
203
+ askedSats: 1001151232,
204
+ },
205
+ {
206
+ offeredTokens: 1000000n,
207
+ info: '1000sat/token, half accept',
208
+ priceNanoSatsPerToken: 1000n * 1000000000n,
209
+ acceptedTokens: 500000n,
210
+ askedSats: 500575744,
211
+ },
212
+ {
213
+ offeredTokens: 1000000n,
214
+ info: '1000sat/token, 1 accept',
215
+ priceNanoSatsPerToken: 1000n * 1000000000n,
216
+ acceptedTokens: 1n,
217
+ askedSats: 1024,
218
+ },
219
+ {
220
+ offeredTokens: 1000000n,
221
+ info: '1000000sat/token, 1000 accept',
222
+ priceNanoSatsPerToken: 1000000n * 1000000000n,
223
+ acceptedTokens: 1000n,
224
+ askedSats: 1005060096,
225
+ },
226
+ {
227
+ offeredTokens: 1000000n,
228
+ info: '1000000sat/token, 1 accept',
229
+ priceNanoSatsPerToken: 1000000n * 1000000000n,
230
+ acceptedTokens: 1n,
231
+ askedSats: 1048576,
232
+ },
233
+ {
234
+ offeredTokens: 1000000n,
235
+ info: '1000000sat/token, 1 accept',
236
+ priceNanoSatsPerToken: 1000000000n * 1000000000n,
237
+ acceptedTokens: 1n,
238
+ askedSats: 1006632960,
239
+ },
240
+ {
241
+ offeredTokens: 1000000000n,
242
+ info: '0.001sat/token, full accept',
243
+ priceNanoSatsPerToken: 1000000n,
244
+ acceptedTokens: 1000000000n,
245
+ askedSats: 1000000,
246
+ },
247
+ {
248
+ offeredTokens: 1000000000n,
249
+ info: '0.001sat/token, half accept',
250
+ priceNanoSatsPerToken: 1000000n,
251
+ acceptedTokens: 500000000n,
252
+ askedSats: 500000,
253
+ },
254
+ {
255
+ offeredTokens: 1000000000n,
256
+ info: '0.001sat/token, dust accept',
257
+ priceNanoSatsPerToken: 1000000n,
258
+ acceptedTokens: 546000n,
259
+ askedSats: 546,
260
+ },
261
+ {
262
+ offeredTokens: 1000000000n,
263
+ info: '1sat/token, full accept',
264
+ priceNanoSatsPerToken: 1000000000n,
265
+ acceptedTokens: 1000000000n,
266
+ askedSats: 1000000000,
267
+ },
268
+ {
269
+ offeredTokens: 1000000000n,
270
+ info: '1sat/token, half accept',
271
+ priceNanoSatsPerToken: 1000000000n,
272
+ acceptedTokens: 500000000n,
273
+ askedSats: 500000000,
274
+ },
275
+ {
276
+ offeredTokens: 1000000000n,
277
+ info: '1sat/token, dust accept',
278
+ priceNanoSatsPerToken: 1000000000n,
279
+ acceptedTokens: 546n,
280
+ askedSats: 546,
281
+ },
282
+ {
283
+ offeredTokens: 1000000000n,
284
+ info: '1000sat/token, 983040 accept',
285
+ priceNanoSatsPerToken: 1000n * 1000000000n,
286
+ acceptedTokens: 983040n,
287
+ askedSats: 989855744,
288
+ },
289
+ {
290
+ offeredTokens: 1000000000n,
291
+ info: '1000sat/token, 65536 accept',
292
+ priceNanoSatsPerToken: 1000n * 1000000000n,
293
+ acceptedTokens: 65536n,
294
+ askedSats: 67108864,
295
+ },
296
+ {
297
+ offeredTokens: 1000000000000n,
298
+ info: '0.000001sat/token, full accept',
299
+ priceNanoSatsPerToken: 1000n,
300
+ acceptedTokens: 999999995904n,
301
+ askedSats: 1000108,
302
+ },
303
+ {
304
+ offeredTokens: 1000000000000n,
305
+ info: '0.000001sat/token, half accept',
306
+ priceNanoSatsPerToken: 1000n,
307
+ acceptedTokens: 546045952n,
308
+ askedSats: 547,
309
+ },
310
+ {
311
+ offeredTokens: 1000000000000n,
312
+ info: '0.001sat/token, full accept',
313
+ priceNanoSatsPerToken: 1000000n,
314
+ acceptedTokens: 999999995904n,
315
+ askedSats: 1068115230,
316
+ },
317
+ {
318
+ offeredTokens: 1000000000000n,
319
+ info: '0.001sat/token, dust accept',
320
+ priceNanoSatsPerToken: 1000000n,
321
+ acceptedTokens: 589824n,
322
+ askedSats: 630,
323
+ },
324
+ {
325
+ offeredTokens: 1000000000000000n,
326
+ info: '0.000000001sat/token, full accept',
327
+ priceNanoSatsPerToken: 1n,
328
+ acceptedTokens: 999999986991104n,
329
+ askedSats: 1000358,
330
+ },
331
+ {
332
+ offeredTokens: 1000000000000000n,
333
+ info: '0.000000001sat/token, dust accept',
334
+ priceNanoSatsPerToken: 1n,
335
+ acceptedTokens: 546014494720n,
336
+ askedSats: 547,
337
+ },
338
+ {
339
+ offeredTokens: 1000000000000000n,
340
+ info: '0.000001sat/token, full accept',
341
+ priceNanoSatsPerToken: 1000n,
342
+ acceptedTokens: 999999986991104n,
343
+ askedSats: 1072883592,
344
+ },
345
+ {
346
+ offeredTokens: 1000000000000000n,
347
+ info: '0.000001sat/token, dust accept',
348
+ priceNanoSatsPerToken: 1000n,
349
+ acceptedTokens: 570425344n,
350
+ askedSats: 612,
351
+ },
352
+ {
353
+ offeredTokens: 1000000000000000n,
354
+ info: '0.001sat/token, 1/1000 accept',
355
+ priceNanoSatsPerToken: 1000000n,
356
+ acceptedTokens: 999989182464n,
357
+ askedSats: 1004470272,
358
+ },
359
+ {
360
+ offeredTokens: 1000000000000000n,
361
+ info: '0.001sat/token, min accept',
362
+ priceNanoSatsPerToken: 1000000n,
363
+ acceptedTokens: 0x1000000n,
364
+ askedSats: 65536,
365
+ },
366
+ {
367
+ offeredTokens: 1000000000000000n,
368
+ info: '1sat/token, 1/1000000 accept',
369
+ priceNanoSatsPerToken: 1000000000n,
370
+ acceptedTokens: 989855744n,
371
+ askedSats: 989855744,
372
+ },
373
+ {
374
+ offeredTokens: 1000000000000000n,
375
+ info: '1sat/token, min accept',
376
+ priceNanoSatsPerToken: 1000000000n,
377
+ acceptedTokens: 0x1000000n,
378
+ askedSats: 16777216,
379
+ },
380
+ {
381
+ offeredTokens: 1000000000000000000n,
382
+ info: '0.000000001sat/token, full accept',
383
+ priceNanoSatsPerToken: 1n,
384
+ acceptedTokens: 999999997191651328n,
385
+ askedSats: 1047737894,
386
+ },
387
+ {
388
+ offeredTokens: 1000000000000000000n,
389
+ info: '0.000000001sat/token, dust accept',
390
+ priceNanoSatsPerToken: 1n,
391
+ acceptedTokens: 558345748480n,
392
+ askedSats: 585,
393
+ },
394
+ {
395
+ offeredTokens: 1000000000000000000n,
396
+ info: '0.000001sat/token, 1/1000 accept',
397
+ priceNanoSatsPerToken: 1000n,
398
+ acceptedTokens: 999997235527680n,
399
+ askedSats: 1002438656,
400
+ },
401
+ {
402
+ offeredTokens: 1000000000000000000n,
403
+ info: '0.000001sat/token, min accept',
404
+ priceNanoSatsPerToken: 1000n,
405
+ acceptedTokens: 0x100000000n,
406
+ askedSats: 65536,
407
+ },
408
+ {
409
+ offeredTokens: 1000000000000000000n,
410
+ info: '0.001sat/token, 1/1000000 accept',
411
+ priceNanoSatsPerToken: 1000000n,
412
+ acceptedTokens: 996432412672n,
413
+ askedSats: 1006632960,
414
+ },
415
+ {
416
+ offeredTokens: 1000000000000000000n,
417
+ info: '0.001sat/token, min accept',
418
+ priceNanoSatsPerToken: 1000000n,
419
+ acceptedTokens: 0x100000000n,
420
+ askedSats: 16777216,
421
+ },
422
+ {
423
+ offeredTokens: 0x7fffffffffffffffn,
424
+ info: '0.000000001sat/token, max sats accept',
425
+ priceNanoSatsPerToken: 1n,
426
+ acceptedTokens: 999999997191651328n,
427
+ askedSats: 1010248448,
428
+ },
429
+ {
430
+ offeredTokens: 0x7fffffffffffffffn,
431
+ info: '0.000000001sat/token, dust accept',
432
+ priceNanoSatsPerToken: 1n,
433
+ acceptedTokens: 558345748480n,
434
+ askedSats: 768,
435
+ },
436
+ {
437
+ offeredTokens: 0x7fffffffffffffffn,
438
+ info: '0.000001sat/token, max sats accept',
439
+ priceNanoSatsPerToken: 1000n,
440
+ acceptedTokens: 999997235527680n,
441
+ askedSats: 1017249792,
442
+ },
443
+ {
444
+ offeredTokens: 0x7fffffffffffffffn,
445
+ info: '0.000001sat/token, min accept',
446
+ priceNanoSatsPerToken: 1000n,
447
+ acceptedTokens: 0x100000000n,
448
+ askedSats: 65536,
449
+ },
450
+ {
451
+ offeredTokens: 0x7fffffffffffffffn,
452
+ info: '0.001sat/token, max sats accept',
453
+ priceNanoSatsPerToken: 1000000n,
454
+ acceptedTokens: 0xc300000000n,
455
+ askedSats: 1090519040,
456
+ },
457
+ {
458
+ offeredTokens: 0x7fffffffffffffffn,
459
+ info: '0.001sat/token, min accept',
460
+ priceNanoSatsPerToken: 1000000n,
461
+ acceptedTokens: 0x100000000n,
462
+ askedSats: 16777216,
463
+ },
464
+ {
465
+ offeredTokens: 0xffffffffffffffffn,
466
+ info: '0.000000001sat/token, max sats accept',
467
+ priceNanoSatsPerToken: 1n,
468
+ acceptedTokens: 999999228392505344n,
469
+ askedSats: 1027665664,
470
+ },
471
+ {
472
+ offeredTokens: 0xffffffffffffffffn,
473
+ info: '0.000000001sat/token, dust accept',
474
+ priceNanoSatsPerToken: 1n,
475
+ acceptedTokens: 0x10000000000n,
476
+ askedSats: 1280,
477
+ },
478
+ {
479
+ offeredTokens: 0xffffffffffffffffn,
480
+ info: '0.000001sat/token, max sats accept',
481
+ priceNanoSatsPerToken: 1000n,
482
+ acceptedTokens: 999456069648384n,
483
+ askedSats: 1089339392,
484
+ },
485
+ {
486
+ offeredTokens: 0xffffffffffffffffn,
487
+ info: '0.000001sat/token, min accept',
488
+ priceNanoSatsPerToken: 1000n,
489
+ acceptedTokens: 0x10000000000n,
490
+ askedSats: 1245184,
491
+ },
492
+ ];
493
+
494
+ for (const testCase of TEST_CASES) {
495
+ it(`AgoraPartial SLP ${testCase.offeredTokens} for ${testCase.info}`, async () => {
496
+ const agoraPartial = AgoraPartial.approximateParams({
497
+ offeredTokens: testCase.offeredTokens,
498
+ priceNanoSatsPerToken: testCase.priceNanoSatsPerToken,
499
+ minAcceptedTokens: testCase.acceptedTokens,
500
+ makerPk,
501
+ ...BASE_PARAMS_SLP,
502
+ });
503
+ const askedSats = agoraPartial.askedSats(testCase.acceptedTokens);
504
+ const requiredSats = askedSats + 2000n;
505
+ const [fuelInput, takerInput] = await makeBuilderInputs([
506
+ 4000,
507
+ Number(requiredSats),
508
+ ]);
509
+
510
+ const offer = await makeSlpOffer({
511
+ chronik,
512
+ ecc,
513
+ agoraPartial,
514
+ makerSk,
515
+ fuelInput,
516
+ });
517
+ const acceptTxid = await takeSlpOffer({
518
+ chronik,
519
+ ecc,
520
+ takerSk,
521
+ offer,
522
+ takerInput,
523
+ acceptedTokens: testCase.acceptedTokens,
524
+ });
525
+ const acceptTx = await chronik.tx(acceptTxid);
526
+ const offeredTokens = agoraPartial.offeredTokens();
527
+ const agora = new Agora(chronik);
528
+ if (testCase.acceptedTokens == offeredTokens) {
529
+ // FULL ACCEPT
530
+ // 0th output is OP_RETURN SLP SEND
531
+ expect(acceptTx.outputs[0].outputScript).to.equal(
532
+ toHex(
533
+ slpSend(agoraPartial.tokenId, agoraPartial.tokenType, [
534
+ 0,
535
+ agoraPartial.offeredTokens(),
536
+ ]).bytecode,
537
+ ),
538
+ );
539
+ // 1st output is sats to maker
540
+ expect(acceptTx.outputs[1].token).to.equal(undefined);
541
+ expect(acceptTx.outputs[1].value).to.equal(testCase.askedSats);
542
+ expect(acceptTx.outputs[1].outputScript).to.equal(
543
+ makerScriptHex,
544
+ );
545
+ // 2nd output is tokens to taker
546
+ expect(acceptTx.outputs[2].token?.amount).to.equal(
547
+ offeredTokens.toString(),
548
+ );
549
+ expect(acceptTx.outputs[2].value).to.equal(DEFAULT_DUST_LIMIT);
550
+ expect(acceptTx.outputs[2].outputScript).to.equal(
551
+ takerScriptHex,
552
+ );
553
+ // Offer is now gone
554
+ const newOffers = await agora.activeOffersByTokenId(
555
+ offer.token.tokenId,
556
+ );
557
+ expect(newOffers).to.deep.equal([]);
558
+ return;
559
+ }
560
+
561
+ // PARTIAL ACCEPT
562
+ const leftoverTokens = offeredTokens - testCase.acceptedTokens;
563
+ const leftoverTruncTokens =
564
+ leftoverTokens >> BigInt(8 * agoraPartial.numTokenTruncBytes);
565
+ // 0th output is OP_RETURN SLP SEND
566
+ expect(acceptTx.outputs[0].outputScript).to.equal(
567
+ toHex(
568
+ slpSend(agoraPartial.tokenId, agoraPartial.tokenType, [
569
+ 0,
570
+ leftoverTokens,
571
+ testCase.acceptedTokens,
572
+ ]).bytecode,
573
+ ),
574
+ );
575
+ // 1st output is sats to maker
576
+ expect(acceptTx.outputs[1].token).to.equal(undefined);
577
+ expect(acceptTx.outputs[1].value).to.equal(testCase.askedSats);
578
+ expect(acceptTx.outputs[1].outputScript).to.equal(makerScriptHex);
579
+ // 2nd output is back to the P2SH Script
580
+ expect(acceptTx.outputs[2].token?.amount).to.equal(
581
+ leftoverTokens.toString(),
582
+ );
583
+ expect(acceptTx.outputs[2].value).to.equal(DEFAULT_DUST_LIMIT);
584
+ expect(acceptTx.outputs[2].outputScript.slice(0, 4)).to.equal(
585
+ 'a914',
586
+ );
587
+ // 3rd output is tokens to taker
588
+ expect(acceptTx.outputs[3].token?.amount).to.equal(
589
+ testCase.acceptedTokens.toString(),
590
+ );
591
+ expect(acceptTx.outputs[3].value).to.equal(DEFAULT_DUST_LIMIT);
592
+ expect(acceptTx.outputs[3].outputScript).to.equal(takerScriptHex);
593
+ // Offer is now modified
594
+ const newOffers = await agora.activeOffersByTokenId(
595
+ offer.token.tokenId,
596
+ );
597
+ expect(newOffers.length).to.equal(1);
598
+ const newOffer = newOffers[0];
599
+ expect(newOffer.variant).to.deep.equal({
600
+ type: 'PARTIAL',
601
+ params: new AgoraPartial({
602
+ ...agoraPartial,
603
+ truncTokens: leftoverTruncTokens,
604
+ }),
605
+ });
606
+
607
+ // Cancel leftover offer
608
+ const cancelFeeSats = newOffer.cancelFeeSats({
609
+ recipientScript: makerScript,
610
+ extraInputs: [fuelInput], // dummy input for measuring
611
+ });
612
+ const cancelTxSer = newOffer
613
+ .cancelTx({
614
+ ecc,
615
+ cancelSk: makerSk,
616
+ fuelInputs: await makeBuilderInputs([
617
+ Number(cancelFeeSats),
618
+ ]),
619
+ recipientScript: makerScript,
620
+ })
621
+ .ser();
622
+ const cancelTxid = (await chronik.broadcastTx(cancelTxSer)).txid;
623
+ const cancelTx = await chronik.tx(cancelTxid);
624
+ expect(cancelTx.outputs[1].token?.amount).to.equal(
625
+ leftoverTokens.toString(),
626
+ );
627
+ expect(cancelTx.outputs[1].outputScript).to.equal(makerScriptHex);
628
+ });
629
+ }
630
+ });
@@ -0,0 +1,13 @@
1
+ /** tsconfig for building the actual library */
2
+ {
3
+ "extends": "./tsconfig.json",
4
+ "compilerOptions": {
5
+ "noEmit": false,
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "sourceMap": true,
9
+ "outDir": "./dist"
10
+ },
11
+ "include": ["./src/**/*"],
12
+ "exclude": ["./**/*.test.ts"]
13
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ /* Language and Environment */
4
+ "target": "es2020",
5
+ /* ES2020 for bigint, DOM for WebAssemby */
6
+ "lib": ["ES2020", "DOM"],
7
+ /* Modules */
8
+ "module": "NodeNext",
9
+ "moduleResolution": "NodeNext",
10
+ /* Emit */
11
+ "noEmit": true,
12
+ /* Interop Constraints */
13
+ "esModuleInterop": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ /* Type Checking */
16
+ "strict": true
17
+ },
18
+ "include": ["src/**/*", "tests/**/*"]
19
+ }