@uswap/toolboxes 4.3.6

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 (275) hide show
  1. package/dist/src/cardano/index.cjs +4 -0
  2. package/dist/src/cardano/index.cjs.map +11 -0
  3. package/dist/src/cardano/index.js +4 -0
  4. package/dist/src/cardano/index.js.map +11 -0
  5. package/dist/src/cosmos/index.cjs +4 -0
  6. package/dist/src/cosmos/index.cjs.map +20 -0
  7. package/dist/src/cosmos/index.js +4 -0
  8. package/dist/src/cosmos/index.js.map +20 -0
  9. package/dist/src/evm/index.cjs +4 -0
  10. package/dist/src/evm/index.cjs.map +20 -0
  11. package/dist/src/evm/index.js +4 -0
  12. package/dist/src/evm/index.js.map +20 -0
  13. package/dist/src/index.cjs +5 -0
  14. package/dist/src/index.cjs.map +67 -0
  15. package/dist/src/index.js +5 -0
  16. package/dist/src/index.js.map +67 -0
  17. package/dist/src/near/index.cjs +4 -0
  18. package/dist/src/near/index.cjs.map +16 -0
  19. package/dist/src/near/index.js +4 -0
  20. package/dist/src/near/index.js.map +16 -0
  21. package/dist/src/radix/index.cjs +4 -0
  22. package/dist/src/radix/index.cjs.map +10 -0
  23. package/dist/src/radix/index.js +4 -0
  24. package/dist/src/radix/index.js.map +10 -0
  25. package/dist/src/ripple/index.cjs +4 -0
  26. package/dist/src/ripple/index.cjs.map +10 -0
  27. package/dist/src/ripple/index.js +4 -0
  28. package/dist/src/ripple/index.js.map +10 -0
  29. package/dist/src/solana/index.cjs +4 -0
  30. package/dist/src/solana/index.cjs.map +11 -0
  31. package/dist/src/solana/index.js +4 -0
  32. package/dist/src/solana/index.js.map +11 -0
  33. package/dist/src/substrate/index.cjs +4 -0
  34. package/dist/src/substrate/index.cjs.map +13 -0
  35. package/dist/src/substrate/index.js +4 -0
  36. package/dist/src/substrate/index.js.map +13 -0
  37. package/dist/src/sui/index.cjs +4 -0
  38. package/dist/src/sui/index.cjs.map +11 -0
  39. package/dist/src/sui/index.js +4 -0
  40. package/dist/src/sui/index.js.map +11 -0
  41. package/dist/src/ton/index.cjs +4 -0
  42. package/dist/src/ton/index.cjs.map +11 -0
  43. package/dist/src/ton/index.js +4 -0
  44. package/dist/src/ton/index.js.map +11 -0
  45. package/dist/src/tron/index.cjs +4 -0
  46. package/dist/src/tron/index.cjs.map +13 -0
  47. package/dist/src/tron/index.js +4 -0
  48. package/dist/src/tron/index.js.map +13 -0
  49. package/dist/src/utxo/index.cjs +5 -0
  50. package/dist/src/utxo/index.cjs.map +21 -0
  51. package/dist/src/utxo/index.js +5 -0
  52. package/dist/src/utxo/index.js.map +21 -0
  53. package/dist/types/cardano/index.d.ts +3 -0
  54. package/dist/types/cardano/index.d.ts.map +1 -0
  55. package/dist/types/cardano/toolbox.d.ts +34 -0
  56. package/dist/types/cardano/toolbox.d.ts.map +1 -0
  57. package/dist/types/cardano/types.d.ts +11 -0
  58. package/dist/types/cardano/types.d.ts.map +1 -0
  59. package/dist/types/cosmos/index.d.ts +5 -0
  60. package/dist/types/cosmos/index.d.ts.map +1 -0
  61. package/dist/types/cosmos/thorchainUtils/addressFormat.d.ts +5 -0
  62. package/dist/types/cosmos/thorchainUtils/addressFormat.d.ts.map +1 -0
  63. package/dist/types/cosmos/thorchainUtils/index.d.ts +5 -0
  64. package/dist/types/cosmos/thorchainUtils/index.d.ts.map +1 -0
  65. package/dist/types/cosmos/thorchainUtils/messages.d.ts +208 -0
  66. package/dist/types/cosmos/thorchainUtils/messages.d.ts.map +1 -0
  67. package/dist/types/cosmos/thorchainUtils/registry.d.ts +4 -0
  68. package/dist/types/cosmos/thorchainUtils/registry.d.ts.map +1 -0
  69. package/dist/types/cosmos/thorchainUtils/types/MsgCompiled.d.ts +2 -0
  70. package/dist/types/cosmos/thorchainUtils/types/MsgCompiled.d.ts.map +1 -0
  71. package/dist/types/cosmos/thorchainUtils/types/client-types.d.ts +63 -0
  72. package/dist/types/cosmos/thorchainUtils/types/client-types.d.ts.map +1 -0
  73. package/dist/types/cosmos/thorchainUtils/types/index.d.ts +2 -0
  74. package/dist/types/cosmos/thorchainUtils/types/index.d.ts.map +1 -0
  75. package/dist/types/cosmos/toolbox/cosmos.d.ts +62 -0
  76. package/dist/types/cosmos/toolbox/cosmos.d.ts.map +1 -0
  77. package/dist/types/cosmos/toolbox/index.d.ts +15 -0
  78. package/dist/types/cosmos/toolbox/index.d.ts.map +1 -0
  79. package/dist/types/cosmos/toolbox/thorchain.d.ts +158 -0
  80. package/dist/types/cosmos/toolbox/thorchain.d.ts.map +1 -0
  81. package/dist/types/cosmos/types.d.ts +49 -0
  82. package/dist/types/cosmos/types.d.ts.map +1 -0
  83. package/dist/types/cosmos/util.d.ts +74 -0
  84. package/dist/types/cosmos/util.d.ts.map +1 -0
  85. package/dist/types/evm/api.d.ts +8 -0
  86. package/dist/types/evm/api.d.ts.map +1 -0
  87. package/dist/types/evm/contracts/eth/multicall.d.ts +36 -0
  88. package/dist/types/evm/contracts/eth/multicall.d.ts.map +1 -0
  89. package/dist/types/evm/contracts/op/gasOracle.d.ts +40 -0
  90. package/dist/types/evm/contracts/op/gasOracle.d.ts.map +1 -0
  91. package/dist/types/evm/helpers.d.ts +6 -0
  92. package/dist/types/evm/helpers.d.ts.map +1 -0
  93. package/dist/types/evm/index.d.ts +5 -0
  94. package/dist/types/evm/index.d.ts.map +1 -0
  95. package/dist/types/evm/toolbox/baseEVMToolbox.d.ts +83 -0
  96. package/dist/types/evm/toolbox/baseEVMToolbox.d.ts.map +1 -0
  97. package/dist/types/evm/toolbox/evm.d.ts +767 -0
  98. package/dist/types/evm/toolbox/evm.d.ts.map +1 -0
  99. package/dist/types/evm/toolbox/index.d.ts +7 -0
  100. package/dist/types/evm/toolbox/index.d.ts.map +1 -0
  101. package/dist/types/evm/toolbox/op.d.ts +76 -0
  102. package/dist/types/evm/toolbox/op.d.ts.map +1 -0
  103. package/dist/types/evm/types.d.ts +108 -0
  104. package/dist/types/evm/types.d.ts.map +1 -0
  105. package/dist/types/index.d.ts +75 -0
  106. package/dist/types/index.d.ts.map +1 -0
  107. package/dist/types/near/helpers/core.d.ts +15 -0
  108. package/dist/types/near/helpers/core.d.ts.map +1 -0
  109. package/dist/types/near/helpers/gasEstimation.d.ts +41 -0
  110. package/dist/types/near/helpers/gasEstimation.d.ts.map +1 -0
  111. package/dist/types/near/helpers/nep141.d.ts +36 -0
  112. package/dist/types/near/helpers/nep141.d.ts.map +1 -0
  113. package/dist/types/near/index.d.ts +10 -0
  114. package/dist/types/near/index.d.ts.map +1 -0
  115. package/dist/types/near/toolbox.d.ts +32 -0
  116. package/dist/types/near/toolbox.d.ts.map +1 -0
  117. package/dist/types/near/types/contract.d.ts +38 -0
  118. package/dist/types/near/types/contract.d.ts.map +1 -0
  119. package/dist/types/near/types/nep141.d.ts +29 -0
  120. package/dist/types/near/types/nep141.d.ts.map +1 -0
  121. package/dist/types/near/types/toolbox.d.ts +51 -0
  122. package/dist/types/near/types/toolbox.d.ts.map +1 -0
  123. package/dist/types/near/types.d.ts +47 -0
  124. package/dist/types/near/types.d.ts.map +1 -0
  125. package/dist/types/radix/index.d.ts +14 -0
  126. package/dist/types/radix/index.d.ts.map +1 -0
  127. package/dist/types/ripple/index.d.ts +46 -0
  128. package/dist/types/ripple/index.d.ts.map +1 -0
  129. package/dist/types/solana/index.d.ts +23 -0
  130. package/dist/types/solana/index.d.ts.map +1 -0
  131. package/dist/types/solana/toolbox.d.ts +51 -0
  132. package/dist/types/solana/toolbox.d.ts.map +1 -0
  133. package/dist/types/substrate/balance.d.ts +17 -0
  134. package/dist/types/substrate/balance.d.ts.map +1 -0
  135. package/dist/types/substrate/index.d.ts +3 -0
  136. package/dist/types/substrate/index.d.ts.map +1 -0
  137. package/dist/types/substrate/substrate.d.ts +148 -0
  138. package/dist/types/substrate/substrate.d.ts.map +1 -0
  139. package/dist/types/substrate/types.d.ts +100 -0
  140. package/dist/types/substrate/types.d.ts.map +1 -0
  141. package/dist/types/sui/index.d.ts +3 -0
  142. package/dist/types/sui/index.d.ts.map +1 -0
  143. package/dist/types/sui/toolbox.d.ts +19 -0
  144. package/dist/types/sui/toolbox.d.ts.map +1 -0
  145. package/dist/types/sui/types.d.ts +16 -0
  146. package/dist/types/sui/types.d.ts.map +1 -0
  147. package/dist/types/ton/index.d.ts +3 -0
  148. package/dist/types/ton/index.d.ts.map +1 -0
  149. package/dist/types/ton/toolbox.d.ts +14 -0
  150. package/dist/types/ton/toolbox.d.ts.map +1 -0
  151. package/dist/types/ton/types.d.ts +22 -0
  152. package/dist/types/ton/types.d.ts.map +1 -0
  153. package/dist/types/tron/helpers/trc20.abi.d.ts +156 -0
  154. package/dist/types/tron/helpers/trc20.abi.d.ts.map +1 -0
  155. package/dist/types/tron/helpers/trongrid.d.ts +8 -0
  156. package/dist/types/tron/helpers/trongrid.d.ts.map +1 -0
  157. package/dist/types/tron/index.d.ts +6 -0
  158. package/dist/types/tron/index.d.ts.map +1 -0
  159. package/dist/types/tron/toolbox.d.ts +26 -0
  160. package/dist/types/tron/toolbox.d.ts.map +1 -0
  161. package/dist/types/tron/types.d.ts +103 -0
  162. package/dist/types/tron/types.d.ts.map +1 -0
  163. package/dist/types/types.d.ts +26 -0
  164. package/dist/types/types.d.ts.map +1 -0
  165. package/dist/types/utils.d.ts +4 -0
  166. package/dist/types/utils.d.ts.map +1 -0
  167. package/dist/types/utxo/helpers/api.d.ts +101 -0
  168. package/dist/types/utxo/helpers/api.d.ts.map +1 -0
  169. package/dist/types/utxo/helpers/bchaddrjs.d.ts +10 -0
  170. package/dist/types/utxo/helpers/bchaddrjs.d.ts.map +1 -0
  171. package/dist/types/utxo/helpers/coinselect.d.ts +17 -0
  172. package/dist/types/utxo/helpers/coinselect.d.ts.map +1 -0
  173. package/dist/types/utxo/helpers/index.d.ts +5 -0
  174. package/dist/types/utxo/helpers/index.d.ts.map +1 -0
  175. package/dist/types/utxo/helpers/txSize.d.ts +21 -0
  176. package/dist/types/utxo/helpers/txSize.d.ts.map +1 -0
  177. package/dist/types/utxo/index.d.ts +7 -0
  178. package/dist/types/utxo/index.d.ts.map +1 -0
  179. package/dist/types/utxo/toolbox/bitcoinCash.d.ts +93 -0
  180. package/dist/types/utxo/toolbox/bitcoinCash.d.ts.map +1 -0
  181. package/dist/types/utxo/toolbox/index.d.ts +28 -0
  182. package/dist/types/utxo/toolbox/index.d.ts.map +1 -0
  183. package/dist/types/utxo/toolbox/params.d.ts +32 -0
  184. package/dist/types/utxo/toolbox/params.d.ts.map +1 -0
  185. package/dist/types/utxo/toolbox/utxo.d.ts +103 -0
  186. package/dist/types/utxo/toolbox/utxo.d.ts.map +1 -0
  187. package/dist/types/utxo/toolbox/validators.d.ts +4 -0
  188. package/dist/types/utxo/toolbox/validators.d.ts.map +1 -0
  189. package/dist/types/utxo/toolbox/zcash.d.ts +72 -0
  190. package/dist/types/utxo/toolbox/zcash.d.ts.map +1 -0
  191. package/dist/types/utxo/types.d.ts +46 -0
  192. package/dist/types/utxo/types.d.ts.map +1 -0
  193. package/package.json +205 -0
  194. package/src/__tests__/address-validation-all-chains.test.ts +162 -0
  195. package/src/__tests__/addressValidator.test.ts +162 -0
  196. package/src/cardano/__tests__/toolbox.test.ts +48 -0
  197. package/src/cardano/index.ts +2 -0
  198. package/src/cardano/toolbox.ts +168 -0
  199. package/src/cardano/types.ts +10 -0
  200. package/src/cosmos/__tests__/toolbox.test.ts +91 -0
  201. package/src/cosmos/index.ts +4 -0
  202. package/src/cosmos/thorchainUtils/addressFormat.ts +22 -0
  203. package/src/cosmos/thorchainUtils/index.ts +4 -0
  204. package/src/cosmos/thorchainUtils/messages.ts +212 -0
  205. package/src/cosmos/thorchainUtils/registry.ts +43 -0
  206. package/src/cosmos/thorchainUtils/types/MsgCompiled.ts +2800 -0
  207. package/src/cosmos/thorchainUtils/types/client-types.ts +54 -0
  208. package/src/cosmos/thorchainUtils/types/index.ts +1 -0
  209. package/src/cosmos/toolbox/cosmos.ts +345 -0
  210. package/src/cosmos/toolbox/index.ts +35 -0
  211. package/src/cosmos/toolbox/thorchain.ts +249 -0
  212. package/src/cosmos/types.ts +48 -0
  213. package/src/cosmos/util.ts +214 -0
  214. package/src/evm/__tests__/address-validation.test.ts +84 -0
  215. package/src/evm/__tests__/ethereum.test.ts +137 -0
  216. package/src/evm/__tests__/signMessage.test.ts +60 -0
  217. package/src/evm/api.ts +10 -0
  218. package/src/evm/contracts/eth/multicall.ts +165 -0
  219. package/src/evm/contracts/op/gasOracle.ts +145 -0
  220. package/src/evm/helpers.ts +73 -0
  221. package/src/evm/index.ts +4 -0
  222. package/src/evm/toolbox/baseEVMToolbox.ts +695 -0
  223. package/src/evm/toolbox/evm.ts +67 -0
  224. package/src/evm/toolbox/index.ts +44 -0
  225. package/src/evm/toolbox/op.ts +156 -0
  226. package/src/evm/types.ts +146 -0
  227. package/src/index.ts +260 -0
  228. package/src/near/__tests__/core.test.ts +70 -0
  229. package/src/near/helpers/core.ts +85 -0
  230. package/src/near/helpers/gasEstimation.ts +96 -0
  231. package/src/near/helpers/nep141.ts +50 -0
  232. package/src/near/index.ts +21 -0
  233. package/src/near/toolbox.ts +421 -0
  234. package/src/near/types/contract.ts +32 -0
  235. package/src/near/types/nep141.ts +34 -0
  236. package/src/near/types/toolbox.ts +55 -0
  237. package/src/near/types.ts +44 -0
  238. package/src/radix/index.ts +132 -0
  239. package/src/ripple/index.ts +179 -0
  240. package/src/solana/index.ts +36 -0
  241. package/src/solana/toolbox.ts +415 -0
  242. package/src/substrate/balance.ts +88 -0
  243. package/src/substrate/index.ts +2 -0
  244. package/src/substrate/substrate.ts +281 -0
  245. package/src/substrate/types.ts +115 -0
  246. package/src/sui/__tests__/toolbox.test.ts +82 -0
  247. package/src/sui/index.ts +2 -0
  248. package/src/sui/toolbox.ts +165 -0
  249. package/src/sui/types.ts +11 -0
  250. package/src/ton/__tests__/toolbox.test.ts +63 -0
  251. package/src/ton/index.ts +2 -0
  252. package/src/ton/toolbox.ts +136 -0
  253. package/src/ton/types.ts +13 -0
  254. package/src/tron/__tests__/toolbox.test.ts +221 -0
  255. package/src/tron/helpers/trc20.abi.ts +107 -0
  256. package/src/tron/helpers/trongrid.ts +53 -0
  257. package/src/tron/index.ts +21 -0
  258. package/src/tron/toolbox.ts +585 -0
  259. package/src/tron/types.ts +83 -0
  260. package/src/types.ts +28 -0
  261. package/src/utils.ts +27 -0
  262. package/src/utxo/__tests__/zcash-integration.test.ts +97 -0
  263. package/src/utxo/helpers/api.ts +471 -0
  264. package/src/utxo/helpers/bchaddrjs.ts +166 -0
  265. package/src/utxo/helpers/coinselect.ts +92 -0
  266. package/src/utxo/helpers/index.ts +4 -0
  267. package/src/utxo/helpers/txSize.ts +137 -0
  268. package/src/utxo/index.ts +6 -0
  269. package/src/utxo/toolbox/bitcoinCash.ts +243 -0
  270. package/src/utxo/toolbox/index.ts +59 -0
  271. package/src/utxo/toolbox/params.ts +18 -0
  272. package/src/utxo/toolbox/utxo.ts +439 -0
  273. package/src/utxo/toolbox/validators.ts +36 -0
  274. package/src/utxo/toolbox/zcash.ts +245 -0
  275. package/src/utxo/types.ts +39 -0
@@ -0,0 +1,59 @@
1
+ import { Chain, type DerivationPathArray, SwapKitError, type UTXOChain } from "@uswap/helpers";
2
+ import { createBCHToolbox } from "./bitcoinCash";
3
+ import type { UtxoToolboxParams } from "./params";
4
+ import { createUTXOToolbox } from "./utxo";
5
+ import { createZcashToolbox } from "./zcash";
6
+
7
+ type BCHToolbox = Awaited<ReturnType<typeof createBCHToolbox>>;
8
+ type CommonUTXOToolbox = Awaited<
9
+ ReturnType<typeof createUTXOToolbox<Exclude<UTXOChain, typeof Chain.BitcoinCash | typeof Chain.Zcash>>>
10
+ >;
11
+ type ZcashToolbox = Awaited<ReturnType<typeof createZcashToolbox>>;
12
+
13
+ export type UTXOToolboxes = {
14
+ [Chain.BitcoinCash]: BCHToolbox;
15
+ [Chain.Bitcoin]: CommonUTXOToolbox;
16
+ [Chain.Dogecoin]: CommonUTXOToolbox;
17
+ [Chain.Litecoin]: CommonUTXOToolbox;
18
+ [Chain.Dash]: CommonUTXOToolbox;
19
+ [Chain.Zcash]: ZcashToolbox;
20
+ };
21
+
22
+ export type UTXOWallets = {
23
+ [key in keyof UTXOToolboxes]: UTXOToolboxes[key];
24
+ };
25
+
26
+ export async function getUtxoToolbox<T extends keyof UTXOToolboxes>(
27
+ chain: T,
28
+ params?: UtxoToolboxParams[T] | { phrase?: string; derivationPath?: DerivationPathArray; index?: number },
29
+ ): Promise<UTXOToolboxes[T]> {
30
+ switch (chain) {
31
+ case Chain.BitcoinCash: {
32
+ const toolbox = await createBCHToolbox((params as UtxoToolboxParams[typeof Chain.BitcoinCash]) || {});
33
+ return toolbox as UTXOToolboxes[T];
34
+ }
35
+
36
+ case Chain.Zcash: {
37
+ const toolbox = await createZcashToolbox(params as UtxoToolboxParams[typeof Chain.Zcash]);
38
+ return toolbox as UTXOToolboxes[T];
39
+ }
40
+
41
+ case Chain.Bitcoin:
42
+ case Chain.Dogecoin:
43
+ case Chain.Litecoin:
44
+ case Chain.Dash: {
45
+ const toolbox = await createUTXOToolbox({
46
+ chain,
47
+ ...(params as UtxoToolboxParams[Exclude<T, typeof Chain.BitcoinCash | typeof Chain.Zcash>]),
48
+ });
49
+ return toolbox as UTXOToolboxes[Exclude<T, typeof Chain.BitcoinCash | typeof Chain.Zcash>];
50
+ }
51
+
52
+ default:
53
+ throw new SwapKitError("toolbox_utxo_not_supported", { chain });
54
+ }
55
+ }
56
+
57
+ export { stripToCashAddress } from "./bitcoinCash";
58
+ export * from "./params";
59
+ export { bchValidateAddress, stripPrefix, validateZcashAddress } from "./validators";
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Internal type definitions for UTXO toolbox parameters.
3
+ * These are not exported from the package to avoid leaking third-party library types.
4
+ */
5
+
6
+ import type { ZcashPsbt } from "@bitgo/utxo-lib/dist/src/bitgo";
7
+ import { Chain, type ChainSigner } from "@uswap/helpers";
8
+ import type { Psbt } from "bitcoinjs-lib";
9
+ import type { TransactionBuilderType, TransactionType, UTXOType } from "../types";
10
+
11
+ export type UtxoToolboxParams = {
12
+ [Chain.BitcoinCash]: { signer: ChainSigner<{ builder: TransactionBuilderType; utxos: UTXOType[] }, TransactionType> };
13
+ [Chain.Bitcoin]: { signer: ChainSigner<Psbt, Psbt> };
14
+ [Chain.Dogecoin]: { signer: ChainSigner<Psbt, Psbt> };
15
+ [Chain.Litecoin]: { signer: ChainSigner<Psbt, Psbt> };
16
+ [Chain.Dash]: { signer: ChainSigner<Psbt, Psbt> };
17
+ [Chain.Zcash]: { signer?: ChainSigner<ZcashPsbt, ZcashPsbt> };
18
+ };
@@ -0,0 +1,439 @@
1
+ import secp256k1 from "@bitcoinerlab/secp256k1";
2
+ // @ts-expect-error
3
+ import { ECPair, HDNode } from "@psf/bitcoincashjs-lib";
4
+ import { HDKey } from "@scure/bip32";
5
+ import { mnemonicToSeedSync } from "@scure/bip39";
6
+ import {
7
+ AssetValue,
8
+ applyFeeMultiplier,
9
+ Chain,
10
+ type ChainSigner,
11
+ DerivationPath,
12
+ type DerivationPathArray,
13
+ derivationPathToString,
14
+ FeeOption,
15
+ NetworkDerivationPath,
16
+ SwapKitError,
17
+ SwapKitNumber,
18
+ type UTXOChain,
19
+ updateDerivationPath,
20
+ } from "@uswap/helpers";
21
+ import { address as btcLibAddress, initEccLib, Psbt, payments } from "bitcoinjs-lib";
22
+ import type { ECPairInterface } from "ecpair";
23
+ import { ECPairFactory } from "ecpair";
24
+ import { getBalance } from "../../utils";
25
+ import {
26
+ accumulative,
27
+ calculateTxSize,
28
+ compileMemo,
29
+ getDustThreshold,
30
+ getInputSize,
31
+ getUtxoApi,
32
+ getUtxoNetwork,
33
+ UTXOScriptType,
34
+ } from "../helpers";
35
+ import type { BchECPair, TargetOutput, UTXOBuildTxParams, UTXOTransferParams, UTXOType } from "../types";
36
+ import type { UtxoToolboxParams } from "./params";
37
+ import { bchValidateAddress, validateZcashAddress } from "./validators";
38
+
39
+ export const nonSegwitChains: UTXOChain[] = [Chain.Dash, Chain.Dogecoin, Chain.Zcash, Chain.BitcoinCash];
40
+
41
+ export function addInputsAndOutputs({
42
+ inputs,
43
+ outputs,
44
+ chain,
45
+ psbt,
46
+ sender,
47
+ compiledMemo,
48
+ }: {
49
+ inputs: UTXOType[];
50
+ outputs: TargetOutput[];
51
+ chain: UTXOChain;
52
+ psbt: Psbt;
53
+ sender: string;
54
+ compiledMemo: Buffer<ArrayBufferLike> | null;
55
+ }) {
56
+ for (const utxo of inputs) {
57
+ const witnessInfo = !!utxo.witnessUtxo && !nonSegwitChains.includes(chain) && { witnessUtxo: utxo.witnessUtxo };
58
+
59
+ const nonWitnessInfo = nonSegwitChains.includes(chain) && {
60
+ nonWitnessUtxo: utxo.txHex ? Buffer.from(utxo.txHex, "hex") : undefined,
61
+ };
62
+
63
+ psbt.addInput({ hash: utxo.hash, index: utxo.index, ...witnessInfo, ...nonWitnessInfo });
64
+ }
65
+
66
+ for (const output of outputs) {
67
+ const address = "address" in output && output.address ? output.address : sender;
68
+ const hasOutputScript = output.script;
69
+
70
+ if (hasOutputScript && !compiledMemo) {
71
+ continue;
72
+ }
73
+
74
+ const mappedOutput = hasOutputScript
75
+ ? { script: compiledMemo as Buffer<ArrayBufferLike>, value: 0 }
76
+ : { address, value: output.value };
77
+
78
+ initEccLib(secp256k1);
79
+ psbt.addOutput(mappedOutput);
80
+ }
81
+
82
+ return { inputs, psbt };
83
+ }
84
+
85
+ async function createTransaction({
86
+ assetValue,
87
+ recipient,
88
+ memo,
89
+ feeRate,
90
+ sender,
91
+ fetchTxHex = false,
92
+ }: UTXOBuildTxParams): Promise<{ psbt: Psbt; utxos: UTXOType[]; inputs: UTXOType[] }> {
93
+ const chain = assetValue.chain as UTXOChain;
94
+ const compiledMemo = memo ? await compileMemo(memo) : null;
95
+
96
+ const inputsAndOutputs = await getInputsAndTargetOutputs({ assetValue, fetchTxHex, memo, recipient, sender });
97
+
98
+ const { inputs, outputs } = accumulative({ ...inputsAndOutputs, chain, feeRate });
99
+
100
+ // .inputs and .outputs will be undefined if no solution was found
101
+ if (!(inputs && outputs)) throw new SwapKitError("toolbox_utxo_insufficient_balance", { assetValue, sender });
102
+ const getNetwork = await getUtxoNetwork();
103
+ const psbt = new Psbt({ network: getNetwork(chain) });
104
+
105
+ if (chain === Chain.Dogecoin) psbt.setMaximumFeeRate(650000000);
106
+
107
+ const { psbt: mappedPsbt, inputs: mappedInputs } = await addInputsAndOutputs({
108
+ chain,
109
+ compiledMemo,
110
+ inputs,
111
+ outputs,
112
+ psbt,
113
+ sender,
114
+ });
115
+
116
+ return { inputs: mappedInputs, psbt: mappedPsbt, utxos: inputsAndOutputs.inputs };
117
+ }
118
+
119
+ export async function getUTXOAddressValidator() {
120
+ const getNetwork = await getUtxoNetwork();
121
+
122
+ return function validateAddress({ address, chain }: { address: string; chain: UTXOChain }) {
123
+ if (chain === Chain.BitcoinCash) {
124
+ return bchValidateAddress(address);
125
+ }
126
+
127
+ if (chain === Chain.Zcash) {
128
+ return validateZcashAddress(address);
129
+ }
130
+
131
+ try {
132
+ initEccLib(secp256k1);
133
+ btcLibAddress.toOutputScript(address, getNetwork(chain));
134
+ return true;
135
+ } catch {
136
+ return false;
137
+ }
138
+ };
139
+ }
140
+
141
+ async function createSignerWithKeys({
142
+ chain,
143
+ phrase,
144
+ derivationPath,
145
+ }: {
146
+ chain: UTXOChain;
147
+ phrase: string;
148
+ derivationPath: string;
149
+ }) {
150
+ const keyPair = (await getCreateKeysForPath(chain as typeof Chain.Bitcoin))({ derivationPath, phrase });
151
+
152
+ async function signTransaction(psbt: Psbt) {
153
+ await psbt.signAllInputs(keyPair);
154
+ return psbt;
155
+ }
156
+
157
+ function getAddress() {
158
+ const addressGetter = addressFromKeysGetter(chain);
159
+ return addressGetter(keyPair);
160
+ }
161
+
162
+ return { getAddress, signTransaction };
163
+ }
164
+
165
+ export async function createUTXOToolbox<T extends UTXOChain>({
166
+ chain,
167
+ ...toolboxParams
168
+ }: (UtxoToolboxParams[T] | { phrase?: string; derivationPath?: DerivationPathArray; index?: number }) & { chain: T }) {
169
+ const phrase = "phrase" in toolboxParams ? toolboxParams.phrase : undefined;
170
+
171
+ const index = "index" in toolboxParams ? toolboxParams.index || 0 : 0;
172
+
173
+ const derivationPath = derivationPathToString(
174
+ "derivationPath" in toolboxParams && toolboxParams.derivationPath
175
+ ? toolboxParams.derivationPath
176
+ : updateDerivationPath(NetworkDerivationPath[chain], { index }),
177
+ );
178
+
179
+ const signer = phrase
180
+ ? await createSignerWithKeys({ chain, derivationPath, phrase })
181
+ : "signer" in toolboxParams
182
+ ? toolboxParams.signer
183
+ : undefined;
184
+
185
+ function getAddress() {
186
+ return Promise.resolve(signer?.getAddress());
187
+ }
188
+
189
+ // const { signer } = params || {};
190
+ const validateAddress = await getUTXOAddressValidator();
191
+ const createKeysForPath = await getCreateKeysForPath(chain);
192
+
193
+ return {
194
+ accumulative,
195
+ broadcastTx: (txHash: string) => getUtxoApi(chain).broadcastTx(txHash),
196
+ calculateTxSize,
197
+ createKeysForPath,
198
+ createTransaction,
199
+ estimateMaxSendableAmount: estimateMaxSendableAmount(chain),
200
+ estimateTransactionFee: estimateTransactionFee(chain),
201
+ getAddress,
202
+ getAddressFromKeys: addressFromKeysGetter(chain),
203
+
204
+ getBalance: getBalance(chain),
205
+ getFeeRates: () => getFeeRates(chain),
206
+ getInputsOutputsFee,
207
+ getPrivateKeyFromMnemonic: (params: { phrase: string; derivationPath: string }) => {
208
+ const keys = createKeysForPath(params);
209
+ return keys.toWIF();
210
+ },
211
+ transfer: transfer(signer as UtxoToolboxParams["BTC"]["signer"]),
212
+ validateAddress: (address: string) => validateAddress({ address, chain }),
213
+ };
214
+ }
215
+
216
+ async function getInputsOutputsFee({
217
+ assetValue,
218
+ feeOptionKey = FeeOption.Fast,
219
+ feeRate,
220
+ memo,
221
+ sender,
222
+ recipient,
223
+ }: Omit<UTXOBuildTxParams, "feeRate"> & { feeOptionKey?: FeeOption; feeRate?: number }) {
224
+ const chain = assetValue.chain as UTXOChain;
225
+
226
+ const inputsAndOutputs = await getInputsAndTargetOutputs({ assetValue, memo, recipient, sender });
227
+
228
+ const feeRateWhole = feeRate ? Math.floor(feeRate) : (await getFeeRates(chain))[feeOptionKey];
229
+
230
+ return accumulative({ ...inputsAndOutputs, chain, feeRate: feeRateWhole });
231
+ }
232
+
233
+ function estimateMaxSendableAmount(chain: UTXOChain) {
234
+ return async function estimateMaxSendableAmount({
235
+ from,
236
+ memo,
237
+ feeRate,
238
+ feeOptionKey = FeeOption.Fast,
239
+ recipients = 1,
240
+ }: {
241
+ from: string;
242
+ memo?: string;
243
+ feeRate?: number;
244
+ feeOptionKey?: FeeOption;
245
+ recipients?: number | TargetOutput[];
246
+ }) {
247
+ const addressData = await getUtxoApi(chain).getAddressData(from);
248
+ const feeRateWhole = feeRate ? Math.ceil(feeRate) : (await getFeeRates(chain))[feeOptionKey];
249
+
250
+ const inputs = addressData?.utxo
251
+ .map((utxo) => ({
252
+ ...utxo,
253
+ hash: "",
254
+ // type: utxo.witnessUtxo ? UTXOScriptType.P2WPKH : UTXOScriptType.P2PKH,
255
+ type: UTXOScriptType.P2PKH,
256
+ }))
257
+ .filter((utxo) => utxo.value > Math.max(getDustThreshold(chain), getInputSize(utxo) * feeRateWhole));
258
+
259
+ if (!inputs?.length) return AssetValue.from({ chain });
260
+
261
+ const balance = AssetValue.from({ chain, value: inputs.reduce((sum, utxo) => sum + utxo.value, 0) });
262
+
263
+ const outputs =
264
+ typeof recipients === "number"
265
+ ? (Array.from({ length: recipients }, () => ({ address: from, value: 0 })) as TargetOutput[])
266
+ : recipients;
267
+
268
+ if (memo) {
269
+ const script = await compileMemo(memo);
270
+ outputs.push({ address: from, script, value: 0 });
271
+ }
272
+
273
+ const txSize = calculateTxSize({ feeRate: feeRateWhole, inputs, outputs });
274
+
275
+ const fee = txSize * feeRateWhole;
276
+
277
+ return balance.sub(fee);
278
+ };
279
+ }
280
+
281
+ function estimateTransactionFee(chain: UTXOChain) {
282
+ return async (params: {
283
+ assetValue: AssetValue;
284
+ recipient: string;
285
+ sender: string;
286
+ memo?: string;
287
+ feeOptionKey?: FeeOption;
288
+ feeRate?: number;
289
+ fetchTxHex?: boolean;
290
+ }) => {
291
+ const inputFees = await getInputsOutputsFee(params);
292
+
293
+ return AssetValue.from({ chain, value: SwapKitNumber.fromBigInt(BigInt(inputFees.fee), 8).getValue("string") });
294
+ };
295
+ }
296
+
297
+ type CreateKeysForPathReturnType = {
298
+ [Chain.BitcoinCash]: BchECPair;
299
+ [Chain.Bitcoin]: ECPairInterface;
300
+ [Chain.Dash]: ECPairInterface;
301
+ [Chain.Dogecoin]: ECPairInterface;
302
+ [Chain.Litecoin]: ECPairInterface;
303
+ [Chain.Zcash]: ECPairInterface;
304
+ };
305
+
306
+ export async function getCreateKeysForPath<T extends keyof CreateKeysForPathReturnType>(
307
+ chain: T,
308
+ ): Promise<(params: { wif?: string; phrase?: string; derivationPath?: string }) => CreateKeysForPathReturnType[T]> {
309
+ const getNetwork = await getUtxoNetwork();
310
+
311
+ switch (chain) {
312
+ case Chain.BitcoinCash: {
313
+ return function createKeysForPath({
314
+ phrase,
315
+ derivationPath = `${DerivationPath.BCH}/0`,
316
+ wif,
317
+ }: {
318
+ wif?: string;
319
+ phrase?: string;
320
+ derivationPath?: string;
321
+ }) {
322
+ const network = getNetwork(chain);
323
+
324
+ if (wif) {
325
+ return ECPair.fromWIF(wif, network) as BchECPair;
326
+ }
327
+ if (!phrase) throw new SwapKitError("toolbox_utxo_invalid_params", { error: "No phrase provided" });
328
+
329
+ const masterHDNode = HDNode.fromSeedBuffer(Buffer.from(mnemonicToSeedSync(phrase)), network);
330
+ const keyPair = masterHDNode.derivePath(derivationPath).keyPair;
331
+
332
+ return keyPair as BchECPair;
333
+ } as (params: { wif?: string; phrase?: string; derivationPath?: string }) => CreateKeysForPathReturnType[T];
334
+ }
335
+ case Chain.Bitcoin:
336
+ case Chain.Dogecoin:
337
+ case Chain.Litecoin:
338
+ case Chain.Zcash:
339
+ case Chain.Dash: {
340
+ return function createKeysForPath({
341
+ phrase,
342
+ wif,
343
+ derivationPath,
344
+ }: {
345
+ phrase?: string;
346
+ wif?: string;
347
+ derivationPath: string;
348
+ }) {
349
+ if (!(wif || phrase))
350
+ throw new SwapKitError("toolbox_utxo_invalid_params", { error: "Either phrase or wif must be provided" });
351
+
352
+ const factory = ECPairFactory(secp256k1);
353
+ const network = getNetwork(chain);
354
+
355
+ if (wif) return factory.fromWIF(wif, network);
356
+
357
+ const seed = mnemonicToSeedSync(phrase as string);
358
+ const master = HDKey.fromMasterSeed(seed, network).derive(derivationPath);
359
+ if (!master.privateKey)
360
+ throw new SwapKitError("toolbox_utxo_invalid_params", { error: "Could not get private key from phrase" });
361
+
362
+ return factory.fromPrivateKey(Buffer.from(master.privateKey), { network });
363
+ } as (params: { wif?: string; phrase?: string; derivationPath?: string }) => CreateKeysForPathReturnType[T];
364
+ }
365
+ default:
366
+ throw new SwapKitError("toolbox_utxo_not_supported", { chain });
367
+ }
368
+ }
369
+
370
+ export function addressFromKeysGetter(chain: UTXOChain) {
371
+ const getNetwork = getUtxoNetwork();
372
+
373
+ return function getAddressFromKeys(keys: ECPairInterface | BchECPair) {
374
+ if (!keys) throw new SwapKitError("toolbox_utxo_invalid_params", { error: "Keys must be provided" });
375
+
376
+ const method = nonSegwitChains.includes(chain) ? payments.p2pkh : payments.p2wpkh;
377
+ const { address } = method({ network: getNetwork(chain), pubkey: keys.publicKey as Buffer });
378
+ if (!address) throw new SwapKitError("toolbox_utxo_invalid_address", { error: "Address not defined" });
379
+
380
+ return address;
381
+ };
382
+ }
383
+
384
+ function transfer(signer?: ChainSigner<Psbt, Psbt>) {
385
+ return async function transfer({ memo, recipient, feeOptionKey, feeRate, assetValue }: UTXOTransferParams) {
386
+ const from = await signer?.getAddress();
387
+
388
+ const chain = assetValue.chain as UTXOChain;
389
+
390
+ if (!(signer && from)) throw new SwapKitError("toolbox_utxo_no_signer");
391
+ if (!recipient)
392
+ throw new SwapKitError("toolbox_utxo_invalid_params", { error: "Recipient address must be provided" });
393
+ const txFeeRate = feeRate || (await getFeeRates(chain))[feeOptionKey || FeeOption.Fast];
394
+
395
+ const { psbt } = await createTransaction({ assetValue, feeRate: txFeeRate, memo, recipient, sender: from });
396
+ const signedPsbt = await signer.signTransaction(psbt);
397
+ signedPsbt.finalizeAllInputs(); // Finalise inputs
398
+ // TX extracted and formatted to hex
399
+ return getUtxoApi(chain).broadcastTx(signedPsbt.extractTransaction().toHex());
400
+ };
401
+ }
402
+
403
+ async function getFeeRates(chain: UTXOChain) {
404
+ const suggestedFeeRate = await getUtxoApi(chain).getSuggestedTxFee();
405
+
406
+ return {
407
+ [FeeOption.Average]: suggestedFeeRate,
408
+ [FeeOption.Fast]: applyFeeMultiplier(suggestedFeeRate, FeeOption.Fast),
409
+ [FeeOption.Fastest]: applyFeeMultiplier(suggestedFeeRate, FeeOption.Fastest),
410
+ };
411
+ }
412
+
413
+ async function getInputsAndTargetOutputs({
414
+ assetValue,
415
+ recipient,
416
+ memo,
417
+ sender,
418
+ fetchTxHex: fetchTxOverwrite = false,
419
+ }: Omit<UTXOBuildTxParams, "feeRate">) {
420
+ const chain = assetValue.chain as UTXOChain;
421
+ const feeRate = (await getFeeRates(chain))[FeeOption.Fastest];
422
+
423
+ const fetchTxHex = fetchTxOverwrite || nonSegwitChains.includes(chain);
424
+
425
+ const amountToSend = assetValue.getBaseValue("number");
426
+
427
+ // Overestimate by 5000 byte * highest feeRate to ensure we have enough UTXOs for fees and change
428
+ const targetValue = Math.ceil(amountToSend + feeRate * 5000);
429
+
430
+ const inputs = await getUtxoApi(chain).getUtxos({ address: sender, fetchTxHex, targetValue });
431
+
432
+ return {
433
+ inputs,
434
+ outputs: [
435
+ { address: recipient, value: amountToSend },
436
+ ...(memo ? [{ address: "", script: await compileMemo(memo), value: 0 }] : []),
437
+ ],
438
+ };
439
+ }
@@ -0,0 +1,36 @@
1
+ import { networks, address as zcashAddress } from "@bitgo/utxo-lib";
2
+ import bs58check from "bs58check";
3
+ import { UtxoNetwork as bchNetwork, detectAddressNetwork, isValidAddress } from "../helpers";
4
+
5
+ export function stripPrefix(address: string) {
6
+ return address.replace(/(bchtest:|bitcoincash:)/, "");
7
+ }
8
+
9
+ export function bchValidateAddress(address: string) {
10
+ const strippedAddress = stripPrefix(address);
11
+ return isValidAddress(strippedAddress) && detectAddressNetwork(strippedAddress) === bchNetwork.Mainnet;
12
+ }
13
+
14
+ export function validateZcashAddress(address: string): boolean {
15
+ try {
16
+ if (address.startsWith("z")) {
17
+ console.warn("Shielded Zcash addresses (z-addresses) are not supported. Use transparent addresses (t1/t3) only.");
18
+ return false;
19
+ }
20
+
21
+ const network = networks.zcash;
22
+
23
+ try {
24
+ zcashAddress.toOutputScript(address, network);
25
+ return true;
26
+ } catch {
27
+ const decoded = bs58check.decode(address);
28
+ if (decoded.length < 21) return false;
29
+
30
+ const version = decoded[0];
31
+ return version === network.pubKeyHash || version === network.scriptHash;
32
+ }
33
+ } catch {
34
+ return false;
35
+ }
36
+ }