mainnet-js 1.0.7 → 1.0.9

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.
Files changed (59) hide show
  1. package/dist/index.html +1 -1
  2. package/dist/{mainnet-1.0.7.js → mainnet-1.0.9.js} +19 -9
  3. package/dist/module/config.d.ts +4 -0
  4. package/dist/module/config.d.ts.map +1 -0
  5. package/dist/module/config.js +5 -0
  6. package/dist/module/config.js.map +1 -0
  7. package/dist/module/index.d.ts +1 -0
  8. package/dist/module/index.d.ts.map +1 -1
  9. package/dist/module/index.js +2 -0
  10. package/dist/module/index.js.map +1 -1
  11. package/dist/module/mine/mine.d.ts.map +1 -1
  12. package/dist/module/mine/mine.js +2 -2
  13. package/dist/module/mine/mine.js.map +1 -1
  14. package/dist/module/network/ElectrumNetworkProvider.d.ts +6 -2
  15. package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
  16. package/dist/module/network/ElectrumNetworkProvider.js +69 -45
  17. package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
  18. package/dist/module/network/interface.d.ts +11 -8
  19. package/dist/module/network/interface.d.ts.map +1 -1
  20. package/dist/module/transaction/Wif.d.ts +1 -1
  21. package/dist/module/transaction/Wif.d.ts.map +1 -1
  22. package/dist/module/transaction/Wif.js +17 -9
  23. package/dist/module/transaction/Wif.js.map +1 -1
  24. package/dist/module/util/deriveCashaddr.d.ts +1 -0
  25. package/dist/module/util/deriveCashaddr.d.ts.map +1 -1
  26. package/dist/module/util/deriveCashaddr.js +5 -0
  27. package/dist/module/util/deriveCashaddr.js.map +1 -1
  28. package/dist/module/util/index.d.ts +1 -0
  29. package/dist/module/util/index.d.ts.map +1 -1
  30. package/dist/module/util/index.js +1 -0
  31. package/dist/module/util/index.js.map +1 -1
  32. package/dist/module/wallet/Util.d.ts.map +1 -1
  33. package/dist/module/wallet/Util.js +1 -0
  34. package/dist/module/wallet/Util.js.map +1 -1
  35. package/dist/module/wallet/Wif.d.ts +3 -0
  36. package/dist/module/wallet/Wif.d.ts.map +1 -1
  37. package/dist/module/wallet/Wif.js +20 -26
  38. package/dist/module/wallet/Wif.js.map +1 -1
  39. package/dist/module/wallet/interface.d.ts +1 -0
  40. package/dist/module/wallet/interface.d.ts.map +1 -1
  41. package/dist/module/wallet/model.d.ts.map +1 -1
  42. package/dist/module/wallet/model.js +4 -3
  43. package/dist/module/wallet/model.js.map +1 -1
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +1 -1
  46. package/src/config.ts +4 -0
  47. package/src/index.ts +3 -0
  48. package/src/mine/mine.ts +3 -2
  49. package/src/network/ElectrumNetworkProvider.ts +99 -51
  50. package/src/network/interface.ts +12 -12
  51. package/src/transaction/Wif.ts +25 -10
  52. package/src/util/deriveCashaddr.ts +6 -0
  53. package/src/util/index.ts +1 -0
  54. package/src/wallet/Cashtokens.test.ts +149 -6
  55. package/src/wallet/Util.ts +1 -0
  56. package/src/wallet/Wif.test.ts +5 -4
  57. package/src/wallet/Wif.ts +35 -27
  58. package/src/wallet/interface.ts +1 -0
  59. package/src/wallet/model.ts +6 -3
@@ -19,23 +19,21 @@ export interface ElectrumClusterParams {
19
19
  timeout: number;
20
20
  }
21
21
 
22
+ export interface ElectrumTokenData {
23
+ amount: string;
24
+ category: string;
25
+ nft?: {
26
+ capability?: NFTCapability;
27
+ commitment?: string;
28
+ };
29
+ }
30
+
22
31
  export interface ElectrumUtxo {
23
32
  tx_pos: number;
24
33
  value: number;
25
34
  tx_hash: string;
26
35
  height: number;
27
- token_data:
28
- | {
29
- amount: string;
30
- category: string;
31
- nft:
32
- | {
33
- capability: NFTCapability | undefined;
34
- commitment: string | undefined;
35
- }
36
- | undefined;
37
- }
38
- | undefined;
36
+ token_data?: ElectrumTokenData;
39
37
  }
40
38
 
41
39
  export interface ElectrumRawTransaction {
@@ -65,12 +63,14 @@ export interface ElectrumRawTransactionVin {
65
63
  vout: number;
66
64
  value?: number; // optional extention by mainnet.cash
67
65
  address?: string; // optional extension by mainnet.cash
66
+ tokenData?: ElectrumTokenData; // optional extension by mainnet.cash
68
67
  }
69
68
 
70
69
  export interface ElectrumRawTransactionVout {
71
70
  n: number;
72
71
  scriptPubKey: ElectrumRawTransactionVoutScriptPubKey;
73
72
  value: number;
73
+ tokenData?: ElectrumTokenData;
74
74
  }
75
75
 
76
76
  export interface ElectrumRawTransactionVoutScriptPubKey {
@@ -240,8 +240,8 @@ export function prepareTokenOutputs(
240
240
  }
241
241
 
242
242
  if (
243
- token.capability === NFTCapability.none &&
244
- token.commitment !== tokenInputs[0].token?.commitment
243
+ tokenInputs[0].token?.capability === NFTCapability.none &&
244
+ tokenInputs[0].token?.commitment !== token.commitment
245
245
  ) {
246
246
  throw new Error("Can not change the commitment of an immutable token");
247
247
  }
@@ -286,7 +286,8 @@ export async function getSuitableUtxos(
286
286
  amountRequired: BigInt | undefined,
287
287
  bestHeight: number,
288
288
  feePaidBy: FeePaidByEnum,
289
- requests: SendRequestType[]
289
+ requests: SendRequestType[],
290
+ ensureUtxos: UtxoI[] = []
290
291
  ): Promise<UtxoI[]> {
291
292
  let suitableUtxos: UtxoI[] = [];
292
293
  let amountAvailable = BigInt(0);
@@ -294,6 +295,16 @@ export async function getSuitableUtxos(
294
295
  const tokenRequests = requests.filter(
295
296
  (val) => val instanceof TokenSendRequest
296
297
  ) as TokenSendRequest[];
298
+
299
+ // if we do a new token genesis, we shall filter all token utxos out
300
+ const isTokenGenesis = tokenRequests.some(
301
+ (val) => !val.tokenId || (val as any)._isGenesis
302
+ );
303
+ const bchOnlyTransfer = tokenRequests.length === 0;
304
+ let filteredInputs =
305
+ isTokenGenesis || bchOnlyTransfer
306
+ ? inputs.slice(0).filter((val) => !val.token)
307
+ : inputs.slice();
297
308
  const tokenIds = tokenRequests
298
309
  .map((val) => val.tokenId)
299
310
  .filter((value, index, array) => array.indexOf(value) === index);
@@ -304,8 +315,6 @@ export async function getSuitableUtxos(
304
315
  tokenAmountsRequired.push({ tokenId, requiredAmount });
305
316
  }
306
317
 
307
- let filteredInputs = inputs.slice(0);
308
-
309
318
  // find suitable token inputs first
310
319
  for (const { tokenId, requiredAmount } of tokenAmountsRequired) {
311
320
  let tokenAmountAvailable = 0;
@@ -325,10 +334,10 @@ export async function getSuitableUtxos(
325
334
  }
326
335
  }
327
336
 
328
- // find plain outputs
337
+ // find plain bch outputs
329
338
  for (const u of filteredInputs) {
330
339
  if (u.token) {
331
- // continue;
340
+ continue;
332
341
  }
333
342
 
334
343
  if (u.coinbase && u.height && bestHeight) {
@@ -347,14 +356,20 @@ export async function getSuitableUtxos(
347
356
  }
348
357
  }
349
358
 
359
+ const addEnsured = (suitableUtxos) => {
360
+ return [...suitableUtxos, ...ensureUtxos].filter(
361
+ (val, index, array) => array.indexOf(val) === index
362
+ );
363
+ };
364
+
350
365
  // if the fee is split with a feePaidBy option, skip checking change.
351
366
  if (feePaidBy && feePaidBy != FeePaidByEnum.change) {
352
- return suitableUtxos;
367
+ return addEnsured(suitableUtxos);
353
368
  }
354
369
 
355
370
  // If the amount needed is met, or no amount is given, return
356
371
  if (typeof amountRequired === "undefined") {
357
- return suitableUtxos;
372
+ return addEnsured(suitableUtxos);
358
373
  } else if (amountAvailable < amountRequired) {
359
374
  let e = Error(
360
375
  `Amount required was not met, ${amountRequired} satoshis needed, ${amountAvailable} satoshis available`
@@ -365,7 +380,7 @@ export async function getSuitableUtxos(
365
380
  };
366
381
  throw e;
367
382
  } else {
368
- return suitableUtxos;
383
+ return addEnsured(suitableUtxos);
369
384
  }
370
385
  }
371
386
 
@@ -131,3 +131,9 @@ export function isTokenaddr(address: string): boolean {
131
131
  ].indexOf(result.version) !== -1
132
132
  );
133
133
  }
134
+
135
+ export function checkTokenaddr(cashaddr: string, enforce: boolean) {
136
+ if (enforce && !isTokenaddr(cashaddr)) {
137
+ throw new Error("Error trying to send to a non-tokenaware cash address");
138
+ }
139
+ }
package/src/util/index.ts CHANGED
@@ -12,6 +12,7 @@ export { convert, convertObject } from "./convert.js";
12
12
  export { delay } from "./delay.js";
13
13
  export { derivedNetwork } from "./deriveNetwork.js";
14
14
  export { derivePublicKeyHash } from "./derivePublicKeyHash.js";
15
+ export * from "./deriveCashaddr.js";
15
16
  export {
16
17
  getAddrsByXpubKey,
17
18
  getAddrsByXpubKeyObject,
@@ -1,9 +1,15 @@
1
1
  import { RegTestWallet, TestNetWallet, Wallet } from "./Wif";
2
2
  import { initProviders, disconnectProviders } from "../network/Connection";
3
- import { SendRequest, TokenMintRequest, TokenSendRequest } from "./model";
3
+ import {
4
+ SendRequest,
5
+ SendResponse,
6
+ TokenMintRequest,
7
+ TokenSendRequest,
8
+ } from "./model";
4
9
  import { Network, NFTCapability } from "../interface";
5
10
  import { binToHex, utf8ToBin } from "@bitauth/libauth";
6
11
  import { delay } from "../util";
12
+ import { Config } from "../config";
7
13
 
8
14
  beforeAll(async () => {
9
15
  await initProviders();
@@ -194,9 +200,12 @@ describe(`Test cashtokens`, () => {
194
200
  const response = await alice.tokenMint(tokenId, [
195
201
  new TokenMintRequest({
196
202
  cashaddr: alice.cashaddr!,
203
+ commitment: "test",
204
+ capability: NFTCapability.none,
197
205
  }),
198
206
  new TokenMintRequest({
199
207
  cashaddr: alice.cashaddr!,
208
+ commitment: "test2",
200
209
  }),
201
210
  ]);
202
211
  expect(await alice.getTokenBalance(tokenId)).toBe(0);
@@ -313,7 +322,7 @@ describe(`Test cashtokens`, () => {
313
322
  expect(tokenId).toEqual(response.tokenIds![0]);
314
323
  });
315
324
 
316
- test("Test explicit burning of FT+NFT", async () => {
325
+ test("Test explicit burning of FT and NFT", async () => {
317
326
  const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
318
327
  const genesisResponse = await alice.tokenGenesis({
319
328
  cashaddr: alice.cashaddr!,
@@ -439,13 +448,15 @@ describe(`Test cashtokens`, () => {
439
448
  expect(bobUtxos[1].satoshis).toBe(3349);
440
449
  });
441
450
 
442
- test("Test cashtoken waiting and watching balance", async () => {
451
+ test("Test cashtoken waiting and watching", async () => {
443
452
  const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
444
453
  const bob = await RegTestWallet.newRandom();
445
454
 
446
455
  const genesisResponse = await alice.tokenGenesis({
447
456
  amount: 100,
448
457
  value: 5000,
458
+ capability: NFTCapability.minting,
459
+ commitment: "test",
449
460
  cashaddr: alice.cashaddr!,
450
461
  });
451
462
 
@@ -457,16 +468,17 @@ describe(`Test cashtokens`, () => {
457
468
  expect(tokenUtxos[0].satoshis).toBe(5000);
458
469
 
459
470
  let seenBalance = 0;
471
+ let sendResponse: SendResponse = {};
460
472
  setTimeout(
461
- () =>
462
- alice.send([
473
+ async () =>
474
+ (sendResponse = await alice.send([
463
475
  new TokenSendRequest({
464
476
  cashaddr: bob.cashaddr!,
465
477
  amount: 100,
466
478
  tokenId: tokenId,
467
479
  value: 1500,
468
480
  }),
469
- ]),
481
+ ])),
470
482
  0
471
483
  );
472
484
 
@@ -474,10 +486,141 @@ describe(`Test cashtokens`, () => {
474
486
  seenBalance = balance;
475
487
  });
476
488
 
489
+ let bobTxId = ".";
490
+ const txCancel = bob.watchAddressTokenTransactions((tx) => {
491
+ bobTxId = tx.txid;
492
+ });
493
+
477
494
  const balance = await bob.waitForTokenBalance(tokenId, 100);
495
+ await delay(500);
478
496
  expect(balance).toBe(100);
479
497
  expect(seenBalance).toBe(100);
498
+ expect(sendResponse.txId).toBe(bobTxId);
480
499
  await cancel();
500
+ await txCancel();
481
501
  await delay(500);
482
502
  });
503
+
504
+ test("Test double genesis should not burn tokens", async () => {
505
+ const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
506
+ const bob = await RegTestWallet.newRandom();
507
+
508
+ // prepare inputs for two token geneses
509
+ await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
510
+ await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
511
+
512
+ const genesisResponse = await bob.tokenGenesis({
513
+ amount: 100,
514
+ });
515
+
516
+ const tokenId = genesisResponse.tokenIds![0];
517
+ const tokenBalance = await bob.getTokenBalance(tokenId);
518
+
519
+ expect(tokenBalance).toBe(100);
520
+ const tokenUtxos = await bob.getTokenUtxos(tokenId);
521
+ expect(tokenUtxos.length).toBe(1);
522
+
523
+ const genesis2Response = await bob.tokenGenesis({
524
+ amount: 200,
525
+ });
526
+
527
+ const tokenId2 = genesis2Response.tokenIds![0];
528
+ const tokenBalance2 = await bob.getTokenBalance(tokenId2);
529
+ expect(tokenBalance2).toBe(200);
530
+ const tokenUtxos2 = await bob.getTokenUtxos(tokenId2);
531
+ expect(tokenUtxos2.length).toBe(1);
532
+
533
+ expect((await bob.getTokenUtxos()).length).toBe(2);
534
+ });
535
+
536
+ test("Test sending tokens should not burn tokens", async () => {
537
+ const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
538
+ const bob = await RegTestWallet.newRandom();
539
+
540
+ // prepare inputs for two token geneses
541
+ await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
542
+ await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
543
+
544
+ const genesisResponse = await bob.tokenGenesis({
545
+ amount: 100,
546
+ });
547
+
548
+ const tokenId = genesisResponse.tokenIds![0];
549
+ const tokenBalance = await bob.getTokenBalance(tokenId);
550
+
551
+ expect(tokenBalance).toBe(100);
552
+ const tokenUtxos = await bob.getTokenUtxos(tokenId);
553
+ expect(tokenUtxos.length).toBe(1);
554
+
555
+ const genesis2Response = await bob.tokenGenesis({
556
+ amount: 200,
557
+ });
558
+
559
+ const tokenId2 = genesis2Response.tokenIds![0];
560
+ const tokenBalance2 = await bob.getTokenBalance(tokenId2);
561
+ expect(tokenBalance2).toBe(200);
562
+ const tokenUtxos2 = await bob.getTokenUtxos(tokenId2);
563
+ expect(tokenUtxos2.length).toBe(1);
564
+
565
+ expect((await bob.getTokenUtxos()).length).toBe(2);
566
+
567
+ const charlie = await RegTestWallet.newRandom();
568
+ await bob.send({
569
+ cashaddr: charlie.cashaddr!,
570
+ tokenId: tokenId,
571
+ amount: 50,
572
+ });
573
+ expect((await bob.getTokenUtxos()).length).toBe(2);
574
+ expect((await charlie.getTokenUtxos()).length).toBe(1);
575
+ expect(await bob.getTokenBalance(tokenId)).toBe(50);
576
+ expect(await charlie.getTokenBalance(tokenId)).toBe(50);
577
+ });
578
+
579
+ test("Test sending bch should not burn tokens", async () => {
580
+ const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
581
+ const bob = await RegTestWallet.newRandom();
582
+
583
+ // prepare inputs for two token geneses
584
+ await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
585
+
586
+ const genesisResponse = await bob.tokenGenesis({
587
+ amount: 100,
588
+ });
589
+
590
+ const tokenId = genesisResponse.tokenIds![0];
591
+ const tokenBalance = await bob.getTokenBalance(tokenId);
592
+
593
+ expect(tokenBalance).toBe(100);
594
+ const tokenUtxos = await bob.getTokenUtxos(tokenId);
595
+ expect(tokenUtxos.length).toBe(1);
596
+
597
+ await bob.send({ cashaddr: alice.cashaddr!, value: 1000, unit: "sat" });
598
+
599
+ const tokenBalance2 = await bob.getTokenBalance(tokenId);
600
+ expect(tokenBalance2).toBe(100);
601
+ const tokenUtxos2 = await bob.getTokenUtxos(tokenId);
602
+ expect(tokenUtxos2.length).toBe(1);
603
+ });
604
+
605
+ test("Test enforcing tokenaddresses", async () => {
606
+ const bob = await RegTestWallet.newRandom();
607
+
608
+ const previousValue = Config.EnforceCashTokenReceiptAddresses;
609
+
610
+ const wrap = (addr) => {
611
+ return new Promise(() => {
612
+ return new TokenSendRequest({ cashaddr: addr, tokenId: "" });
613
+ });
614
+ };
615
+
616
+ Config.EnforceCashTokenReceiptAddresses = false;
617
+ expect(wrap(bob.cashaddr)).resolves.not.toThrow();
618
+ expect(wrap(bob.tokenaddr)).resolves.not.toThrow();
619
+
620
+ Config.EnforceCashTokenReceiptAddresses = true;
621
+ expect(wrap(bob.cashaddr)).rejects.toThrow();
622
+ expect(wrap(bob.tokenaddr)).resolves.not.toThrow();
623
+
624
+ Config.EnforceCashTokenReceiptAddresses = previousValue;
625
+ });
483
626
  });
@@ -100,6 +100,7 @@ export class Util {
100
100
  .vout.find((val) => val.n === input.vout)!;
101
101
  input.address = output.scriptPubKey.addresses[0];
102
102
  input.value = output.value;
103
+ input.tokenData = output.tokenData;
103
104
  });
104
105
  }
105
106
 
@@ -806,11 +806,11 @@ describe(`Wallet subscriptions`, () => {
806
806
  });
807
807
 
808
808
  let bobWatchResult = false;
809
- const bobWatchCancel = (
810
- bob.provider! as ElectrumNetworkProvider
811
- ).watchAddressStatus(bob.getDepositAddress(), (_status) => {
809
+ let bobTransactionId = "";
810
+ const bobWatchCancel = bob.watchAddress((txHash) => {
812
811
  bobWatchCancel();
813
812
  bobWatchResult = true;
813
+ bobTransactionId = txHash;
814
814
  });
815
815
 
816
816
  let bobBalanceWatchResult = false;
@@ -847,7 +847,7 @@ describe(`Wallet subscriptions`, () => {
847
847
  blockNumberWaitResult = true;
848
848
  }, 0);
849
849
 
850
- await alice.send({
850
+ const sendResponse = await alice.send({
851
851
  cashaddr: bob.getDepositAddress(),
852
852
  value: 0.001,
853
853
  unit: "bch",
@@ -862,6 +862,7 @@ describe(`Wallet subscriptions`, () => {
862
862
  expect(waitBalanceResult).toBe(true);
863
863
  expect(aliceWatchResult).toBe(true);
864
864
  expect(bobWatchResult).toBe(true);
865
+ expect(bobTransactionId).toBe(sendResponse.txId);
865
866
  expect(bobBalanceWatchResult).toBe(true);
866
867
  expect(blockWatchResult).toBe(true);
867
868
  expect(blockWaitResult).toBe(true);
package/src/wallet/Wif.ts CHANGED
@@ -711,25 +711,32 @@ export class Wallet extends BaseWallet {
711
711
  return this.getBalanceFromUtxos();
712
712
  }
713
713
 
714
- // // waiting for any transaction hash of this wallet
715
- // // commented out until fulcrum supports new method https://github.com/cculianu/Fulcrum/pull/89
716
- // public watchAddress(callback: (txHash: string) => void): CancelWatchFn {
717
- // return (this.provider! as ElectrumNetworkProvider).watchAddress(
718
- // this.getDepositAddress(),
719
- // callback
720
- // );
721
- // }
722
-
723
- // // waiting for any transaction of this wallet
724
- // // commented out until fulcrum supports new method https://github.com/cculianu/Fulcrum/pull/89
725
- // public watchAddressTransactions(
726
- // callback: (tx: ElectrumRawTransaction) => void
727
- // ): CancelWatchFn {
728
- // return (this.provider! as ElectrumNetworkProvider).watchAddressTransactions(
729
- // this.getDepositAddress(),
730
- // callback
731
- // );
732
- // }
714
+ // watching for any transaction hash of this wallet
715
+ public watchAddress(callback: (txHash: string) => void): CancelWatchFn {
716
+ return (this.provider! as ElectrumNetworkProvider).watchAddress(
717
+ this.getDepositAddress(),
718
+ callback
719
+ );
720
+ }
721
+
722
+ // watching for any transaction of this wallet
723
+ public watchAddressTransactions(
724
+ callback: (tx: ElectrumRawTransaction) => void
725
+ ): CancelWatchFn {
726
+ return (this.provider! as ElectrumNetworkProvider).watchAddressTransactions(
727
+ this.getDepositAddress(),
728
+ callback
729
+ );
730
+ }
731
+
732
+ // watching for cashtoken transaction of this wallet
733
+ public watchAddressTokenTransactions(
734
+ callback: (tx: ElectrumRawTransaction) => void
735
+ ): CancelWatchFn {
736
+ return (
737
+ this.provider! as ElectrumNetworkProvider
738
+ ).watchAddressTokenTransactions(this.getDepositAddress(), callback);
739
+ }
733
740
 
734
741
  // sets up a callback to be called upon wallet's balance change
735
742
  // can be cancelled by calling the function returned from this one
@@ -1157,7 +1164,7 @@ export class Wallet extends BaseWallet {
1157
1164
  if (change > 0) {
1158
1165
  outputs.push(
1159
1166
  new TokenSendRequest({
1160
- cashaddr: changeAddress || this.cashaddr,
1167
+ cashaddr: changeAddress || this.tokenaddr!,
1161
1168
  amount: change,
1162
1169
  tokenId: tokenId,
1163
1170
  commitment: tokenOutputs[0].commitment,
@@ -1195,7 +1202,8 @@ export class Wallet extends BaseWallet {
1195
1202
  BigInt(spendAmount) + BigInt(feeEstimate),
1196
1203
  bestHeight,
1197
1204
  feePaidBy,
1198
- sendRequests
1205
+ sendRequests,
1206
+ options?.ensureUtxos || []
1199
1207
  );
1200
1208
  if (fundingUtxos.length === 0) {
1201
1209
  throw Error(
@@ -1437,7 +1445,7 @@ export class Wallet extends BaseWallet {
1437
1445
  ): Promise<SendResponse> {
1438
1446
  return this.send(
1439
1447
  new TokenSendRequest({
1440
- cashaddr: genesisRequest.cashaddr || this.cashaddr!,
1448
+ cashaddr: genesisRequest.cashaddr || this.tokenaddr!,
1441
1449
  amount: genesisRequest.amount,
1442
1450
  value: genesisRequest.value,
1443
1451
  capability: genesisRequest.capability,
@@ -1488,7 +1496,7 @@ export class Wallet extends BaseWallet {
1488
1496
  : nftUtxos[0].token!.amount;
1489
1497
  const safeNewAmount = Math.max(0, newAmount);
1490
1498
  const mintingInput = new TokenSendRequest({
1491
- cashaddr: this.cashaddr!,
1499
+ cashaddr: this.tokenaddr!,
1492
1500
  tokenId: tokenId,
1493
1501
  capability: nftUtxos[0].token!.capability,
1494
1502
  commitment: nftUtxos[0].token!.commitment,
@@ -1501,7 +1509,7 @@ export class Wallet extends BaseWallet {
1501
1509
  ...mintRequests.map(
1502
1510
  (val) =>
1503
1511
  new TokenSendRequest({
1504
- cashaddr: val.cashaddr || this.cashaddr!,
1512
+ cashaddr: val.cashaddr || this.tokenaddr!,
1505
1513
  amount: 0,
1506
1514
  tokenId: tokenId,
1507
1515
  value: val.value,
@@ -1570,7 +1578,7 @@ export class Wallet extends BaseWallet {
1570
1578
  const safeNewAmount = Math.max(0, newAmount);
1571
1579
  changeSendRequests = [
1572
1580
  new TokenSendRequest({
1573
- cashaddr: burnRequest.cashaddr || this.cashaddr!,
1581
+ cashaddr: burnRequest.cashaddr || this.tokenaddr!,
1574
1582
  tokenId: burnRequest.tokenId,
1575
1583
  capability: burnRequest.capability,
1576
1584
  commitment: burnRequest.commitment,
@@ -1590,7 +1598,7 @@ export class Wallet extends BaseWallet {
1590
1598
  const safeNewAmount = Math.max(0, newAmount);
1591
1599
  changeSendRequests = [
1592
1600
  new TokenSendRequest({
1593
- cashaddr: burnRequest.cashaddr || this.cashaddr!,
1601
+ cashaddr: burnRequest.cashaddr || this.tokenaddr!,
1594
1602
  tokenId: burnRequest.tokenId,
1595
1603
  amount: safeNewAmount,
1596
1604
  value: tokenUtxos[0].satoshis,
@@ -1603,7 +1611,7 @@ export class Wallet extends BaseWallet {
1603
1611
  return this.send([opReturn, ...changeSendRequests], {
1604
1612
  checkTokenQuantities: false,
1605
1613
  queryBalance: false,
1606
- utxoIds: utxoIds.length > 0 ? utxoIds : undefined,
1614
+ ensureUtxos: utxoIds.length > 0 ? utxoIds : undefined,
1607
1615
  });
1608
1616
  }
1609
1617
 
@@ -54,6 +54,7 @@ export interface SendRequestOptionsI {
54
54
  awaitTransactionPropagation?: boolean;
55
55
  feePaidBy?: FeePaidByEnum;
56
56
  checkTokenQuantities?: boolean; // true
57
+ ensureUtxos?: UtxoI[]; // ensure these inputs will be consumed in the transaction
57
58
  }
58
59
 
59
60
  export interface MnemonicI {
@@ -4,6 +4,8 @@ import { UnitEnum } from "../enum.js";
4
4
  import { NFTCapability, UtxoI } from "../interface.js";
5
5
  import { DELIMITER } from "../constant.js";
6
6
  import { utf8ToBin } from "@bitauth/libauth";
7
+ import { Config } from "../config.js";
8
+ import { checkTokenaddr } from "../util/deriveCashaddr.js";
7
9
 
8
10
  // These are the minimal models used to provide types for the express server
9
11
  //
@@ -94,7 +96,7 @@ export class TokenBurnRequest {
94
96
  }
95
97
 
96
98
  export class TokenSendRequest {
97
- cashaddr: string;
99
+ cashaddr: string; // cashaddr or tokenaddr to send tokens to
98
100
  value?: number; // satoshi value
99
101
  amount: number; // fungible token amount
100
102
  tokenId: string;
@@ -116,6 +118,8 @@ export class TokenSendRequest {
116
118
  capability?: NFTCapability;
117
119
  commitment?: string;
118
120
  }) {
121
+ checkTokenaddr(cashaddr, Config.EnforceCashTokenReceiptAddresses);
122
+
119
123
  this.cashaddr = cashaddr;
120
124
  this.value = value;
121
125
  this.amount = amount || 0;
@@ -142,8 +146,7 @@ export class TokenMintRequest {
142
146
  cashaddr?: string;
143
147
  value?: number;
144
148
  }) {
145
- // be explicit about minting capability for new NFTs
146
- this.capability = capability || NFTCapability.none;
149
+ this.capability = capability;
147
150
  this.commitment = commitment;
148
151
  this.cashaddr = cashaddr;
149
152
  this.value = value;