@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
@@ -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
+ }
@@ -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;
@@ -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
@@ -68,3 +68,4 @@ export * from './promise';
68
68
  export * from './registry';
69
69
  export * from './swap';
70
70
  export * from './translate';
71
+ export * from './bitcoin';
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
- return isEvmCompatible || isSubstrateCompatible || isTonCompatible || isCardanoCompatible;
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";