mainnet-js 1.1.34 → 2.0.1

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 (122) hide show
  1. package/dist/index.html +1 -1
  2. package/dist/{mainnet-1.1.34.js → mainnet-2.0.1.js} +26 -338
  3. package/dist/module/db/SqlProvider.d.ts +2 -2
  4. package/dist/module/db/SqlProvider.d.ts.map +1 -1
  5. package/dist/module/db/SqlProvider.js +6 -24
  6. package/dist/module/db/SqlProvider.js.map +1 -1
  7. package/dist/module/index.d.ts +0 -3
  8. package/dist/module/index.d.ts.map +1 -1
  9. package/dist/module/index.js +3 -6
  10. package/dist/module/index.js.map +1 -1
  11. package/dist/module/transaction/Wif.d.ts +4 -8
  12. package/dist/module/transaction/Wif.d.ts.map +1 -1
  13. package/dist/module/transaction/Wif.js +6 -10
  14. package/dist/module/transaction/Wif.js.map +1 -1
  15. package/dist/module/util/deriveCashaddr.d.ts +1 -0
  16. package/dist/module/util/deriveCashaddr.d.ts.map +1 -1
  17. package/dist/module/util/deriveCashaddr.js +8 -1
  18. package/dist/module/util/deriveCashaddr.js.map +1 -1
  19. package/dist/module/wallet/Base.d.ts +1 -1
  20. package/dist/module/wallet/Base.js +1 -1
  21. package/dist/module/wallet/Bcmr.d.ts +3 -1
  22. package/dist/module/wallet/Bcmr.d.ts.map +1 -1
  23. package/dist/module/wallet/Bcmr.js +4 -8
  24. package/dist/module/wallet/Bcmr.js.map +1 -1
  25. package/dist/module/wallet/Util.d.ts +2 -2
  26. package/dist/module/wallet/Util.js +2 -2
  27. package/dist/module/wallet/Wif.d.ts +0 -28
  28. package/dist/module/wallet/Wif.d.ts.map +1 -1
  29. package/dist/module/wallet/Wif.js +2 -109
  30. package/dist/module/wallet/Wif.js.map +1 -1
  31. package/dist/module/wallet/createWallet.d.ts +0 -12
  32. package/dist/module/wallet/createWallet.d.ts.map +1 -1
  33. package/dist/module/wallet/createWallet.js +0 -43
  34. package/dist/module/wallet/createWallet.js.map +1 -1
  35. package/dist/module/wallet/interface.d.ts +0 -2
  36. package/dist/module/wallet/interface.d.ts.map +1 -1
  37. package/dist/module/webhook/Webhook.d.ts +1 -6
  38. package/dist/module/webhook/Webhook.d.ts.map +1 -1
  39. package/dist/module/webhook/Webhook.js +0 -4
  40. package/dist/module/webhook/Webhook.js.map +1 -1
  41. package/dist/module/webhook/index.d.ts +0 -1
  42. package/dist/module/webhook/index.d.ts.map +1 -1
  43. package/dist/module/webhook/index.js +0 -1
  44. package/dist/module/webhook/index.js.map +1 -1
  45. package/dist/module/webhook/interface.d.ts +0 -1
  46. package/dist/module/webhook/interface.d.ts.map +1 -1
  47. package/dist/tsconfig.tsbuildinfo +1 -1
  48. package/package.json +5 -10
  49. package/src/db/SqlProvider.test.ts +2 -18
  50. package/src/db/SqlProvider.ts +5 -26
  51. package/src/index.ts +3 -7
  52. package/src/transaction/Wif.ts +2 -19
  53. package/src/util/deriveCashaddr.test.ts +8 -0
  54. package/src/util/deriveCashaddr.ts +9 -0
  55. package/src/wallet/Base.ts +1 -1
  56. package/src/wallet/Bcmr.ts +4 -9
  57. package/src/wallet/Util.ts +2 -2
  58. package/src/wallet/Wif.test.ts +0 -23
  59. package/src/wallet/Wif.ts +2 -148
  60. package/src/wallet/createWallet.ts +0 -53
  61. package/src/wallet/interface.ts +0 -2
  62. package/src/webhook/Webhook.ts +4 -10
  63. package/src/webhook/index.ts +0 -1
  64. package/src/webhook/interface.ts +0 -1
  65. package/webpack.config.cjs +7 -7
  66. package/dist/module/slp/GsppProvider.d.ts +0 -55
  67. package/dist/module/slp/GsppProvider.d.ts.map +0 -1
  68. package/dist/module/slp/GsppProvider.js +0 -204
  69. package/dist/module/slp/GsppProvider.js.map +0 -1
  70. package/dist/module/slp/SlpDbProvider.d.ts +0 -52
  71. package/dist/module/slp/SlpDbProvider.d.ts.map +0 -1
  72. package/dist/module/slp/SlpDbProvider.js +0 -175
  73. package/dist/module/slp/SlpDbProvider.js.map +0 -1
  74. package/dist/module/slp/SlpDbTemplates.d.ts +0 -313
  75. package/dist/module/slp/SlpDbTemplates.d.ts.map +0 -1
  76. package/dist/module/slp/SlpDbTemplates.js +0 -375
  77. package/dist/module/slp/SlpDbTemplates.js.map +0 -1
  78. package/dist/module/slp/SlpLibAuth.d.ts +0 -210
  79. package/dist/module/slp/SlpLibAuth.d.ts.map +0 -1
  80. package/dist/module/slp/SlpLibAuth.js +0 -451
  81. package/dist/module/slp/SlpLibAuth.js.map +0 -1
  82. package/dist/module/slp/SlpProvider.d.ts +0 -24
  83. package/dist/module/slp/SlpProvider.d.ts.map +0 -1
  84. package/dist/module/slp/SlpProvider.js +0 -29
  85. package/dist/module/slp/SlpProvider.js.map +0 -1
  86. package/dist/module/slp/index.d.ts +0 -6
  87. package/dist/module/slp/index.d.ts.map +0 -1
  88. package/dist/module/slp/index.js +0 -5
  89. package/dist/module/slp/index.js.map +0 -1
  90. package/dist/module/slp/interface.d.ts +0 -114
  91. package/dist/module/slp/interface.d.ts.map +0 -1
  92. package/dist/module/slp/interface.js +0 -7
  93. package/dist/module/slp/interface.js.map +0 -1
  94. package/dist/module/util/bchaddr.d.ts +0 -2
  95. package/dist/module/util/bchaddr.d.ts.map +0 -1
  96. package/dist/module/util/bchaddr.js +0 -16
  97. package/dist/module/util/bchaddr.js.map +0 -1
  98. package/dist/module/wallet/Slp.d.ts +0 -431
  99. package/dist/module/wallet/Slp.d.ts.map +0 -1
  100. package/dist/module/wallet/Slp.js +0 -770
  101. package/dist/module/wallet/Slp.js.map +0 -1
  102. package/dist/module/webhook/WebhookSlp.d.ts +0 -15
  103. package/dist/module/webhook/WebhookSlp.d.ts.map +0 -1
  104. package/dist/module/webhook/WebhookSlp.js +0 -100
  105. package/dist/module/webhook/WebhookSlp.js.map +0 -1
  106. package/src/slp/GsppProvider.test.ts +0 -40
  107. package/src/slp/GsppProvider.ts +0 -329
  108. package/src/slp/SlpDbProvider.test.ts +0 -27
  109. package/src/slp/SlpDbProvider.ts +0 -291
  110. package/src/slp/SlpDbTemplates.ts +0 -400
  111. package/src/slp/SlpLibAuth.test.ts +0 -162
  112. package/src/slp/SlpLibAuth.ts +0 -532
  113. package/src/slp/SlpProvider.ts +0 -100
  114. package/src/slp/index.ts +0 -6
  115. package/src/slp/interface.ts +0 -128
  116. package/src/util/bchaddr.test.ts +0 -27
  117. package/src/util/bchaddr.ts +0 -27
  118. package/src/wallet/Slp.test.headless.js +0 -120
  119. package/src/wallet/Slp.test.ts +0 -1000
  120. package/src/wallet/Slp.ts +0 -1014
  121. package/src/webhook/WebhookSlp.test.ts +0 -288
  122. package/src/webhook/WebhookSlp.ts +0 -123
package/src/wallet/Slp.ts DELETED
@@ -1,1014 +0,0 @@
1
- import {
2
- Wallet,
3
- RegTestWallet,
4
- TestNetWallet,
5
- WifWallet,
6
- TestNetWifWallet,
7
- RegTestWifWallet,
8
- WatchWallet,
9
- TestNetWatchWallet,
10
- RegTestWatchWallet,
11
- } from "../wallet/Wif.js";
12
- import {
13
- SlpFormattedUtxo,
14
- SlpGenesisOptions,
15
- SlpGenesisResult,
16
- SlpMintOptions,
17
- SlpMintResult,
18
- SlpSendRequest,
19
- SlpSendResponse,
20
- SlpTokenBalance,
21
- SlpTokenInfo,
22
- SlpTokenType,
23
- SlpTxI,
24
- SlpUtxoI,
25
- } from "../slp/interface.js";
26
- import { SlpDbProvider } from "../slp/SlpDbProvider.js";
27
- import { ImageI } from "../qr/interface.js";
28
- import { qrAddress } from "../qr/Qr.js";
29
- import { TxI, UtxoI } from "../interface.js";
30
- import { ElectrumRawTransaction } from "../network/interface.js";
31
- import BigNumber from "bignumber.js";
32
- import { getRelayFeeCache } from "../network/getRelayFeeCache.js";
33
- import {
34
- buildEncodedTransaction,
35
- getFeeAmount,
36
- getSuitableUtxos,
37
- } from "../transaction/Wif.js";
38
- import {
39
- SlpGetGenesisOutputs,
40
- SlpGetMintOutputs,
41
- SlpGetSendOutputs,
42
- } from "../slp/SlpLibAuth.js";
43
- import { binToHex, Output } from "@bitauth/libauth";
44
- import { SendRequest } from "./model.js";
45
- import {
46
- SlpCancelWatchFn,
47
- SlpProvider,
48
- SlpWatchBalanceCallback,
49
- SlpWatchTransactionCallback,
50
- } from "../slp/SlpProvider.js";
51
- import { toCashAddress, toSlpAddress } from "../util/bchaddr.js";
52
- import { GsppProvider } from "../slp/GsppProvider.js";
53
- import { delay } from "../util/delay.js";
54
- import { Util } from "./Util.js";
55
- import { FeePaidByEnum } from "./enum.js";
56
- import {
57
- getRuntimePlatform,
58
- RuntimePlatform,
59
- } from "../util/getRuntimePlatform.js";
60
-
61
- /**
62
- * Class to manage an slp enabled wallet.
63
- */
64
- export class Slp {
65
- slpaddr: string;
66
- readonly wallet: Wallet;
67
- public provider: SlpProvider;
68
- // a loookup table of spent inputs to keep track of NFT parent token consumption. related to a bug in SLPDB
69
- private spentParentUtxos: string[] = [];
70
-
71
- static get walletType() {
72
- return Wallet;
73
- }
74
-
75
- public static defaultProvider = "slpdb";
76
-
77
- /**
78
- * Initializes an Slp Wallet.
79
- *
80
- * @param wallet A non-slp wallet object
81
- */
82
- constructor(wallet: Wallet) {
83
- this.slpaddr = toSlpAddress(wallet.cashaddr!);
84
- this.wallet = wallet;
85
-
86
- let provider = Slp.defaultProvider;
87
- if (
88
- getRuntimePlatform() === RuntimePlatform.node &&
89
- process.env.SLP_PROVIDER
90
- )
91
- provider = process.env.SLP_PROVIDER!;
92
-
93
- if (provider === "gspp") {
94
- this.provider = new GsppProvider(this.wallet.network);
95
- } else {
96
- // provider === "slpdb"
97
- this.provider = new SlpDbProvider(this.wallet.network);
98
- }
99
- }
100
-
101
- /**
102
- * setProvider - sets the provider to fetch slp data from
103
- */
104
- public setProvider(provider: SlpProvider) {
105
- return (this.provider = provider);
106
- }
107
-
108
- /**
109
- * getDepositAddress - get the slp deposit address
110
- *
111
- * a high-level function,
112
- *
113
- * @see {@link https://rest-unstable.mainnet.cash/api-docs/#/wallet%2Fslp/slpDepositAddress|/wallet/slp/deposit_address} for REST endpoint
114
- *
115
- * @returns The the slp address as a string
116
- */
117
- public getDepositAddress() {
118
- return this.slpaddr;
119
- }
120
-
121
- /**
122
- * getDepositQr - get an slp address qrcode, encoded for display on the web
123
- *
124
- * a high-level function
125
- *
126
- * @see {@link https://rest-unstable.mainnet.cash/api-docs/#/wallet%2Fslp/slpDepositQr|/wallet/slp/deposit_qr} for REST endpoint
127
- *
128
- * @returns The qrcode for the slp address
129
- */
130
- public getDepositQr(): ImageI {
131
- const result = qrAddress(this.slpaddr);
132
- result.alt = "A Bitcoin Cash Simple Ledger Protocol QR Code";
133
- return result;
134
- }
135
-
136
- /**
137
- * getTokenInfo - get data associated with a token
138
- *
139
- * a high-level function
140
- *
141
- * @see {@link https://rest-unstable.mainnet.cash/api-docs/#/wallet%2Fslp/slpTokenInfo|/wallet/slp/token_info} for REST endpoint
142
- *
143
- * @param tokenId The tokenId to request information about
144
- *
145
- * @returns Promise to the slp token info or undefined.
146
- */
147
- public getTokenInfo(tokenId: string): Promise<SlpTokenInfo | undefined> {
148
- return this.provider.SlpTokenInfo(tokenId);
149
- }
150
-
151
- /**
152
- * getSlpOutpoints - get a list of SLP unspent outpoints
153
- *
154
- * an intermediate function contributing to the output of wallet.getUtxos() and /wallet/utxos for slp enabled wallets
155
- *
156
- * @param slpaddr The slpaddr to request slp unspent outpoints for
157
- *
158
- * @returns Promise to a list of slp unspent outpoints
159
- */
160
- public async getSlpOutpoints(): Promise<String[]> {
161
- return this.provider.SlpOutpoints(this.slpaddr);
162
- }
163
-
164
- /**
165
- * getSlpUtxos - get a list of SLP unspent outputs
166
- *
167
- * @returns Promise to a list of slp unspent outputs
168
- */
169
- public async getSlpUtxos(): Promise<SlpUtxoI[]> {
170
- return this.provider.SlpUtxos(this.slpaddr);
171
- }
172
-
173
- /**
174
- * getFormattedSlpUtxos - get a list of unspent outputs
175
- *
176
- * an intermediate function
177
- *
178
- * @returns Promise to a list of slp formatted unspent outputs
179
- */
180
- public async getFormattedSlpUtxos(): Promise<SlpFormattedUtxo[]> {
181
- const utxos = await this.getSlpUtxos();
182
- return utxos.map((val) => {
183
- let utxo = {} as SlpFormattedUtxo;
184
- utxo.ticker = val.ticker;
185
- utxo.tokenId = val.tokenId;
186
- utxo.value = val.value.toString();
187
- utxo.satoshis = val.satoshis;
188
- utxo.decimals = val.decimals;
189
- utxo.txId = val.txid;
190
- utxo.index = val.vout;
191
- utxo.utxoId = utxo.txId + ":" + utxo.index;
192
- utxo.type = val.type;
193
- return utxo;
194
- });
195
- }
196
-
197
- /**
198
- * getBatonUtxos - get a list of baton unspent outputs
199
- *
200
- * an intermediate function
201
- *
202
- * @param tokenId The id of the slp token
203
- *
204
- * @returns Promise to a list of slp unspent outputs
205
- */
206
- public async getBatonUtxos(tokenId?: string): Promise<SlpUtxoI[]> {
207
- return this.provider.SlpBatonUtxos(this.slpaddr, tokenId);
208
- }
209
-
210
- /**
211
- * getHistory - get a transaction history for a particular address
212
- *
213
- * an intermediate function
214
- *
215
- * @param tokenId The id of the slp token
216
- *
217
- * @returns Promise to a list of transactions
218
- */
219
- public async getHistory(tokenId?: string): Promise<SlpTxI[]> {
220
- return this.provider.SlpAddressTransactionHistory(this.slpaddr, tokenId);
221
- }
222
-
223
- /**
224
- * getLastTransaction - get a last SLP token transaction of a particular address
225
- *
226
- * @param {boolean} [confirmedOnly=false] When confirmedOnly is true, results will be limited to only transactions included in a block.
227
- *
228
- * @returns Promise to the transaction hex or error
229
- */
230
- public async getLastTransaction(
231
- confirmedOnly: boolean = false
232
- ): Promise<ElectrumRawTransaction> {
233
- let history: TxI[] = await this.getHistory();
234
- if (confirmedOnly) {
235
- history = history.filter((val) => val.height > 0);
236
- }
237
- const [lastTx] = history.slice(-1);
238
- return this.wallet.provider!.getRawTransactionObject(lastTx.tx_hash);
239
- }
240
-
241
- /**
242
- * getBalance - get a token balance for a particular address
243
- *
244
- * a high-level function, see also /wallet/slp/balance REST endpoint
245
- *
246
- * @param tokenId The id of the slp token
247
- *
248
- * @returns Promise to an SlpTokenBalance
249
- */
250
- public async getBalance(tokenId: string): Promise<SlpTokenBalance> {
251
- if (!tokenId) {
252
- throw new Error(`Invalid tokenId ${tokenId}`);
253
- }
254
- return this.provider.SlpTokenBalance(this.slpaddr, tokenId);
255
- }
256
-
257
- /**
258
- * getAllBalances - get all token balances for a particular address
259
- *
260
- * a high-level function, see also /wallet/slp/all_balances REST endpoint
261
- *
262
- * @returns Promise to an array of SlpTokenBalance
263
- */
264
- public async getAllBalances(): Promise<SlpTokenBalance[]> {
265
- return this.provider.SlpAllTokenBalances(this.slpaddr);
266
- }
267
-
268
- /**
269
- * watchBalance - set up a callback to be called upon wallet's slp balance change
270
- *
271
- * can be cancelled by calling the function returned from this one
272
- *
273
- * @param callback The callback function to be called each time the balance changes
274
- * @param tokenId Specific token id to watch
275
- *
276
- * @returns A function to cancel the watching
277
- */
278
- public watchBalance(
279
- callback: SlpWatchBalanceCallback,
280
- tokenId: string
281
- ): SlpCancelWatchFn {
282
- return this.provider.SlpWatchBalance(callback, this.slpaddr, tokenId);
283
- }
284
-
285
- /**
286
- * waitForBalance - wait for address balance to be greater than or equal to the target value
287
- *
288
- * This call halts the program execution
289
- *
290
- * @param value Target balance value
291
- * @param tokenId Specific token id to watch
292
- *
293
- * @returns Actual token balance after reaching or surpassing the target value
294
- */
295
- public async waitForBalance(
296
- value: BigNumber.Value,
297
- tokenId: string
298
- ): Promise<SlpTokenBalance> {
299
- return this.provider.SlpWaitForBalance(value, this.slpaddr, tokenId);
300
- }
301
-
302
- /**
303
- * watchBalance - set up a callback to be called upon wallet's slp transactions occurring
304
- *
305
- * can be cancelled by calling the function returned from this one
306
- *
307
- * @param callback The callback function to be called each time the balance changes
308
- * @param tokenId Specific token id to watch, optional
309
- *
310
- * @returns A function to cancel the watching
311
- */
312
- public watchTransactions(
313
- callback: SlpWatchTransactionCallback,
314
- tokenId?: string
315
- ): SlpCancelWatchFn {
316
- return this.provider.SlpWatchTransactions(callback, this.slpaddr, tokenId);
317
- }
318
-
319
- /**
320
- * waitForBalance - wait for the next SLP transaction to occur
321
- *
322
- * This call halts the program execution
323
- *
324
- * @param tokenId Specific token id to watch, optional
325
- *
326
- * @returns Transaction object
327
- */
328
- public async waitForTransaction(tokenId?: string): Promise<SlpTxI> {
329
- return this.provider.SlpWaitForTransaction(this.slpaddr, tokenId);
330
- }
331
-
332
- /**
333
- * genesis - create a new Type1 SLP token
334
- *
335
- * @param options Token creation options @see SlpGenesisOptions
336
- *
337
- * @returns Token Id and new token balance
338
- */
339
- public async genesis(options: SlpGenesisOptions): Promise<SlpGenesisResult> {
340
- let result = await this._processGenesis(options);
341
- return {
342
- tokenId: result,
343
- balance: await this.getBalance(result),
344
- };
345
- }
346
-
347
- /**
348
- * nftParentGenesis - create a new NFT Parent token
349
- *
350
- * @param options Token creation options @see SlpGenesisOptions
351
- *
352
- * @returns Token Id and new token balance
353
- */
354
- public async nftParentGenesis(
355
- options: SlpGenesisOptions
356
- ): Promise<SlpGenesisResult> {
357
- options.type = SlpTokenType.NftParent;
358
- let result = await this._processGenesis(options);
359
- return {
360
- tokenId: result,
361
- balance: await this.getBalance(result),
362
- };
363
- }
364
-
365
- /**
366
- * nftParentGenesis - create a new NFT Child token
367
- *
368
- * @param parentTokenId Parent token id, at least one is required and will be spent in the child genesis process
369
- * @param options Token creation options @see SlpGenesisOptions
370
- *
371
- * @returns Token Id and new token balance
372
- */
373
- public async nftChildGenesis(
374
- options: SlpGenesisOptions
375
- ): Promise<SlpGenesisResult> {
376
- if (!options.parentTokenId) {
377
- throw new Error(
378
- `The 'parentTokenId' was not set or invalid ${options.parentTokenId}`
379
- );
380
- }
381
-
382
- let parentUtxos = await this.provider.SlpSpendableUtxos(
383
- this.slpaddr,
384
- options.parentTokenId
385
- );
386
-
387
- parentUtxos = parentUtxos.filter(
388
- (val) => this.spentParentUtxos.indexOf(`${val.txid}:${val.vout}`) === -1
389
- );
390
- parentUtxos = parentUtxos.sort((a, b) => a.value.comparedTo(b.value));
391
-
392
- if (!parentUtxos.length) {
393
- throw new Error(
394
- `You do not own any NFT parent tokens with id ${options.parentTokenId}`
395
- );
396
- }
397
-
398
- if (parentUtxos[0].type !== SlpTokenType.NftParent) {
399
- throw new Error(
400
- `The 'parentTokenId' is not of type ${SlpTokenType.NftParent}`
401
- );
402
- }
403
-
404
- // we are about to spend exactly 1 NFT parent
405
- // if we do not have it, we have to make one by splitting
406
- if (parentUtxos[0].value.isGreaterThan(new BigNumber(1))) {
407
- await this.send([
408
- {
409
- slpaddr: this.slpaddr,
410
- tokenId: options.parentTokenId,
411
- value: new BigNumber(1),
412
- },
413
- ]);
414
- return await this.nftChildGenesis(options);
415
- }
416
-
417
- options.type = SlpTokenType.NftChild;
418
- options.endBaton = true;
419
- options.initialAmount = 1;
420
- options.decimals = 0;
421
- let result = await this._processGenesis(options, [parentUtxos[0]]);
422
-
423
- const tx = (await this.wallet.provider!.getRawTransactionObject(
424
- result
425
- )) as ElectrumRawTransaction;
426
- tx.vin.forEach((val) =>
427
- this.spentParentUtxos.push(`${val.txid}:${val.vout}`)
428
- );
429
-
430
- return {
431
- tokenId: result,
432
- balance: await this.getBalance(result),
433
- };
434
- }
435
-
436
- /**
437
- * _processGenesis - prepare the genesis transaction with given parameters
438
- *
439
- * a private utility wrapper to pre-process transactions
440
- *
441
- * @param options genesis options to controll the process
442
- *
443
- * @returns the created tokenId (which is genesis transaction id) and token balance
444
- */
445
- private async _processGenesis(
446
- options: SlpGenesisOptions,
447
- ensureInputs: UtxoI[] = []
448
- ) {
449
- options = this.substituteOptionals(options);
450
-
451
- let slpOutputsResult = await SlpGetGenesisOutputs(options);
452
-
453
- let fundingBchUtxos = await this.wallet
454
- .slpAware(true)
455
- .getAddressUtxos(this.wallet.cashaddr!);
456
-
457
- fundingBchUtxos = [...ensureInputs, ...fundingBchUtxos];
458
-
459
- return this.processSlpTransaction(fundingBchUtxos, slpOutputsResult);
460
- }
461
-
462
- /**
463
- * sendMax - send the maximum spendable amount for a token to an slpaddr.
464
- *
465
- * a high-level function, see also /wallet/slp/send_max REST endpoint
466
- *
467
- * @param slpaddr destination SLP address
468
- * @param tokenId the id of the token to be spent
469
- *
470
- * @returns transaction id and token balance
471
- */
472
- public async sendMax(
473
- slpaddr: string,
474
- tokenId: string
475
- ): Promise<SlpSendResponse> {
476
- const balance = await this.getBalance(tokenId);
477
- const requests: SlpSendRequest[] = [balance].map((val) => ({
478
- slpaddr: slpaddr,
479
- value: val.value,
480
- ticker: val.ticker,
481
- tokenId: val.tokenId,
482
- }));
483
- return this.send(requests);
484
- }
485
-
486
- /**
487
- * explorerUrl Web url to a transaction on a block explorer
488
- *
489
- * @param txId transaction Id
490
- * @returns Url string
491
- */
492
- public explorerUrl(txId: string) {
493
- const explorerUrlMap = {
494
- mainnet: "https://simpleledger.info/#tx/",
495
- testnet: "https://testnet.simpleledger.info/#tx/",
496
- regtest: "",
497
- };
498
-
499
- return explorerUrlMap[this.wallet.network] + txId;
500
- }
501
-
502
- /**
503
- * send - attempt to process a list of slp send requests.
504
- *
505
- * a high-level function, see also /wallet/slp/send REST endpoint
506
- *
507
- * @param [requests] list of send requests
508
- *
509
- * @returns transaction id and token balance
510
- */
511
- public async send(requests: SlpSendRequest[]): Promise<SlpSendResponse> {
512
- let [actualTokenId, result] = await this._processSendRequests(requests);
513
- return {
514
- txId: result,
515
- balance: await this.getBalance(actualTokenId),
516
- explorerUrl: this.explorerUrl(result),
517
- };
518
- }
519
-
520
- /**
521
- * _processSendRequests - given a list of sendRequests, estimate fees, build the transaction and submit it.
522
- *
523
- * A private utility wrapper to pre-process transactions
524
- *
525
- * Unstable - behavior may change without notice.
526
- *
527
- * @param {SlpSendRequest[]} sendRequests
528
- */
529
- private async _processSendRequests(sendRequests: SlpSendRequest[]) {
530
- if (!sendRequests.length) {
531
- throw Error("Empty send requests");
532
- }
533
- if (sendRequests.length > 19) {
534
- throw Error("Too many send requests in one transaction");
535
- }
536
- const uniqueTokenIds = new Set(sendRequests.map((val) => val.tokenId));
537
- if (uniqueTokenIds.size > 1) {
538
- throw Error(
539
- "You have two different token types with the same ticker. Pass tokenId parameter"
540
- );
541
- }
542
-
543
- const tokenId = sendRequests[0].tokenId;
544
- if (!tokenId.match(/^[0-9a-fA-F]{64}$/)) {
545
- throw new Error(
546
- "Invalid tokenId, must be 64 character long hexadecimal string"
547
- );
548
- }
549
-
550
- const slpUtxos = await this.provider.SlpSpendableUtxos(
551
- this.slpaddr,
552
- tokenId
553
- );
554
- let slpOutputsResult = await SlpGetSendOutputs(
555
- this.slpaddr,
556
- slpUtxos,
557
- sendRequests
558
- );
559
-
560
- let fundingBchUtxos = await this.wallet
561
- .slpAware(true)
562
- .getAddressUtxos(this.wallet.cashaddr!);
563
- let slpToBchUtxos = slpOutputsResult.FundingSlpUtxos.map(
564
- (val) => val as UtxoI
565
- );
566
- fundingBchUtxos = [...slpToBchUtxos, ...fundingBchUtxos];
567
-
568
- const actualTokenId = slpUtxos[0].tokenId;
569
- return [
570
- actualTokenId,
571
- await this.processSlpTransaction(
572
- fundingBchUtxos,
573
- slpOutputsResult,
574
- actualTokenId
575
- ),
576
- ];
577
- }
578
-
579
- /**
580
- * mint - create new tokens to increase the circulation supply.
581
- *
582
- * a high-level function, see also /wallet/slp/mint endpoint
583
- *
584
- * @param value amount to mint
585
- * @param tokenId the tokenId of the slp being minted
586
- * @param endBaton boolean indicating whether the token should continue to be "mintable"
587
- *
588
- * @returns transaction id and token balance
589
- */
590
- public async mint(options: SlpMintOptions): Promise<SlpMintResult> {
591
- let [actualTokenId, result] = await this._processMint(options);
592
- return {
593
- txId: result,
594
- balance: await this.getBalance(actualTokenId),
595
- };
596
- }
597
-
598
- /**
599
- * _processMint - given mint parameters, prepare the transaction
600
- *
601
- * a private utility wrapper to pre-process transactions
602
- *
603
- * @param value amount to mint
604
- * @param tokenId the tokenId of the slp being minted
605
- * @param endBaton boolean indicating whether the token should continue to be "mintable"
606
- *
607
- * @returns the tokenId and minting transaction id
608
- */
609
- private async _processMint(options: SlpMintOptions) {
610
- options = this.substituteOptionals(options);
611
-
612
- options.value = new BigNumber(options.value);
613
- if (
614
- options.value.isLessThanOrEqualTo(0) &&
615
- options.batonReceiverSlpAddr === this.slpaddr
616
- ) {
617
- throw Error("Mint amount should be greater than zero");
618
- }
619
-
620
- const slpBatonUtxos = await this.getBatonUtxos(options.tokenId);
621
- if (!slpBatonUtxos.length) {
622
- throw Error(
623
- `You do not possess the minting baton for ${options.tokenId}`
624
- );
625
- }
626
-
627
- let slpOutputsResult = await SlpGetMintOutputs(options, slpBatonUtxos);
628
-
629
- let bchUtxos = await this.wallet
630
- .slpAware(true)
631
- .getAddressUtxos(this.wallet.cashaddr!);
632
- let fundingBchUtxos = bchUtxos;
633
- let slpToBchUtxos = slpOutputsResult.FundingSlpUtxos.map(
634
- (val) => val as UtxoI
635
- );
636
- fundingBchUtxos = [...slpToBchUtxos, ...fundingBchUtxos];
637
-
638
- return [
639
- options.tokenId,
640
- await this.processSlpTransaction(
641
- fundingBchUtxos,
642
- slpOutputsResult,
643
- options.tokenId
644
- ),
645
- ];
646
- }
647
-
648
- /**
649
- * processSlpTransaction - process the prepared SLP transaction and submit it to the network
650
- *
651
- * @param fundingBchUtxos ensure these BCH utxos to be spent in the process
652
- * @param slpOutputsResult prepared SLP outputs to be added to transaction
653
- *
654
- * @returns the tokenId and minting transaction id
655
- */
656
- private async processSlpTransaction(
657
- fundingBchUtxos: UtxoI[],
658
- slpOutputsResult: {
659
- SlpOutputs: Output[];
660
- FundingSlpUtxos: SlpUtxoI[];
661
- BchSendRequests: SendRequest[];
662
- },
663
- tokenId?: string
664
- ): Promise<string> {
665
- if (!this.wallet.privateKey) {
666
- throw new Error(
667
- `Wallet ${this.wallet.name} is missing either a network or private key`
668
- );
669
- }
670
-
671
- if (!fundingBchUtxos.length) {
672
- throw new Error("No bch available to fund this transaction");
673
- }
674
-
675
- const bestHeight = await this.wallet.provider!.getBlockHeight()!;
676
-
677
- const relayFeePerByteInSatoshi = await getRelayFeeCache(
678
- this.wallet.provider!
679
- );
680
-
681
- const feeEstimate = await getFeeAmount({
682
- utxos: fundingBchUtxos,
683
- sendRequests: slpOutputsResult.BchSendRequests,
684
- privateKey: this.wallet.privateKey,
685
- sourceAddress: this.wallet.cashaddr!,
686
- relayFeePerByteInSatoshi: relayFeePerByteInSatoshi,
687
- slpOutputs: slpOutputsResult.SlpOutputs,
688
- feePaidBy: FeePaidByEnum.change,
689
- });
690
-
691
- const bchSpendAmount = slpOutputsResult.BchSendRequests.map(
692
- (val) => val.value
693
- ).reduce((a, b) => a + b, 0);
694
-
695
- let fundingUtxos = await getSuitableUtxos(
696
- fundingBchUtxos,
697
- BigInt(bchSpendAmount) + BigInt(feeEstimate),
698
- bestHeight,
699
- FeePaidByEnum.change,
700
- slpOutputsResult.BchSendRequests
701
- );
702
-
703
- if (fundingUtxos.length === 0) {
704
- throw Error(
705
- "The available inputs couldn't satisfy the request with fees"
706
- );
707
- }
708
-
709
- const fee = await getFeeAmount({
710
- utxos: fundingUtxos,
711
- sendRequests: slpOutputsResult.BchSendRequests,
712
- privateKey: this.wallet.privateKey,
713
- sourceAddress: this.wallet.cashaddr!,
714
- relayFeePerByteInSatoshi: relayFeePerByteInSatoshi,
715
- slpOutputs: slpOutputsResult.SlpOutputs,
716
- feePaidBy: FeePaidByEnum.change,
717
- });
718
-
719
- const { encodedTransaction } = await buildEncodedTransaction({
720
- inputs: fundingUtxos,
721
- outputs: slpOutputsResult.BchSendRequests,
722
- signingKey: this.wallet.privateKey,
723
- sourceAddress: this.wallet.cashaddr!,
724
- fee,
725
- discardChange: false,
726
- slpOutputs: slpOutputsResult.SlpOutputs,
727
- });
728
-
729
- return this._submitTransaction(encodedTransaction, tokenId);
730
- }
731
-
732
- /**
733
- * _submitTransaction - transform binary transaction to hex and submit it to the network provider
734
- *
735
- * a private utility wrapper submit raw transactions
736
- *
737
- * @param transaction raw transaction
738
- *
739
- * @returns the transaction id of the broadcasted transaction
740
- */
741
- private async _submitTransaction(
742
- transaction: Uint8Array,
743
- tokenId?: string
744
- ): Promise<string> {
745
- let rawTransaction = binToHex(transaction);
746
-
747
- const slpPromise = new Promise(async (resolve) => {
748
- const txHash = await Util.getTransactionHash(rawTransaction);
749
-
750
- const cancelWatchFn = this.provider.SlpWatchTransactions(
751
- async (tx: SlpTxI) => {
752
- if (tx.tx_hash === txHash) {
753
- cancelWatchFn();
754
- resolve(txHash);
755
- }
756
- },
757
- undefined,
758
- tokenId || txHash
759
- );
760
- });
761
-
762
- const bchPromise = this.wallet.provider!.sendRawTransaction(
763
- rawTransaction,
764
- true
765
- );
766
-
767
- const [_, txHash] = await Promise.all([slpPromise, bchPromise]);
768
-
769
- // allow for indexer processing, delay value is a bit arbitrary
770
- await delay(100);
771
-
772
- return txHash;
773
- }
774
-
775
- /**
776
- * substituteOptionals - substitute optional fields with default values
777
- *
778
- * will ensure that baton and token receiver are intialized as SLP address of this wallet if absent
779
- * will ensure that baton will not be ended if endBaton is undefined
780
- * a private utility wrapper substitute optionals
781
- *
782
- * @param options genesis or mint options to substitute values int
783
- *
784
- * @returns options with relevant values substituted/initialized
785
- */
786
- private substituteOptionals(options: any): any {
787
- if (!options.batonReceiverSlpAddr) {
788
- options.batonReceiverSlpAddr = this.slpaddr;
789
- }
790
- if (!options.tokenReceiverSlpAddr) {
791
- options.tokenReceiverSlpAddr = this.slpaddr;
792
- }
793
- if (options.endBaton === undefined) {
794
- options.endBaton = false;
795
- }
796
-
797
- return options;
798
- }
799
-
800
- //#region Convenience methods to initialize Slp aware BCH wallet.
801
-
802
- /**
803
- * fromId - create an SLP aware wallet from encoded walletId string
804
- *
805
- * @param walletId walletId options to steer the creation process
806
- *
807
- * @returns wallet instantiated accordingly to the walletId rules
808
- */
809
- public static async fromId(walletId: string): Promise<Wallet> {
810
- const wallet = await this.walletType.fromId(walletId);
811
- wallet._slpAware = true;
812
- return wallet;
813
- }
814
-
815
- /**
816
- * named - create an SLP aware named wallet
817
- *
818
- * @param name user friendly wallet alias
819
- * @param dbName name under which the wallet will be stored in the database
820
- * @param force force recreate wallet in the database if a record already exist
821
- *
822
- * @returns instantiated wallet
823
- */
824
- public static async named(
825
- name: string,
826
- dbName?: string,
827
- force?: boolean
828
- ): Promise<Wallet> {
829
- const wallet = await this.walletType.named(name, dbName, force);
830
- wallet.derivationPath = "m/44'/245'/0'/0/0";
831
- wallet._slpAware = true;
832
- return wallet;
833
- }
834
-
835
- /**
836
- * fromSeed - create an SLP aware wallet using the seed phrase and derivation path
837
- *
838
- * unless specified the derivation path m/44'/245'/0'/0/0 will be userd
839
- * this derivation path is standard for Electron Cash SLP and other SLP enabled wallets
840
- *
841
- * @param seed BIP39 12 word seed phrase
842
- * @param derivationPath BIP44 HD wallet derivation path to get a single the private key from hierarchy
843
- *
844
- * @returns instantiated wallet
845
- */
846
- public static async fromSeed(
847
- seed: string,
848
- derivationPath: string = "m/44'/245'/0'/0/0"
849
- ): Promise<Wallet> {
850
- const wallet = await this.walletType.fromSeed(seed, derivationPath);
851
- wallet._slpAware = true;
852
- return wallet;
853
- }
854
-
855
- /**
856
- * newRandom - create an SLP aware random wallet
857
- *
858
- * if `name` parameter is specified, the wallet will also be persisted to DB
859
- *
860
- * @param name user friendly wallet alias
861
- * @param dbName name under which the wallet will be stored in the database
862
- *
863
- * @returns instantiated wallet
864
- */
865
- public static async newRandom(
866
- name: string = "",
867
- dbName?: string
868
- ): Promise<Wallet> {
869
- const wallet = await this.walletType.newRandom(name, dbName);
870
- wallet.derivationPath = "m/44'/245'/0'/0/0";
871
- wallet._slpAware = true;
872
- return wallet;
873
- }
874
-
875
- /**
876
- * fromWIF - create an SLP aware wallet using the private key supplied in `Wallet Import Format`
877
- *
878
- * @param wif WIF encoded private key string
879
- *
880
- * @returns instantiated wallet
881
- */
882
- public static async fromWIF(wif: string): Promise<Wallet> {
883
- const wallet = await this.walletType.fromWIF(wif);
884
- wallet.derivationPath = "m/44'/245'/0'/0/0";
885
- wallet._slpAware = true;
886
- return wallet;
887
- }
888
-
889
- /**
890
- * watchOnly - create an SLP aware watch-only wallet
891
- *
892
- * such kind of wallet does not have a private key and is unable to spend any funds
893
- * however it still allows to use many utility functions such as getting and watching balance, etc.
894
- *
895
- * @param address cashaddress or slpaddress of a wallet
896
- *
897
- * @returns instantiated wallet
898
- */
899
- public static async watchOnly(address: string): Promise<Wallet> {
900
- const wallet = await this.walletType.watchOnly(toCashAddress(address));
901
- wallet.derivationPath = "m/44'/245'/0'/0/0";
902
- wallet._slpAware = true;
903
- return wallet;
904
- }
905
-
906
- /**
907
- * fromCashaddr - create an SLP aware watch-only wallet in the network derived from the address
908
- *
909
- * such kind of wallet does not have a private key and is unable to spend any funds
910
- * however it still allows to use many utility functions such as getting and watching balance, etc.
911
- *
912
- * @param address cashaddress of a wallet
913
- *
914
- * @returns instantiated wallet
915
- */
916
- public static async fromCashaddr(address: string): Promise<Wallet> {
917
- const wallet = await this.walletType.fromCashaddr(address);
918
- wallet.derivationPath = "m/44'/245'/0'/0/0";
919
- wallet._slpAware = true;
920
- return wallet;
921
- }
922
-
923
- /**
924
- * fromSlpaddr - create an SLP aware watch-only wallet in the network derived from the address
925
- *
926
- * such kind of wallet does not have a private key and is unable to spend any funds
927
- * however it still allows to use many utility functions such as getting and watching balance, etc.
928
- *
929
- * @param address slpaddress of a wallet
930
- *
931
- * @returns instantiated wallet
932
- */
933
- public static async fromSlpaddr(address: string): Promise<Wallet> {
934
- const wallet = await this.walletType.fromSlpaddr(address);
935
- wallet.derivationPath = "m/44'/245'/0'/0/0";
936
- wallet._slpAware = true;
937
- return wallet;
938
- }
939
- //#endregion
940
- }
941
-
942
- //#region Specific wallet classes
943
- /**
944
- * Class to manage an slp enabled testnet wallet.
945
- */
946
- export class TestNetSlp extends Slp {
947
- static get walletType() {
948
- return TestNetWallet;
949
- }
950
- }
951
-
952
- /**
953
- * Class to manage an slp enabled regtest wallet.
954
- */
955
- export class RegTestSlp extends Slp {
956
- static get walletType() {
957
- return RegTestWallet;
958
- }
959
- }
960
-
961
- /**
962
- * Class to manage a bitcoin cash wif wallet.
963
- */
964
- export class WifSlp extends Slp {
965
- static get walletType() {
966
- return WifWallet;
967
- }
968
- }
969
-
970
- /**
971
- * Class to manage a testnet wif wallet.
972
- */
973
- export class TestNetWifSlp extends Slp {
974
- static get walletType() {
975
- return TestNetWifWallet;
976
- }
977
- }
978
-
979
- /**
980
- * Class to manage a regtest wif wallet.
981
- */
982
- export class RegTestWifSlp extends Slp {
983
- static get walletType() {
984
- return RegTestWifWallet;
985
- }
986
- }
987
-
988
- /**
989
- * Class to manage a bitcoin cash watch wallet.
990
- */
991
- export class WatchSlp extends Slp {
992
- static get walletType() {
993
- return WatchWallet;
994
- }
995
- }
996
-
997
- /**
998
- * Class to manage a testnet watch wallet.
999
- */
1000
- export class TestNetWatchSlp extends Slp {
1001
- static get walletType() {
1002
- return TestNetWatchWallet;
1003
- }
1004
- }
1005
-
1006
- /**
1007
- * Class to manage a regtest watch wallet.
1008
- */
1009
- export class RegTestWatchSlp extends Slp {
1010
- static get walletType() {
1011
- return RegTestWatchWallet;
1012
- }
1013
- }
1014
- //#endregion