@subwallet/extension-base 1.3.41-0 → 1.3.42-0
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/background/KoniTypes.d.ts +121 -4
- package/background/KoniTypes.js +18 -0
- package/background/errors/BitcoinProviderError.d.ts +6 -0
- package/background/errors/BitcoinProviderError.js +47 -0
- package/cjs/background/KoniTypes.js +20 -1
- package/cjs/background/errors/BitcoinProviderError.js +54 -0
- package/cjs/constants/bitcoin.js +22 -0
- package/cjs/constants/index.js +16 -1
- package/cjs/core/logic-validation/recipientAddress.js +9 -0
- package/cjs/core/logic-validation/transfer.js +25 -5
- package/cjs/core/types.js +1 -0
- package/cjs/core/utils.js +15 -1
- package/cjs/koni/background/handlers/Extension.js +59 -3
- package/cjs/koni/background/handlers/State.js +52 -11
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/helpers/subscribe/bitcoin.js +94 -0
- package/cjs/services/balance-service/helpers/subscribe/index.js +19 -7
- package/cjs/services/balance-service/index.js +32 -4
- package/cjs/services/balance-service/transfer/bitcoin-transfer.js +119 -0
- package/cjs/services/balance-service/transfer/token.js +2 -0
- package/cjs/services/base/types.js +2 -0
- package/cjs/services/chain-service/constants.js +14 -3
- package/cjs/services/chain-service/handler/bitcoin/BitcoinApi.js +105 -0
- package/cjs/services/chain-service/handler/bitcoin/BitcoinChainHandler.js +78 -0
- package/cjs/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/blockstream-testnet-strategy.js +371 -0
- package/cjs/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/index.js +19 -0
- package/cjs/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/mempool-testnet-strategy.js +368 -0
- package/cjs/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet/index.js +302 -0
- package/cjs/services/chain-service/handler/bitcoin/strategy/types.js +1 -0
- package/cjs/services/chain-service/index.js +27 -3
- package/cjs/services/chain-service/utils/index.js +57 -4
- package/cjs/services/chain-service/utils/patch.js +1 -1
- package/cjs/services/event-service/index.js +4 -0
- package/cjs/services/fee-service/service.js +8 -3
- package/cjs/services/hiro-service/index.js +96 -0
- package/cjs/services/hiro-service/utils/index.js +85 -0
- package/cjs/services/history-service/bitcoin-history.js +58 -0
- package/cjs/services/history-service/helpers/recoverHistoryStatus.js +96 -4
- package/cjs/services/history-service/index.js +41 -3
- package/cjs/services/keyring-service/context/handlers/Derive.js +1 -1
- package/cjs/services/keyring-service/context/handlers/Migration.js +2 -2
- package/cjs/services/keyring-service/context/handlers/Mnemonic.js +4 -3
- package/cjs/services/migration-service/scripts/MigrateNewUnifiedAccount.js +29 -0
- package/cjs/services/migration-service/scripts/index.js +3 -1
- package/cjs/services/request-service/handler/BitcoinRequestHandler.js +440 -0
- package/cjs/services/request-service/index.js +29 -3
- package/cjs/services/rune-service/index.js +105 -0
- package/cjs/services/transaction-service/helpers/index.js +7 -1
- package/cjs/services/transaction-service/index.js +136 -15
- package/cjs/services/transaction-service/utils.js +6 -3
- package/cjs/strategy/api-request-strategy/context/base.js +31 -0
- package/cjs/strategy/api-request-strategy/index.js +90 -0
- package/cjs/strategy/api-request-strategy/types.js +1 -0
- package/cjs/strategy/api-request-strategy/utils/index.js +33 -0
- package/cjs/types/account/info/keyring.js +1 -1
- package/cjs/types/bitcoin.js +24 -0
- package/cjs/types/fee/bitcoin.js +1 -0
- package/cjs/types/fee/index.js +11 -0
- package/cjs/types/index.js +11 -0
- package/cjs/utils/account/analyze.js +3 -3
- package/cjs/utils/account/common.js +16 -6
- package/cjs/utils/account/derive/info/solo.js +68 -19
- package/cjs/utils/account/derive/info/unified.js +2 -0
- package/cjs/utils/account/derive/validate.js +70 -2
- package/cjs/utils/account/transform.js +11 -5
- package/cjs/utils/bitcoin/common.js +98 -0
- package/cjs/utils/bitcoin/fee.js +21 -0
- package/cjs/utils/bitcoin/index.js +38 -0
- package/cjs/utils/bitcoin/utxo-management.js +281 -0
- package/cjs/utils/fee/transfer.js +48 -0
- package/cjs/utils/index.js +15 -1
- package/constants/bitcoin.d.ts +3 -0
- package/constants/bitcoin.js +13 -0
- package/constants/index.d.ts +2 -0
- package/constants/index.js +3 -1
- package/core/logic-validation/recipientAddress.js +10 -1
- package/core/logic-validation/transfer.d.ts +2 -2
- package/core/logic-validation/transfer.js +27 -7
- package/core/types.d.ts +1 -0
- package/core/types.js +1 -0
- package/core/utils.d.ts +1 -0
- package/core/utils.js +15 -2
- package/koni/background/handlers/Extension.d.ts +2 -0
- package/koni/background/handlers/Extension.js +58 -4
- package/koni/background/handlers/State.d.ts +7 -3
- package/koni/background/handlers/State.js +52 -12
- package/package.json +144 -8
- package/packageInfo.js +1 -1
- package/services/balance-service/helpers/subscribe/bitcoin.d.ts +2 -0
- package/services/balance-service/helpers/subscribe/bitcoin.js +87 -0
- package/services/balance-service/helpers/subscribe/index.d.ts +2 -2
- package/services/balance-service/helpers/subscribe/index.js +20 -8
- package/services/balance-service/index.d.ts +2 -0
- package/services/balance-service/index.js +32 -4
- package/services/balance-service/transfer/bitcoin-transfer.d.ts +14 -0
- package/services/balance-service/transfer/bitcoin-transfer.js +112 -0
- package/services/balance-service/transfer/token.js +2 -0
- package/services/base/types.d.ts +2 -0
- package/services/base/types.js +2 -0
- package/services/chain-service/constants.d.ts +6 -0
- package/services/chain-service/constants.js +8 -2
- package/services/chain-service/handler/bitcoin/BitcoinApi.d.ts +31 -0
- package/services/chain-service/handler/bitcoin/BitcoinApi.js +98 -0
- package/services/chain-service/handler/bitcoin/BitcoinChainHandler.d.ts +16 -0
- package/services/chain-service/handler/bitcoin/BitcoinChainHandler.js +70 -0
- package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/blockstream-testnet-strategy.d.ts +28 -0
- package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/blockstream-testnet-strategy.js +362 -0
- package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/index.d.ts +2 -0
- package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/index.js +5 -0
- package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/mempool-testnet-strategy.d.ts +28 -0
- package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/mempool-testnet-strategy.js +359 -0
- package/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet/index.d.ts +28 -0
- package/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet/index.js +293 -0
- package/services/chain-service/handler/bitcoin/strategy/types.d.ts +291 -0
- package/services/chain-service/handler/bitcoin/strategy/types.js +1 -0
- package/services/chain-service/index.d.ts +3 -0
- package/services/chain-service/index.js +31 -5
- package/services/chain-service/types.d.ts +20 -0
- package/services/chain-service/utils/index.d.ts +4 -0
- package/services/chain-service/utils/index.js +50 -4
- package/services/chain-service/utils/patch.js +1 -1
- package/services/event-service/index.d.ts +3 -0
- package/services/event-service/index.js +4 -0
- package/services/event-service/types.d.ts +3 -0
- package/services/fee-service/service.js +8 -3
- package/services/hiro-service/index.d.ts +17 -0
- package/services/hiro-service/index.js +88 -0
- package/services/hiro-service/utils/index.d.ts +6 -0
- package/services/hiro-service/utils/index.js +72 -0
- package/services/history-service/bitcoin-history.d.ts +4 -0
- package/services/history-service/bitcoin-history.js +52 -0
- package/services/history-service/helpers/recoverHistoryStatus.d.ts +3 -1
- package/services/history-service/helpers/recoverHistoryStatus.js +96 -4
- package/services/history-service/index.d.ts +1 -0
- package/services/history-service/index.js +42 -4
- package/services/keyring-service/context/handlers/Derive.js +2 -2
- package/services/keyring-service/context/handlers/Migration.js +2 -2
- package/services/keyring-service/context/handlers/Mnemonic.js +4 -3
- package/services/migration-service/scripts/MigrateNewUnifiedAccount.d.ts +4 -0
- package/services/migration-service/scripts/MigrateNewUnifiedAccount.js +21 -0
- package/services/migration-service/scripts/index.js +3 -1
- package/services/request-service/handler/BitcoinRequestHandler.d.ts +23 -0
- package/services/request-service/handler/BitcoinRequestHandler.js +427 -0
- package/services/request-service/index.d.ts +9 -2
- package/services/request-service/index.js +25 -3
- package/services/rune-service/index.d.ts +17 -0
- package/services/rune-service/index.js +97 -0
- package/services/transaction-service/helpers/index.d.ts +3 -1
- package/services/transaction-service/helpers/index.js +5 -0
- package/services/transaction-service/index.d.ts +3 -5
- package/services/transaction-service/index.js +135 -16
- package/services/transaction-service/types.d.ts +12 -2
- package/services/transaction-service/utils.js +7 -4
- package/strategy/api-request-strategy/context/base.d.ts +15 -0
- package/strategy/api-request-strategy/context/base.js +24 -0
- package/strategy/api-request-strategy/index.d.ts +15 -0
- package/strategy/api-request-strategy/index.js +83 -0
- package/strategy/api-request-strategy/types.d.ts +22 -0
- package/strategy/api-request-strategy/types.js +1 -0
- package/strategy/api-request-strategy/utils/index.d.ts +2 -0
- package/strategy/api-request-strategy/utils/index.js +23 -0
- package/types/account/info/keyring.d.ts +1 -1
- package/types/account/info/keyring.js +1 -1
- package/types/balance/index.d.ts +4 -1
- package/types/balance/transfer.d.ts +17 -0
- package/types/bitcoin.d.ts +93 -0
- package/types/bitcoin.js +17 -0
- package/types/fee/base.d.ts +4 -1
- package/types/fee/bitcoin.d.ts +18 -0
- package/types/fee/bitcoin.js +1 -0
- package/types/fee/index.d.ts +1 -0
- package/types/fee/index.js +2 -1
- package/types/fee/subscription.d.ts +4 -3
- package/types/index.d.ts +1 -0
- package/types/index.js +1 -0
- package/utils/account/analyze.js +4 -4
- package/utils/account/common.d.ts +7 -8
- package/utils/account/common.js +16 -6
- package/utils/account/derive/info/solo.js +70 -21
- package/utils/account/derive/info/unified.js +2 -0
- package/utils/account/derive/validate.d.ts +1 -0
- package/utils/account/derive/validate.js +68 -1
- package/utils/account/transform.d.ts +1 -1
- package/utils/account/transform.js +11 -5
- package/utils/bitcoin/common.d.ts +22 -0
- package/utils/bitcoin/common.js +88 -0
- package/utils/bitcoin/fee.d.ts +2 -0
- package/utils/bitcoin/fee.js +14 -0
- package/utils/bitcoin/index.d.ts +3 -0
- package/utils/bitcoin/index.js +6 -0
- package/utils/bitcoin/utxo-management.d.ts +33 -0
- package/utils/bitcoin/utxo-management.js +266 -0
- package/utils/fee/transfer.d.ts +3 -1
- package/utils/fee/transfer.js +47 -1
- package/utils/index.d.ts +1 -0
- package/utils/index.js +6 -3
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { filteredOutTxsUtxos, getInscriptionUtxos, getRuneUtxos } from '@subwallet/extension-base/utils';
|
|
5
|
+
import { BitcoinAddressType } from '@subwallet/keyring/types';
|
|
6
|
+
import { BtcSizeFeeEstimator, getBitcoinAddressInfo, validateBitcoinAddress } from '@subwallet/keyring/utils';
|
|
7
|
+
import BigN from 'bignumber.js';
|
|
8
|
+
|
|
9
|
+
// Source: https://github.com/leather-wallet/extension/blob/dev/src/app/common/transactions/bitcoin/utils.ts
|
|
10
|
+
export function getSizeInfo(payload) {
|
|
11
|
+
const {
|
|
12
|
+
inputLength,
|
|
13
|
+
recipients,
|
|
14
|
+
sender
|
|
15
|
+
} = payload;
|
|
16
|
+
const senderInfo = validateBitcoinAddress(sender) ? getBitcoinAddressInfo(sender) : null;
|
|
17
|
+
const inputAddressTypeWithFallback = senderInfo ? senderInfo.type : BitcoinAddressType.p2wpkh;
|
|
18
|
+
const outputMap = {};
|
|
19
|
+
for (const recipient of recipients) {
|
|
20
|
+
const recipientInfo = validateBitcoinAddress(recipient) ? getBitcoinAddressInfo(recipient) : null;
|
|
21
|
+
const outputAddressTypeWithFallback = recipientInfo ? recipientInfo.type : BitcoinAddressType.p2wpkh;
|
|
22
|
+
const outputKey = outputAddressTypeWithFallback + '_output_count';
|
|
23
|
+
if (outputMap[outputKey]) {
|
|
24
|
+
outputMap[outputKey]++;
|
|
25
|
+
} else {
|
|
26
|
+
outputMap[outputKey] = 1;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const txSizer = new BtcSizeFeeEstimator();
|
|
30
|
+
return txSizer.calcTxSize({
|
|
31
|
+
input_script: inputAddressTypeWithFallback,
|
|
32
|
+
input_count: inputLength,
|
|
33
|
+
...outputMap
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// https://github.com/leather-wallet/extension/blob/dev/src/app/common/transactions/bitcoin/utils.ts
|
|
38
|
+
export function getSpendableAmount({
|
|
39
|
+
feeRate,
|
|
40
|
+
recipients,
|
|
41
|
+
sender,
|
|
42
|
+
utxos
|
|
43
|
+
}) {
|
|
44
|
+
const balance = utxos.map(utxo => utxo.value).reduce((prevVal, curVal) => prevVal + curVal, 0);
|
|
45
|
+
const size = getSizeInfo({
|
|
46
|
+
inputLength: utxos.length,
|
|
47
|
+
recipients,
|
|
48
|
+
sender
|
|
49
|
+
});
|
|
50
|
+
const fee = Math.ceil(size.txVBytes * feeRate);
|
|
51
|
+
const bigNumberBalance = new BigN(balance);
|
|
52
|
+
return {
|
|
53
|
+
spendableAmount: BigN.max(0, bigNumberBalance.minus(fee)),
|
|
54
|
+
fee
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export const getTransferableBitcoinUtxos = async (bitcoinApi, address) => {
|
|
58
|
+
try {
|
|
59
|
+
const [utxos, runeTxsUtxos, inscriptionUtxos] = await Promise.all([bitcoinApi.api.getUtxos(address).catch(error => {
|
|
60
|
+
console.log('Error fetching UTXOs:', error);
|
|
61
|
+
return [];
|
|
62
|
+
}), getRuneUtxos(bitcoinApi, address).catch(error => {
|
|
63
|
+
console.log('Error fetching Rune UTXOs:', error);
|
|
64
|
+
return [];
|
|
65
|
+
}), getInscriptionUtxos(bitcoinApi, address).catch(error => {
|
|
66
|
+
console.log('Error fetching Inscription UTXOs:', error);
|
|
67
|
+
return [];
|
|
68
|
+
})]);
|
|
69
|
+
let filteredUtxos;
|
|
70
|
+
if (!utxos || !utxos.length) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// filter out pending utxos
|
|
75
|
+
// filteredUtxos = filterOutPendingTxsUtxos(utxos);
|
|
76
|
+
|
|
77
|
+
// filter out rune utxos
|
|
78
|
+
filteredUtxos = filteredOutTxsUtxos(utxos, runeTxsUtxos);
|
|
79
|
+
|
|
80
|
+
// filter out dust utxos
|
|
81
|
+
// filter out inscription utxos
|
|
82
|
+
filteredUtxos = filteredOutTxsUtxos(utxos, inscriptionUtxos);
|
|
83
|
+
return filteredUtxos;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.log('Error while fetching Bitcoin balances', error);
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
export const combineBitcoinFee = (feeInfo, feeOptions, feeCustom) => {
|
|
5
|
+
if (feeOptions && feeOptions !== 'custom') {
|
|
6
|
+
var _feeInfo$options;
|
|
7
|
+
return (_feeInfo$options = feeInfo.options) === null || _feeInfo$options === void 0 ? void 0 : _feeInfo$options[feeOptions];
|
|
8
|
+
} else if (feeOptions === 'custom' && feeCustom) {
|
|
9
|
+
return feeCustom;
|
|
10
|
+
} else {
|
|
11
|
+
var _feeInfo$options2;
|
|
12
|
+
return (_feeInfo$options2 = feeInfo.options) === null || _feeInfo$options2 === void 0 ? void 0 : _feeInfo$options2[feeInfo.options.default];
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { _BitcoinApi } from '@subwallet/extension-base/services/chain-service/types';
|
|
2
|
+
import { DetermineUtxosForSpendArgs, UtxoResponseItem } from '@subwallet/extension-base/types';
|
|
3
|
+
export declare function filterUneconomicalUtxos({ feeRate, recipients, sender, utxos }: {
|
|
4
|
+
utxos: UtxoResponseItem[];
|
|
5
|
+
feeRate: number;
|
|
6
|
+
sender: string;
|
|
7
|
+
recipients: string[];
|
|
8
|
+
}): UtxoResponseItem[];
|
|
9
|
+
export declare function determineUtxosForSpendAll({ feeRate, recipient, sender, utxos }: DetermineUtxosForSpendArgs): {
|
|
10
|
+
inputs: UtxoResponseItem[];
|
|
11
|
+
outputs: {
|
|
12
|
+
value: number;
|
|
13
|
+
address: string;
|
|
14
|
+
}[];
|
|
15
|
+
size: number;
|
|
16
|
+
fee: number;
|
|
17
|
+
isCustomFeeRate: boolean;
|
|
18
|
+
};
|
|
19
|
+
export declare function determineUtxosForSpend({ amount, feeRate, recipient, sender, utxos }: DetermineUtxosForSpendArgs): {
|
|
20
|
+
filteredUtxos: UtxoResponseItem[];
|
|
21
|
+
inputs: UtxoResponseItem[];
|
|
22
|
+
outputs: {
|
|
23
|
+
value: number;
|
|
24
|
+
address: string;
|
|
25
|
+
}[];
|
|
26
|
+
size: number;
|
|
27
|
+
fee: number;
|
|
28
|
+
isCustomFeeRate: boolean;
|
|
29
|
+
};
|
|
30
|
+
export declare function filterOutPendingTxsUtxos(utxos: UtxoResponseItem[]): UtxoResponseItem[];
|
|
31
|
+
export declare function filteredOutTxsUtxos(allTxsUtxos: UtxoResponseItem[], filteredOutTxsUtxos: UtxoResponseItem[]): UtxoResponseItem[];
|
|
32
|
+
export declare function getRuneUtxos(bitcoinApi: _BitcoinApi, address: string): Promise<UtxoResponseItem[]>;
|
|
33
|
+
export declare function getInscriptionUtxos(bitcoinApi: _BitcoinApi, address: string): Promise<UtxoResponseItem[]>;
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// Copyright 2019-2022 @subwallet/extension-base
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
5
|
+
import { BTC_DUST_AMOUNT } from '@subwallet/extension-base/constants';
|
|
6
|
+
import { InsufficientFundsError, TransferTxErrorType } from '@subwallet/extension-base/types';
|
|
7
|
+
import { balanceFormatter, formatNumber } from '@subwallet/extension-base/utils';
|
|
8
|
+
import { BitcoinAddressType } from '@subwallet/keyring/types';
|
|
9
|
+
import { getBitcoinAddressInfo, validateBitcoinAddress } from '@subwallet/keyring/utils';
|
|
10
|
+
import BigN from 'bignumber.js';
|
|
11
|
+
import { getSizeInfo, getSpendableAmount } from "./common.js";
|
|
12
|
+
|
|
13
|
+
// https://github.com/leather-wallet/extension/blob/dev/src/app/common/transactions/bitcoin/utils.ts
|
|
14
|
+
// Check if the spendable amount drops when adding a utxo. If it drops, don't use that utxo.
|
|
15
|
+
// Method might be not particularly efficient as it would
|
|
16
|
+
// go through the utxo array multiple times, but it's reliable.
|
|
17
|
+
export function filterUneconomicalUtxos({
|
|
18
|
+
feeRate,
|
|
19
|
+
recipients,
|
|
20
|
+
sender,
|
|
21
|
+
utxos
|
|
22
|
+
}) {
|
|
23
|
+
const addressInfo = validateBitcoinAddress(sender) ? getBitcoinAddressInfo(sender) : null;
|
|
24
|
+
const inputAddressTypeWithFallback = addressInfo ? addressInfo.type : BitcoinAddressType.p2wpkh;
|
|
25
|
+
const filteredAndSortUtxos = utxos.filter(utxo => utxo.value >= BTC_DUST_AMOUNT[inputAddressTypeWithFallback]).sort((a, b) => a.value - b.value); // ascending order
|
|
26
|
+
|
|
27
|
+
return filteredAndSortUtxos.reduce((utxos, utxo, currentIndex) => {
|
|
28
|
+
const utxosWithout = utxos.filter(u => u.txid !== utxo.txid);
|
|
29
|
+
const {
|
|
30
|
+
spendableAmount: spendableAmountWithout
|
|
31
|
+
} = getSpendableAmount({
|
|
32
|
+
utxos: utxosWithout,
|
|
33
|
+
feeRate,
|
|
34
|
+
recipients,
|
|
35
|
+
sender
|
|
36
|
+
});
|
|
37
|
+
const {
|
|
38
|
+
spendableAmount
|
|
39
|
+
} = getSpendableAmount({
|
|
40
|
+
utxos,
|
|
41
|
+
feeRate,
|
|
42
|
+
recipients,
|
|
43
|
+
sender
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// console.log(utxosWithout, feeWithout, spendableAmountWithout.toString());
|
|
47
|
+
// console.log(utxos, fee, spendableAmount.toString());
|
|
48
|
+
|
|
49
|
+
if (spendableAmount.lte(0)) {
|
|
50
|
+
return utxosWithout;
|
|
51
|
+
} else {
|
|
52
|
+
// if spendable amount becomes bigger, do not use that utxo
|
|
53
|
+
return spendableAmountWithout.gt(spendableAmount) ? utxosWithout : utxos;
|
|
54
|
+
}
|
|
55
|
+
}, [...filteredAndSortUtxos]).reverse();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// https://github.com/leather-wallet/extension/blob/dev/src/app/common/transactions/bitcoin/coinselect/local-coin-selection.ts
|
|
59
|
+
export function determineUtxosForSpendAll({
|
|
60
|
+
feeRate,
|
|
61
|
+
recipient,
|
|
62
|
+
sender,
|
|
63
|
+
utxos
|
|
64
|
+
}) {
|
|
65
|
+
if (!validateBitcoinAddress(recipient)) {
|
|
66
|
+
throw new Error('Cannot calculate spend of invalid address type');
|
|
67
|
+
}
|
|
68
|
+
const recipientAddressInfo = getBitcoinAddressInfo(recipient);
|
|
69
|
+
const recipientDustLimit = BTC_DUST_AMOUNT[recipientAddressInfo.type] || 546;
|
|
70
|
+
const recipients = [recipient];
|
|
71
|
+
const filteredUtxos = filterUneconomicalUtxos({
|
|
72
|
+
utxos,
|
|
73
|
+
feeRate,
|
|
74
|
+
recipients,
|
|
75
|
+
sender
|
|
76
|
+
});
|
|
77
|
+
const sizeInfo = getSizeInfo({
|
|
78
|
+
sender,
|
|
79
|
+
inputLength: filteredUtxos.length,
|
|
80
|
+
recipients
|
|
81
|
+
});
|
|
82
|
+
const amount = filteredUtxos.reduce((acc, utxo) => acc + utxo.value, 0) - Math.ceil(sizeInfo.txVBytes * feeRate);
|
|
83
|
+
if (amount <= 0) {
|
|
84
|
+
throw new InsufficientFundsError();
|
|
85
|
+
}
|
|
86
|
+
if (amount < recipientDustLimit) {
|
|
87
|
+
const atLeastStr = formatNumber(recipientDustLimit, 8, balanceFormatter, {
|
|
88
|
+
maxNumberFormat: 8,
|
|
89
|
+
minNumberFormat: 8
|
|
90
|
+
});
|
|
91
|
+
throw new TransactionError(TransferTxErrorType.NOT_ENOUGH_VALUE, `You must transfer at least ${atLeastStr} BTC`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Fee has already been deducted from the amount with send all
|
|
95
|
+
const outputs = [{
|
|
96
|
+
value: amount,
|
|
97
|
+
address: recipient
|
|
98
|
+
}];
|
|
99
|
+
const fee = Math.ceil(sizeInfo.txVBytes * feeRate);
|
|
100
|
+
return {
|
|
101
|
+
inputs: filteredUtxos,
|
|
102
|
+
outputs,
|
|
103
|
+
size: sizeInfo.txVBytes,
|
|
104
|
+
fee,
|
|
105
|
+
isCustomFeeRate: false
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// https://github.com/leather-wallet/extension/blob/dev/src/app/common/transactions/bitcoin/coinselect/local-coin-selection.ts
|
|
110
|
+
export function determineUtxosForSpend({
|
|
111
|
+
amount,
|
|
112
|
+
feeRate,
|
|
113
|
+
recipient,
|
|
114
|
+
sender,
|
|
115
|
+
utxos
|
|
116
|
+
}) {
|
|
117
|
+
if (!validateBitcoinAddress(recipient)) {
|
|
118
|
+
throw new Error('Cannot calculate spend of invalid address type');
|
|
119
|
+
}
|
|
120
|
+
const recipientAddressInfo = getBitcoinAddressInfo(recipient);
|
|
121
|
+
const recipientDustLimit = BTC_DUST_AMOUNT[recipientAddressInfo.type] || 546;
|
|
122
|
+
if (amount < recipientDustLimit) {
|
|
123
|
+
const atLeastStr = formatNumber(recipientDustLimit, 8, balanceFormatter, {
|
|
124
|
+
maxNumberFormat: 8,
|
|
125
|
+
minNumberFormat: 8
|
|
126
|
+
});
|
|
127
|
+
throw new TransactionError(TransferTxErrorType.NOT_ENOUGH_VALUE, `You must transfer at least ${atLeastStr} BTC`);
|
|
128
|
+
}
|
|
129
|
+
const orderedUtxos = utxos.sort((a, b) => b.value - a.value);
|
|
130
|
+
const recipients = [recipient, sender];
|
|
131
|
+
const filteredUtxos = filterUneconomicalUtxos({
|
|
132
|
+
utxos: orderedUtxos,
|
|
133
|
+
feeRate,
|
|
134
|
+
recipients,
|
|
135
|
+
sender
|
|
136
|
+
});
|
|
137
|
+
const neededUtxos = [];
|
|
138
|
+
let sum = new BigN(0);
|
|
139
|
+
let sizeInfo = null;
|
|
140
|
+
for (const utxo of filteredUtxos) {
|
|
141
|
+
sizeInfo = getSizeInfo({
|
|
142
|
+
inputLength: neededUtxos.length,
|
|
143
|
+
sender,
|
|
144
|
+
recipients
|
|
145
|
+
});
|
|
146
|
+
const currentValue = new BigN(amount).plus(Math.ceil(sizeInfo.txVBytes * feeRate));
|
|
147
|
+
if (sum.gte(currentValue)) {
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
sum = sum.plus(utxo.value);
|
|
151
|
+
neededUtxos.push(utxo);
|
|
152
|
+
|
|
153
|
+
// re calculate size info, some case array end
|
|
154
|
+
sizeInfo = getSizeInfo({
|
|
155
|
+
inputLength: neededUtxos.length,
|
|
156
|
+
sender,
|
|
157
|
+
recipients
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (!sizeInfo) {
|
|
161
|
+
throw new InsufficientFundsError();
|
|
162
|
+
}
|
|
163
|
+
const fee = Math.ceil(sizeInfo.txVBytes * feeRate);
|
|
164
|
+
const amountLeft = sum.minus(amount).minus(fee);
|
|
165
|
+
if (amountLeft.lte(0)) {
|
|
166
|
+
throw new InsufficientFundsError();
|
|
167
|
+
}
|
|
168
|
+
const senderAddressInfo = getBitcoinAddressInfo(sender);
|
|
169
|
+
const dustLimit = BTC_DUST_AMOUNT[senderAddressInfo.type] || 546;
|
|
170
|
+
const outputs = [
|
|
171
|
+
// outputs[0] = the desired amount going to recipient
|
|
172
|
+
{
|
|
173
|
+
value: amount,
|
|
174
|
+
address: recipient
|
|
175
|
+
}];
|
|
176
|
+
if (amountLeft.gte(dustLimit)) {
|
|
177
|
+
// outputs[1] = the remainder to be returned to a change address
|
|
178
|
+
outputs.push({
|
|
179
|
+
value: amountLeft.toNumber(),
|
|
180
|
+
address: sender
|
|
181
|
+
});
|
|
182
|
+
} else {
|
|
183
|
+
// Todo: This solution for improve later, current throw error
|
|
184
|
+
// // Increase the fee to use the remaining balance
|
|
185
|
+
console.warn(`Change output of ${amountLeft.toString()} satoshis is below dust limit (${dustLimit} satoshis for ${senderAddressInfo.type}). Omitting change output.`);
|
|
186
|
+
//
|
|
187
|
+
sizeInfo = getSizeInfo({
|
|
188
|
+
inputLength: neededUtxos.length,
|
|
189
|
+
sender,
|
|
190
|
+
recipients: recipients.slice(0, 1)
|
|
191
|
+
});
|
|
192
|
+
const newFee = sum.minus(amount).toNumber();
|
|
193
|
+
return {
|
|
194
|
+
filteredUtxos,
|
|
195
|
+
inputs: neededUtxos,
|
|
196
|
+
outputs,
|
|
197
|
+
size: sizeInfo.txVBytes,
|
|
198
|
+
fee: newFee,
|
|
199
|
+
isCustomFeeRate: true
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
filteredUtxos,
|
|
204
|
+
inputs: neededUtxos,
|
|
205
|
+
outputs,
|
|
206
|
+
size: sizeInfo.txVBytes,
|
|
207
|
+
fee,
|
|
208
|
+
isCustomFeeRate: false
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
export function filterOutPendingTxsUtxos(utxos) {
|
|
212
|
+
return utxos.filter(utxo => utxo.status.confirmed);
|
|
213
|
+
}
|
|
214
|
+
export function filteredOutTxsUtxos(allTxsUtxos, filteredOutTxsUtxos) {
|
|
215
|
+
if (!filteredOutTxsUtxos.length) {
|
|
216
|
+
return allTxsUtxos;
|
|
217
|
+
}
|
|
218
|
+
const listFilterOut = filteredOutTxsUtxos.map(utxo => {
|
|
219
|
+
return `${utxo.txid}:${utxo.vout}`;
|
|
220
|
+
});
|
|
221
|
+
return allTxsUtxos.filter(element => !listFilterOut.includes(`${element.txid}:${element.vout}`));
|
|
222
|
+
}
|
|
223
|
+
export async function getRuneUtxos(bitcoinApi, address) {
|
|
224
|
+
const responseRuneUtxos = await bitcoinApi.api.getRuneUtxos(address);
|
|
225
|
+
const runeUtxos = [];
|
|
226
|
+
responseRuneUtxos.forEach(responseRuneUtxo => {
|
|
227
|
+
const txid = responseRuneUtxo.txid;
|
|
228
|
+
const vout = responseRuneUtxo.vout;
|
|
229
|
+
const utxoValue = responseRuneUtxo.satoshi;
|
|
230
|
+
if (txid && vout && utxoValue) {
|
|
231
|
+
const item = {
|
|
232
|
+
txid,
|
|
233
|
+
vout,
|
|
234
|
+
status: {
|
|
235
|
+
confirmed: true // not use in filter out rune utxos
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
value: utxoValue
|
|
239
|
+
};
|
|
240
|
+
runeUtxos.push(item);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
return runeUtxos;
|
|
244
|
+
}
|
|
245
|
+
export async function getInscriptionUtxos(bitcoinApi, address) {
|
|
246
|
+
try {
|
|
247
|
+
const inscriptions = await bitcoinApi.api.getAddressInscriptions(address);
|
|
248
|
+
return inscriptions.map(inscription => {
|
|
249
|
+
const [txid, vout] = inscription.output.split(':');
|
|
250
|
+
return {
|
|
251
|
+
txid,
|
|
252
|
+
vout: parseInt(vout),
|
|
253
|
+
status: {
|
|
254
|
+
confirmed: true,
|
|
255
|
+
// not use in filter out inscription utxos
|
|
256
|
+
block_height: inscription.genesis_block_height,
|
|
257
|
+
block_hash: inscription.genesis_block_hash,
|
|
258
|
+
block_time: inscription.genesis_timestamp
|
|
259
|
+
},
|
|
260
|
+
value: parseInt(inscription.value)
|
|
261
|
+
};
|
|
262
|
+
});
|
|
263
|
+
} catch (e) {
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
266
|
+
}
|
package/utils/fee/transfer.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types';
|
|
2
2
|
import { AmountData } from '@subwallet/extension-base/background/KoniTypes';
|
|
3
|
-
import { _CardanoApi, _EvmApi, _SubstrateApi, _TonApi } from '@subwallet/extension-base/services/chain-service/types';
|
|
3
|
+
import { _BitcoinApi, _CardanoApi, _EvmApi, _SubstrateApi, _TonApi } from '@subwallet/extension-base/services/chain-service/types';
|
|
4
4
|
import { FeeChainType, FeeInfo, TransactionFee } from '@subwallet/extension-base/types';
|
|
5
5
|
import { ResponseSubscribeTransfer } from '@subwallet/extension-base/types/balance/transfer';
|
|
6
6
|
export interface CalculateMaxTransferable extends TransactionFee {
|
|
7
7
|
address: string;
|
|
8
|
+
to?: string;
|
|
8
9
|
value: string;
|
|
9
10
|
srcToken: _ChainAsset;
|
|
10
11
|
destToken?: _ChainAsset;
|
|
@@ -14,6 +15,7 @@ export interface CalculateMaxTransferable extends TransactionFee {
|
|
|
14
15
|
evmApi: _EvmApi;
|
|
15
16
|
tonApi: _TonApi;
|
|
16
17
|
cardanoApi: _CardanoApi;
|
|
18
|
+
bitcoinApi: _BitcoinApi;
|
|
17
19
|
isTransferLocalTokenAndPayThatTokenAsFee: boolean;
|
|
18
20
|
isTransferNativeTokenAndPayLocalTokenAsFee: boolean;
|
|
19
21
|
nativeToken: _ChainAsset;
|
package/utils/fee/transfer.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { _SUPPORT_TOKEN_PAY_FEE_GROUP, XCM_FEE_RATIO } from '@subwallet/extension-base/constants';
|
|
5
5
|
import { _isSnowBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser';
|
|
6
6
|
import { DEFAULT_CARDANO_TTL_OFFSET } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/cardano/consts';
|
|
7
|
+
import { createBitcoinTransaction } from '@subwallet/extension-base/services/balance-service/transfer/bitcoin-transfer';
|
|
7
8
|
import { createCardanoTransaction } from '@subwallet/extension-base/services/balance-service/transfer/cardano-transfer';
|
|
8
9
|
import { getERC20TransactionObject, getEVMTransactionObject } from '@subwallet/extension-base/services/balance-service/transfer/smart-contract';
|
|
9
10
|
import { createSubstrateExtrinsic } from '@subwallet/extension-base/services/balance-service/transfer/token';
|
|
@@ -14,13 +15,15 @@ import { isAvailChainBridge } from '@subwallet/extension-base/services/balance-s
|
|
|
14
15
|
import { _isPolygonChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/polygonBridge';
|
|
15
16
|
import { _isPosChainBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/posBridge';
|
|
16
17
|
import { estimateXcmFee } from '@subwallet/extension-base/services/balance-service/transfer/xcm/utils';
|
|
17
|
-
import { _getAssetDecimals, _getContractAddressOfToken, _isChainCardanoCompatible, _isChainEvmCompatible, _isChainTonCompatible, _isLocalToken, _isNativeToken, _isPureEvmChain, _isTokenEvmSmartContract, _isTokenTransferredByCardano, _isTokenTransferredByEvm, _isTokenTransferredByTon } from '@subwallet/extension-base/services/chain-service/utils';
|
|
18
|
+
import { _getAssetDecimals, _getContractAddressOfToken, _isChainBitcoinCompatible, _isChainCardanoCompatible, _isChainEvmCompatible, _isChainTonCompatible, _isLocalToken, _isNativeToken, _isPureEvmChain, _isTokenEvmSmartContract, _isTokenTransferredByBitcoin, _isTokenTransferredByCardano, _isTokenTransferredByEvm, _isTokenTransferredByTon } from '@subwallet/extension-base/services/chain-service/utils';
|
|
18
19
|
import { calculateToAmountByReservePool, FEE_COVERAGE_PERCENTAGE_SPECIAL_CASE } from '@subwallet/extension-base/services/fee-service/utils';
|
|
19
20
|
import { getHydrationRate } from '@subwallet/extension-base/services/fee-service/utils/tokenPayFee';
|
|
20
21
|
import { isCardanoTransaction, isTonTransaction } from '@subwallet/extension-base/services/transaction-service/helpers';
|
|
21
22
|
import { BN_ZERO } from '@subwallet/extension-base/utils';
|
|
22
23
|
import { isCardanoAddress, isTonAddress } from '@subwallet/keyring';
|
|
24
|
+
import { isBitcoinAddress } from '@subwallet/keyring/utils/address/validate';
|
|
23
25
|
import BigN from 'bignumber.js';
|
|
26
|
+
import * as bitcoin from 'bitcoinjs-lib';
|
|
24
27
|
import { u8aToHex } from '@polkadot/util';
|
|
25
28
|
import { addressToEvm, isEthereumAddress } from '@polkadot/util-crypto';
|
|
26
29
|
import { combineEthFee, combineSubstrateFee } from "./combine.js";
|
|
@@ -40,6 +43,8 @@ export const detectTransferTxType = (srcToken, srcChain, destChain) => {
|
|
|
40
43
|
return 'ton';
|
|
41
44
|
} else if (_isChainCardanoCompatible(srcChain) && _isTokenTransferredByCardano(srcToken)) {
|
|
42
45
|
return 'cardano';
|
|
46
|
+
} else if (_isChainBitcoinCompatible(srcChain) && _isTokenTransferredByBitcoin(srcToken)) {
|
|
47
|
+
return 'bitcoin';
|
|
43
48
|
} else {
|
|
44
49
|
return 'substrate';
|
|
45
50
|
}
|
|
@@ -69,6 +74,7 @@ export const calculateMaxTransferable = async (id, request, freeBalance, fee) =>
|
|
|
69
74
|
export const calculateTransferMaxTransferable = async (id, request, freeBalance, fee) => {
|
|
70
75
|
const {
|
|
71
76
|
address,
|
|
77
|
+
bitcoinApi,
|
|
72
78
|
cardanoApi,
|
|
73
79
|
destChain,
|
|
74
80
|
evmApi,
|
|
@@ -80,6 +86,7 @@ export const calculateTransferMaxTransferable = async (id, request, freeBalance,
|
|
|
80
86
|
srcChain,
|
|
81
87
|
srcToken,
|
|
82
88
|
substrateApi,
|
|
89
|
+
to,
|
|
83
90
|
tonApi,
|
|
84
91
|
value
|
|
85
92
|
} = request;
|
|
@@ -149,6 +156,18 @@ export const calculateTransferMaxTransferable = async (id, request, freeBalance,
|
|
|
149
156
|
cardanoApi,
|
|
150
157
|
nativeTokenInfo: nativeToken
|
|
151
158
|
});
|
|
159
|
+
} else if (isBitcoinAddress(address) && _isTokenTransferredByBitcoin(srcToken)) {
|
|
160
|
+
const network = srcChain.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin;
|
|
161
|
+
[transaction] = await createBitcoinTransaction({
|
|
162
|
+
chain: srcChain.slug,
|
|
163
|
+
from: address,
|
|
164
|
+
to: to || address,
|
|
165
|
+
value,
|
|
166
|
+
feeInfo: fee,
|
|
167
|
+
transferAll: false,
|
|
168
|
+
bitcoinApi,
|
|
169
|
+
network: network
|
|
170
|
+
});
|
|
152
171
|
} else {
|
|
153
172
|
[transaction] = await createSubstrateExtrinsic({
|
|
154
173
|
transferAll: false,
|
|
@@ -194,6 +213,15 @@ export const calculateTransferMaxTransferable = async (id, request, freeBalance,
|
|
|
194
213
|
...fee,
|
|
195
214
|
estimatedFee
|
|
196
215
|
};
|
|
216
|
+
} else if (feeChainType === 'bitcoin') {
|
|
217
|
+
// Calculate fee for bitcoin transaction
|
|
218
|
+
// TODO: Support maxTransferable for bitcoin
|
|
219
|
+
estimatedFee = '0';
|
|
220
|
+
feeOptions = {
|
|
221
|
+
...fee,
|
|
222
|
+
vSize: 0,
|
|
223
|
+
estimatedFee
|
|
224
|
+
};
|
|
197
225
|
} else {
|
|
198
226
|
if (transaction) {
|
|
199
227
|
if (isTonTransaction(transaction)) {
|
|
@@ -233,6 +261,12 @@ export const calculateTransferMaxTransferable = async (id, request, freeBalance,
|
|
|
233
261
|
estimatedFee,
|
|
234
262
|
gasLimit: '0'
|
|
235
263
|
};
|
|
264
|
+
} else if (fee.type === 'bitcoin') {
|
|
265
|
+
feeOptions = {
|
|
266
|
+
...fee,
|
|
267
|
+
estimatedFee,
|
|
268
|
+
vSize: 0
|
|
269
|
+
};
|
|
236
270
|
} else {
|
|
237
271
|
feeOptions = {
|
|
238
272
|
...fee,
|
|
@@ -395,6 +429,12 @@ export const calculateXcmMaxTransferable = async (id, request, freeBalance, fee)
|
|
|
395
429
|
...fee,
|
|
396
430
|
estimatedFee
|
|
397
431
|
};
|
|
432
|
+
} else if (feeChainType === 'bitcoin') {
|
|
433
|
+
feeOptions = {
|
|
434
|
+
...fee,
|
|
435
|
+
estimatedFee,
|
|
436
|
+
vSize: 0
|
|
437
|
+
};
|
|
398
438
|
} else {
|
|
399
439
|
// Not implemented yet
|
|
400
440
|
estimatedFee = '0';
|
|
@@ -411,6 +451,12 @@ export const calculateXcmMaxTransferable = async (id, request, freeBalance, fee)
|
|
|
411
451
|
estimatedFee,
|
|
412
452
|
gasLimit: '0'
|
|
413
453
|
};
|
|
454
|
+
} else if (fee.type === 'bitcoin') {
|
|
455
|
+
feeOptions = {
|
|
456
|
+
...fee,
|
|
457
|
+
estimatedFee,
|
|
458
|
+
vSize: 0
|
|
459
|
+
};
|
|
414
460
|
} else {
|
|
415
461
|
feeOptions = {
|
|
416
462
|
...fee,
|
package/utils/index.d.ts
CHANGED
package/utils/index.js
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
import { CrowdloanParaState } from '@subwallet/extension-base/background/KoniTypes';
|
|
5
5
|
import { getRandomIpfsGateway, SUBWALLET_IPFS } from '@subwallet/extension-base/koni/api/nft/config';
|
|
6
|
-
import { _isChainCardanoCompatible, _isChainEvmCompatible, _isChainSubstrateCompatible, _isChainTonCompatible } from '@subwallet/extension-base/services/chain-service/utils';
|
|
6
|
+
import { _isChainBitcoinCompatible, _isChainCardanoCompatible, _isChainEvmCompatible, _isChainSubstrateCompatible, _isChainTonCompatible } from '@subwallet/extension-base/services/chain-service/utils';
|
|
7
7
|
import { reformatAddress } from '@subwallet/extension-base/utils/account';
|
|
8
8
|
import { decodeAddress, encodeAddress, isCardanoAddress, isTonAddress } from '@subwallet/keyring';
|
|
9
|
+
import { isBitcoinAddress } from '@subwallet/keyring/utils/address/validate';
|
|
9
10
|
import { t } from 'i18next';
|
|
10
11
|
import { assert, BN, hexToU8a, isHex } from '@polkadot/util';
|
|
11
12
|
import { ethereumEncode, isEthereumAddress } from '@polkadot/util-crypto';
|
|
@@ -256,7 +257,8 @@ export function isAddressAndChainCompatible(address, chain) {
|
|
|
256
257
|
const isTonCompatible = isTonAddress(address) && _isChainTonCompatible(chain);
|
|
257
258
|
const isSubstrateCompatible = !isEthereumAddress(address) && !isTonAddress(address) && _isChainSubstrateCompatible(chain); // todo: need isSubstrateAddress util function to check exactly
|
|
258
259
|
const isCardanoCompatible = isCardanoAddress(address) && _isChainCardanoCompatible(chain);
|
|
259
|
-
|
|
260
|
+
const isBitcoinCompatible = isBitcoinAddress(address) && _isChainBitcoinCompatible(chain);
|
|
261
|
+
return isEvmCompatible || isSubstrateCompatible || isTonCompatible || isCardanoCompatible || isBitcoinCompatible;
|
|
260
262
|
}
|
|
261
263
|
export function getDomainFromUrl(url) {
|
|
262
264
|
return url.replace(/^(https?:\/\/)?(www\.)?/, '').split('/')[0];
|
|
@@ -342,4 +344,5 @@ export * from "./object.js";
|
|
|
342
344
|
export * from "./promise.js";
|
|
343
345
|
export * from "./registry.js";
|
|
344
346
|
export * from "./swap.js";
|
|
345
|
-
export * from "./translate.js";
|
|
347
|
+
export * from "./translate.js";
|
|
348
|
+
export * from "./bitcoin/index.js";
|