@vultisig/core-chain 2.15.0 → 2.15.2
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 +16 -0
- package/dist/chains/cosmos/gas.d.ts +13 -0
- package/dist/chains/cosmos/gas.d.ts.map +1 -1
- package/dist/chains/cosmos/gas.js +103 -0
- package/dist/chains/cosmos/gas.js.map +1 -1
- package/dist/chains/utxo/client/getUtxoAddressInfo.d.ts +4 -3
- package/dist/chains/utxo/client/getUtxoAddressInfo.d.ts.map +1 -1
- package/dist/chains/utxo/client/getUtxoAddressInfo.js +30 -3
- package/dist/chains/utxo/client/getUtxoAddressInfo.js.map +1 -1
- package/dist/chains/utxo/fee/byteFee.d.ts.map +1 -1
- package/dist/chains/utxo/fee/byteFee.js +4 -3
- package/dist/chains/utxo/fee/byteFee.js.map +1 -1
- package/dist/chains/utxo/fee/zip317.d.ts +30 -0
- package/dist/chains/utxo/fee/zip317.d.ts.map +1 -0
- package/dist/chains/utxo/fee/zip317.js +36 -0
- package/dist/chains/utxo/fee/zip317.js.map +1 -0
- package/dist/chains/utxo/tx/getUtxos.d.ts.map +1 -1
- package/dist/chains/utxo/tx/getUtxos.js +1 -1
- package/dist/chains/utxo/tx/getUtxos.js.map +1 -1
- package/dist/chains/utxo/zcashBranchId.d.ts +6 -0
- package/dist/chains/utxo/zcashBranchId.d.ts.map +1 -0
- package/dist/chains/utxo/zcashBranchId.js +83 -0
- package/dist/chains/utxo/zcashBranchId.js.map +1 -0
- package/package.json +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @vultisig/core-chain
|
|
2
2
|
|
|
3
|
+
## 2.15.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#716](https://github.com/vultisig/vultisig-sdk/pull/716) [`3f622f6`](https://github.com/vultisig/vultisig-sdk/commit/3f622f631089d0e33eb879be3407401887ebf0c8) Thanks [@realpaaao](https://github.com/realpaaao)! - Add a canonical ZIP-317 conventional-fee module to core-chain and floor the Zcash send-builder fee at 5,000 zats per logical action, so low fee rates can no longer produce transactions the network rejects with "tx unpaid action limit exceeded".
|
|
8
|
+
|
|
9
|
+
## 2.15.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#709](https://github.com/vultisig/vultisig-sdk/pull/709) [`de621f3`](https://github.com/vultisig/vultisig-sdk/commit/de621f3fd2a8c1ca64e73f6fe64afb7d77fb3e43) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Resolve Cosmos fee amounts from live node min gas prices when available, keeping the existing static amounts as safe floors.
|
|
14
|
+
|
|
15
|
+
- [#712](https://github.com/vultisig/vultisig-sdk/pull/712) [`9439a61`](https://github.com/vultisig/vultisig-sdk/commit/9439a6194abf3533ad06aa84847c81b2af7fe8df) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Filter Blockchair UTXO selection to confirmed spendable outputs and request an explicit address-info UTXO limit.
|
|
16
|
+
|
|
17
|
+
- [#714](https://github.com/vultisig/vultisig-sdk/pull/714) [`625fb42`](https://github.com/vultisig/vultisig-sdk/commit/625fb4205f265587f66f447b4059543756ef1095) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Fetch the live Zcash ZIP-243 consensus branch ID for SDK signing and fail loudly instead of using a stale compiled fallback.
|
|
18
|
+
|
|
3
19
|
## 2.15.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
import { IbcEnabledCosmosChain } from '../../Chain.js';
|
|
2
|
+
import type { CoinKey } from '../../coin/Coin.js';
|
|
2
3
|
export declare const cosmosGasRecord: Record<IbcEnabledCosmosChain, bigint>;
|
|
4
|
+
type FetchOpts = {
|
|
5
|
+
fetchImpl?: typeof fetch;
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
};
|
|
8
|
+
type ParsedDecimal = {
|
|
9
|
+
numerator: bigint;
|
|
10
|
+
denominator: bigint;
|
|
11
|
+
};
|
|
12
|
+
export declare const getFeeAmountFromGasPrice: (gasLimit: bigint, gasPrice: ParsedDecimal) => bigint;
|
|
13
|
+
export declare const getMinGasPriceForDenom: (minimumGasPrice: string, targetDenom: string) => ParsedDecimal | undefined;
|
|
14
|
+
export declare const getCosmosFeeAmount: (coin: CoinKey<IbcEnabledCosmosChain>, opts?: FetchOpts) => Promise<bigint>;
|
|
15
|
+
export {};
|
|
3
16
|
//# sourceMappingURL=gas.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/cosmos/gas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,qBAAqB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"gas.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/cosmos/gas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAO9C,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CASjE,CAAA;AAED,KAAK,SAAS,GAAG;IACf,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,CAAA;AAMD,KAAK,aAAa,GAAG;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AA2BD,eAAO,MAAM,wBAAwB,GAAI,UAAU,MAAM,EAAE,UAAU,aAAa,KAAG,MAIpF,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,iBAAiB,MAAM,EAAE,aAAa,MAAM,KAAG,aAAa,GAAG,SAYrG,CAAA;AAyDD,eAAO,MAAM,kBAAkB,GAC7B,MAAM,OAAO,CAAC,qBAAqB,CAAC,EACpC,OAAM,SAAc,KACnB,OAAO,CAAC,MAAM,CAehB,CAAA"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { Chain } from '../../Chain.js';
|
|
2
|
+
import { cosmosFeeCoinDenom } from './cosmosFeeCoinDenom.js';
|
|
3
|
+
import { getCosmosGasLimit } from './cosmosGasLimitRecord.js';
|
|
4
|
+
import { cosmosRpcUrl } from './cosmosRpcUrl.js';
|
|
2
5
|
const defaultGas = 7500n;
|
|
3
6
|
export const cosmosGasRecord = {
|
|
4
7
|
[Chain.Cosmos]: defaultGas,
|
|
@@ -10,4 +13,104 @@ export const cosmosGasRecord = {
|
|
|
10
13
|
[Chain.Noble]: 30000n,
|
|
11
14
|
[Chain.Akash]: 200000n,
|
|
12
15
|
};
|
|
16
|
+
const minGasPriceConfigPath = '/cosmos/base/node/v1beta1/config';
|
|
17
|
+
const minGasPriceFetchTimeoutMs = 3_000;
|
|
18
|
+
const maxLiveFeeMultiplier = 10n;
|
|
19
|
+
const parseDecimal = (value) => {
|
|
20
|
+
if (!/^\d+(?:\.\d+)?$/.test(value))
|
|
21
|
+
return undefined;
|
|
22
|
+
const [whole, fraction = ''] = value.split('.');
|
|
23
|
+
const denominator = 10n ** BigInt(fraction.length);
|
|
24
|
+
const numerator = BigInt(`${whole}${fraction}`);
|
|
25
|
+
return { numerator, denominator };
|
|
26
|
+
};
|
|
27
|
+
const parseMinGasPriceEntry = (entry) => {
|
|
28
|
+
const match = entry.trim().match(/^(\d+(?:\.\d+)?)([a-zA-Z][a-zA-Z0-9/._:-]*)$/);
|
|
29
|
+
if (!match)
|
|
30
|
+
return undefined;
|
|
31
|
+
const [, amount, denom] = match;
|
|
32
|
+
const decimal = parseDecimal(amount);
|
|
33
|
+
if (!decimal)
|
|
34
|
+
return undefined;
|
|
35
|
+
return { ...decimal, denom };
|
|
36
|
+
};
|
|
37
|
+
export const getFeeAmountFromGasPrice = (gasLimit, gasPrice) => {
|
|
38
|
+
const total = gasLimit * gasPrice.numerator;
|
|
39
|
+
return (total + gasPrice.denominator - 1n) / gasPrice.denominator;
|
|
40
|
+
};
|
|
41
|
+
export const getMinGasPriceForDenom = (minimumGasPrice, targetDenom) => {
|
|
42
|
+
for (const entry of minimumGasPrice.split(',')) {
|
|
43
|
+
const parsed = parseMinGasPriceEntry(entry);
|
|
44
|
+
if (parsed?.denom.toLowerCase() === targetDenom.toLowerCase()) {
|
|
45
|
+
return {
|
|
46
|
+
numerator: parsed.numerator,
|
|
47
|
+
denominator: parsed.denominator,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
};
|
|
53
|
+
const getTimeoutController = (signal) => {
|
|
54
|
+
const controller = new AbortController();
|
|
55
|
+
const abort = () => controller.abort();
|
|
56
|
+
if (signal?.aborted) {
|
|
57
|
+
abort();
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
controller,
|
|
64
|
+
cleanup: () => {
|
|
65
|
+
signal?.removeEventListener('abort', abort);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
const fetchMinGasPrice = async (chain, { fetchImpl = fetch, signal } = {}) => {
|
|
70
|
+
const timeoutController = getTimeoutController(signal);
|
|
71
|
+
const timeout = setTimeout(() => timeoutController.controller.abort(), minGasPriceFetchTimeoutMs);
|
|
72
|
+
const timeoutPromise = new Promise((_resolve, reject) => {
|
|
73
|
+
const rejectTimeout = () => reject(new Error(`Cosmos min gas config request timed out after ${minGasPriceFetchTimeoutMs}ms`));
|
|
74
|
+
if (timeoutController.controller.signal.aborted) {
|
|
75
|
+
rejectTimeout();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
timeoutController.controller.signal.addEventListener('abort', rejectTimeout, { once: true });
|
|
79
|
+
});
|
|
80
|
+
try {
|
|
81
|
+
return await Promise.race([
|
|
82
|
+
(async () => {
|
|
83
|
+
const response = await fetchImpl(`${cosmosRpcUrl[chain]}${minGasPriceConfigPath}`, {
|
|
84
|
+
signal: timeoutController.controller.signal,
|
|
85
|
+
});
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
throw new Error(`Cosmos ${chain} min gas config request failed: ${response.status}`);
|
|
88
|
+
}
|
|
89
|
+
const data = (await response.json());
|
|
90
|
+
return data.minimum_gas_price ?? '';
|
|
91
|
+
})(),
|
|
92
|
+
timeoutPromise,
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
clearTimeout(timeout);
|
|
97
|
+
timeoutController.cleanup();
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
export const getCosmosFeeAmount = async (coin, opts = {}) => {
|
|
101
|
+
const floor = cosmosGasRecord[coin.chain];
|
|
102
|
+
try {
|
|
103
|
+
const minimumGasPrice = await fetchMinGasPrice(coin.chain, opts);
|
|
104
|
+
const gasPrice = getMinGasPriceForDenom(minimumGasPrice, cosmosFeeCoinDenom[coin.chain]);
|
|
105
|
+
if (!gasPrice)
|
|
106
|
+
return floor;
|
|
107
|
+
const computedFee = getFeeAmountFromGasPrice(getCosmosGasLimit(coin), gasPrice);
|
|
108
|
+
if (computedFee > floor * maxLiveFeeMultiplier)
|
|
109
|
+
return floor;
|
|
110
|
+
return computedFee > floor ? computedFee : floor;
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return floor;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
13
116
|
//# sourceMappingURL=gas.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/cosmos/gas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAyB,MAAM,aAAa,CAAA;AAE1D,MAAM,UAAU,GAAG,KAAK,CAAA;AAExB,MAAM,CAAC,MAAM,eAAe,GAA0C;IACpE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU;IAC1B,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK;IACtB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU;IAC1B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,UAAU;IACzB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,iBAAiB;IAC/B,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,UAAU;IAChC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM;IACrB,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,OAAO;CACvB,CAAA"}
|
|
1
|
+
{"version":3,"file":"gas.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/cosmos/gas.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,9 @@ import { ChainAccount } from '@vultisig/core-chain/ChainAccount';
|
|
|
3
3
|
type BlockchairAddressResponse = {
|
|
4
4
|
data: {
|
|
5
5
|
[address: string]: {
|
|
6
|
-
address
|
|
6
|
+
address?: {
|
|
7
7
|
balance: number;
|
|
8
|
+
unspent_output_count?: number;
|
|
8
9
|
};
|
|
9
10
|
utxo: {
|
|
10
11
|
block_id: number;
|
|
@@ -15,11 +16,11 @@ type BlockchairAddressResponse = {
|
|
|
15
16
|
recipient: string;
|
|
16
17
|
script_hex: string;
|
|
17
18
|
is_from_coinbase: boolean;
|
|
18
|
-
is_spendable
|
|
19
|
+
is_spendable?: boolean;
|
|
19
20
|
}[];
|
|
20
21
|
};
|
|
21
22
|
};
|
|
22
23
|
};
|
|
23
|
-
export declare const getUtxoAddressInfo: (
|
|
24
|
+
export declare const getUtxoAddressInfo: (account: ChainAccount<UtxoChain>) => Promise<BlockchairAddressResponse>;
|
|
24
25
|
export {};
|
|
25
26
|
//# sourceMappingURL=getUtxoAddressInfo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getUtxoAddressInfo.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/client/getUtxoAddressInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;AAKhE,KAAK,yBAAyB,GAAG;IAC/B,IAAI,EAAE;QACJ,CAAC,OAAO,EAAE,MAAM,GAAG;YACjB,OAAO,EAAE;
|
|
1
|
+
{"version":3,"file":"getUtxoAddressInfo.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/client/getUtxoAddressInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;AAKhE,KAAK,yBAAyB,GAAG;IAC/B,IAAI,EAAE;QACJ,CAAC,OAAO,EAAE,MAAM,GAAG;YACjB,OAAO,CAAC,EAAE;gBACR,OAAO,EAAE,MAAM,CAAA;gBACf,oBAAoB,CAAC,EAAE,MAAM,CAAA;aAC9B,CAAA;YACD,IAAI,EAAE;gBACJ,QAAQ,EAAE,MAAM,CAAA;gBAChB,gBAAgB,EAAE,MAAM,CAAA;gBACxB,KAAK,EAAE,MAAM,CAAA;gBACb,KAAK,EAAE,MAAM,CAAA;gBACb,SAAS,EAAE,MAAM,CAAA;gBACjB,SAAS,EAAE,MAAM,CAAA;gBACjB,UAAU,EAAE,MAAM,CAAA;gBAClB,gBAAgB,EAAE,OAAO,CAAA;gBACzB,YAAY,CAAC,EAAE,OAAO,CAAA;aACvB,EAAE,CAAA;SACJ,CAAA;KACF,CAAA;CACF,CAAA;AAYD,eAAO,MAAM,kBAAkB,GAAU,SAAS,YAAY,CAAC,SAAS,CAAC,uCAsCxE,CAAA"}
|
|
@@ -1,7 +1,34 @@
|
|
|
1
1
|
import { queryUrl } from '@vultisig/lib-utils/query/queryUrl';
|
|
2
2
|
import { getBlockchairBaseUrl } from './getBlockchairBaseUrl.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
const blockchairUtxoPageSize = 1_000;
|
|
4
|
+
const getAddressInfoUrl = ({ address, chain, offset, }) => `${getBlockchairBaseUrl(chain)}/dashboards/address/${address}?limit=${blockchairUtxoPageSize}&offset=${offset}`;
|
|
5
|
+
export const getUtxoAddressInfo = async (account) => {
|
|
6
|
+
const utxo = [];
|
|
7
|
+
let firstPage;
|
|
8
|
+
let expectedUtxoCount;
|
|
9
|
+
for (let offset = 0;; offset += blockchairUtxoPageSize) {
|
|
10
|
+
const page = await queryUrl(getAddressInfoUrl({ ...account, offset }));
|
|
11
|
+
firstPage ??= page;
|
|
12
|
+
const entry = page.data[account.address];
|
|
13
|
+
const pageUtxos = entry?.utxo ?? [];
|
|
14
|
+
utxo.push(...pageUtxos);
|
|
15
|
+
expectedUtxoCount ??= entry?.address?.unspent_output_count;
|
|
16
|
+
const hasAllReportedUtxos = expectedUtxoCount !== undefined && utxo.length >= expectedUtxoCount;
|
|
17
|
+
const hasNoMorePages = expectedUtxoCount === undefined && pageUtxos.length < blockchairUtxoPageSize;
|
|
18
|
+
if (expectedUtxoCount !== undefined && pageUtxos.length === 0 && utxo.length < expectedUtxoCount) {
|
|
19
|
+
throw new Error(`Blockchair returned ${utxo.length} UTXOs for ${account.chain}:${account.address}, expected ${expectedUtxoCount}`);
|
|
20
|
+
}
|
|
21
|
+
if (hasAllReportedUtxos || pageUtxos.length === 0 || hasNoMorePages) {
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!firstPage) {
|
|
26
|
+
throw new Error(`Failed to fetch UTXO address info for ${account.chain}:${account.address}`);
|
|
27
|
+
}
|
|
28
|
+
const firstEntry = firstPage.data[account.address];
|
|
29
|
+
if (firstEntry) {
|
|
30
|
+
firstEntry.utxo = utxo;
|
|
31
|
+
}
|
|
32
|
+
return firstPage;
|
|
6
33
|
};
|
|
7
34
|
//# sourceMappingURL=getUtxoAddressInfo.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getUtxoAddressInfo.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/client/getUtxoAddressInfo.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"getUtxoAddressInfo.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/client/getUtxoAddressInfo.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAA;AAE7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAwB7D,MAAM,sBAAsB,GAAG,KAAK,CAAA;AAEpC,MAAM,iBAAiB,GAAG,CAAC,EACzB,OAAO,EACP,KAAK,EACL,MAAM,GAGP,EAAE,EAAE,CAAC,GAAG,oBAAoB,CAAC,KAAK,CAAC,uBAAuB,OAAO,UAAU,sBAAsB,WAAW,MAAM,EAAE,CAAA;AAErH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,OAAgC,EAAE,EAAE;IAC3E,MAAM,IAAI,GAAsD,EAAE,CAAA;IAClE,IAAI,SAAgD,CAAA;IACpD,IAAI,iBAAqC,CAAA;IAEzC,KAAK,IAAI,MAAM,GAAG,CAAC,GAAI,MAAM,IAAI,sBAAsB,EAAE,CAAC;QACxD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAA4B,iBAAiB,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;QACjG,SAAS,KAAK,IAAI,CAAA;QAElB,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACxC,MAAM,SAAS,GAAG,KAAK,EAAE,IAAI,IAAI,EAAE,CAAA;QACnC,IAAI,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAA;QAEvB,iBAAiB,KAAK,KAAK,EAAE,OAAO,EAAE,oBAAoB,CAAA;QAC1D,MAAM,mBAAmB,GAAG,iBAAiB,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,IAAI,iBAAiB,CAAA;QAC/F,MAAM,cAAc,GAAG,iBAAiB,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,sBAAsB,CAAA;QAEnG,IAAI,iBAAiB,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;YACjG,MAAM,IAAI,KAAK,CACb,uBAAuB,IAAI,CAAC,MAAM,cAAc,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,cAAc,iBAAiB,EAAE,CAClH,CAAA;QACH,CAAC;QAED,IAAI,mBAAmB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,cAAc,EAAE,CAAC;YACpE,MAAK;QACP,CAAC;IACH,CAAC;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,yCAAyC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;IAC9F,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAClD,IAAI,UAAU,EAAE,CAAC;QACf,UAAU,CAAC,IAAI,GAAG,IAAI,CAAA;IACxB,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"byteFee.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/fee/byteFee.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAKtD,eAAO,MAAM,cAAc,GAAU,OAAO,SAAS,
|
|
1
|
+
{"version":3,"file":"byteFee.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/fee/byteFee.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAKtD,eAAO,MAAM,cAAc,GAAU,OAAO,SAAS,oBAoBpD,CAAA"}
|
|
@@ -2,9 +2,10 @@ import { UtxoChain } from '@vultisig/core-chain/Chain';
|
|
|
2
2
|
import { getUtxoStats } from '@vultisig/core-chain/chains/utxo/client/getUtxoStats';
|
|
3
3
|
const byteFeeMultiplier = (value) => (value * 25n) / 10n;
|
|
4
4
|
export const getUtxoByteFee = async (chain) => {
|
|
5
|
-
// ZIP-317 requires
|
|
6
|
-
//
|
|
7
|
-
//
|
|
5
|
+
// ZIP-317 requires 5,000 zats per logical action (10,000 zat floor) — see
|
|
6
|
+
// ./zip317 for the conventional-fee formula. Blockchair reports ~1 sat/byte
|
|
7
|
+
// which is below that floor; 100 sat/byte clears it for any realistic tx
|
|
8
|
+
// shape (a P2PKH input pays 14,800 zats vs 5,000 required per action).
|
|
8
9
|
if (chain === UtxoChain.Zcash)
|
|
9
10
|
return 100n;
|
|
10
11
|
const { data: { suggested_transaction_fee_per_byte_sat }, } = await getUtxoStats(chain);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"byteFee.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/fee/byteFee.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,sDAAsD,CAAA;AAEnF,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAA;AAEhE,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,KAAgB,EAAE,EAAE;IACvD,yEAAyE;IACzE,
|
|
1
|
+
{"version":3,"file":"byteFee.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/fee/byteFee.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,sDAAsD,CAAA;AAEnF,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAA;AAEhE,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,KAAgB,EAAE,EAAE;IACvD,0EAA0E;IAC1E,4EAA4E;IAC5E,yEAAyE;IACzE,uEAAuE;IACvE,IAAI,KAAK,KAAK,SAAS,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IAE1C,MAAM,EACJ,IAAI,EAAE,EAAE,sCAAsC,EAAE,GACjD,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAA;IAE7B,MAAM,IAAI,GAAG,MAAM,CAAC,sCAAsC,CAAC,CAAA;IAE3D,IAAI,KAAK,KAAK,SAAS,CAAC,QAAQ,EAAE,CAAC;QACjC,iIAAiI;QACjI,+GAA+G;QAC/G,OAAO,IAAI,GAAG,GAAG,CAAA;IACnB,CAAC;IAED,OAAO,iBAAiB,CAAC,MAAM,CAAC,sCAAsC,CAAC,CAAC,CAAA;AAC1E,CAAC,CAAA"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZIP-317 conventional fee for a transparent-only Zcash transaction.
|
|
3
|
+
* Nodes relay zero "unpaid actions" by default, so any tx paying less is
|
|
4
|
+
* rejected at broadcast with "tx unpaid action limit exceeded".
|
|
5
|
+
* Canonical implementation — consumers (extension dApp guard, SDK send
|
|
6
|
+
* builder) should derive their floors from here.
|
|
7
|
+
* https://zips.z.cash/zip-0317
|
|
8
|
+
*/
|
|
9
|
+
export declare const zcashMarginalFee = 5000n;
|
|
10
|
+
export declare const zcashGraceActions = 2n;
|
|
11
|
+
type CeilDivInput = {
|
|
12
|
+
value: bigint;
|
|
13
|
+
divisor: bigint;
|
|
14
|
+
};
|
|
15
|
+
/** Ceiling division for bigints: smallest n such that n * divisor >= value. */
|
|
16
|
+
export declare const ceilDiv: ({ value, divisor }: CeilDivInput) => bigint;
|
|
17
|
+
type GetZcashConventionalFeeInput = {
|
|
18
|
+
/** Transparent P2PKH inputs; sized at 148 bytes each per ZIP-317. */
|
|
19
|
+
inputCount: number;
|
|
20
|
+
/** Serialized size of each tx_out in bytes (value + script length + script). */
|
|
21
|
+
outputSizes: bigint[];
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Minimum fee the Zcash network relays for a transparent tx of the given
|
|
25
|
+
* shape: 5,000 zats per logical action with a two-action grace window, where
|
|
26
|
+
* logical actions = max(ceil(tx_in bytes / 150), ceil(tx_out bytes / 34)).
|
|
27
|
+
*/
|
|
28
|
+
export declare const getZcashConventionalFee: ({ inputCount, outputSizes }: GetZcashConventionalFeeInput) => bigint;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=zip317.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip317.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/fee/zip317.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,QAAQ,CAAA;AACrC,eAAO,MAAM,iBAAiB,KAAK,CAAA;AAMnC,KAAK,YAAY,GAAG;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,+EAA+E;AAC/E,eAAO,MAAM,OAAO,GAAI,oBAAoB,YAAY,KAAG,MAA0C,CAAA;AAErG,KAAK,4BAA4B,GAAG;IAClC,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAA;IAClB,gFAAgF;IAChF,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAAI,6BAA6B,4BAA4B,KAAG,MAYnG,CAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { bigIntMax } from '@vultisig/lib-utils/bigint/bigIntMax';
|
|
2
|
+
import { bigIntSum } from '@vultisig/lib-utils/bigint/bigIntSum';
|
|
3
|
+
/**
|
|
4
|
+
* ZIP-317 conventional fee for a transparent-only Zcash transaction.
|
|
5
|
+
* Nodes relay zero "unpaid actions" by default, so any tx paying less is
|
|
6
|
+
* rejected at broadcast with "tx unpaid action limit exceeded".
|
|
7
|
+
* Canonical implementation — consumers (extension dApp guard, SDK send
|
|
8
|
+
* builder) should derive their floors from here.
|
|
9
|
+
* https://zips.z.cash/zip-0317
|
|
10
|
+
*/
|
|
11
|
+
export const zcashMarginalFee = 5000n;
|
|
12
|
+
export const zcashGraceActions = 2n;
|
|
13
|
+
/** Serialized size of a signed transparent P2PKH input (ZIP-317 §3.1). */
|
|
14
|
+
const p2pkhInputSize = 148n;
|
|
15
|
+
const inputActionSize = 150n;
|
|
16
|
+
const outputActionSize = 34n;
|
|
17
|
+
/** Ceiling division for bigints: smallest n such that n * divisor >= value. */
|
|
18
|
+
export const ceilDiv = ({ value, divisor }) => (value + divisor - 1n) / divisor;
|
|
19
|
+
/**
|
|
20
|
+
* Minimum fee the Zcash network relays for a transparent tx of the given
|
|
21
|
+
* shape: 5,000 zats per logical action with a two-action grace window, where
|
|
22
|
+
* logical actions = max(ceil(tx_in bytes / 150), ceil(tx_out bytes / 34)).
|
|
23
|
+
*/
|
|
24
|
+
export const getZcashConventionalFee = ({ inputCount, outputSizes }) => {
|
|
25
|
+
const inputActions = ceilDiv({
|
|
26
|
+
value: BigInt(inputCount) * p2pkhInputSize,
|
|
27
|
+
divisor: inputActionSize,
|
|
28
|
+
});
|
|
29
|
+
const outputActions = ceilDiv({
|
|
30
|
+
value: bigIntSum(outputSizes),
|
|
31
|
+
divisor: outputActionSize,
|
|
32
|
+
});
|
|
33
|
+
const logicalActions = bigIntMax(inputActions, outputActions);
|
|
34
|
+
return zcashMarginalFee * bigIntMax(zcashGraceActions, logicalActions);
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=zip317.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zip317.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/fee/zip317.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAA;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAA;AAEhE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAA;AACrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAA;AACnC,0EAA0E;AAC1E,MAAM,cAAc,GAAG,IAAI,CAAA;AAC3B,MAAM,eAAe,GAAG,IAAI,CAAA;AAC5B,MAAM,gBAAgB,GAAG,GAAG,CAAA;AAO5B,+EAA+E;AAC/E,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAgB,EAAU,EAAE,CAAC,CAAC,KAAK,GAAG,OAAO,GAAG,EAAE,CAAC,GAAG,OAAO,CAAA;AASrG;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,EAAE,UAAU,EAAE,WAAW,EAAgC,EAAU,EAAE;IAC3G,MAAM,YAAY,GAAG,OAAO,CAAC;QAC3B,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,GAAG,cAAc;QAC1C,OAAO,EAAE,eAAe;KACzB,CAAC,CAAA;IACF,MAAM,aAAa,GAAG,OAAO,CAAC;QAC5B,KAAK,EAAE,SAAS,CAAC,WAAW,CAAC;QAC7B,OAAO,EAAE,gBAAgB;KAC1B,CAAC,CAAA;IACF,MAAM,cAAc,GAAG,SAAS,CAAC,YAAY,EAAE,aAAa,CAAC,CAAA;IAE7D,OAAO,gBAAgB,GAAG,SAAS,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAA;AACxE,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getUtxos.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/tx/getUtxos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,SAAS,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,eAAO,MAAM,QAAQ,GAAU,SAAS,YAAY,CAAC,SAAS,CAAC,KAAG,OAAO,CAAC,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"getUtxos.d.ts","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/tx/getUtxos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,SAAS,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAIpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,eAAO,MAAM,QAAQ,GAAU,SAAS,YAAY,CAAC,SAAS,CAAC,KAAG,OAAO,CAAC,cAAc,EAAE,CAkBzF,CAAA"}
|
|
@@ -9,7 +9,7 @@ export const getUtxos = async (account) => {
|
|
|
9
9
|
const { data } = await getUtxoAddressInfo(account);
|
|
10
10
|
const { utxo } = data[account.address];
|
|
11
11
|
return utxo
|
|
12
|
-
.filter(({ value }) => value > minUtxo[account.chain])
|
|
12
|
+
.filter(({ block_id, is_spendable, value }) => value > minUtxo[account.chain] && is_spendable !== false && block_id > 0)
|
|
13
13
|
.map(({ transaction_hash, value, index }) => ({
|
|
14
14
|
hash: transaction_hash,
|
|
15
15
|
amount: BigInt(value),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getUtxos.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/tx/getUtxos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAa,MAAM,gBAAgB,CAAA;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAKpC,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAAE,OAAgC,EAA6B,EAAE;IAC5F,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;QACjC,OAAO,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IACtC,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAElD,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAEtC,OAAO,IAAI;SACR,MAAM,
|
|
1
|
+
{"version":3,"file":"getUtxos.js","sourceRoot":"","sources":["../../../../../../../packages/core/chain/chains/utxo/tx/getUtxos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAa,MAAM,gBAAgB,CAAA;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAKpC,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAAE,OAAgC,EAA6B,EAAE;IAC5F,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;QACjC,OAAO,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IACtC,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAElD,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAEtC,OAAO,IAAI;SACR,MAAM,CACL,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,YAAY,KAAK,KAAK,IAAI,QAAQ,GAAG,CAAC,CAChH;SACA,GAAG,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAC5C,IAAI,EAAE,gBAAgB;QACtB,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC;QACrB,KAAK;KACN,CAAC,CAAC,CAAA;AACP,CAAC,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const zcashBranchIdToWalletCoreHex: (bigEndianHex: string) => string;
|
|
2
|
+
export declare const zcashBranchIdToNumber: (bigEndianHex: string) => number;
|
|
3
|
+
export declare const getZcashBranchIdHex: () => Promise<string>;
|
|
4
|
+
export declare const getZcashBranchId: () => Promise<number>;
|
|
5
|
+
export declare const resetZcashBranchIdCacheForTests: () => void;
|
|
6
|
+
//# sourceMappingURL=zcashBranchId.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zcashBranchId.d.ts","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/utxo/zcashBranchId.ts"],"names":[],"mappings":"AAkCA,eAAO,MAAM,4BAA4B,GAAI,cAAc,MAAM,KAAG,MAGnE,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,cAAc,MAAM,KAAG,MACP,CAAA;AAyCtD,eAAO,MAAM,mBAAmB,QAAa,OAAO,CAAC,MAAM,CAqB1D,CAAA;AAED,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,MAAM,CAIvD,CAAA;AAED,eAAO,MAAM,+BAA+B,YAG3C,CAAA"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { rootApiUrl } from '@vultisig/core-config';
|
|
2
|
+
import { queryUrl } from '@vultisig/lib-utils/query/queryUrl';
|
|
3
|
+
const cacheTtlMs = 60 * 60 * 1000;
|
|
4
|
+
const rpcTimeoutMs = 10_000;
|
|
5
|
+
const zcashRpcUrl = `${rootApiUrl}/zcash`;
|
|
6
|
+
let cache;
|
|
7
|
+
let inFlight;
|
|
8
|
+
const assertFourByteHex = (hex) => {
|
|
9
|
+
if (!/^[0-9a-fA-F]{8}$/.test(hex)) {
|
|
10
|
+
throw new Error(`Invalid Zcash consensus branch id: expected 4-byte hex, received "${hex}"`);
|
|
11
|
+
}
|
|
12
|
+
return hex.toLowerCase();
|
|
13
|
+
};
|
|
14
|
+
export const zcashBranchIdToWalletCoreHex = (bigEndianHex) => {
|
|
15
|
+
const hex = assertFourByteHex(bigEndianHex);
|
|
16
|
+
return hex.match(/../g).reverse().join('');
|
|
17
|
+
};
|
|
18
|
+
export const zcashBranchIdToNumber = (bigEndianHex) => Number.parseInt(assertFourByteHex(bigEndianHex), 16);
|
|
19
|
+
const fetchZcashBranchIdHex = async () => {
|
|
20
|
+
const controller = new AbortController();
|
|
21
|
+
const timeout = setTimeout(() => {
|
|
22
|
+
controller.abort();
|
|
23
|
+
}, rpcTimeoutMs);
|
|
24
|
+
let response;
|
|
25
|
+
try {
|
|
26
|
+
response = await queryUrl(zcashRpcUrl, {
|
|
27
|
+
body: {
|
|
28
|
+
jsonrpc: '1.0',
|
|
29
|
+
id: 'vultisig-sdk',
|
|
30
|
+
method: 'getblockchaininfo',
|
|
31
|
+
params: [],
|
|
32
|
+
},
|
|
33
|
+
signal: controller.signal,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (controller.signal.aborted) {
|
|
38
|
+
throw new Error('Zcash RPC timed out while fetching consensus branch id');
|
|
39
|
+
}
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
clearTimeout(timeout);
|
|
44
|
+
}
|
|
45
|
+
if (response.error) {
|
|
46
|
+
throw new Error(`Zcash RPC error: ${response.error.message ?? 'unknown error'}`);
|
|
47
|
+
}
|
|
48
|
+
const nextBlock = response.result?.consensus?.nextblock;
|
|
49
|
+
if (!nextBlock) {
|
|
50
|
+
throw new Error('Zcash RPC response is missing consensus.nextblock');
|
|
51
|
+
}
|
|
52
|
+
return zcashBranchIdToWalletCoreHex(nextBlock);
|
|
53
|
+
};
|
|
54
|
+
export const getZcashBranchIdHex = async () => {
|
|
55
|
+
const now = Date.now();
|
|
56
|
+
if (cache && cache.expiresAt > now) {
|
|
57
|
+
return cache.value;
|
|
58
|
+
}
|
|
59
|
+
if (!inFlight) {
|
|
60
|
+
inFlight = fetchZcashBranchIdHex()
|
|
61
|
+
.then(value => {
|
|
62
|
+
cache = {
|
|
63
|
+
value,
|
|
64
|
+
expiresAt: Date.now() + cacheTtlMs,
|
|
65
|
+
};
|
|
66
|
+
return value;
|
|
67
|
+
})
|
|
68
|
+
.finally(() => {
|
|
69
|
+
inFlight = undefined;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return inFlight;
|
|
73
|
+
};
|
|
74
|
+
export const getZcashBranchId = async () => {
|
|
75
|
+
const walletCoreHex = await getZcashBranchIdHex();
|
|
76
|
+
const bigEndianHex = walletCoreHex.match(/../g).reverse().join('');
|
|
77
|
+
return zcashBranchIdToNumber(bigEndianHex);
|
|
78
|
+
};
|
|
79
|
+
export const resetZcashBranchIdCacheForTests = () => {
|
|
80
|
+
cache = undefined;
|
|
81
|
+
inFlight = undefined;
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=zcashBranchId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zcashBranchId.js","sourceRoot":"","sources":["../../../../../../packages/core/chain/chains/utxo/zcashBranchId.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vultisig/core-chain",
|
|
3
|
-
"version": "2.15.
|
|
3
|
+
"version": "2.15.2",
|
|
4
4
|
"description": "Blockchain chain logic shared across Vultisig clients",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -750,6 +750,11 @@
|
|
|
750
750
|
"import": "./dist/chains/utxo/fee/byteFee.js",
|
|
751
751
|
"default": "./dist/chains/utxo/fee/byteFee.js"
|
|
752
752
|
},
|
|
753
|
+
"./chains/utxo/fee/zip317": {
|
|
754
|
+
"types": "./dist/chains/utxo/fee/zip317.d.ts",
|
|
755
|
+
"import": "./dist/chains/utxo/fee/zip317.js",
|
|
756
|
+
"default": "./dist/chains/utxo/fee/zip317.js"
|
|
757
|
+
},
|
|
753
758
|
"./chains/utxo/minUtxo": {
|
|
754
759
|
"types": "./dist/chains/utxo/minUtxo.d.ts",
|
|
755
760
|
"import": "./dist/chains/utxo/minUtxo.js",
|
|
@@ -785,6 +790,11 @@
|
|
|
785
790
|
"import": "./dist/chains/utxo/tx/UtxoScriptType.js",
|
|
786
791
|
"default": "./dist/chains/utxo/tx/UtxoScriptType.js"
|
|
787
792
|
},
|
|
793
|
+
"./chains/utxo/zcashBranchId": {
|
|
794
|
+
"types": "./dist/chains/utxo/zcashBranchId.d.ts",
|
|
795
|
+
"import": "./dist/chains/utxo/zcashBranchId.js",
|
|
796
|
+
"default": "./dist/chains/utxo/zcashBranchId.js"
|
|
797
|
+
},
|
|
788
798
|
"./coin/AccountCoin": {
|
|
789
799
|
"types": "./dist/coin/AccountCoin.d.ts",
|
|
790
800
|
"import": "./dist/coin/AccountCoin.js",
|