@swapkit/toolboxes 4.0.0-beta.50 → 4.0.0-beta.52

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 (232) hide show
  1. package/dist/src/cosmos/index.cjs +2 -2
  2. package/dist/src/cosmos/index.cjs.map +10 -6
  3. package/dist/src/cosmos/index.js +2 -2
  4. package/dist/src/cosmos/index.js.map +10 -6
  5. package/dist/src/evm/index.cjs +2 -2
  6. package/dist/src/evm/index.cjs.map +10 -8
  7. package/dist/src/evm/index.js +2 -2
  8. package/dist/src/evm/index.js.map +10 -8
  9. package/dist/src/index.cjs +4 -2
  10. package/dist/src/index.cjs.map +54 -4
  11. package/dist/src/index.js +4 -2
  12. package/dist/src/index.js.map +54 -4
  13. package/dist/src/near/index.cjs +2 -2
  14. package/dist/src/near/index.cjs.map +7 -5
  15. package/dist/src/near/index.js +2 -2
  16. package/dist/src/near/index.js.map +7 -5
  17. package/dist/src/radix/index.cjs +2 -2
  18. package/dist/src/radix/index.cjs.map +2 -2
  19. package/dist/src/radix/index.js +2 -2
  20. package/dist/src/radix/index.js.map +2 -2
  21. package/dist/src/ripple/index.cjs +2 -2
  22. package/dist/src/ripple/index.cjs.map +2 -2
  23. package/dist/src/ripple/index.js +2 -2
  24. package/dist/src/ripple/index.js.map +2 -2
  25. package/dist/src/solana/index.cjs +2 -2
  26. package/dist/src/solana/index.cjs.map +5 -4
  27. package/dist/src/solana/index.js +2 -2
  28. package/dist/src/solana/index.js.map +5 -4
  29. package/dist/src/substrate/index.cjs +2 -2
  30. package/dist/src/substrate/index.cjs.map +6 -5
  31. package/dist/src/substrate/index.js +2 -2
  32. package/dist/src/substrate/index.js.map +6 -5
  33. package/dist/src/tron/index.cjs +2 -2
  34. package/dist/src/tron/index.cjs.map +6 -5
  35. package/dist/src/tron/index.js +2 -2
  36. package/dist/src/tron/index.js.map +6 -5
  37. package/dist/src/utxo/index.cjs +4 -4
  38. package/dist/src/utxo/index.cjs.map +10 -7
  39. package/dist/src/utxo/index.js +4 -4
  40. package/dist/src/utxo/index.js.map +10 -7
  41. package/{src/cosmos/index.ts → dist/types/cosmos/index.d.ts} +1 -0
  42. package/dist/types/cosmos/index.d.ts.map +1 -0
  43. package/dist/types/cosmos/thorchainUtils/addressFormat.d.ts +5 -0
  44. package/dist/types/cosmos/thorchainUtils/addressFormat.d.ts.map +1 -0
  45. package/{src/cosmos/thorchainUtils/index.ts → dist/types/cosmos/thorchainUtils/index.d.ts} +1 -0
  46. package/dist/types/cosmos/thorchainUtils/index.d.ts.map +1 -0
  47. package/dist/types/cosmos/thorchainUtils/messages.d.ts +208 -0
  48. package/dist/types/cosmos/thorchainUtils/messages.d.ts.map +1 -0
  49. package/dist/types/cosmos/thorchainUtils/registry.d.ts +4 -0
  50. package/dist/types/cosmos/thorchainUtils/registry.d.ts.map +1 -0
  51. package/dist/types/cosmos/thorchainUtils/types/MsgCompiled.d.ts +2 -0
  52. package/dist/types/cosmos/thorchainUtils/types/MsgCompiled.d.ts.map +1 -0
  53. package/dist/types/cosmos/thorchainUtils/types/client-types.d.ts +66 -0
  54. package/dist/types/cosmos/thorchainUtils/types/client-types.d.ts.map +1 -0
  55. package/dist/types/cosmos/thorchainUtils/types/index.d.ts +2 -0
  56. package/dist/types/cosmos/thorchainUtils/types/index.d.ts.map +1 -0
  57. package/dist/types/cosmos/toolbox/cosmos.d.ts +93 -0
  58. package/dist/types/cosmos/toolbox/cosmos.d.ts.map +1 -0
  59. package/dist/types/cosmos/toolbox/index.d.ts +14 -0
  60. package/dist/types/cosmos/toolbox/index.d.ts.map +1 -0
  61. package/dist/types/cosmos/toolbox/thorchain.d.ts +158 -0
  62. package/dist/types/cosmos/toolbox/thorchain.d.ts.map +1 -0
  63. package/{src/cosmos/types.ts → dist/types/cosmos/types.d.ts} +24 -29
  64. package/dist/types/cosmos/types.d.ts.map +1 -0
  65. package/dist/types/cosmos/util.d.ts +68 -0
  66. package/dist/types/cosmos/util.d.ts.map +1 -0
  67. package/dist/types/evm/api.d.ts +8 -0
  68. package/dist/types/evm/api.d.ts.map +1 -0
  69. package/dist/types/evm/contracts/eth/multicall.d.ts +36 -0
  70. package/dist/types/evm/contracts/eth/multicall.d.ts.map +1 -0
  71. package/dist/types/evm/contracts/op/gasOracle.d.ts +40 -0
  72. package/dist/types/evm/contracts/op/gasOracle.d.ts.map +1 -0
  73. package/dist/types/evm/helpers.d.ts +20 -0
  74. package/dist/types/evm/helpers.d.ts.map +1 -0
  75. package/{src/evm/index.ts → dist/types/evm/index.d.ts} +1 -0
  76. package/dist/types/evm/index.d.ts.map +1 -0
  77. package/dist/types/evm/toolbox/baseEVMToolbox.d.ts +82 -0
  78. package/dist/types/evm/toolbox/baseEVMToolbox.d.ts.map +1 -0
  79. package/dist/types/evm/toolbox/evm.d.ts +367 -0
  80. package/dist/types/evm/toolbox/evm.d.ts.map +1 -0
  81. package/dist/types/evm/toolbox/index.d.ts +89 -0
  82. package/dist/types/evm/toolbox/index.d.ts.map +1 -0
  83. package/dist/types/evm/toolbox/op.d.ts +62 -0
  84. package/dist/types/evm/toolbox/op.d.ts.map +1 -0
  85. package/dist/types/evm/types.d.ts +98 -0
  86. package/dist/types/evm/types.d.ts.map +1 -0
  87. package/dist/types/index.d.ts +63 -0
  88. package/dist/types/index.d.ts.map +1 -0
  89. package/dist/types/near/helpers/core.d.ts +15 -0
  90. package/dist/types/near/helpers/core.d.ts.map +1 -0
  91. package/dist/types/near/helpers/gasEstimation.d.ts +41 -0
  92. package/dist/types/near/helpers/gasEstimation.d.ts.map +1 -0
  93. package/dist/types/near/helpers/nep141.d.ts +72 -0
  94. package/dist/types/near/helpers/nep141.d.ts.map +1 -0
  95. package/dist/types/near/index.d.ts +10 -0
  96. package/dist/types/near/index.d.ts.map +1 -0
  97. package/dist/types/near/toolbox.d.ts +4 -0
  98. package/dist/types/near/toolbox.d.ts.map +1 -0
  99. package/dist/types/near/types/contract.d.ts +38 -0
  100. package/dist/types/near/types/contract.d.ts.map +1 -0
  101. package/dist/types/near/types/nep141.d.ts +56 -0
  102. package/dist/types/near/types/nep141.d.ts.map +1 -0
  103. package/dist/types/near/types/toolbox.d.ts +57 -0
  104. package/dist/types/near/types/toolbox.d.ts.map +1 -0
  105. package/dist/types/near/types.d.ts +44 -0
  106. package/dist/types/near/types.d.ts.map +1 -0
  107. package/dist/types/radix/index.d.ts +14 -0
  108. package/dist/types/radix/index.d.ts.map +1 -0
  109. package/dist/types/ripple/index.d.ts +43 -0
  110. package/dist/types/ripple/index.d.ts.map +1 -0
  111. package/dist/types/solana/index.d.ts +37 -0
  112. package/dist/types/solana/index.d.ts.map +1 -0
  113. package/dist/types/solana/toolbox.d.ts +41 -0
  114. package/dist/types/solana/toolbox.d.ts.map +1 -0
  115. package/dist/types/substrate/balance.d.ts +17 -0
  116. package/dist/types/substrate/balance.d.ts.map +1 -0
  117. package/{src/substrate/index.ts → dist/types/substrate/index.d.ts} +1 -0
  118. package/dist/types/substrate/index.d.ts.map +1 -0
  119. package/dist/types/substrate/substrate.d.ts +148 -0
  120. package/dist/types/substrate/substrate.d.ts.map +1 -0
  121. package/dist/types/substrate/types.d.ts +100 -0
  122. package/dist/types/substrate/types.d.ts.map +1 -0
  123. package/dist/types/tron/helpers/trc20.abi.d.ts +156 -0
  124. package/dist/types/tron/helpers/trc20.abi.d.ts.map +1 -0
  125. package/dist/types/tron/helpers/trongrid.d.ts +8 -0
  126. package/dist/types/tron/helpers/trongrid.d.ts.map +1 -0
  127. package/dist/types/tron/index.d.ts +6 -0
  128. package/dist/types/tron/index.d.ts.map +1 -0
  129. package/dist/types/tron/toolbox.d.ts +26 -0
  130. package/dist/types/tron/toolbox.d.ts.map +1 -0
  131. package/dist/types/tron/types.d.ts +101 -0
  132. package/dist/types/tron/types.d.ts.map +1 -0
  133. package/dist/types/types.d.ts +18 -0
  134. package/dist/types/types.d.ts.map +1 -0
  135. package/dist/types/utils.d.ts +4 -0
  136. package/dist/types/utils.d.ts.map +1 -0
  137. package/dist/types/utxo/helpers/api.d.ts +133 -0
  138. package/dist/types/utxo/helpers/api.d.ts.map +1 -0
  139. package/dist/types/utxo/helpers/bchaddrjs.d.ts +10 -0
  140. package/dist/types/utxo/helpers/bchaddrjs.d.ts.map +1 -0
  141. package/dist/types/utxo/helpers/coinselect.d.ts +16 -0
  142. package/dist/types/utxo/helpers/coinselect.d.ts.map +1 -0
  143. package/{src/utxo/helpers/index.ts → dist/types/utxo/helpers/index.d.ts} +1 -0
  144. package/dist/types/utxo/helpers/index.d.ts.map +1 -0
  145. package/dist/types/utxo/helpers/txSize.d.ts +21 -0
  146. package/dist/types/utxo/helpers/txSize.d.ts.map +1 -0
  147. package/{src/utxo/index.ts → dist/types/utxo/index.d.ts} +1 -0
  148. package/dist/types/utxo/index.d.ts.map +1 -0
  149. package/dist/types/utxo/toolbox/bitcoinCash.d.ts +104 -0
  150. package/dist/types/utxo/toolbox/bitcoinCash.d.ts.map +1 -0
  151. package/dist/types/utxo/toolbox/index.d.ts +50 -0
  152. package/dist/types/utxo/toolbox/index.d.ts.map +1 -0
  153. package/dist/types/utxo/toolbox/utxo.d.ts +102 -0
  154. package/dist/types/utxo/toolbox/utxo.d.ts.map +1 -0
  155. package/dist/types/utxo/toolbox/zcash.d.ts +83 -0
  156. package/dist/types/utxo/toolbox/zcash.d.ts.map +1 -0
  157. package/dist/types/utxo/types.d.ts +46 -0
  158. package/dist/types/utxo/types.d.ts.map +1 -0
  159. package/package.json +15 -18
  160. package/dist/chunk-0h4xdrwz.js +0 -5
  161. package/dist/chunk-0h4xdrwz.js.map +0 -10
  162. package/dist/chunk-4yap1fvd.js +0 -4
  163. package/dist/chunk-4yap1fvd.js.map +0 -10
  164. package/dist/chunk-9bqegm61.js +0 -4
  165. package/dist/chunk-9bqegm61.js.map +0 -10
  166. package/dist/chunk-fazw0jvt.js +0 -4
  167. package/dist/chunk-fazw0jvt.js.map +0 -9
  168. package/dist/chunk-fjfxga2v.js +0 -4
  169. package/dist/chunk-fjfxga2v.js.map +0 -10
  170. package/dist/chunk-s47y8512.js +0 -5
  171. package/dist/chunk-s47y8512.js.map +0 -9
  172. package/dist/chunk-vtd17cje.js +0 -4
  173. package/dist/chunk-vtd17cje.js.map +0 -10
  174. package/dist/chunk-zcdeg6h9.js +0 -5
  175. package/dist/chunk-zcdeg6h9.js.map +0 -10
  176. package/src/cosmos/thorchainUtils/addressFormat.ts +0 -26
  177. package/src/cosmos/thorchainUtils/messages.ts +0 -262
  178. package/src/cosmos/thorchainUtils/registry.ts +0 -44
  179. package/src/cosmos/thorchainUtils/types/MsgCompiled.ts +0 -2800
  180. package/src/cosmos/thorchainUtils/types/client-types.ts +0 -73
  181. package/src/cosmos/thorchainUtils/types/index.ts +0 -1
  182. package/src/cosmos/toolbox/cosmos.ts +0 -375
  183. package/src/cosmos/toolbox/index.ts +0 -33
  184. package/src/cosmos/toolbox/thorchain.ts +0 -313
  185. package/src/cosmos/util.ts +0 -266
  186. package/src/evm/__tests__/address-validation.test.ts +0 -86
  187. package/src/evm/__tests__/ethereum.test.ts +0 -141
  188. package/src/evm/api.ts +0 -21
  189. package/src/evm/contracts/eth/multicall.ts +0 -165
  190. package/src/evm/contracts/op/gasOracle.ts +0 -151
  191. package/src/evm/helpers.ts +0 -194
  192. package/src/evm/toolbox/baseEVMToolbox.ts +0 -762
  193. package/src/evm/toolbox/evm.ts +0 -66
  194. package/src/evm/toolbox/index.ts +0 -52
  195. package/src/evm/toolbox/op.ts +0 -131
  196. package/src/evm/types.ts +0 -146
  197. package/src/index.ts +0 -263
  198. package/src/near/__tests__/core.test.ts +0 -80
  199. package/src/near/helpers/contractFactory.ts +0 -22
  200. package/src/near/helpers/core.ts +0 -91
  201. package/src/near/helpers/gasEstimation.ts +0 -110
  202. package/src/near/helpers/index.ts +0 -5
  203. package/src/near/helpers/nep141.ts +0 -110
  204. package/src/near/index.ts +0 -24
  205. package/src/near/toolbox.ts +0 -509
  206. package/src/near/types/contract.ts +0 -48
  207. package/src/near/types/nep141.ts +0 -66
  208. package/src/near/types.ts +0 -57
  209. package/src/radix/index.ts +0 -156
  210. package/src/ripple/index.ts +0 -192
  211. package/src/solana/index.ts +0 -55
  212. package/src/solana/toolbox.ts +0 -433
  213. package/src/substrate/balance.ts +0 -92
  214. package/src/substrate/substrate.ts +0 -320
  215. package/src/substrate/types.ts +0 -120
  216. package/src/tron/__tests__/toolbox.test.ts +0 -147
  217. package/src/tron/helpers/trc20.abi.ts +0 -107
  218. package/src/tron/helpers/trongrid.ts +0 -54
  219. package/src/tron/index.ts +0 -17
  220. package/src/tron/toolbox.ts +0 -650
  221. package/src/tron/types.ts +0 -120
  222. package/src/utils.ts +0 -27
  223. package/src/utxo/__tests__/zcash-integration.test.ts +0 -114
  224. package/src/utxo/helpers/api.ts +0 -560
  225. package/src/utxo/helpers/bchaddrjs.ts +0 -183
  226. package/src/utxo/helpers/coinselect.ts +0 -98
  227. package/src/utxo/helpers/txSize.ts +0 -104
  228. package/src/utxo/toolbox/bitcoinCash.ts +0 -320
  229. package/src/utxo/toolbox/index.ts +0 -90
  230. package/src/utxo/toolbox/utxo.ts +0 -525
  231. package/src/utxo/toolbox/zcash.ts +0 -208
  232. package/src/utxo/types.ts +0 -57
@@ -1,183 +0,0 @@
1
- import { SwapKitError } from "@swapkit/helpers";
2
- import base58check from "bs58check";
3
- // @ts-ignore
4
- import cashaddr from "cashaddrjs";
5
-
6
- enum Format {
7
- Legacy = "legacy",
8
- Bitpay = "bitpay",
9
- Cashaddr = "cashaddr",
10
- }
11
- enum UtxoNetwork {
12
- Mainnet = "mainnet",
13
- Testnet = "testnet",
14
- }
15
- enum Type {
16
- P2PKH = "p2pkh",
17
- P2SH = "p2sh",
18
- }
19
-
20
- const VERSION_BYTE = {
21
- [Format.Legacy]: {
22
- [UtxoNetwork.Mainnet]: {
23
- [Type.P2PKH]: 0,
24
- [Type.P2SH]: 5,
25
- },
26
- [UtxoNetwork.Testnet]: {
27
- [Type.P2PKH]: 111,
28
- [Type.P2SH]: 196,
29
- },
30
- },
31
- [Format.Bitpay]: {
32
- [UtxoNetwork.Mainnet]: {
33
- [Type.P2PKH]: 28,
34
- [Type.P2SH]: 40,
35
- },
36
- [UtxoNetwork.Testnet]: {
37
- [Type.P2PKH]: 111,
38
- [Type.P2SH]: 196,
39
- },
40
- },
41
- };
42
-
43
- type DecodedType = {
44
- format: Format;
45
- network: UtxoNetwork;
46
- type: Type;
47
- hash: any;
48
- };
49
-
50
- function isValidAddress(input: any) {
51
- try {
52
- decodeAddress(input);
53
- return true;
54
- } catch (_error) {
55
- return false;
56
- }
57
- }
58
-
59
- function detectAddressNetwork(address: string) {
60
- return decodeAddress(address)?.network;
61
- }
62
-
63
- function toLegacyAddress(address: string): string {
64
- const decoded = decodeAddress(address);
65
- if (decoded?.format === Format.Legacy) {
66
- return address;
67
- }
68
- return encodeAsLegacy(decoded);
69
- }
70
-
71
- function toCashAddress(address: string): string {
72
- const decoded = decodeAddress(address);
73
- return encodeAsCashaddr(decoded);
74
- }
75
-
76
- function decodeAddress(address: string) {
77
- try {
78
- const decoded = decodeBase58Address(address);
79
- if (decoded) {
80
- return decoded;
81
- }
82
- } catch (_error) {
83
- // Try to decode as cashaddr if base58 decoding fails.
84
- }
85
- try {
86
- const decoded = decodeCashAddress(address);
87
- if (decoded) {
88
- return decoded;
89
- }
90
- } catch (_error) {
91
- // Try to decode as bitpay if cashaddr decoding fails.
92
- }
93
- throw new SwapKitError("toolbox_utxo_invalid_address", { address });
94
- }
95
-
96
- function decodeBase58Address(address: string) {
97
- try {
98
- const payload = base58check.decode(address);
99
-
100
- // BASE_58_CHECK_PAYLOAD_LENGTH
101
- if (payload.length !== 21) throw new SwapKitError("toolbox_utxo_invalid_address", { address });
102
- const versionByte = payload[0];
103
- const hash = Array.prototype.slice.call(payload, 1);
104
-
105
- switch (versionByte) {
106
- case VERSION_BYTE[Format.Legacy][UtxoNetwork.Mainnet][Type.P2PKH]:
107
- return { hash, format: Format.Legacy, network: UtxoNetwork.Mainnet, type: Type.P2PKH };
108
-
109
- case VERSION_BYTE[Format.Legacy][UtxoNetwork.Mainnet][Type.P2SH]:
110
- return { hash, format: Format.Legacy, network: UtxoNetwork.Mainnet, type: Type.P2SH };
111
-
112
- case VERSION_BYTE[Format.Legacy][UtxoNetwork.Testnet][Type.P2PKH]:
113
- return { hash, format: Format.Legacy, network: UtxoNetwork.Testnet, type: Type.P2PKH };
114
-
115
- case VERSION_BYTE[Format.Legacy][UtxoNetwork.Testnet][Type.P2SH]:
116
- return { hash, format: Format.Legacy, network: UtxoNetwork.Testnet, type: Type.P2SH };
117
-
118
- case VERSION_BYTE[Format.Bitpay][UtxoNetwork.Mainnet][Type.P2PKH]:
119
- return { hash, format: Format.Bitpay, network: UtxoNetwork.Mainnet, type: Type.P2PKH };
120
-
121
- case VERSION_BYTE[Format.Bitpay][UtxoNetwork.Mainnet][Type.P2SH]:
122
- return { hash, format: Format.Bitpay, network: UtxoNetwork.Mainnet, type: Type.P2SH };
123
-
124
- default:
125
- return;
126
- }
127
- } catch (_error) {
128
- return;
129
- }
130
- }
131
-
132
- function decodeCashAddress(address: string) {
133
- if (address.indexOf(":") !== -1) {
134
- try {
135
- return decodeCashAddressWithPrefix(address);
136
- } catch (_error) {
137
- // Try to decode as legacy if cashaddr decoding fails.
138
- }
139
- } else {
140
- const prefixes = ["bitcoincash", "bchtest", "bchreg"];
141
- for (const prefix of prefixes) {
142
- try {
143
- return decodeCashAddressWithPrefix(`${prefix}:${address}`);
144
- } catch (_error) {
145
- // Try next prefix if decoding fails.
146
- }
147
- }
148
- }
149
-
150
- return;
151
- }
152
-
153
- function decodeCashAddressWithPrefix(address: string) {
154
- try {
155
- const { hash, prefix, type } = cashaddr.decode(address);
156
-
157
- return {
158
- format: Format.Cashaddr,
159
- hash: Array.prototype.slice.call(hash, 0),
160
- network: prefix === "bitcoincash" ? UtxoNetwork.Mainnet : UtxoNetwork.Testnet,
161
- type: type === "P2PKH" ? Type.P2PKH : Type.P2SH,
162
- };
163
- } catch (_error) {
164
- return;
165
- }
166
- }
167
-
168
- function encodeAsLegacy(decoded: DecodedType) {
169
- const versionByte = VERSION_BYTE[Format.Legacy][decoded.network][decoded.type];
170
- const buffer = Buffer.alloc(1 + decoded.hash.length);
171
- buffer[0] = versionByte;
172
- buffer.set(decoded.hash, 1);
173
- return base58check.encode(buffer);
174
- }
175
-
176
- function encodeAsCashaddr(decoded: DecodedType) {
177
- const prefix = decoded.network === UtxoNetwork.Mainnet ? "bitcoincash" : "bchtest";
178
- const type = decoded.type === Type.P2PKH ? "P2PKH" : "P2SH";
179
- const hash = new Uint8Array(decoded.hash);
180
- return cashaddr.encode(prefix, type, hash);
181
- }
182
-
183
- export { detectAddressNetwork, isValidAddress, UtxoNetwork, toCashAddress, toLegacyAddress };
@@ -1,98 +0,0 @@
1
- import { Chain, SwapKitError, type UTXOChain } from "@swapkit/helpers";
2
-
3
- import {
4
- TX_OVERHEAD,
5
- UTXOScriptType,
6
- calculateTxSize,
7
- getInputSize,
8
- getOutputSize,
9
- getScriptTypeForAddress,
10
- } from "../helpers";
11
- import type { TargetOutput, UTXOCalculateTxSizeParams, UTXOType } from "../types";
12
-
13
- export const getDustThreshold = (chain: UTXOChain) => {
14
- switch (chain) {
15
- case Chain.Bitcoin:
16
- case Chain.BitcoinCash:
17
- return 550;
18
- case Chain.Dash:
19
- case Chain.Litecoin:
20
- return 5500;
21
- case Chain.Dogecoin:
22
- return 100000;
23
- case Chain.Zcash:
24
- return 546;
25
- default:
26
- throw new SwapKitError("toolbox_utxo_not_supported", { chain });
27
- }
28
- };
29
-
30
- export const accumulative = ({
31
- inputs,
32
- outputs,
33
- feeRate: initialFeeRate = 1,
34
- chain = Chain.Bitcoin,
35
- }: UTXOCalculateTxSizeParams & { outputs: TargetOutput[]; chain: UTXOChain }) => {
36
- const feeRate = Math.ceil(initialFeeRate);
37
-
38
- const newTxType =
39
- inputs[0] && "address" in inputs[0] && inputs[0].address
40
- ? getScriptTypeForAddress(inputs[0].address)
41
- : UTXOScriptType.P2PKH;
42
- // skip input if adding it would cost more than input is worth
43
- const filteredInputs = inputs.filter((input) => getInputSize(input) * feeRate <= input.value);
44
-
45
- const txSizeWithoutInputs =
46
- TX_OVERHEAD + outputs.reduce((total, output) => total + getOutputSize(output, newTxType), 0);
47
-
48
- const amountToSend = outputs.reduce((total, output) => total + output.value, 0);
49
-
50
- let fees = txSizeWithoutInputs * feeRate;
51
- let inputsValue = 0;
52
- const inputsToUse: typeof inputs = [];
53
-
54
- for (const input of filteredInputs) {
55
- const inputSize = getInputSize(input);
56
- const inputFee = feeRate * inputSize;
57
-
58
- fees += inputFee;
59
- inputsValue += input.value;
60
-
61
- inputsToUse.push(input);
62
-
63
- const totalCost = fees + amountToSend;
64
-
65
- // we need more inputs
66
- if (inputsValue < totalCost) continue;
67
-
68
- const remainder = inputsValue - totalCost;
69
-
70
- const feeForExtraOutput = feeRate * getOutputSize({ address: "", value: 0 }, newTxType);
71
-
72
- // potential change address
73
- if (remainder > feeForExtraOutput) {
74
- const feeAfterExtraOutput = feeForExtraOutput + fees;
75
- const remainderAfterExtraOutput = inputsValue - (amountToSend + feeAfterExtraOutput);
76
-
77
- // is it worth a change output aka can we send it in the future?
78
- if (
79
- remainderAfterExtraOutput >
80
- Math.max(getInputSize({} as UTXOType) * feeRate, getDustThreshold(chain))
81
- ) {
82
- return {
83
- inputs: inputsToUse,
84
- outputs: outputs.concat({ value: remainderAfterExtraOutput, address: "" }),
85
- fee: feeAfterExtraOutput,
86
- };
87
- }
88
- }
89
- return {
90
- inputs: inputsToUse,
91
- outputs,
92
- fee: fees,
93
- };
94
- }
95
-
96
- // We don't have enough inputs, let's calculate transaction fee accrude to the last input
97
- return { fee: feeRate * calculateTxSize({ inputs, outputs, feeRate }) };
98
- };
@@ -1,104 +0,0 @@
1
- import { SwapKitError } from "@swapkit/helpers";
2
- import { opcodes, script } from "bitcoinjs-lib";
3
- import type {
4
- TargetOutput,
5
- UTXOCalculateTxSizeParams,
6
- UTXOInputWithScriptType,
7
- UTXOType,
8
- } from "../types";
9
-
10
- /**
11
- * Minimum transaction fee
12
- * 1000 satoshi/kB (similar to current `minrelaytxfee`)
13
- * @see https://github.com/bitcoin/bitcoin/blob/db88db47278d2e7208c50d16ab10cb355067d071/src/validation.h#L56
14
- */
15
- export const MIN_TX_FEE = 1000;
16
- export const TX_OVERHEAD = 4 + 1 + 1 + 4; //10
17
- export const OP_RETURN_OVERHEAD = 1 + 8 + 1; //10
18
- const TX_INPUT_BASE = 32 + 4 + 1 + 4; // 41
19
- const TX_INPUT_PUBKEYHASH = 107;
20
-
21
- export function compileMemo(memo: string) {
22
- const data = Buffer.from(memo, "utf8"); // converts MEMO to buffer
23
- return script.compile([opcodes.OP_RETURN as number, data]); // Compile OP_RETURN script
24
- }
25
-
26
- export enum UTXOScriptType {
27
- P2PKH = "P2PKH", // legacy
28
- // P2SH = 'P2SH', // multisig
29
- P2WPKH = "P2WPKH", // bech32 - native segwit
30
- // P2TR = "P2TR", // taproot
31
- }
32
-
33
- export const InputSizes: Record<UTXOScriptType, number> = {
34
- [UTXOScriptType.P2PKH]: 148,
35
- // [UTXOScriptType.P2SH]: 91,
36
- [UTXOScriptType.P2WPKH]: 68,
37
- };
38
-
39
- export const OutputSizes: Record<UTXOScriptType, number> = {
40
- [UTXOScriptType.P2PKH]: 34,
41
- // [UTXOScriptType.P2SH]: 91,
42
- [UTXOScriptType.P2WPKH]: 31,
43
- };
44
-
45
- export const getScriptTypeForAddress = (address: string) => {
46
- if (address.startsWith("bc1") || address.startsWith("ltc1")) {
47
- return UTXOScriptType.P2WPKH;
48
- }
49
- // if (address.startsWith('3') || address.startsWith('M')) {
50
- // return UTXOScriptType.P2SH;
51
- // }
52
- if (
53
- address.startsWith("1") ||
54
- address.startsWith("3") ||
55
- address.startsWith("L") ||
56
- address.startsWith("M") ||
57
- address.startsWith("X") ||
58
- address.startsWith("D") ||
59
- address.startsWith("bitcoincash:q") ||
60
- address.startsWith("q")
61
- ) {
62
- return UTXOScriptType.P2PKH;
63
- }
64
- throw new SwapKitError("toolbox_utxo_invalid_address", { address });
65
- };
66
-
67
- export const calculateTxSize = ({ inputs, outputs, feeRate }: UTXOCalculateTxSizeParams) => {
68
- const newTxType =
69
- inputs[0] && "address" in inputs[0] && inputs[0].address
70
- ? getScriptTypeForAddress(inputs[0].address)
71
- : UTXOScriptType.P2PKH;
72
- const inputSize = inputs
73
- .filter(
74
- (utxo) =>
75
- utxo.value >=
76
- InputSizes["type" in utxo ? utxo.type : UTXOScriptType.P2PKH] * Math.ceil(feeRate),
77
- )
78
- .reduce((total, utxo) => total + getInputSize(utxo), 0);
79
-
80
- const outputSize =
81
- outputs?.reduce((total, output) => total + getOutputSize(output), 0) || OutputSizes[newTxType];
82
-
83
- return TX_OVERHEAD + inputSize + outputSize;
84
- };
85
-
86
- export const getInputSize = (input: UTXOInputWithScriptType | UTXOType) => {
87
- if ("type" in input) {
88
- return InputSizes[input.type];
89
- }
90
- if ("address" in input && input.address) {
91
- return InputSizes[getScriptTypeForAddress(input.address as string)];
92
- }
93
- return TX_INPUT_BASE + TX_INPUT_PUBKEYHASH;
94
- };
95
-
96
- export const getOutputSize = (output: TargetOutput, scriptType?: UTXOScriptType) => {
97
- if (output?.script) {
98
- return OP_RETURN_OVERHEAD + output.script.length + (output.script.length >= 74 ? 2 : 1);
99
- }
100
- if (scriptType) {
101
- return OutputSizes[scriptType];
102
- }
103
- return OutputSizes[UTXOScriptType.P2PKH];
104
- };
@@ -1,320 +0,0 @@
1
- import {
2
- Transaction,
3
- TransactionBuilder,
4
- address as bchAddress,
5
- // @ts-ignore
6
- } from "@psf/bitcoincashjs-lib";
7
- import {
8
- Chain,
9
- type ChainSigner,
10
- type DerivationPathArray,
11
- FeeOption,
12
- NetworkDerivationPath,
13
- SwapKitError,
14
- derivationPathToString,
15
- updateDerivationPath,
16
- } from "@swapkit/helpers";
17
- import { Psbt } from "bitcoinjs-lib";
18
- import type { UtxoToolboxParams } from ".";
19
- import {
20
- accumulative,
21
- UtxoNetwork as bchNetwork,
22
- compileMemo,
23
- detectAddressNetwork,
24
- getUtxoApi,
25
- getUtxoNetwork,
26
- isValidAddress,
27
- toCashAddress,
28
- toLegacyAddress,
29
- } from "../helpers";
30
- import type {
31
- BchECPair,
32
- TargetOutput,
33
- TransactionBuilderType,
34
- TransactionType,
35
- UTXOBuildTxParams,
36
- UTXOTransferParams,
37
- UTXOType,
38
- } from "../types";
39
- import { createUTXOToolbox, getCreateKeysForPath } from "./utxo";
40
-
41
- const chain = Chain.BitcoinCash;
42
-
43
- export function stripPrefix(address: string) {
44
- return address.replace(/(bchtest:|bitcoincash:)/, "");
45
- }
46
-
47
- export function bchValidateAddress(address: string) {
48
- const strippedAddress = stripPrefix(address);
49
- return (
50
- isValidAddress(strippedAddress) && detectAddressNetwork(strippedAddress) === bchNetwork.Mainnet
51
- );
52
- }
53
-
54
- export function stripToCashAddress(address: string) {
55
- return stripPrefix(toCashAddress(address));
56
- }
57
-
58
- async function createSignerWithKeys(keys: BchECPair) {
59
- async function signTransaction({
60
- builder,
61
- utxos,
62
- }: { builder: TransactionBuilderType; utxos: UTXOType[] }) {
63
- utxos.forEach((utxo, index) => {
64
- builder.sign(index, keys, undefined, 0x41, utxo.witnessUtxo?.value);
65
- });
66
-
67
- return builder.build();
68
- }
69
-
70
- const getAddress = () => {
71
- const address = keys.getAddress(0);
72
- return Promise.resolve(stripToCashAddress(address));
73
- };
74
-
75
- return {
76
- getAddress,
77
- signTransaction,
78
- };
79
- }
80
-
81
- export async function createBCHToolbox<T extends Chain.BitcoinCash>(
82
- toolboxParams:
83
- | UtxoToolboxParams[T]
84
- | {
85
- phrase?: string;
86
- derivationPath?: DerivationPathArray;
87
- index?: number;
88
- },
89
- ) {
90
- const phrase = "phrase" in toolboxParams ? toolboxParams.phrase : undefined;
91
-
92
- const index = "index" in toolboxParams ? toolboxParams.index || 0 : 0;
93
-
94
- const derivationPath = derivationPathToString(
95
- "derivationPath" in toolboxParams && toolboxParams.derivationPath
96
- ? toolboxParams.derivationPath
97
- : updateDerivationPath(NetworkDerivationPath[chain], { index }),
98
- );
99
-
100
- const keys = phrase ? (await getCreateKeysForPath(chain))({ phrase, derivationPath }) : undefined;
101
-
102
- const signer = keys
103
- ? await createSignerWithKeys(keys)
104
- : "signer" in toolboxParams
105
- ? toolboxParams.signer
106
- : undefined;
107
-
108
- function getAddress() {
109
- return Promise.resolve(signer?.getAddress());
110
- }
111
-
112
- const { getBalance, getFeeRates, broadcastTx, ...toolbox } = await createUTXOToolbox({ chain });
113
-
114
- function handleGetBalance(address: string, _scamFilter = true) {
115
- return getBalance(stripPrefix(toCashAddress(address)));
116
- }
117
-
118
- return {
119
- ...toolbox,
120
- getAddress,
121
- broadcastTx,
122
- createTransaction,
123
- buildTx,
124
- getAddressFromKeys,
125
- getBalance: handleGetBalance,
126
- getFeeRates,
127
- stripPrefix,
128
- stripToCashAddress,
129
- validateAddress: bchValidateAddress,
130
- transfer: transfer({ getFeeRates, broadcastTx, signer }),
131
- };
132
- }
133
-
134
- async function createTransaction({
135
- assetValue,
136
- recipient,
137
- memo,
138
- feeRate,
139
- sender,
140
- }: UTXOBuildTxParams) {
141
- if (!bchValidateAddress(recipient))
142
- throw new SwapKitError("toolbox_utxo_invalid_address", { address: recipient });
143
-
144
- // Overestimate by 7500 byte * feeRate to ensure we have enough UTXOs for fees and change
145
- const targetValue = Math.ceil(assetValue.getBaseValue("number") + feeRate * 7500);
146
-
147
- const utxos = await getUtxoApi(chain).getUtxos({
148
- address: stripToCashAddress(sender),
149
- fetchTxHex: true,
150
- targetValue,
151
- });
152
-
153
- const compiledMemo = memo ? await compileMemo(memo) : null;
154
-
155
- const targetOutputs: TargetOutput[] = [];
156
- // output to recipient
157
- targetOutputs.push({
158
- address: recipient,
159
- value: assetValue.getBaseValue("number"),
160
- });
161
- const { inputs, outputs } = accumulative({
162
- inputs: utxos,
163
- outputs: targetOutputs,
164
- feeRate,
165
- chain,
166
- });
167
-
168
- // .inputs and .outputs will be undefined if no solution was found
169
- if (!(inputs && outputs))
170
- throw new SwapKitError("toolbox_utxo_insufficient_balance", { sender, assetValue });
171
- const getNetwork = await getUtxoNetwork();
172
- const builder = new TransactionBuilder(getNetwork(chain)) as TransactionBuilderType;
173
-
174
- await Promise.all(
175
- inputs.map(async (utxo: UTXOType) => {
176
- const txHex = await getUtxoApi(chain).getRawTx(utxo.hash);
177
-
178
- builder.addInput(Transaction.fromBuffer(Buffer.from(txHex, "hex")), utxo.index);
179
- }),
180
- );
181
-
182
- for (const output of outputs) {
183
- const address =
184
- "address" in output && output.address ? output.address : toLegacyAddress(sender);
185
- const getNetwork = await getUtxoNetwork();
186
- const outputScript = bchAddress.toOutputScript(toLegacyAddress(address), getNetwork(chain));
187
-
188
- builder.addOutput(outputScript, output.value);
189
- }
190
-
191
- // add output for memo
192
- if (compiledMemo) {
193
- builder.addOutput(compiledMemo, 0); // Add OP_RETURN {script, value}
194
- }
195
-
196
- return { builder, utxos: inputs };
197
- }
198
-
199
- function transfer({
200
- broadcastTx,
201
- getFeeRates,
202
- signer,
203
- }: {
204
- broadcastTx: (txHash: string) => Promise<string>;
205
- getFeeRates: () => Promise<Record<FeeOption, number>>;
206
- signer?: ChainSigner<{ builder: TransactionBuilderType; utxos: UTXOType[] }, TransactionType>;
207
- }) {
208
- return async function transfer({
209
- recipient,
210
- assetValue,
211
- feeOptionKey = FeeOption.Fast,
212
- ...rest
213
- }: UTXOTransferParams) {
214
- const from = await signer?.getAddress();
215
- if (!(signer && from)) throw new SwapKitError("toolbox_utxo_no_signer");
216
- if (!recipient)
217
- throw new SwapKitError("toolbox_utxo_invalid_params", {
218
- error: "Recipient address must be provided",
219
- });
220
-
221
- const feeRate = rest.feeRate || (await getFeeRates())[feeOptionKey];
222
-
223
- // try out if psbt tx is faster/better/nicer
224
- const { builder, utxos } = await createTransaction({
225
- ...rest,
226
- assetValue,
227
- feeRate,
228
- recipient,
229
- sender: from,
230
- });
231
-
232
- const tx = await signer.signTransaction({ builder, utxos });
233
- const txHex = tx.toHex();
234
-
235
- return broadcastTx(txHex);
236
- };
237
- }
238
-
239
- // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: TODO: refactor
240
- async function buildTx({
241
- assetValue,
242
- recipient,
243
- memo,
244
- feeRate,
245
- sender,
246
- setSigHashType,
247
- }: UTXOBuildTxParams & { setSigHashType?: boolean }) {
248
- const recipientCashAddress = toCashAddress(recipient);
249
- if (!bchValidateAddress(recipientCashAddress))
250
- throw new SwapKitError("toolbox_utxo_invalid_address", { address: recipientCashAddress });
251
-
252
- // Overestimate by 7500 byte * feeRate to ensure we have enough UTXOs for fees and change
253
- const targetValue = Math.ceil(assetValue.getBaseValue("number") + feeRate * 7500);
254
-
255
- const utxos = await getUtxoApi(chain).getUtxos({
256
- address: stripToCashAddress(sender),
257
- fetchTxHex: false,
258
- targetValue,
259
- });
260
-
261
- const feeRateWhole = Number(feeRate.toFixed(0));
262
- const compiledMemo = memo ? await compileMemo(memo) : null;
263
-
264
- const targetOutputs = [] as TargetOutput[];
265
-
266
- // output to recipient
267
- targetOutputs.push({
268
- address: toLegacyAddress(recipient),
269
- value: assetValue.getBaseValue("number"),
270
- });
271
-
272
- //2. add output memo to targets (optional)
273
- if (compiledMemo) {
274
- targetOutputs.push({ script: compiledMemo, value: 0 });
275
- }
276
-
277
- const { inputs, outputs } = accumulative({
278
- inputs: utxos,
279
- outputs: targetOutputs,
280
- feeRate: feeRateWhole,
281
- chain,
282
- });
283
-
284
- // .inputs and .outputs will be undefined if no solution was found
285
- if (!(inputs && outputs))
286
- throw new SwapKitError("toolbox_utxo_insufficient_balance", { sender, assetValue });
287
- const getNetwork = await getUtxoNetwork();
288
- const psbt = new Psbt({ network: getNetwork(chain) }); // Network-specific
289
-
290
- for (const { hash, index, witnessUtxo } of inputs) {
291
- psbt.addInput({
292
- hash,
293
- index,
294
- witnessUtxo,
295
- sighashType: setSigHashType ? 0x41 : undefined,
296
- });
297
- }
298
-
299
- // Outputs
300
- for (const output of outputs) {
301
- const address =
302
- "address" in output && output.address ? output.address : toLegacyAddress(sender);
303
- const params = output.script
304
- ? compiledMemo
305
- ? { script: compiledMemo, value: 0 }
306
- : undefined
307
- : { address, value: output.value };
308
-
309
- if (params) {
310
- psbt.addOutput(params);
311
- }
312
- }
313
-
314
- return { psbt, utxos, inputs: inputs as UTXOType[] };
315
- }
316
-
317
- function getAddressFromKeys(keys: { getAddress: (index?: number) => string }) {
318
- const address = keys.getAddress(0);
319
- return stripToCashAddress(address);
320
- }