@subwallet/extension-base 1.3.41-0 → 1.3.43-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.
Files changed (219) hide show
  1. package/background/KoniTypes.d.ts +134 -5
  2. package/background/KoniTypes.js +18 -0
  3. package/background/errors/BitcoinProviderError.d.ts +6 -0
  4. package/background/errors/BitcoinProviderError.js +47 -0
  5. package/background/types.d.ts +1 -1
  6. package/cjs/background/KoniTypes.js +20 -1
  7. package/cjs/background/errors/BitcoinProviderError.js +54 -0
  8. package/cjs/constants/bitcoin.js +22 -0
  9. package/cjs/constants/index.js +16 -1
  10. package/cjs/core/logic-validation/recipientAddress.js +9 -0
  11. package/cjs/core/logic-validation/request.js +316 -3
  12. package/cjs/core/logic-validation/transfer.js +25 -5
  13. package/cjs/core/types.js +1 -0
  14. package/cjs/core/utils.js +15 -1
  15. package/cjs/koni/background/handlers/Extension.js +477 -93
  16. package/cjs/koni/background/handlers/State.js +249 -16
  17. package/cjs/koni/background/handlers/Tabs.js +119 -6
  18. package/cjs/packageInfo.js +1 -1
  19. package/cjs/page/bitcoin/index.js +67 -0
  20. package/cjs/page/index.js +5 -0
  21. package/cjs/services/balance-service/helpers/subscribe/bitcoin.js +94 -0
  22. package/cjs/services/balance-service/helpers/subscribe/index.js +19 -7
  23. package/cjs/services/balance-service/index.js +32 -4
  24. package/cjs/services/balance-service/transfer/bitcoin-transfer.js +119 -0
  25. package/cjs/services/balance-service/transfer/token.js +2 -0
  26. package/cjs/services/base/types.js +2 -0
  27. package/cjs/services/buy-service/index.js +17 -2
  28. package/cjs/services/chain-service/constants.js +14 -3
  29. package/cjs/services/chain-service/handler/bitcoin/BitcoinApi.js +105 -0
  30. package/cjs/services/chain-service/handler/bitcoin/BitcoinChainHandler.js +78 -0
  31. package/cjs/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/blockstream-testnet-strategy.js +371 -0
  32. package/cjs/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/index.js +19 -0
  33. package/cjs/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/mempool-testnet-strategy.js +368 -0
  34. package/cjs/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet/index.js +302 -0
  35. package/cjs/services/chain-service/handler/bitcoin/strategy/types.js +1 -0
  36. package/cjs/services/chain-service/index.js +27 -3
  37. package/cjs/services/chain-service/utils/index.js +57 -4
  38. package/cjs/services/chain-service/utils/patch.js +1 -1
  39. package/cjs/services/earning-service/handlers/native-staking/para-chain.js +27 -5
  40. package/cjs/services/event-service/index.js +4 -0
  41. package/cjs/services/fee-service/service.js +8 -3
  42. package/cjs/services/hiro-service/index.js +96 -0
  43. package/cjs/services/hiro-service/utils/index.js +85 -0
  44. package/cjs/services/history-service/bitcoin-history.js +58 -0
  45. package/cjs/services/history-service/helpers/recoverHistoryStatus.js +96 -4
  46. package/cjs/services/history-service/index.js +41 -3
  47. package/cjs/services/keyring-service/context/handlers/Derive.js +1 -1
  48. package/cjs/services/keyring-service/context/handlers/Migration.js +2 -2
  49. package/cjs/services/keyring-service/context/handlers/Mnemonic.js +4 -3
  50. package/cjs/services/migration-service/scripts/MigrateNewUnifiedAccount.js +29 -0
  51. package/cjs/services/migration-service/scripts/index.js +3 -1
  52. package/cjs/services/request-service/handler/AuthRequestHandler.js +18 -0
  53. package/cjs/services/request-service/handler/BitcoinRequestHandler.js +427 -0
  54. package/cjs/services/request-service/index.js +29 -3
  55. package/cjs/services/rune-service/index.js +105 -0
  56. package/cjs/services/transaction-service/helpers/index.js +7 -1
  57. package/cjs/services/transaction-service/index.js +206 -16
  58. package/cjs/services/transaction-service/utils.js +6 -3
  59. package/cjs/strategy/api-request-strategy/context/base.js +31 -0
  60. package/cjs/strategy/api-request-strategy/index.js +90 -0
  61. package/cjs/strategy/api-request-strategy/types.js +1 -0
  62. package/cjs/strategy/api-request-strategy/utils/index.js +33 -0
  63. package/cjs/types/account/info/keyring.js +1 -1
  64. package/cjs/types/bitcoin.js +24 -0
  65. package/cjs/types/fee/bitcoin.js +1 -0
  66. package/cjs/types/fee/index.js +11 -0
  67. package/cjs/types/index.js +11 -0
  68. package/cjs/utils/account/analyze.js +3 -3
  69. package/cjs/utils/account/common.js +16 -6
  70. package/cjs/utils/account/derive/info/solo.js +68 -19
  71. package/cjs/utils/account/derive/info/unified.js +2 -0
  72. package/cjs/utils/account/derive/validate.js +70 -2
  73. package/cjs/utils/account/transform.js +11 -5
  74. package/cjs/utils/auth.js +2 -1
  75. package/cjs/utils/bitcoin/common.js +98 -0
  76. package/cjs/utils/bitcoin/fee.js +21 -0
  77. package/cjs/utils/bitcoin/index.js +38 -0
  78. package/cjs/utils/bitcoin/utxo-management.js +281 -0
  79. package/cjs/utils/fee/transfer.js +48 -0
  80. package/cjs/utils/index.js +15 -1
  81. package/constants/bitcoin.d.ts +3 -0
  82. package/constants/bitcoin.js +13 -0
  83. package/constants/index.d.ts +2 -0
  84. package/constants/index.js +3 -1
  85. package/core/logic-validation/recipientAddress.js +10 -1
  86. package/core/logic-validation/request.d.ts +6 -2
  87. package/core/logic-validation/request.js +309 -3
  88. package/core/logic-validation/transfer.d.ts +2 -2
  89. package/core/logic-validation/transfer.js +27 -7
  90. package/core/types.d.ts +1 -0
  91. package/core/types.js +1 -0
  92. package/core/utils.d.ts +1 -0
  93. package/core/utils.js +15 -2
  94. package/koni/background/handlers/Extension.d.ts +5 -0
  95. package/koni/background/handlers/Extension.js +387 -9
  96. package/koni/background/handlers/State.d.ts +10 -3
  97. package/koni/background/handlers/State.js +240 -15
  98. package/koni/background/handlers/Tabs.d.ts +7 -2
  99. package/koni/background/handlers/Tabs.js +119 -9
  100. package/package.json +149 -8
  101. package/packageInfo.js +1 -1
  102. package/page/bitcoin/index.d.ts +17 -0
  103. package/page/bitcoin/index.js +60 -0
  104. package/page/index.d.ts +2 -1
  105. package/page/index.js +4 -0
  106. package/services/balance-service/helpers/subscribe/bitcoin.d.ts +2 -0
  107. package/services/balance-service/helpers/subscribe/bitcoin.js +87 -0
  108. package/services/balance-service/helpers/subscribe/index.d.ts +2 -2
  109. package/services/balance-service/helpers/subscribe/index.js +20 -8
  110. package/services/balance-service/index.d.ts +2 -0
  111. package/services/balance-service/index.js +32 -4
  112. package/services/balance-service/transfer/bitcoin-transfer.d.ts +14 -0
  113. package/services/balance-service/transfer/bitcoin-transfer.js +112 -0
  114. package/services/balance-service/transfer/cardano-transfer.d.ts +2 -0
  115. package/services/balance-service/transfer/token.js +2 -0
  116. package/services/base/types.d.ts +2 -0
  117. package/services/base/types.js +2 -0
  118. package/services/buy-service/index.js +17 -2
  119. package/services/chain-service/constants.d.ts +6 -0
  120. package/services/chain-service/constants.js +8 -2
  121. package/services/chain-service/handler/bitcoin/BitcoinApi.d.ts +31 -0
  122. package/services/chain-service/handler/bitcoin/BitcoinApi.js +98 -0
  123. package/services/chain-service/handler/bitcoin/BitcoinChainHandler.d.ts +16 -0
  124. package/services/chain-service/handler/bitcoin/BitcoinChainHandler.js +70 -0
  125. package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/blockstream-testnet-strategy.d.ts +28 -0
  126. package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/blockstream-testnet-strategy.js +362 -0
  127. package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/index.d.ts +2 -0
  128. package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/index.js +5 -0
  129. package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/mempool-testnet-strategy.d.ts +28 -0
  130. package/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/mempool-testnet-strategy.js +359 -0
  131. package/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet/index.d.ts +28 -0
  132. package/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet/index.js +293 -0
  133. package/services/chain-service/handler/bitcoin/strategy/types.d.ts +291 -0
  134. package/services/chain-service/handler/bitcoin/strategy/types.js +1 -0
  135. package/services/chain-service/index.d.ts +3 -0
  136. package/services/chain-service/index.js +31 -5
  137. package/services/chain-service/types.d.ts +20 -0
  138. package/services/chain-service/utils/index.d.ts +4 -0
  139. package/services/chain-service/utils/index.js +50 -4
  140. package/services/chain-service/utils/patch.js +1 -1
  141. package/services/earning-service/handlers/native-staking/para-chain.js +27 -5
  142. package/services/event-service/index.d.ts +3 -0
  143. package/services/event-service/index.js +4 -0
  144. package/services/event-service/types.d.ts +3 -0
  145. package/services/fee-service/service.js +8 -3
  146. package/services/hiro-service/index.d.ts +17 -0
  147. package/services/hiro-service/index.js +88 -0
  148. package/services/hiro-service/utils/index.d.ts +6 -0
  149. package/services/hiro-service/utils/index.js +72 -0
  150. package/services/history-service/bitcoin-history.d.ts +4 -0
  151. package/services/history-service/bitcoin-history.js +52 -0
  152. package/services/history-service/helpers/recoverHistoryStatus.d.ts +3 -1
  153. package/services/history-service/helpers/recoverHistoryStatus.js +96 -4
  154. package/services/history-service/index.d.ts +1 -0
  155. package/services/history-service/index.js +42 -4
  156. package/services/keyring-service/context/handlers/Derive.js +2 -2
  157. package/services/keyring-service/context/handlers/Migration.js +2 -2
  158. package/services/keyring-service/context/handlers/Mnemonic.js +4 -3
  159. package/services/migration-service/scripts/MigrateNewUnifiedAccount.d.ts +4 -0
  160. package/services/migration-service/scripts/MigrateNewUnifiedAccount.js +21 -0
  161. package/services/migration-service/scripts/index.js +3 -1
  162. package/services/request-service/handler/AuthRequestHandler.js +19 -1
  163. package/services/request-service/handler/BitcoinRequestHandler.d.ts +22 -0
  164. package/services/request-service/handler/BitcoinRequestHandler.js +414 -0
  165. package/services/request-service/index.d.ts +8 -2
  166. package/services/request-service/index.js +25 -3
  167. package/services/rune-service/index.d.ts +17 -0
  168. package/services/rune-service/index.js +97 -0
  169. package/services/transaction-service/helpers/index.d.ts +3 -1
  170. package/services/transaction-service/helpers/index.js +5 -0
  171. package/services/transaction-service/index.d.ts +4 -5
  172. package/services/transaction-service/index.js +205 -17
  173. package/services/transaction-service/types.d.ts +13 -2
  174. package/services/transaction-service/utils.js +7 -4
  175. package/strategy/api-request-strategy/context/base.d.ts +15 -0
  176. package/strategy/api-request-strategy/context/base.js +24 -0
  177. package/strategy/api-request-strategy/index.d.ts +15 -0
  178. package/strategy/api-request-strategy/index.js +83 -0
  179. package/strategy/api-request-strategy/types.d.ts +22 -0
  180. package/strategy/api-request-strategy/types.js +1 -0
  181. package/strategy/api-request-strategy/utils/index.d.ts +2 -0
  182. package/strategy/api-request-strategy/utils/index.js +23 -0
  183. package/types/account/info/keyring.d.ts +1 -1
  184. package/types/account/info/keyring.js +1 -1
  185. package/types/balance/index.d.ts +4 -1
  186. package/types/balance/transfer.d.ts +19 -0
  187. package/types/bitcoin.d.ts +93 -0
  188. package/types/bitcoin.js +17 -0
  189. package/types/buy.d.ts +1 -1
  190. package/types/fee/base.d.ts +4 -1
  191. package/types/fee/bitcoin.d.ts +18 -0
  192. package/types/fee/bitcoin.js +1 -0
  193. package/types/fee/index.d.ts +1 -0
  194. package/types/fee/index.js +2 -1
  195. package/types/fee/subscription.d.ts +4 -3
  196. package/types/index.d.ts +1 -0
  197. package/types/index.js +1 -0
  198. package/utils/account/analyze.js +4 -4
  199. package/utils/account/common.d.ts +7 -8
  200. package/utils/account/common.js +16 -6
  201. package/utils/account/derive/info/solo.js +70 -21
  202. package/utils/account/derive/info/unified.js +2 -0
  203. package/utils/account/derive/validate.d.ts +1 -0
  204. package/utils/account/derive/validate.js +68 -1
  205. package/utils/account/transform.d.ts +1 -1
  206. package/utils/account/transform.js +11 -5
  207. package/utils/auth.js +3 -2
  208. package/utils/bitcoin/common.d.ts +22 -0
  209. package/utils/bitcoin/common.js +88 -0
  210. package/utils/bitcoin/fee.d.ts +2 -0
  211. package/utils/bitcoin/fee.js +14 -0
  212. package/utils/bitcoin/index.d.ts +3 -0
  213. package/utils/bitcoin/index.js +6 -0
  214. package/utils/bitcoin/utxo-management.d.ts +33 -0
  215. package/utils/bitcoin/utxo-management.js +266 -0
  216. package/utils/fee/transfer.d.ts +3 -1
  217. package/utils/fee/transfer.js +47 -1
  218. package/utils/index.d.ts +1 -0
  219. package/utils/index.js +6 -3
@@ -32,6 +32,9 @@ export class BalanceService {
32
32
  stopPromiseHandler = createPromiseHandler();
33
33
  status = ServiceStatus.NOT_INITIALIZED;
34
34
  isReload = false;
35
+ get isStarted() {
36
+ return this.status === ServiceStatus.STARTED;
37
+ }
35
38
  detectAccountBalanceStore = new DetectAccountBalanceStore();
36
39
  balanceDetectSubject = new BehaviorSubject({});
37
40
  intervalTime = 3 * 60 * 1000;
@@ -57,7 +60,7 @@ export class BalanceService {
57
60
  this.status = ServiceStatus.INITIALIZED;
58
61
 
59
62
  // Start service
60
- await this.start();
63
+ // await this.start(); // Commented out to avoid auto start when app not fully initialized
61
64
 
62
65
  // Handle events
63
66
  this.state.eventService.onLazy(this.handleEvents.bind(this));
@@ -143,7 +146,7 @@ export class BalanceService {
143
146
  }
144
147
  if (needReload) {
145
148
  addLazy('reloadBalanceByEvents', () => {
146
- if (!this.isReload) {
149
+ if (!this.isReload && this.isStarted) {
147
150
  this.runSubscribeBalances().catch(console.error);
148
151
  }
149
152
  }, lazyTime, undefined, true);
@@ -194,8 +197,9 @@ export class BalanceService {
194
197
  const substrateApiMap = this.state.chainService.getSubstrateApiMap();
195
198
  const tonApiMap = this.state.chainService.getTonApiMap();
196
199
  const cardanoApiMap = this.state.chainService.getCardanoApiMap();
200
+ const bitcoinApiMap = this.state.chainService.getBitcoinApiMap();
197
201
  let unsub = noop;
198
- unsub = subscribeBalance([address], [chain], [tSlug], assetMap, chainInfoMap, substrateApiMap, evmApiMap, tonApiMap, cardanoApiMap, result => {
202
+ unsub = subscribeBalance([address], [chain], [tSlug], assetMap, chainInfoMap, substrateApiMap, evmApiMap, tonApiMap, cardanoApiMap, bitcoinApiMap, result => {
199
203
  const rs = result[0];
200
204
  let value;
201
205
  switch (balanceType) {
@@ -366,13 +370,14 @@ export class BalanceService {
366
370
  const substrateApiMap = this.state.chainService.getSubstrateApiMap();
367
371
  const tonApiMap = this.state.chainService.getTonApiMap();
368
372
  const cardanoApiMap = this.state.chainService.getCardanoApiMap();
373
+ const bitcoinApiMap = this.state.chainService.getBitcoinApiMap();
369
374
  const activeChainSlugs = Object.keys(this.state.getActiveChainInfoMap());
370
375
  const assetState = this.state.chainService.subscribeAssetSettings().value;
371
376
  const assets = Object.values(assetMap).filter(asset => {
372
377
  var _assetState$asset$slu;
373
378
  return activeChainSlugs.includes(asset.originChain) && ((_assetState$asset$slu = assetState[asset.slug]) === null || _assetState$asset$slu === void 0 ? void 0 : _assetState$asset$slu.visible);
374
379
  }).map(asset => asset.slug);
375
- const unsub = subscribeBalance(addresses, activeChainSlugs, assets, assetMap, chainInfoMap, substrateApiMap, evmApiMap, tonApiMap, cardanoApiMap, result => {
380
+ const unsub = subscribeBalance(addresses, activeChainSlugs, assets, assetMap, chainInfoMap, substrateApiMap, evmApiMap, tonApiMap, cardanoApiMap, bitcoinApiMap, result => {
376
381
  !cancel && this.setBalanceItem(result);
377
382
  }, ExtrinsicType.TRANSFER_BALANCE);
378
383
  const unsub2 = this.state.subscribeMantaPayBalance();
@@ -382,6 +387,29 @@ export class BalanceService {
382
387
  unsub2 && unsub2();
383
388
  };
384
389
  }
390
+ async refreshBalanceForAddress(address, chain, asset, extrinsicType) {
391
+ // Check if address and chain are valid
392
+ const chainInfoMap = this.state.chainService.getChainInfoMap();
393
+ if (!chainInfoMap[chain]) {
394
+ console.warn(`Chain ${chain} is not supported`);
395
+ return;
396
+ }
397
+
398
+ // Get necessary data
399
+ const assetMap = this.state.chainService.getAssetRegistry();
400
+ const evmApiMap = this.state.chainService.getEvmApiMap();
401
+ const substrateApiMap = this.state.chainService.getSubstrateApiMap();
402
+ const tonApiMap = this.state.chainService.getTonApiMap();
403
+ const cardanoApiMap = this.state.chainService.getCardanoApiMap();
404
+ const bitcoinApiMap = this.state.chainService.getBitcoinApiMap();
405
+ return new Promise(resolve => {
406
+ const unsub = subscribeBalance([address], [chain], [asset], assetMap, chainInfoMap, substrateApiMap, evmApiMap, tonApiMap, cardanoApiMap, bitcoinApiMap, result => {
407
+ this.setBalanceItem(result);
408
+ unsub();
409
+ resolve();
410
+ }, extrinsicType || ExtrinsicType.TRANSFER_BALANCE);
411
+ });
412
+ }
385
413
 
386
414
  /** Unsubscribe balance subscription */
387
415
  runUnsubscribeBalances() {
@@ -0,0 +1,14 @@
1
+ import { _BitcoinApi } from '@subwallet/extension-base/services/chain-service/types';
2
+ import { FeeInfo, TransactionFee } from '@subwallet/extension-base/types';
3
+ import { Network, Psbt } from 'bitcoinjs-lib';
4
+ export interface TransferBitcoinProps extends TransactionFee {
5
+ bitcoinApi: _BitcoinApi;
6
+ chain: string;
7
+ from: string;
8
+ feeInfo: FeeInfo;
9
+ to: string;
10
+ transferAll: boolean;
11
+ value: string;
12
+ network: Network;
13
+ }
14
+ export declare function createBitcoinTransaction(params: TransferBitcoinProps): Promise<[Psbt, string, string | undefined]>;
@@ -0,0 +1,112 @@
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 { _BITCOIN_CHAIN_SLUG, _BITCOIN_NAME, _BITCOIN_TESTNET_NAME } from '@subwallet/extension-base/services/chain-service/constants';
6
+ import { combineBitcoinFee, determineUtxosForSpend, determineUtxosForSpendAll, getTransferableBitcoinUtxos } from '@subwallet/extension-base/utils';
7
+ import { BitcoinAddressType } from '@subwallet/keyring/types';
8
+ import { getBitcoinAddressInfo } from '@subwallet/keyring/utils';
9
+ import { keyring } from '@subwallet/ui-keyring';
10
+ import BigN from 'bignumber.js';
11
+ import { Psbt } from 'bitcoinjs-lib';
12
+ export async function createBitcoinTransaction(params) {
13
+ const {
14
+ bitcoinApi,
15
+ chain,
16
+ feeCustom: _feeCustom,
17
+ feeInfo: _feeInfo,
18
+ feeOption,
19
+ from,
20
+ network,
21
+ to,
22
+ transferAll,
23
+ value
24
+ } = params;
25
+ const feeCustom = _feeCustom;
26
+ const feeInfo = _feeInfo;
27
+ const bitcoinFee = combineBitcoinFee(feeInfo, feeOption, feeCustom);
28
+ const utxos = await getTransferableBitcoinUtxos(bitcoinApi, from);
29
+ try {
30
+ const amountValue = parseFloat(value);
31
+ const determineUtxosArgs = {
32
+ amount: amountValue,
33
+ feeRate: bitcoinFee.feeRate,
34
+ recipient: to,
35
+ sender: from,
36
+ utxos
37
+ };
38
+ const {
39
+ fee,
40
+ inputs,
41
+ isCustomFeeRate,
42
+ outputs,
43
+ size
44
+ } = transferAll ? determineUtxosForSpendAll(determineUtxosArgs) : determineUtxosForSpend(determineUtxosArgs);
45
+ const pair = keyring.getPair(from);
46
+ const tx = new Psbt({
47
+ network
48
+ });
49
+ let transferAmount = new BigN(0);
50
+ for (const input of inputs) {
51
+ const addressInfo = getBitcoinAddressInfo(pair.address);
52
+ if (addressInfo.type === BitcoinAddressType.p2pkh || addressInfo.type === BitcoinAddressType.p2sh) {
53
+ // BIP-44 (Legacy)
54
+ const hex = await bitcoinApi.api.getTxHex(input.txid);
55
+ tx.addInput({
56
+ hash: input.txid,
57
+ index: input.vout,
58
+ nonWitnessUtxo: Buffer.from(hex, 'hex')
59
+ });
60
+ } else if (addressInfo.type === BitcoinAddressType.p2wpkh) {
61
+ // BIP-84 (Native SegWit)
62
+ tx.addInput({
63
+ hash: input.txid,
64
+ index: input.vout,
65
+ witnessUtxo: {
66
+ script: pair.bitcoin.output,
67
+ value: input.value
68
+ }
69
+ });
70
+ } else if (addressInfo.type === BitcoinAddressType.p2tr) {
71
+ // BIP-86 (Taproot)
72
+ tx.addInput({
73
+ hash: input.txid,
74
+ index: input.vout,
75
+ witnessUtxo: {
76
+ script: pair.bitcoin.output,
77
+ value: input.value // UTXO value in satoshis
78
+ },
79
+
80
+ tapInternalKey: pair.bitcoin.internalPubkey // X-only public key (32 bytes)
81
+ });
82
+ } else {
83
+ throw new Error(`Unsupported address type: ${addressInfo.type}`);
84
+ }
85
+ }
86
+ for (const output of outputs) {
87
+ tx.addOutput({
88
+ address: output.address || from,
89
+ value: output.value
90
+ });
91
+ if (output.address === to) {
92
+ transferAmount = transferAmount.plus(output.value);
93
+ }
94
+ }
95
+ const customFeeRate = fee / size;
96
+ const customFeeRateResult = isCustomFeeRate ? customFeeRate.toString() : undefined;
97
+ return [tx, transferAmount.toString(), customFeeRateResult];
98
+ } catch (e) {
99
+ if (e instanceof TransactionError) {
100
+ throw e;
101
+ }
102
+ console.warn('Failed to create Bitcoin transaction:', e);
103
+ throw new Error(`You don’t have enough BTC (${convertChainToSymbol(chain)}) for the transaction. Lower your BTC amount and try again`);
104
+ }
105
+ }
106
+ function convertChainToSymbol(chain) {
107
+ if (chain === _BITCOIN_CHAIN_SLUG) {
108
+ return _BITCOIN_NAME;
109
+ } else {
110
+ return _BITCOIN_TESTNET_NAME;
111
+ }
112
+ }
@@ -1,4 +1,5 @@
1
1
  import { _ChainAsset } from '@subwallet/chain-list/types';
2
+ import { ErrorValidation } from '@subwallet/extension-base/background/KoniTypes';
2
3
  import { _CardanoApi } from '@subwallet/extension-base/services/chain-service/types';
3
4
  export interface CardanoTransactionConfigProps {
4
5
  tokenInfo: _ChainAsset;
@@ -20,5 +21,6 @@ export interface CardanoTransactionConfig {
20
21
  cardanoTtlOffset: number;
21
22
  estimateCardanoFee: string;
22
23
  cardanoPayload: string;
24
+ errors?: ErrorValidation[];
23
25
  }
24
26
  export declare function createCardanoTransaction(params: CardanoTransactionConfigProps): Promise<[CardanoTransactionConfig | null, string]>;
@@ -108,6 +108,8 @@ export const createSubstrateExtrinsic = async ({
108
108
  transfer = api.tx.balances.transfer(to, new BN(value));
109
109
  }
110
110
  }
111
+ } else if (_TRANSFER_CHAIN_GROUP.truth.includes(networkKey)) {
112
+ transfer = api.tx.assetManager.transfer(to, _getTokenOnChainInfo(tokenInfo), value);
111
113
  }
112
114
  return [transfer, transferAmount || value];
113
115
  };
@@ -5,6 +5,8 @@ export declare enum ServiceStatus {
5
5
  INITIALIZED = "initialized",
6
6
  STARTED = "started",
7
7
  STARTING = "starting",
8
+ STARTED_FULL = "started_full",
9
+ STARTING_FULL = "starting_full",
8
10
  STOPPED = "stopped",
9
11
  STOPPING = "stopping"
10
12
  }
@@ -10,6 +10,8 @@ export let ServiceStatus;
10
10
  ServiceStatus["INITIALIZED"] = "initialized";
11
11
  ServiceStatus["STARTED"] = "started";
12
12
  ServiceStatus["STARTING"] = "starting";
13
+ ServiceStatus["STARTED_FULL"] = "started_full";
14
+ ServiceStatus["STARTING_FULL"] = "starting_full";
13
15
  ServiceStatus["STOPPED"] = "stopped";
14
16
  ServiceStatus["STOPPING"] = "stopping";
15
17
  })(ServiceStatus || (ServiceStatus = {}));
@@ -6,7 +6,18 @@ import { fetchStaticData } from '@subwallet/extension-base/utils/fetchStaticData
6
6
  import { BehaviorSubject } from 'rxjs';
7
7
  import { DEFAULT_SERVICE_INFO } from "./constants/index.js";
8
8
  const convertSupportType = support => {
9
- return support === 'ETHEREUM' ? AccountChainType.ETHEREUM : AccountChainType.SUBSTRATE;
9
+ switch (support) {
10
+ case 'ETHEREUM':
11
+ return AccountChainType.ETHEREUM;
12
+ case 'SUBSTRATE':
13
+ return AccountChainType.SUBSTRATE;
14
+ case 'CARDANO':
15
+ return AccountChainType.CARDANO;
16
+ case 'TON':
17
+ return AccountChainType.TON;
18
+ default:
19
+ return null;
20
+ }
10
21
  };
11
22
  export default class BuyService {
12
23
  #state;
@@ -29,11 +40,15 @@ export default class BuyService {
29
40
  const data = await fetchStaticData('buy-token-configs');
30
41
  const result = {};
31
42
  for (const datum of data) {
43
+ const support = convertSupportType(datum.support);
44
+ if (!support) {
45
+ continue;
46
+ }
32
47
  const temp = {
33
48
  serviceInfo: {
34
49
  ...DEFAULT_SERVICE_INFO
35
50
  },
36
- support: convertSupportType(datum.support),
51
+ support,
37
52
  services: [],
38
53
  slug: datum.slug,
39
54
  symbol: datum.symbol,
@@ -72,6 +72,7 @@ export declare const _TRANSFER_CHAIN_GROUP: {
72
72
  pendulum: string[];
73
73
  centrifuge: string[];
74
74
  disable_transfer: string[];
75
+ truth: string[];
75
76
  };
76
77
  export declare const _BALANCE_PARSING_CHAIN_GROUP: {
77
78
  bobabeam: string[];
@@ -95,9 +96,14 @@ export declare const EVM_REFORMAT_DECIMALS: {
95
96
  acala: string[];
96
97
  };
97
98
  export declare const LATEST_CHAIN_DATA_FETCHING_INTERVAL = 120000;
99
+ export declare const _BITCOIN_CHAIN_SLUG = "bitcoin";
100
+ export declare const _BITCOIN_TESTNET_CHAIN_SLUG = "bitcoinTestnet";
101
+ export declare const _BITCOIN_NAME = "Bitcoin";
102
+ export declare const _BITCOIN_TESTNET_NAME = "Bitcoin Testnet";
98
103
  export declare const _CHAIN_INFO_SRC: string;
99
104
  export declare const _CHAIN_ASSET_SRC: string;
100
105
  export declare const _ASSET_REF_SRC: string;
101
106
  export declare const _MULTI_CHAIN_ASSET_SRC: string;
102
107
  export declare const _CHAIN_LOGO_MAP_SRC: string;
103
108
  export declare const _ASSET_LOGO_MAP_SRC: string;
109
+ export declare const _BTC_SERVICE_TOKEN: string;
@@ -261,7 +261,8 @@ export const _TRANSFER_CHAIN_GROUP = {
261
261
  avail: ['kate', 'goldberg_testnet'],
262
262
  pendulum: ['pendulum', 'amplitude', 'amplitude_test', 'hydradx_main', 'bifrost', 'bifrost_dot', 'jamton'],
263
263
  centrifuge: ['centrifuge'],
264
- disable_transfer: ['crab', 'pangolin']
264
+ disable_transfer: ['crab', 'pangolin'],
265
+ truth: ['truth_network']
265
266
  };
266
267
  export const _BALANCE_PARSING_CHAIN_GROUP = {
267
268
  bobabeam: ['bobabeam', 'bobabase']
@@ -302,9 +303,14 @@ export const LATEST_CHAIN_DATA_FETCHING_INTERVAL = 120000;
302
303
 
303
304
  // TODO: review
304
305
  const TARGET_BRANCH = process.env.NODE_ENV !== 'production' ? 'koni-dev' : 'master';
306
+ export const _BITCOIN_CHAIN_SLUG = 'bitcoin';
307
+ export const _BITCOIN_TESTNET_CHAIN_SLUG = 'bitcoinTestnet';
308
+ export const _BITCOIN_NAME = 'Bitcoin';
309
+ export const _BITCOIN_TESTNET_NAME = 'Bitcoin Testnet';
305
310
  export const _CHAIN_INFO_SRC = `https://raw.githubusercontent.com/Koniverse/SubWallet-Chain/${TARGET_BRANCH}/packages/chain-list/src/data/ChainInfo.json`;
306
311
  export const _CHAIN_ASSET_SRC = `https://raw.githubusercontent.com/Koniverse/SubWallet-Chain/${TARGET_BRANCH}/packages/chain-list/src/data/ChainAsset.json`;
307
312
  export const _ASSET_REF_SRC = `https://raw.githubusercontent.com/Koniverse/SubWallet-Chain/${TARGET_BRANCH}/packages/chain-list/src/data/AssetRef.json`;
308
313
  export const _MULTI_CHAIN_ASSET_SRC = `https://raw.githubusercontent.com/Koniverse/SubWallet-Chain/${TARGET_BRANCH}/packages/chain-list/src/data/MultiChainAsset.json`;
309
314
  export const _CHAIN_LOGO_MAP_SRC = `https://raw.githubusercontent.com/Koniverse/SubWallet-Chain/${TARGET_BRANCH}/packages/chain-list/src/data/ChainLogoMap.json`;
310
- export const _ASSET_LOGO_MAP_SRC = `https://raw.githubusercontent.com/Koniverse/SubWallet-Chain/${TARGET_BRANCH}/packages/chain-list/src/data/AssetLogoMap.json`;
315
+ export const _ASSET_LOGO_MAP_SRC = `https://raw.githubusercontent.com/Koniverse/SubWallet-Chain/${TARGET_BRANCH}/packages/chain-list/src/data/AssetLogoMap.json`;
316
+ export const _BTC_SERVICE_TOKEN = process.env.BTC_SERVICE_TOKEN || '';
@@ -0,0 +1,31 @@
1
+ import { BitcoinApiStrategy } from '@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/types';
2
+ import { PromiseHandler } from '@subwallet/extension-base/utils/promise';
3
+ import { BehaviorSubject } from 'rxjs';
4
+ import { _ApiOptions } from '../../handler/types';
5
+ import { _BitcoinApi, _ChainConnectionStatus } from '../../types';
6
+ export declare class BitcoinApi implements _BitcoinApi {
7
+ chainSlug: string;
8
+ apiUrl: string;
9
+ apiError?: string;
10
+ apiRetry: number;
11
+ readonly isApiConnectedSubject: BehaviorSubject<boolean>;
12
+ readonly connectionStatusSubject: BehaviorSubject<_ChainConnectionStatus>;
13
+ isApiReady: boolean;
14
+ isApiReadyOnce: boolean;
15
+ isReadyHandler: PromiseHandler<_BitcoinApi>;
16
+ providerName: string;
17
+ api: BitcoinApiStrategy;
18
+ constructor(chainSlug: string, apiUrl: string, { providerName }?: _ApiOptions);
19
+ get isApiConnected(): boolean;
20
+ private createApiStrategy;
21
+ get connectionStatus(): _ChainConnectionStatus;
22
+ private updateConnectionStatus;
23
+ get isReady(): Promise<_BitcoinApi>;
24
+ updateApiUrl(apiUrl: string): Promise<void>;
25
+ recoverConnect(): Promise<void>;
26
+ connect(): void;
27
+ disconnect(): Promise<void>;
28
+ destroy(): Promise<void>;
29
+ onConnect(): void;
30
+ onDisconnect(): void;
31
+ }
@@ -0,0 +1,98 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { BlockStreamTestnetRequestStrategy, MempoolTestnetRequestStrategy } from '@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet';
5
+ import { SubWalletMainnetRequestStrategy } from '@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet';
6
+ import { createPromiseHandler } from '@subwallet/extension-base/utils/promise';
7
+ import { BehaviorSubject } from 'rxjs';
8
+ import { _ChainConnectionStatus } from "../../types.js";
9
+
10
+ // const isBlockStreamProvider = (apiUrl: string): boolean => apiUrl === 'https://blockstream-testnet.openbit.app' || apiUrl === 'https://electrs.openbit.app';
11
+ // const BLOCKSTREAM_TESTNET_API_URL = 'https://blockstream.info/testnet/api/';
12
+ // const MEMPOOL_TESTNET_V4_API_URL = 'https://mempool.space/testnet4/api/';
13
+
14
+ export class BitcoinApi {
15
+ apiRetry = 0;
16
+ isApiConnectedSubject = new BehaviorSubject(false);
17
+ connectionStatusSubject = new BehaviorSubject(_ChainConnectionStatus.DISCONNECTED);
18
+ isApiReady = false;
19
+ isApiReadyOnce = false;
20
+ constructor(chainSlug, apiUrl, {
21
+ providerName
22
+ } = {}) {
23
+ this.chainSlug = chainSlug;
24
+ this.apiUrl = apiUrl;
25
+ this.providerName = providerName || 'unknown';
26
+ this.isReadyHandler = createPromiseHandler();
27
+ this.api = this.createApiStrategy(apiUrl);
28
+ this.connect();
29
+ }
30
+ get isApiConnected() {
31
+ return this.isApiConnectedSubject.getValue();
32
+ }
33
+ createApiStrategy(apiUrl) {
34
+ const isTestnet = apiUrl.includes('testnet');
35
+ const isBlockstreamUrl = apiUrl.includes('blockstream');
36
+ if (isTestnet) {
37
+ return isBlockstreamUrl ? new BlockStreamTestnetRequestStrategy(apiUrl) : new MempoolTestnetRequestStrategy(apiUrl);
38
+ }
39
+ return new SubWalletMainnetRequestStrategy(apiUrl);
40
+ }
41
+ get connectionStatus() {
42
+ return this.connectionStatusSubject.getValue();
43
+ }
44
+ updateConnectionStatus(status) {
45
+ const isConnected = status === _ChainConnectionStatus.CONNECTED;
46
+ if (isConnected !== this.isApiConnectedSubject.value) {
47
+ this.isApiConnectedSubject.next(isConnected);
48
+ }
49
+ if (status !== this.connectionStatusSubject.value) {
50
+ this.connectionStatusSubject.next(status);
51
+ }
52
+ }
53
+ get isReady() {
54
+ return this.isReadyHandler.promise;
55
+ }
56
+ async updateApiUrl(apiUrl) {
57
+ if (this.apiUrl === apiUrl) {
58
+ return;
59
+ }
60
+ await this.disconnect();
61
+ this.apiUrl = apiUrl;
62
+ this.api = this.createApiStrategy(apiUrl);
63
+ this.connect();
64
+ }
65
+ async recoverConnect() {
66
+ await this.isReadyHandler.promise;
67
+ }
68
+ connect() {
69
+ this.updateConnectionStatus(_ChainConnectionStatus.CONNECTING);
70
+ this.onConnect();
71
+ }
72
+ async disconnect() {
73
+ this.onDisconnect();
74
+ this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED);
75
+ return Promise.resolve();
76
+ }
77
+ destroy() {
78
+ return this.disconnect();
79
+ }
80
+ onConnect() {
81
+ if (!this.isApiConnected) {
82
+ console.log(`Connected to ${this.chainSlug} at ${this.apiUrl}`);
83
+ this.isApiReady = true;
84
+ if (this.isApiReadyOnce) {
85
+ this.isReadyHandler.resolve(this);
86
+ }
87
+ }
88
+ this.updateConnectionStatus(_ChainConnectionStatus.CONNECTED);
89
+ }
90
+ onDisconnect() {
91
+ this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED);
92
+ if (this.isApiConnected) {
93
+ console.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl}`);
94
+ this.isApiReady = false;
95
+ this.isReadyHandler = createPromiseHandler();
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,16 @@
1
+ import { ChainService } from '@subwallet/extension-base/services/chain-service';
2
+ import { AbstractChainHandler } from '../AbstractChainHandler';
3
+ import { _ApiOptions } from '../types';
4
+ import { BitcoinApi } from './BitcoinApi';
5
+ export declare class BitcoinChainHandler extends AbstractChainHandler {
6
+ private apiMap;
7
+ constructor(parent?: ChainService);
8
+ getApiMap(): Record<string, BitcoinApi>;
9
+ getApiByChain(chain: string): BitcoinApi;
10
+ setApi(chainSlug: string, api: BitcoinApi): void;
11
+ initApi(chainSlug: string, apiUrl: string, { onUpdateStatus, providerName }?: Omit<_ApiOptions, 'metadata'>): Promise<BitcoinApi>;
12
+ recoverApi(chainSlug: string): Promise<void>;
13
+ destroyApi(chain: string): void;
14
+ sleep(): Promise<void>;
15
+ wakeUp(): Promise<void>;
16
+ }
@@ -0,0 +1,70 @@
1
+ // Copyright 2019-2022 @subwallet/extension-base authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { AbstractChainHandler } from "../AbstractChainHandler.js";
5
+ import { BitcoinApi } from "./BitcoinApi.js";
6
+ export class BitcoinChainHandler extends AbstractChainHandler {
7
+ apiMap = {};
8
+
9
+ // eslint-disable-next-line no-useless-constructor
10
+ constructor(parent) {
11
+ super(parent);
12
+ }
13
+ getApiMap() {
14
+ return this.apiMap;
15
+ }
16
+ getApiByChain(chain) {
17
+ return this.apiMap[chain];
18
+ }
19
+ setApi(chainSlug, api) {
20
+ this.apiMap[chainSlug] = api;
21
+ }
22
+ async initApi(chainSlug, apiUrl, {
23
+ onUpdateStatus,
24
+ providerName
25
+ } = {}) {
26
+ const existed = this.getApiByChain(chainSlug);
27
+ if (existed) {
28
+ existed.connect();
29
+ if (apiUrl !== existed.apiUrl) {
30
+ existed.updateApiUrl(apiUrl).catch(console.error);
31
+ }
32
+ return existed;
33
+ }
34
+ const apiObject = new BitcoinApi(chainSlug, apiUrl, {
35
+ providerName
36
+ });
37
+ apiObject.connectionStatusSubject.subscribe(this.handleConnection.bind(this, chainSlug));
38
+ apiObject.connectionStatusSubject.subscribe(onUpdateStatus);
39
+ return Promise.resolve(apiObject);
40
+ }
41
+ async recoverApi(chainSlug) {
42
+ const existed = this.getApiByChain(chainSlug);
43
+ if (existed && !existed.isApiReadyOnce) {
44
+ console.log(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`);
45
+ return existed.recoverConnect();
46
+ }
47
+ }
48
+ destroyApi(chain) {
49
+ const api = this.getApiByChain(chain);
50
+ api === null || api === void 0 ? void 0 : api.destroy().catch(console.error);
51
+ }
52
+ async sleep() {
53
+ this.isSleeping = true;
54
+ this.cancelAllRecover();
55
+ await Promise.all(Object.values(this.getApiMap()).map(evmApi => {
56
+ return evmApi.disconnect().catch(console.error);
57
+ }));
58
+ return Promise.resolve();
59
+ }
60
+ wakeUp() {
61
+ var _this$parent;
62
+ this.isSleeping = false;
63
+ const activeChains = ((_this$parent = this.parent) === null || _this$parent === void 0 ? void 0 : _this$parent.getActiveChains()) || [];
64
+ for (const chain of activeChains) {
65
+ const api = this.getApiByChain(chain);
66
+ api === null || api === void 0 ? void 0 : api.connect();
67
+ }
68
+ return Promise.resolve();
69
+ }
70
+ }
@@ -0,0 +1,28 @@
1
+ import { BitcoinAddressSummaryInfo, BitcoinApiStrategy, BitcoinTransactionEventMap, BlockStreamTransactionDetail, BlockStreamTransactionStatus, Inscription, RunesInfoByAddress } from '@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/types';
2
+ import { BaseApiRequestStrategy } from '@subwallet/extension-base/strategy/api-request-strategy';
3
+ import { BitcoinFeeInfo, BitcoinTx, UtxoResponseItem } from '@subwallet/extension-base/types';
4
+ import EventEmitter from 'eventemitter3';
5
+ export declare class BlockStreamTestnetRequestStrategy extends BaseApiRequestStrategy implements BitcoinApiStrategy {
6
+ private readonly baseUrl;
7
+ private readonly isTestnet;
8
+ private timePerBlock;
9
+ constructor(url: string);
10
+ private headers;
11
+ isRateLimited(): boolean;
12
+ getUrl(path: string): string;
13
+ getBlockTime(): Promise<number>;
14
+ computeBlockTime(): Promise<number>;
15
+ getAddressSummaryInfo(address: string): Promise<BitcoinAddressSummaryInfo>;
16
+ getAddressTransaction(address: string, limit?: number): Promise<BitcoinTx[]>;
17
+ getTransactionStatus(txHash: string): Promise<BlockStreamTransactionStatus>;
18
+ getTransactionDetail(txHash: string): Promise<BlockStreamTransactionDetail>;
19
+ getFeeRate(): Promise<BitcoinFeeInfo>;
20
+ getRecommendedFeeRate(): Promise<BitcoinFeeInfo>;
21
+ getUtxos(address: string): Promise<UtxoResponseItem[]>;
22
+ sendRawTransaction(rawTransaction: string): EventEmitter<BitcoinTransactionEventMap, any>;
23
+ simpleSendRawTransaction(rawTransaction: string): Promise<string>;
24
+ getRunes(address: string): Promise<RunesInfoByAddress[]>;
25
+ getRuneUtxos(address: string): Promise<import("@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/types").RuneUtxo[]>;
26
+ getAddressInscriptions(address: string): Promise<Inscription[]>;
27
+ getTxHex(txHash: string): Promise<string>;
28
+ }