@yaswap/yacoin 3.4.1 → 3.4.3
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.
- package/CHANGELOG.md +22 -0
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +3 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/types.d.ts +45 -2
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/wallet/IYacoinWallet.d.ts +24 -3
- package/dist/lib/wallet/YacoinBaseWallet.d.ts +41 -18
- package/dist/lib/wallet/YacoinBaseWallet.js +180 -48
- package/dist/lib/wallet/YacoinBaseWallet.js.map +1 -1
- package/dist/lib/wallet/YacoinHDWallet.d.ts +30 -8
- package/dist/lib/wallet/YacoinHDWallet.js +150 -22
- package/dist/lib/wallet/YacoinHDWallet.js.map +1 -1
- package/dist/lib/wallet/YacoinSingleWallet.d.ts +15 -11
- package/dist/lib/wallet/YacoinSingleWallet.js +54 -21
- package/dist/lib/wallet/YacoinSingleWallet.js.map +1 -1
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @yaswap/bitcoin
|
|
2
2
|
|
|
3
|
+
## 3.4.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Improve getUsedUnusedAddresses and buildTransaction
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @yaswap/client@3.4.3
|
|
10
|
+
- @yaswap/errors@3.4.3
|
|
11
|
+
- @yaswap/types@3.4.3
|
|
12
|
+
- @yaswap/utils@3.4.3
|
|
13
|
+
|
|
14
|
+
## 3.4.2
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Support HD wallet logic
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
- @yaswap/client@3.4.2
|
|
21
|
+
- @yaswap/errors@3.4.2
|
|
22
|
+
- @yaswap/types@3.4.2
|
|
23
|
+
- @yaswap/utils@3.4.2
|
|
24
|
+
|
|
3
25
|
## 3.4.1
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { YacoinSwapBaseProvider } from './swap/YacoinSwapBaseProvider';
|
|
|
8
8
|
export { YacoinSwapEsploraProvider } from './swap/YacoinSwapEsploraProvider';
|
|
9
9
|
export * as YacoinTypes from './types';
|
|
10
10
|
export * as YacoinUtils from './utils';
|
|
11
|
-
export { YacoinBaseWalletProvider } from './wallet/YacoinBaseWallet';
|
|
11
|
+
export { AddressSearchType, YacoinBaseWalletProvider, NUMBER_ADDRESS_LIMIT } from './wallet/YacoinBaseWallet';
|
|
12
12
|
export { YacoinHDWalletProvider } from './wallet/YacoinHDWallet';
|
|
13
13
|
export { YacoinNftProvider } from './nft/YacoinNftProvider';
|
|
14
14
|
export { YacoinSingleWallet } from './wallet/YacoinSingleWallet';
|
package/dist/lib/index.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.YacoinSingleWallet = exports.YacoinNftProvider = exports.YacoinHDWalletProvider = exports.YacoinBaseWalletProvider = exports.YacoinUtils = exports.YacoinTypes = exports.YacoinSwapEsploraProvider = exports.YacoinSwapBaseProvider = exports.YacoinNetworks = exports.YacoinFeeApiProvider = exports.YacoinEsploraBatchBaseProvider = exports.YacoinEsploraBaseProvider = exports.YacoinEsploraApiProvider = exports.YacoinBaseChainProvider = void 0;
|
|
26
|
+
exports.YacoinSingleWallet = exports.YacoinNftProvider = exports.YacoinHDWalletProvider = exports.NUMBER_ADDRESS_LIMIT = exports.YacoinBaseWalletProvider = exports.AddressSearchType = exports.YacoinUtils = exports.YacoinTypes = exports.YacoinSwapEsploraProvider = exports.YacoinSwapBaseProvider = exports.YacoinNetworks = exports.YacoinFeeApiProvider = exports.YacoinEsploraBatchBaseProvider = exports.YacoinEsploraBaseProvider = exports.YacoinEsploraApiProvider = exports.YacoinBaseChainProvider = void 0;
|
|
27
27
|
var YacoinBaseChainProvider_1 = require("./chain/YacoinBaseChainProvider");
|
|
28
28
|
Object.defineProperty(exports, "YacoinBaseChainProvider", { enumerable: true, get: function () { return YacoinBaseChainProvider_1.YacoinBaseChainProvider; } });
|
|
29
29
|
var YacoinEsploraApiProvider_1 = require("./chain/esplora/YacoinEsploraApiProvider");
|
|
@@ -43,7 +43,9 @@ Object.defineProperty(exports, "YacoinSwapEsploraProvider", { enumerable: true,
|
|
|
43
43
|
exports.YacoinTypes = __importStar(require("./types"));
|
|
44
44
|
exports.YacoinUtils = __importStar(require("./utils"));
|
|
45
45
|
var YacoinBaseWallet_1 = require("./wallet/YacoinBaseWallet");
|
|
46
|
+
Object.defineProperty(exports, "AddressSearchType", { enumerable: true, get: function () { return YacoinBaseWallet_1.AddressSearchType; } });
|
|
46
47
|
Object.defineProperty(exports, "YacoinBaseWalletProvider", { enumerable: true, get: function () { return YacoinBaseWallet_1.YacoinBaseWalletProvider; } });
|
|
48
|
+
Object.defineProperty(exports, "NUMBER_ADDRESS_LIMIT", { enumerable: true, get: function () { return YacoinBaseWallet_1.NUMBER_ADDRESS_LIMIT; } });
|
|
47
49
|
var YacoinHDWallet_1 = require("./wallet/YacoinHDWallet");
|
|
48
50
|
Object.defineProperty(exports, "YacoinHDWalletProvider", { enumerable: true, get: function () { return YacoinHDWallet_1.YacoinHDWalletProvider; } });
|
|
49
51
|
var YacoinNftProvider_1 = require("./nft/YacoinNftProvider");
|
package/dist/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2EAA0E;AAAjE,kIAAA,uBAAuB,OAAA;AAChC,qFAAoF;AAA3E,oIAAA,wBAAwB,OAAA;AACjC,uFAAsF;AAA7E,sIAAA,yBAAyB,OAAA;AAClC,iGAAgG;AAAvF,gJAAA,8BAA8B,OAAA;AACvC,mEAAkE;AAAzD,4HAAA,oBAAoB,OAAA;AAC7B,uCAA4C;AAAnC,0GAAA,cAAc,OAAA;AACvB,wEAAuE;AAA9D,gIAAA,sBAAsB,OAAA;AAC/B,8EAA6E;AAApE,sIAAA,yBAAyB,OAAA;AAClC,uDAAuC;AACvC,uDAAuC;AACvC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2EAA0E;AAAjE,kIAAA,uBAAuB,OAAA;AAChC,qFAAoF;AAA3E,oIAAA,wBAAwB,OAAA;AACjC,uFAAsF;AAA7E,sIAAA,yBAAyB,OAAA;AAClC,iGAAgG;AAAvF,gJAAA,8BAA8B,OAAA;AACvC,mEAAkE;AAAzD,4HAAA,oBAAoB,OAAA;AAC7B,uCAA4C;AAAnC,0GAAA,cAAc,OAAA;AACvB,wEAAuE;AAA9D,gIAAA,sBAAsB,OAAA;AAC/B,8EAA6E;AAApE,sIAAA,yBAAyB,OAAA;AAClC,uDAAuC;AACvC,uDAAuC;AACvC,8DAA8G;AAArG,qHAAA,iBAAiB,OAAA;AAAE,4HAAA,wBAAwB,OAAA;AAAE,wHAAA,oBAAoB,OAAA;AAC1E,0DAAiE;AAAxD,wHAAA,sBAAsB,OAAA;AAC/B,6DAA4D;AAAnD,sHAAA,iBAAiB,OAAA;AAC1B,kEAAiE;AAAxD,wHAAA,kBAAkB,OAAA"}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import { Network, TokenScriptType } from '@yaswap/types';
|
|
2
|
+
import { Address, Network, TokenScriptType, TransactionRequest } from '@yaswap/types';
|
|
3
3
|
import { ECPairInterface, Network as YacoinJsLibNetwork } from '@yaswap/yacoinjs-lib';
|
|
4
4
|
export * as YacoinEsploraTypes from './chain/esplora/types';
|
|
5
5
|
export * from './swap/types';
|
|
@@ -18,7 +18,17 @@ export interface YacoinWalletProviderOptions extends YacoinNodeWalletOptions {
|
|
|
18
18
|
baseDerivationPath: string;
|
|
19
19
|
}
|
|
20
20
|
export interface YacoinHDWalletProviderOptions extends YacoinWalletProviderOptions {
|
|
21
|
-
mnemonic
|
|
21
|
+
mnemonic?: string;
|
|
22
|
+
extendedPublicKey?: RawExtendedPublicKey;
|
|
23
|
+
extendedPrivateKey?: RawExtendedPrivateKey;
|
|
24
|
+
}
|
|
25
|
+
export interface RawExtendedPublicKey {
|
|
26
|
+
publicKey: Buffer;
|
|
27
|
+
chainCode: Buffer;
|
|
28
|
+
}
|
|
29
|
+
export interface RawExtendedPrivateKey {
|
|
30
|
+
privateKey: Buffer;
|
|
31
|
+
chainCode: Buffer;
|
|
22
32
|
}
|
|
23
33
|
export interface OutputTarget {
|
|
24
34
|
address?: string;
|
|
@@ -96,3 +106,36 @@ export interface P2SHInput {
|
|
|
96
106
|
vout: any;
|
|
97
107
|
outputScript: Buffer;
|
|
98
108
|
}
|
|
109
|
+
export interface UsedUnusedAddressesResult {
|
|
110
|
+
usedAddresses: {
|
|
111
|
+
change: Address[];
|
|
112
|
+
external: Address[];
|
|
113
|
+
};
|
|
114
|
+
unusedAddress: {
|
|
115
|
+
change: Address | null;
|
|
116
|
+
external: Address | null;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Options for Yacoin sendTransaction and sendTransactionFixedInputs.
|
|
121
|
+
* Extends TransactionRequest with Yacoin-specific options.
|
|
122
|
+
*/
|
|
123
|
+
export interface YacoinSendTransactionOptions extends TransactionRequest {
|
|
124
|
+
/**
|
|
125
|
+
* Pre-selected UTXOs to use as inputs. When set, only these UTXOs are used
|
|
126
|
+
* (e.g. for sendTransactionFixedInputs).
|
|
127
|
+
*/
|
|
128
|
+
inputs?: UTXO[];
|
|
129
|
+
/**
|
|
130
|
+
* When true, use a change address (internal branch) for the change output;
|
|
131
|
+
* when false, use a receiving address (external branch). Default: false.
|
|
132
|
+
*
|
|
133
|
+
* NOTE: This only affects which branch is scanned for UTXOs and where
|
|
134
|
+
* the change output is sent; it does not alter token behavior.
|
|
135
|
+
*/
|
|
136
|
+
change?: boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Maximum number of addresses to scan for UTXOs. Default: 40.
|
|
139
|
+
*/
|
|
140
|
+
addressLimit?: number;
|
|
141
|
+
}
|
package/dist/lib/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../lib/types.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,4EAA4D;AAC5D,+CAA6B;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../lib/types.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,4EAA4D;AAC5D,+CAA6B;AAkG7B,IAAY,WAEX;AAFD,WAAY,WAAW;IACnB,gCAAiB,CAAA;AACrB,CAAC,EAFW,WAAW,GAAX,mBAAW,KAAX,mBAAW,QAEtB;AAED,IAAY,QAEX;AAFD,WAAY,QAAQ;IAChB,yBAAa,CAAA;AACjB,CAAC,EAFW,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QAEnB"}
|
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
import { Chain, Wallet } from '@yaswap/client';
|
|
2
|
-
import { Address, FeeType, Transaction
|
|
3
|
-
import { PsbtInputTarget } from '../types';
|
|
2
|
+
import { Address, FeeType, Transaction } from '@yaswap/types';
|
|
3
|
+
import { PsbtInputTarget, UsedUnusedAddressesResult, YacoinSendTransactionOptions } from '../types';
|
|
4
|
+
import { AddressSearchType } from './YacoinBaseWallet';
|
|
4
5
|
export interface IYacoinWallet<T, S = any> extends Wallet<T, S> {
|
|
5
6
|
getChainProvider(): Chain<T>;
|
|
6
|
-
sendTransaction(txRequest:
|
|
7
|
+
sendTransaction(txRequest: YacoinSendTransactionOptions): Promise<Transaction>;
|
|
8
|
+
sendTransactionFixedInputs(options: YacoinSendTransactionOptions): Promise<Transaction>;
|
|
9
|
+
getTotalFeeFixedInputs(opts: YacoinSendTransactionOptions, max: boolean): Promise<number>;
|
|
7
10
|
updateTransactionFee(tx: string | Transaction, newFee: FeeType): Promise<Transaction>;
|
|
8
11
|
getWalletAddress(address: string): Promise<Address>;
|
|
9
12
|
signPSBT(data: string, inputs: PsbtInputTarget[]): Promise<string>;
|
|
10
13
|
signTx(transaction: string, hash: string, derivationPath: string, txfee: number): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Get one unused receiving or change address.
|
|
16
|
+
*
|
|
17
|
+
* @param change When true, search change addresses; otherwise external/receiving.
|
|
18
|
+
* @param addressLimit Maximum number of address indexes to scan (per branch).
|
|
19
|
+
*/
|
|
20
|
+
getUnusedAddress(change?: boolean, addressLimit?: number): Promise<Address | null>;
|
|
21
|
+
/**
|
|
22
|
+
* Get used addresses.
|
|
23
|
+
*
|
|
24
|
+
* @param addressType Which branch to scan: external, change or both. Defaults to both.
|
|
25
|
+
* @param addressLimit Maximum number of address indexes to scan (per branch).
|
|
26
|
+
*/
|
|
27
|
+
getUsedAddresses(addressType?: AddressSearchType, addressLimit?: number): Promise<Address[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Scan addresses and return both used and first unused addresses per branch.
|
|
30
|
+
*/
|
|
31
|
+
getUsedUnusedAddresses(addressType: AddressSearchType, addressLimit?: number, gapLimit?: number, useCache?: boolean): Promise<UsedUnusedAddressesResult>;
|
|
11
32
|
}
|
|
@@ -4,8 +4,9 @@ import { Address, AddressType, Asset, Transaction, TransactionRequest, CreateTok
|
|
|
4
4
|
import { BIP32Interface } from 'bip32';
|
|
5
5
|
import { payments } from '@yaswap/yacoinjs-lib';
|
|
6
6
|
import { YacoinBaseChainProvider } from '../chain/YacoinBaseChainProvider';
|
|
7
|
-
import { AddressType as YaAddressType, YacoinNetwork, YacoinWalletProviderOptions,
|
|
7
|
+
import { AddressType as YaAddressType, YacoinNetwork, YacoinWalletProviderOptions, OutputTarget, P2SHInput, PsbtInputTarget, Transaction as YaTransaction, UsedUnusedAddressesResult, UTXO, YacoinSendTransactionOptions } from '../types';
|
|
8
8
|
import { CoinSelectTarget } from '../utils';
|
|
9
|
+
export declare const NUMBER_ADDRESS_LIMIT = 40;
|
|
9
10
|
export declare enum AddressSearchType {
|
|
10
11
|
EXTERNAL = 0,
|
|
11
12
|
CHANGE = 1,
|
|
@@ -19,10 +20,11 @@ export declare abstract class YacoinBaseWalletProvider<T extends YacoinBaseChain
|
|
|
19
20
|
protected _network: YacoinNetwork;
|
|
20
21
|
protected _addressType: YaAddressType;
|
|
21
22
|
protected _derivationCache: DerivationCache;
|
|
23
|
+
private _usedUnusedAddressesCache;
|
|
22
24
|
constructor(options: YacoinWalletProviderOptions, chainProvider?: Chain<T>);
|
|
23
25
|
protected onChainProviderUpdate(chainProvider: Chain<T>): void;
|
|
24
26
|
protected abstract baseDerivationNode(): Promise<BIP32Interface>;
|
|
25
|
-
protected abstract buildTransaction(targets: OutputTarget[], feePerByte?: number,
|
|
27
|
+
protected abstract buildTransaction(targets: OutputTarget[], feePerByte?: number, fixedUtxos?: UTXO[], change?: boolean, addressLimit?: number): Promise<{
|
|
26
28
|
hex: string;
|
|
27
29
|
fee: number;
|
|
28
30
|
}>;
|
|
@@ -34,29 +36,50 @@ export declare abstract class YacoinBaseWalletProvider<T extends YacoinBaseChain
|
|
|
34
36
|
abstract signTx(transaction: string, hash: string, derivationPath: string, txfee: number): Promise<string>;
|
|
35
37
|
abstract signBatchP2SHTransaction(inputs: P2SHInput[], addresses: string, tx: any, lockTime?: number, segwit?: boolean): Promise<Buffer[]>;
|
|
36
38
|
getDerivationCache(): DerivationCache;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Get one unused receiving or change address.
|
|
41
|
+
*
|
|
42
|
+
* @param change When true, search change addresses; otherwise external/receiving.
|
|
43
|
+
* @param addressLimit Maximum number of address indexes to scan (per branch). Defaults to NUMBER_ADDRESS_LIMIT.
|
|
44
|
+
* @returns The first unused address found or null if none within the limit.
|
|
45
|
+
*/
|
|
46
|
+
getUnusedAddress(change?: boolean, addressLimit?: number): Promise<Address>;
|
|
47
|
+
/**
|
|
48
|
+
* Get used addresses.
|
|
49
|
+
*
|
|
50
|
+
* @param addressType Which branch to scan: external, change or both. Defaults to both.
|
|
51
|
+
* @param addressLimit Maximum number of address indexes to scan (per branch). Defaults to NUMBER_ADDRESS_LIMIT.
|
|
52
|
+
* @returns List of used addresses for the requested branch(es).
|
|
53
|
+
*/
|
|
54
|
+
getUsedAddresses(addressType?: AddressSearchType, addressLimit?: number): Promise<Address[]>;
|
|
39
55
|
getAddresses(startingIndex?: number, numAddresses?: number, change?: boolean): Promise<Address[]>;
|
|
40
56
|
createToken(options: CreateTokenTransaction): Promise<Transaction>;
|
|
41
|
-
sendTransaction(options: TransactionRequest
|
|
42
|
-
|
|
57
|
+
sendTransaction(options: TransactionRequest & {
|
|
58
|
+
change?: boolean;
|
|
59
|
+
addressLimit?: number;
|
|
60
|
+
inputs?: UTXO[];
|
|
61
|
+
}): Promise<Transaction<YaTransaction>>;
|
|
62
|
+
sendTransactionFixedInputs(options: TransactionRequest & {
|
|
63
|
+
change?: boolean;
|
|
64
|
+
addressLimit?: number;
|
|
65
|
+
inputs?: UTXO[];
|
|
66
|
+
}): Promise<Transaction<YaTransaction>>;
|
|
67
|
+
sendBatchTransaction(transactions: (TransactionRequest & {
|
|
68
|
+
change?: boolean;
|
|
69
|
+
addressLimit?: number;
|
|
70
|
+
})[]): Promise<Transaction<YaTransaction>[]>;
|
|
43
71
|
sendSweepTransaction(externalChangeAddress: AddressType, _asset: Asset, feePerByte: number): Promise<Transaction<YaTransaction>>;
|
|
44
72
|
updateTransactionFee(tx: Transaction<YaTransaction> | string, newFeePerByte: number): Promise<Transaction<YaTransaction>>;
|
|
45
|
-
getTotalFees(transactions:
|
|
46
|
-
protected _sendTransaction(transactions: OutputTarget[], feePerByte?: number): Promise<Transaction<YaTransaction>>;
|
|
47
|
-
protected findAddress(addresses: string[], change?: boolean): Promise<Address>;
|
|
73
|
+
getTotalFees(transactions: YacoinSendTransactionOptions[], max: boolean): Promise<any>;
|
|
74
|
+
protected _sendTransaction(transactions: OutputTarget[], feePerByte?: number, change?: boolean, addressLimit?: number, fixedUtxos?: UTXO[]): Promise<Transaction<YaTransaction>>;
|
|
75
|
+
protected findAddress(addresses: string[], change?: boolean, addressLimit?: number): Promise<Address>;
|
|
48
76
|
getWalletAddress(address: string): Promise<Address>;
|
|
49
77
|
protected getDerivationPathAddress(path: string): Promise<Address>;
|
|
50
|
-
|
|
51
|
-
usedAddresses: Address[];
|
|
52
|
-
unusedAddress: {
|
|
53
|
-
change: Address;
|
|
54
|
-
external: Address;
|
|
55
|
-
};
|
|
56
|
-
}>;
|
|
78
|
+
getUsedUnusedAddresses(addressType: AddressSearchType, addressLimit?: number, gapLimit?: number, useCache?: boolean): Promise<UsedUnusedAddressesResult>;
|
|
57
79
|
protected withCachedUtxos(func: () => any): Promise<any>;
|
|
58
|
-
|
|
59
|
-
protected
|
|
80
|
+
getTotalFeeFixedInputs(opts: YacoinSendTransactionOptions, max: boolean): Promise<number>;
|
|
81
|
+
protected getTotalFee(opts: YacoinSendTransactionOptions, max: boolean): Promise<number>;
|
|
82
|
+
protected getInputsForAmount(_targets: OutputTarget[], feePerByte?: number, fixedUtxos?: UTXO[], sweep?: boolean, addressLimit?: number, change?: boolean): Promise<{
|
|
60
83
|
inputs: UTXO[];
|
|
61
84
|
coinChange: CoinSelectTarget;
|
|
62
85
|
tokenChange: CoinSelectTarget;
|
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.YacoinBaseWalletProvider = exports.AddressSearchType = void 0;
|
|
15
|
+
exports.YacoinBaseWalletProvider = exports.AddressSearchType = exports.NUMBER_ADDRESS_LIMIT = void 0;
|
|
16
16
|
const client_1 = require("@yaswap/client");
|
|
17
17
|
const errors_1 = require("@yaswap/errors");
|
|
18
18
|
const types_1 = require("@yaswap/types");
|
|
@@ -21,7 +21,9 @@ const yacoinjs_lib_1 = require("@yaswap/yacoinjs-lib");
|
|
|
21
21
|
const memoizee_1 = __importDefault(require("memoizee"));
|
|
22
22
|
const types_2 = require("../types");
|
|
23
23
|
const utils_2 = require("../utils");
|
|
24
|
-
|
|
24
|
+
exports.NUMBER_ADDRESS_LIMIT = 40;
|
|
25
|
+
/** Cache TTL in milliseconds for getUsedUnusedAddresses results. */
|
|
26
|
+
const USED_UNUSED_ADDRESSES_CACHE_TTL_MS = 60 * 1000;
|
|
25
27
|
var AddressSearchType;
|
|
26
28
|
(function (AddressSearchType) {
|
|
27
29
|
AddressSearchType[AddressSearchType["EXTERNAL"] = 0] = "EXTERNAL";
|
|
@@ -45,6 +47,7 @@ class YacoinBaseWalletProvider extends client_1.Wallet {
|
|
|
45
47
|
throw new Error(`addressType must be one of ${addressTypes.join(',')}`);
|
|
46
48
|
}
|
|
47
49
|
super(chainProvider);
|
|
50
|
+
this._usedUnusedAddressesCache = {};
|
|
48
51
|
this._baseDerivationPath = baseDerivationPath;
|
|
49
52
|
this._network = chainProvider ? chainProvider.getNetwork() : options.network;
|
|
50
53
|
this._addressType = addressType;
|
|
@@ -56,16 +59,38 @@ class YacoinBaseWalletProvider extends client_1.Wallet {
|
|
|
56
59
|
getDerivationCache() {
|
|
57
60
|
return this._derivationCache;
|
|
58
61
|
}
|
|
59
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Get one unused receiving or change address.
|
|
64
|
+
*
|
|
65
|
+
* @param change When true, search change addresses; otherwise external/receiving.
|
|
66
|
+
* @param addressLimit Maximum number of address indexes to scan (per branch). Defaults to NUMBER_ADDRESS_LIMIT.
|
|
67
|
+
* @returns The first unused address found or null if none within the limit.
|
|
68
|
+
*/
|
|
69
|
+
getUnusedAddress(change = false, addressLimit = exports.NUMBER_ADDRESS_LIMIT) {
|
|
60
70
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61
71
|
const addressType = change ? AddressSearchType.CHANGE : AddressSearchType.EXTERNAL;
|
|
62
72
|
const key = change ? 'change' : 'external';
|
|
63
|
-
|
|
73
|
+
const { unusedAddress } = yield this.getUsedUnusedAddresses(addressType, addressLimit);
|
|
74
|
+
return unusedAddress[key];
|
|
64
75
|
});
|
|
65
76
|
}
|
|
66
|
-
|
|
77
|
+
/**
|
|
78
|
+
* Get used addresses.
|
|
79
|
+
*
|
|
80
|
+
* @param addressType Which branch to scan: external, change or both. Defaults to both.
|
|
81
|
+
* @param addressLimit Maximum number of address indexes to scan (per branch). Defaults to NUMBER_ADDRESS_LIMIT.
|
|
82
|
+
* @returns List of used addresses for the requested branch(es).
|
|
83
|
+
*/
|
|
84
|
+
getUsedAddresses(addressType = AddressSearchType.EXTERNAL_OR_CHANGE, addressLimit = exports.NUMBER_ADDRESS_LIMIT) {
|
|
67
85
|
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
-
|
|
86
|
+
const result = yield this.getUsedUnusedAddresses(addressType, addressLimit);
|
|
87
|
+
if (addressType === AddressSearchType.EXTERNAL) {
|
|
88
|
+
return result.usedAddresses.external;
|
|
89
|
+
}
|
|
90
|
+
if (addressType === AddressSearchType.CHANGE) {
|
|
91
|
+
return result.usedAddresses.change;
|
|
92
|
+
}
|
|
93
|
+
return [...result.usedAddresses.change, ...result.usedAddresses.external];
|
|
69
94
|
});
|
|
70
95
|
}
|
|
71
96
|
getAddresses(startingIndex = 0, numAddresses = 1, change = false) {
|
|
@@ -92,13 +117,35 @@ class YacoinBaseWalletProvider extends client_1.Wallet {
|
|
|
92
117
|
});
|
|
93
118
|
}
|
|
94
119
|
sendTransaction(options) {
|
|
120
|
+
var _a, _b;
|
|
95
121
|
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
-
|
|
122
|
+
const change = (_a = options.change) !== null && _a !== void 0 ? _a : false;
|
|
123
|
+
const addressLimit = (_b = options.addressLimit) !== null && _b !== void 0 ? _b : exports.NUMBER_ADDRESS_LIMIT;
|
|
124
|
+
return this._sendTransaction(this.sendOptionsToOutputs([options]), options.fee, change, addressLimit, options.inputs);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
sendTransactionFixedInputs(options) {
|
|
128
|
+
var _a, _b, _c;
|
|
129
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
const targets = this.sendOptionsToOutputs([options]);
|
|
131
|
+
const fixedUtxos = (_a = options.inputs) !== null && _a !== void 0 ? _a : [];
|
|
132
|
+
const change = (_b = options.change) !== null && _b !== void 0 ? _b : false;
|
|
133
|
+
const addressLimit = (_c = options.addressLimit) !== null && _c !== void 0 ? _c : exports.NUMBER_ADDRESS_LIMIT;
|
|
134
|
+
const { hex, fee } = yield this.buildTransaction(targets, options.fee, fixedUtxos, change, addressLimit);
|
|
135
|
+
const result = yield this.chainProvider.sendRawTransaction(`data=${hex}`);
|
|
136
|
+
if (result == 'There was an error. Check your console.') {
|
|
137
|
+
throw new Error("Cannot send transaction, there might some reasons:\n 1) It might be the fee is not enough, please try increasing the fee.\n 2) The wallet haven't updated latest balance info, please wait 10 seconds and try again.");
|
|
138
|
+
}
|
|
139
|
+
return (0, utils_2.normalizeTransactionObject)((0, utils_2.decodeRawTransaction)(hex, this._network), fee);
|
|
97
140
|
});
|
|
98
141
|
}
|
|
99
142
|
sendBatchTransaction(transactions) {
|
|
143
|
+
var _a, _b;
|
|
100
144
|
return __awaiter(this, void 0, void 0, function* () {
|
|
101
|
-
|
|
145
|
+
const first = transactions[0];
|
|
146
|
+
const change = (_a = first === null || first === void 0 ? void 0 : first.change) !== null && _a !== void 0 ? _a : false;
|
|
147
|
+
const addressLimit = (_b = first === null || first === void 0 ? void 0 : first.addressLimit) !== null && _b !== void 0 ? _b : exports.NUMBER_ADDRESS_LIMIT;
|
|
148
|
+
return [yield this._sendTransaction(this.sendOptionsToOutputs(transactions), undefined, change, addressLimit)];
|
|
102
149
|
});
|
|
103
150
|
}
|
|
104
151
|
sendSweepTransaction(externalChangeAddress, _asset, feePerByte) {
|
|
@@ -112,7 +159,21 @@ class YacoinBaseWalletProvider extends client_1.Wallet {
|
|
|
112
159
|
return __awaiter(this, void 0, void 0, function* () {
|
|
113
160
|
const txHash = typeof tx === 'string' ? tx : tx.hash;
|
|
114
161
|
const transaction = (yield this.chainProvider.getTransactionByHash(txHash))._raw;
|
|
115
|
-
const
|
|
162
|
+
const fixedUtxos = [];
|
|
163
|
+
for (const vin of transaction.vin) {
|
|
164
|
+
const txHex = yield this.chainProvider.getProvider().getRawTransactionByHash(vin.txid);
|
|
165
|
+
const txDecoded = (0, utils_2.decodeRawTransaction)(txHex, this._network);
|
|
166
|
+
const value = new types_1.BigNumber(txDecoded.vout[vin.vout].value).times(1e6).toNumber();
|
|
167
|
+
const address = txDecoded.vout[vin.vout].scriptPubKey.addresses[0];
|
|
168
|
+
const walletAddress = yield this.getWalletAddress(address);
|
|
169
|
+
fixedUtxos.push({
|
|
170
|
+
txid: vin.txid,
|
|
171
|
+
vout: vin.vout,
|
|
172
|
+
value,
|
|
173
|
+
address,
|
|
174
|
+
derivationPath: walletAddress.derivationPath,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
116
177
|
const lookupAddresses = transaction.vout.map((vout) => vout.scriptPubKey.addresses[0]);
|
|
117
178
|
const changeAddress = yield this.findAddress(lookupAddresses, true);
|
|
118
179
|
const changeOutput = transaction.vout.find((vout) => vout.scriptPubKey.addresses[0] === changeAddress.address);
|
|
@@ -125,8 +186,11 @@ class YacoinBaseWalletProvider extends client_1.Wallet {
|
|
|
125
186
|
address: output.scriptPubKey.addresses[0],
|
|
126
187
|
value: new types_1.BigNumber(output.value).times(1e6).toNumber(),
|
|
127
188
|
}));
|
|
128
|
-
const { hex, fee } = yield this.buildTransaction(transactions, newFeePerByte,
|
|
129
|
-
yield this.chainProvider.sendRawTransaction(`data=${hex}`);
|
|
189
|
+
const { hex, fee } = yield this.buildTransaction(transactions, newFeePerByte, fixedUtxos, true, exports.NUMBER_ADDRESS_LIMIT);
|
|
190
|
+
const result = yield this.chainProvider.sendRawTransaction(`data=${hex}`);
|
|
191
|
+
if (result == 'There was an error. Check your console.') {
|
|
192
|
+
throw new Error("Cannot send transaction, there might some reasons:\n 1) It might be the fee is not enough, please try increasing the fee.\n 2) The wallet haven't updated latest balance info, please wait 10 seconds and try again.");
|
|
193
|
+
}
|
|
130
194
|
return (0, utils_2.normalizeTransactionObject)((0, utils_2.decodeRawTransaction)(hex, this._network), fee);
|
|
131
195
|
});
|
|
132
196
|
}
|
|
@@ -143,9 +207,9 @@ class YacoinBaseWalletProvider extends client_1.Wallet {
|
|
|
143
207
|
return fees;
|
|
144
208
|
});
|
|
145
209
|
}
|
|
146
|
-
_sendTransaction(transactions, feePerByte) {
|
|
210
|
+
_sendTransaction(transactions, feePerByte, change = false, addressLimit = exports.NUMBER_ADDRESS_LIMIT, fixedUtxos = []) {
|
|
147
211
|
return __awaiter(this, void 0, void 0, function* () {
|
|
148
|
-
const { hex, fee } = yield this.buildTransaction(transactions, feePerByte);
|
|
212
|
+
const { hex, fee } = yield this.buildTransaction(transactions, feePerByte, fixedUtxos, change, addressLimit);
|
|
149
213
|
const result = yield this.chainProvider.sendRawTransaction(`data=${hex}`);
|
|
150
214
|
if (result == 'There was an error. Check your console.') {
|
|
151
215
|
throw new Error("Cannot send transaction, there might some reasons:\n 1) It might be the fee is not enough, please try increasing the fee.\n 2) The wallet haven't updated latest balance info, please wait 10 seconds and try again.");
|
|
@@ -153,11 +217,11 @@ class YacoinBaseWalletProvider extends client_1.Wallet {
|
|
|
153
217
|
return (0, utils_2.normalizeTransactionObject)((0, utils_2.decodeRawTransaction)(hex, this._network), fee);
|
|
154
218
|
});
|
|
155
219
|
}
|
|
156
|
-
findAddress(addresses, change = false) {
|
|
220
|
+
findAddress(addresses, change = false, addressLimit = exports.NUMBER_ADDRESS_LIMIT) {
|
|
157
221
|
return __awaiter(this, void 0, void 0, function* () {
|
|
158
222
|
// A maximum number of addresses to lookup after which it is deemed that the wallet does not contain this address
|
|
159
|
-
const maxAddresses =
|
|
160
|
-
const addressesPerCall =
|
|
223
|
+
const maxAddresses = addressLimit;
|
|
224
|
+
const addressesPerCall = exports.NUMBER_ADDRESS_LIMIT;
|
|
161
225
|
let index = 0;
|
|
162
226
|
while (index < maxAddresses) {
|
|
163
227
|
const walletAddresses = yield this.getAddresses(index, addressesPerCall, change);
|
|
@@ -200,26 +264,87 @@ class YacoinBaseWalletProvider extends client_1.Wallet {
|
|
|
200
264
|
return addressObject;
|
|
201
265
|
});
|
|
202
266
|
}
|
|
203
|
-
|
|
267
|
+
getUsedUnusedAddresses(addressType, addressLimit = exports.NUMBER_ADDRESS_LIMIT, gapLimit = 1, useCache = true) {
|
|
204
268
|
return __awaiter(this, void 0, void 0, function* () {
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
unusedAddressMap.external = externalAddress;
|
|
269
|
+
const cacheKey = `${addressType}_${addressLimit}_${gapLimit}`;
|
|
270
|
+
if (useCache) {
|
|
271
|
+
const cached = this._usedUnusedAddressesCache[cacheKey];
|
|
272
|
+
if (cached && Date.now() - cached.timestamp < USED_UNUSED_ADDRESSES_CACHE_TTL_MS) {
|
|
273
|
+
return cached.result;
|
|
274
|
+
}
|
|
212
275
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
276
|
+
const usedAddresses = {
|
|
277
|
+
change: [],
|
|
278
|
+
external: [],
|
|
279
|
+
};
|
|
280
|
+
const unusedAddressMap = {
|
|
281
|
+
change: null,
|
|
282
|
+
external: null,
|
|
283
|
+
};
|
|
284
|
+
const consecutiveUnusedCount = { change: 0, external: 0 };
|
|
285
|
+
let numAddressAlreadyGet = 0;
|
|
286
|
+
const numAddressPerCall = 100;
|
|
287
|
+
let addressIndex = 0;
|
|
288
|
+
/* eslint-disable no-unmodified-loop-condition */
|
|
289
|
+
while (((addressType === AddressSearchType.EXTERNAL_OR_CHANGE &&
|
|
290
|
+
(consecutiveUnusedCount.change < gapLimit || consecutiveUnusedCount.external < gapLimit)) ||
|
|
291
|
+
(addressType === AddressSearchType.EXTERNAL && consecutiveUnusedCount.external < gapLimit) ||
|
|
292
|
+
(addressType === AddressSearchType.CHANGE && consecutiveUnusedCount.change < gapLimit)) &&
|
|
293
|
+
numAddressAlreadyGet < addressLimit) {
|
|
294
|
+
/* eslint-enable no-unmodified-loop-condition */
|
|
295
|
+
let addrList = [];
|
|
296
|
+
let changeAddresses = [];
|
|
297
|
+
let externalAddresses = [];
|
|
298
|
+
let maxBatchSize = 0;
|
|
299
|
+
if ((addressType === AddressSearchType.EXTERNAL_OR_CHANGE || addressType === AddressSearchType.CHANGE) &&
|
|
300
|
+
consecutiveUnusedCount.change < gapLimit &&
|
|
301
|
+
numAddressAlreadyGet < addressLimit) {
|
|
302
|
+
const remainingLimit = addressLimit - numAddressAlreadyGet;
|
|
303
|
+
const batchSize = Math.min(numAddressPerCall, remainingLimit);
|
|
304
|
+
changeAddresses = yield this.getAddresses(addressIndex, batchSize, true);
|
|
305
|
+
addrList = addrList.concat(changeAddresses);
|
|
306
|
+
maxBatchSize = Math.max(maxBatchSize, batchSize);
|
|
307
|
+
}
|
|
308
|
+
if ((addressType === AddressSearchType.EXTERNAL_OR_CHANGE || addressType === AddressSearchType.EXTERNAL) &&
|
|
309
|
+
consecutiveUnusedCount.external < gapLimit &&
|
|
310
|
+
numAddressAlreadyGet < addressLimit) {
|
|
311
|
+
const remainingLimit = addressLimit - numAddressAlreadyGet;
|
|
312
|
+
const batchSize = Math.min(numAddressPerCall, remainingLimit);
|
|
313
|
+
externalAddresses = yield this.getAddresses(addressIndex, batchSize, false);
|
|
314
|
+
addrList = addrList.concat(externalAddresses);
|
|
315
|
+
maxBatchSize = Math.max(maxBatchSize, batchSize);
|
|
316
|
+
}
|
|
317
|
+
if (addrList.length === 0) {
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
const transactionCounts = yield this.chainProvider.getProvider().getAddressTransactionCounts(addrList);
|
|
321
|
+
for (const address of addrList) {
|
|
322
|
+
const isUsed = transactionCounts[address.toString()] > 0;
|
|
323
|
+
const isChangeAddress = changeAddresses.some((a) => address.toString() === a.toString());
|
|
324
|
+
const key = isChangeAddress ? 'change' : 'external';
|
|
325
|
+
if (isUsed) {
|
|
326
|
+
usedAddresses[key].push(address);
|
|
327
|
+
consecutiveUnusedCount[key] = 0;
|
|
328
|
+
unusedAddressMap[key] = null;
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
consecutiveUnusedCount[key]++;
|
|
332
|
+
if (!unusedAddressMap[key]) {
|
|
333
|
+
unusedAddressMap[key] = address;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
numAddressAlreadyGet += maxBatchSize;
|
|
338
|
+
addressIndex += maxBatchSize;
|
|
218
339
|
}
|
|
219
|
-
|
|
340
|
+
const result = {
|
|
220
341
|
usedAddresses,
|
|
221
342
|
unusedAddress: unusedAddressMap,
|
|
222
343
|
};
|
|
344
|
+
if (useCache) {
|
|
345
|
+
this._usedUnusedAddressesCache[cacheKey] = { result, timestamp: Date.now() };
|
|
346
|
+
}
|
|
347
|
+
return result;
|
|
223
348
|
});
|
|
224
349
|
}
|
|
225
350
|
withCachedUtxos(func) {
|
|
@@ -238,40 +363,47 @@ class YacoinBaseWalletProvider extends client_1.Wallet {
|
|
|
238
363
|
return result;
|
|
239
364
|
});
|
|
240
365
|
}
|
|
366
|
+
getTotalFeeFixedInputs(opts, max) {
|
|
367
|
+
var _a, _b, _c;
|
|
368
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
369
|
+
const targets = this.sendOptionsToOutputs([opts]);
|
|
370
|
+
const addressLimit = (_a = opts.addressLimit) !== null && _a !== void 0 ? _a : exports.NUMBER_ADDRESS_LIMIT;
|
|
371
|
+
const useChangeUtxos = (_b = opts.change) !== null && _b !== void 0 ? _b : false;
|
|
372
|
+
const { fee } = yield this.getInputsForAmount(targets.filter((t) => !t.value), opts.fee, (_c = opts.inputs) !== null && _c !== void 0 ? _c : [], max, addressLimit, useChangeUtxos);
|
|
373
|
+
return fee;
|
|
374
|
+
});
|
|
375
|
+
}
|
|
241
376
|
getTotalFee(opts, max) {
|
|
377
|
+
var _a, _b, _c, _d;
|
|
242
378
|
return __awaiter(this, void 0, void 0, function* () {
|
|
243
379
|
const targets = this.sendOptionsToOutputs([opts]);
|
|
244
380
|
if (!max) {
|
|
245
|
-
|
|
246
|
-
const { fee } = yield this.getInputsForAmount(targets, opts.fee);
|
|
381
|
+
const { fee } = yield this.getInputsForAmount(targets, opts.fee, [], false, (_a = opts.addressLimit) !== null && _a !== void 0 ? _a : exports.NUMBER_ADDRESS_LIMIT, (_b = opts.change) !== null && _b !== void 0 ? _b : false);
|
|
247
382
|
return fee;
|
|
248
383
|
}
|
|
249
384
|
else {
|
|
250
|
-
const { fee } = yield this.getInputsForAmount(targets.filter((t) => !t.value), opts.fee, [], true);
|
|
385
|
+
const { fee } = yield this.getInputsForAmount(targets.filter((t) => !t.value), opts.fee, [], true, (_c = opts.addressLimit) !== null && _c !== void 0 ? _c : exports.NUMBER_ADDRESS_LIMIT, (_d = opts.change) !== null && _d !== void 0 ? _d : false);
|
|
251
386
|
return fee;
|
|
252
387
|
}
|
|
253
388
|
});
|
|
254
389
|
}
|
|
255
|
-
getInputsForAmount(_targets, feePerByte,
|
|
390
|
+
getInputsForAmount(_targets, feePerByte, fixedUtxos = [], sweep = false, addressLimit = exports.NUMBER_ADDRESS_LIMIT, change = false) {
|
|
256
391
|
return __awaiter(this, void 0, void 0, function* () {
|
|
257
392
|
const tokenTransferOutput = _targets.find((target) => target.tokenName !== undefined && target.tokenScriptType === types_1.TokenScriptType.transfer);
|
|
258
393
|
const feePerBytePromise = this.chainProvider.getProvider().getFeePerByte();
|
|
259
394
|
let utxos = [];
|
|
260
395
|
let tokenUtxos = [];
|
|
261
|
-
const
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
const address = tx.vout[input.vout].scriptPubKey.addresses[0];
|
|
269
|
-
const walletAddress = yield this.getWalletAddress(address);
|
|
270
|
-
const utxo = Object.assign(Object.assign({}, input), { value, address, derivationPath: walletAddress.derivationPath });
|
|
271
|
-
fixedUtxos.push(utxo);
|
|
396
|
+
const addressType = change ? AddressSearchType.EXTERNAL_OR_CHANGE : AddressSearchType.EXTERNAL;
|
|
397
|
+
const addresses = yield this.getUsedAddresses(addressType, addressLimit);
|
|
398
|
+
const enrichedFixedUtxos = yield Promise.all(fixedUtxos.map((utxo) => __awaiter(this, void 0, void 0, function* () {
|
|
399
|
+
let derivationPath = utxo.derivationPath;
|
|
400
|
+
if (derivationPath === undefined) {
|
|
401
|
+
const walletAddress = yield this.getWalletAddress(utxo.address);
|
|
402
|
+
derivationPath = walletAddress.derivationPath;
|
|
272
403
|
}
|
|
273
|
-
|
|
274
|
-
|
|
404
|
+
return Object.assign(Object.assign({}, utxo), { derivationPath });
|
|
405
|
+
})));
|
|
406
|
+
if (!sweep || enrichedFixedUtxos.length === 0) {
|
|
275
407
|
const _utxos = yield this.chainProvider.getProvider().getUnspentTransactions(addresses);
|
|
276
408
|
utxos.push(..._utxos.map((utxo) => {
|
|
277
409
|
const addr = addresses.find((a) => a.address === utxo.address);
|
|
@@ -279,7 +411,7 @@ class YacoinBaseWalletProvider extends client_1.Wallet {
|
|
|
279
411
|
}));
|
|
280
412
|
}
|
|
281
413
|
else {
|
|
282
|
-
utxos =
|
|
414
|
+
utxos = enrichedFixedUtxos;
|
|
283
415
|
}
|
|
284
416
|
if (tokenTransferOutput) {
|
|
285
417
|
const isNFTOutput = tokenTransferOutput.tokenName.indexOf('#') !== -1;
|