@getomnichain/omnichain 0.2.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 (296) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/dist/abstract_gas_pricing.d.ts +31 -0
  4. package/dist/abstract_gas_pricing.d.ts.map +1 -0
  5. package/dist/abstract_gas_pricing.js +22 -0
  6. package/dist/abstract_gas_pricing.js.map +1 -0
  7. package/dist/address.d.ts +10 -0
  8. package/dist/address.d.ts.map +1 -0
  9. package/dist/address.factory.d.ts +26 -0
  10. package/dist/address.factory.d.ts.map +1 -0
  11. package/dist/address.factory.js +75 -0
  12. package/dist/address.factory.js.map +1 -0
  13. package/dist/address.js +13 -0
  14. package/dist/address.js.map +1 -0
  15. package/dist/address_field.decorator.d.ts +17 -0
  16. package/dist/address_field.decorator.d.ts.map +1 -0
  17. package/dist/address_field.decorator.js +34 -0
  18. package/dist/address_field.decorator.js.map +1 -0
  19. package/dist/chain.base.d.ts +79 -0
  20. package/dist/chain.base.d.ts.map +1 -0
  21. package/dist/chain.base.js +113 -0
  22. package/dist/chain.base.js.map +1 -0
  23. package/dist/chain_ids.d.ts +122 -0
  24. package/dist/chain_ids.d.ts.map +1 -0
  25. package/dist/chain_ids.js +193 -0
  26. package/dist/chain_ids.js.map +1 -0
  27. package/dist/errors.d.ts +42 -0
  28. package/dist/errors.d.ts.map +1 -0
  29. package/dist/errors.js +62 -0
  30. package/dist/errors.js.map +1 -0
  31. package/dist/evm/evm_address.d.ts +11 -0
  32. package/dist/evm/evm_address.d.ts.map +1 -0
  33. package/dist/evm/evm_address.js +56 -0
  34. package/dist/evm/evm_address.js.map +1 -0
  35. package/dist/evm/evm_chain.d.ts +123 -0
  36. package/dist/evm/evm_chain.d.ts.map +1 -0
  37. package/dist/evm/evm_chain.js +685 -0
  38. package/dist/evm/evm_chain.js.map +1 -0
  39. package/dist/evm/evm_chains.d.ts +83 -0
  40. package/dist/evm/evm_chains.d.ts.map +1 -0
  41. package/dist/evm/evm_chains.js +493 -0
  42. package/dist/evm/evm_chains.js.map +1 -0
  43. package/dist/evm/evm_gas_estimate.d.ts +45 -0
  44. package/dist/evm/evm_gas_estimate.d.ts.map +1 -0
  45. package/dist/evm/evm_gas_estimate.js +70 -0
  46. package/dist/evm/evm_gas_estimate.js.map +1 -0
  47. package/dist/evm/evm_gas_pricing.d.ts +40 -0
  48. package/dist/evm/evm_gas_pricing.d.ts.map +1 -0
  49. package/dist/evm/evm_gas_pricing.js +56 -0
  50. package/dist/evm/evm_gas_pricing.js.map +1 -0
  51. package/dist/evm/evm_token.d.ts +7 -0
  52. package/dist/evm/evm_token.d.ts.map +1 -0
  53. package/dist/evm/evm_token.js +22 -0
  54. package/dist/evm/evm_token.js.map +1 -0
  55. package/dist/evm/evm_tokens.d.ts +81 -0
  56. package/dist/evm/evm_tokens.d.ts.map +1 -0
  57. package/dist/evm/evm_tokens.js +104 -0
  58. package/dist/evm/evm_tokens.js.map +1 -0
  59. package/dist/evm/evm_transaction_status.d.ts +108 -0
  60. package/dist/evm/evm_transaction_status.d.ts.map +1 -0
  61. package/dist/evm/evm_transaction_status.js +177 -0
  62. package/dist/evm/evm_transaction_status.js.map +1 -0
  63. package/dist/evm/index.d.ts +10 -0
  64. package/dist/evm/index.d.ts.map +1 -0
  65. package/dist/evm/index.js +10 -0
  66. package/dist/evm/index.js.map +1 -0
  67. package/dist/evm/unsigned_evm_transaction.d.ts +19 -0
  68. package/dist/evm/unsigned_evm_transaction.d.ts.map +1 -0
  69. package/dist/evm/unsigned_evm_transaction.js +18 -0
  70. package/dist/evm/unsigned_evm_transaction.js.map +1 -0
  71. package/dist/index.d.ts +18 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +18 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/is_address.decorator.d.ts +3 -0
  76. package/dist/is_address.decorator.d.ts.map +1 -0
  77. package/dist/is_address.decorator.js +51 -0
  78. package/dist/is_address.decorator.js.map +1 -0
  79. package/dist/network_type.d.ts +73 -0
  80. package/dist/network_type.d.ts.map +1 -0
  81. package/dist/network_type.js +144 -0
  82. package/dist/network_type.js.map +1 -0
  83. package/dist/priority.d.ts +23 -0
  84. package/dist/priority.d.ts.map +1 -0
  85. package/dist/priority.js +23 -0
  86. package/dist/priority.js.map +1 -0
  87. package/dist/solana/index.d.ts +9 -0
  88. package/dist/solana/index.d.ts.map +1 -0
  89. package/dist/solana/index.js +9 -0
  90. package/dist/solana/index.js.map +1 -0
  91. package/dist/solana/solana_address.d.ts +20 -0
  92. package/dist/solana/solana_address.d.ts.map +1 -0
  93. package/dist/solana/solana_address.js +45 -0
  94. package/dist/solana/solana_address.js.map +1 -0
  95. package/dist/solana/solana_chain.d.ts +213 -0
  96. package/dist/solana/solana_chain.d.ts.map +1 -0
  97. package/dist/solana/solana_chain.js +704 -0
  98. package/dist/solana/solana_chain.js.map +1 -0
  99. package/dist/solana/solana_chains.d.ts +24 -0
  100. package/dist/solana/solana_chains.d.ts.map +1 -0
  101. package/dist/solana/solana_chains.js +84 -0
  102. package/dist/solana/solana_chains.js.map +1 -0
  103. package/dist/solana/solana_gas_pricing.d.ts +30 -0
  104. package/dist/solana/solana_gas_pricing.d.ts.map +1 -0
  105. package/dist/solana/solana_gas_pricing.js +26 -0
  106. package/dist/solana/solana_gas_pricing.js.map +1 -0
  107. package/dist/solana/solana_token.d.ts +19 -0
  108. package/dist/solana/solana_token.d.ts.map +1 -0
  109. package/dist/solana/solana_token.js +34 -0
  110. package/dist/solana/solana_token.js.map +1 -0
  111. package/dist/solana/solana_tokens.d.ts +22 -0
  112. package/dist/solana/solana_tokens.d.ts.map +1 -0
  113. package/dist/solana/solana_tokens.js +26 -0
  114. package/dist/solana/solana_tokens.js.map +1 -0
  115. package/dist/solana/solana_transaction_status.d.ts +59 -0
  116. package/dist/solana/solana_transaction_status.d.ts.map +1 -0
  117. package/dist/solana/solana_transaction_status.js +144 -0
  118. package/dist/solana/solana_transaction_status.js.map +1 -0
  119. package/dist/solana/unsigned_solana_transaction.d.ts +31 -0
  120. package/dist/solana/unsigned_solana_transaction.d.ts.map +1 -0
  121. package/dist/solana/unsigned_solana_transaction.js +26 -0
  122. package/dist/solana/unsigned_solana_transaction.js.map +1 -0
  123. package/dist/token.d.ts +35 -0
  124. package/dist/token.d.ts.map +1 -0
  125. package/dist/token.js +62 -0
  126. package/dist/token.js.map +1 -0
  127. package/dist/ton/index.d.ts +2 -0
  128. package/dist/ton/index.d.ts.map +1 -0
  129. package/dist/ton/index.js +2 -0
  130. package/dist/ton/index.js.map +1 -0
  131. package/dist/ton/ton_address.d.ts +10 -0
  132. package/dist/ton/ton_address.d.ts.map +1 -0
  133. package/dist/ton/ton_address.js +53 -0
  134. package/dist/ton/ton_address.js.map +1 -0
  135. package/dist/transaction_status.d.ts +140 -0
  136. package/dist/transaction_status.d.ts.map +1 -0
  137. package/dist/transaction_status.js +271 -0
  138. package/dist/transaction_status.js.map +1 -0
  139. package/dist/unsigned_transaction.d.ts +7 -0
  140. package/dist/unsigned_transaction.d.ts.map +1 -0
  141. package/dist/unsigned_transaction.js +9 -0
  142. package/dist/unsigned_transaction.js.map +1 -0
  143. package/dist/utxo/btc/btc_address.d.ts +15 -0
  144. package/dist/utxo/btc/btc_address.d.ts.map +1 -0
  145. package/dist/utxo/btc/btc_address.js +39 -0
  146. package/dist/utxo/btc/btc_address.js.map +1 -0
  147. package/dist/utxo/btc/btc_chain.d.ts +34 -0
  148. package/dist/utxo/btc/btc_chain.d.ts.map +1 -0
  149. package/dist/utxo/btc/btc_chain.js +62 -0
  150. package/dist/utxo/btc/btc_chain.js.map +1 -0
  151. package/dist/utxo/btc/btc_chains.d.ts +25 -0
  152. package/dist/utxo/btc/btc_chains.d.ts.map +1 -0
  153. package/dist/utxo/btc/btc_chains.js +43 -0
  154. package/dist/utxo/btc/btc_chains.js.map +1 -0
  155. package/dist/utxo/btc/btc_token.d.ts +6 -0
  156. package/dist/utxo/btc/btc_token.d.ts.map +1 -0
  157. package/dist/utxo/btc/btc_token.js +11 -0
  158. package/dist/utxo/btc/btc_token.js.map +1 -0
  159. package/dist/utxo/btc/index.d.ts +14 -0
  160. package/dist/utxo/btc/index.d.ts.map +1 -0
  161. package/dist/utxo/btc/index.js +14 -0
  162. package/dist/utxo/btc/index.js.map +1 -0
  163. package/dist/utxo/btc/network_params.d.ts +50 -0
  164. package/dist/utxo/btc/network_params.d.ts.map +1 -0
  165. package/dist/utxo/btc/network_params.js +188 -0
  166. package/dist/utxo/btc/network_params.js.map +1 -0
  167. package/dist/utxo/btc/tools/asset_outpoint.d.ts +7 -0
  168. package/dist/utxo/btc/tools/asset_outpoint.d.ts.map +1 -0
  169. package/dist/utxo/btc/tools/asset_outpoint.js +12 -0
  170. package/dist/utxo/btc/tools/asset_outpoint.js.map +1 -0
  171. package/dist/utxo/btc/tools/bitcoin_core.tool.d.ts +41 -0
  172. package/dist/utxo/btc/tools/bitcoin_core.tool.d.ts.map +1 -0
  173. package/dist/utxo/btc/tools/bitcoin_core.tool.js +172 -0
  174. package/dist/utxo/btc/tools/bitcoin_core.tool.js.map +1 -0
  175. package/dist/utxo/btc/tools/esplora.tool.d.ts +27 -0
  176. package/dist/utxo/btc/tools/esplora.tool.d.ts.map +1 -0
  177. package/dist/utxo/btc/tools/esplora.tool.js +113 -0
  178. package/dist/utxo/btc/tools/esplora.tool.js.map +1 -0
  179. package/dist/utxo/btc/tools/inscription_index.d.ts +6 -0
  180. package/dist/utxo/btc/tools/inscription_index.d.ts.map +1 -0
  181. package/dist/utxo/btc/tools/inscription_index.js +2 -0
  182. package/dist/utxo/btc/tools/inscription_index.js.map +1 -0
  183. package/dist/utxo/btc/tools/ordiscan.tool.d.ts +19 -0
  184. package/dist/utxo/btc/tools/ordiscan.tool.d.ts.map +1 -0
  185. package/dist/utxo/btc/tools/ordiscan.tool.js +53 -0
  186. package/dist/utxo/btc/tools/ordiscan.tool.js.map +1 -0
  187. package/dist/utxo/btc/tools/rare_sat_index.d.ts +6 -0
  188. package/dist/utxo/btc/tools/rare_sat_index.d.ts.map +1 -0
  189. package/dist/utxo/btc/tools/rare_sat_index.js +2 -0
  190. package/dist/utxo/btc/tools/rare_sat_index.js.map +1 -0
  191. package/dist/utxo/btc/tools/rune_index.d.ts +6 -0
  192. package/dist/utxo/btc/tools/rune_index.d.ts.map +1 -0
  193. package/dist/utxo/btc/tools/rune_index.js +2 -0
  194. package/dist/utxo/btc/tools/rune_index.js.map +1 -0
  195. package/dist/utxo/btc/tools/unisat.tool.d.ts +18 -0
  196. package/dist/utxo/btc/tools/unisat.tool.d.ts.map +1 -0
  197. package/dist/utxo/btc/tools/unisat.tool.js +49 -0
  198. package/dist/utxo/btc/tools/unisat.tool.js.map +1 -0
  199. package/dist/utxo/coin_selection.d.ts +29 -0
  200. package/dist/utxo/coin_selection.d.ts.map +1 -0
  201. package/dist/utxo/coin_selection.js +156 -0
  202. package/dist/utxo/coin_selection.js.map +1 -0
  203. package/dist/utxo/doge/doge_chains.d.ts +17 -0
  204. package/dist/utxo/doge/doge_chains.d.ts.map +1 -0
  205. package/dist/utxo/doge/doge_chains.js +28 -0
  206. package/dist/utxo/doge/doge_chains.js.map +1 -0
  207. package/dist/utxo/doge/index.d.ts +3 -0
  208. package/dist/utxo/doge/index.d.ts.map +1 -0
  209. package/dist/utxo/doge/index.js +3 -0
  210. package/dist/utxo/doge/index.js.map +1 -0
  211. package/dist/utxo/doge/network_params.d.ts +4 -0
  212. package/dist/utxo/doge/network_params.d.ts.map +1 -0
  213. package/dist/utxo/doge/network_params.js +24 -0
  214. package/dist/utxo/doge/network_params.js.map +1 -0
  215. package/dist/utxo/ecc.d.ts +2 -0
  216. package/dist/utxo/ecc.d.ts.map +1 -0
  217. package/dist/utxo/ecc.js +11 -0
  218. package/dist/utxo/ecc.js.map +1 -0
  219. package/dist/utxo/fee.d.ts +12 -0
  220. package/dist/utxo/fee.d.ts.map +1 -0
  221. package/dist/utxo/fee.js +51 -0
  222. package/dist/utxo/fee.js.map +1 -0
  223. package/dist/utxo/index.d.ts +20 -0
  224. package/dist/utxo/index.d.ts.map +1 -0
  225. package/dist/utxo/index.js +20 -0
  226. package/dist/utxo/index.js.map +1 -0
  227. package/dist/utxo/ltc/index.d.ts +3 -0
  228. package/dist/utxo/ltc/index.d.ts.map +1 -0
  229. package/dist/utxo/ltc/index.js +3 -0
  230. package/dist/utxo/ltc/index.js.map +1 -0
  231. package/dist/utxo/ltc/ltc_chains.d.ts +17 -0
  232. package/dist/utxo/ltc/ltc_chains.d.ts.map +1 -0
  233. package/dist/utxo/ltc/ltc_chains.js +28 -0
  234. package/dist/utxo/ltc/ltc_chains.js.map +1 -0
  235. package/dist/utxo/ltc/network_params.d.ts +4 -0
  236. package/dist/utxo/ltc/network_params.d.ts.map +1 -0
  237. package/dist/utxo/ltc/network_params.js +27 -0
  238. package/dist/utxo/ltc/network_params.js.map +1 -0
  239. package/dist/utxo/script.d.ts +16 -0
  240. package/dist/utxo/script.d.ts.map +1 -0
  241. package/dist/utxo/script.js +52 -0
  242. package/dist/utxo/script.js.map +1 -0
  243. package/dist/utxo/tools/broadcaster.d.ts +6 -0
  244. package/dist/utxo/tools/broadcaster.d.ts.map +1 -0
  245. package/dist/utxo/tools/broadcaster.js +2 -0
  246. package/dist/utxo/tools/broadcaster.js.map +1 -0
  247. package/dist/utxo/tools/chain_tip_provider.d.ts +5 -0
  248. package/dist/utxo/tools/chain_tip_provider.d.ts.map +1 -0
  249. package/dist/utxo/tools/chain_tip_provider.js +2 -0
  250. package/dist/utxo/tools/chain_tip_provider.js.map +1 -0
  251. package/dist/utxo/tools/fee_estimator.d.ts +6 -0
  252. package/dist/utxo/tools/fee_estimator.d.ts.map +1 -0
  253. package/dist/utxo/tools/fee_estimator.js +2 -0
  254. package/dist/utxo/tools/fee_estimator.js.map +1 -0
  255. package/dist/utxo/tools/raw_transaction_provider.d.ts +8 -0
  256. package/dist/utxo/tools/raw_transaction_provider.d.ts.map +1 -0
  257. package/dist/utxo/tools/raw_transaction_provider.js +2 -0
  258. package/dist/utxo/tools/raw_transaction_provider.js.map +1 -0
  259. package/dist/utxo/tools/utxo_provider.d.ts +7 -0
  260. package/dist/utxo/tools/utxo_provider.d.ts.map +1 -0
  261. package/dist/utxo/tools/utxo_provider.js +2 -0
  262. package/dist/utxo/tools/utxo_provider.js.map +1 -0
  263. package/dist/utxo/unsigned_utxo_transaction.d.ts +32 -0
  264. package/dist/utxo/unsigned_utxo_transaction.d.ts.map +1 -0
  265. package/dist/utxo/unsigned_utxo_transaction.js +32 -0
  266. package/dist/utxo/unsigned_utxo_transaction.js.map +1 -0
  267. package/dist/utxo/utxo.d.ts +43 -0
  268. package/dist/utxo/utxo.d.ts.map +1 -0
  269. package/dist/utxo/utxo.js +2 -0
  270. package/dist/utxo/utxo.js.map +1 -0
  271. package/dist/utxo/utxo_chain.d.ts +102 -0
  272. package/dist/utxo/utxo_chain.d.ts.map +1 -0
  273. package/dist/utxo/utxo_chain.js +524 -0
  274. package/dist/utxo/utxo_chain.js.map +1 -0
  275. package/dist/utxo/utxo_chains.d.ts +29 -0
  276. package/dist/utxo/utxo_chains.d.ts.map +1 -0
  277. package/dist/utxo/utxo_chains.js +63 -0
  278. package/dist/utxo/utxo_chains.js.map +1 -0
  279. package/dist/utxo/utxo_gas_pricing.d.ts +22 -0
  280. package/dist/utxo/utxo_gas_pricing.d.ts.map +1 -0
  281. package/dist/utxo/utxo_gas_pricing.js +20 -0
  282. package/dist/utxo/utxo_gas_pricing.js.map +1 -0
  283. package/dist/utxo/utxo_network_params.d.ts +25 -0
  284. package/dist/utxo/utxo_network_params.d.ts.map +1 -0
  285. package/dist/utxo/utxo_network_params.js +15 -0
  286. package/dist/utxo/utxo_network_params.js.map +1 -0
  287. package/dist/utxo/utxo_transaction_status.d.ts +73 -0
  288. package/dist/utxo/utxo_transaction_status.d.ts.map +1 -0
  289. package/dist/utxo/utxo_transaction_status.js +89 -0
  290. package/dist/utxo/utxo_transaction_status.js.map +1 -0
  291. package/docs/PUBLISHING.md +119 -0
  292. package/docs/README.md +273 -0
  293. package/docs/evm.md +205 -0
  294. package/docs/solana.md +220 -0
  295. package/docs/utxo.md +364 -0
  296. package/package.json +94 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 getomnichain
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # @getomnichain/omnichain
2
+
3
+ Multi-chain TypeScript SDK. One `Chain` / `Token` / `Address` / `UnsignedTransaction` shape for EVM, UTXO (BTC/LTC/DOGE/DASH/ZEC/BCH), Solana, TON, and Tron. Line-for-line parity port of Python's [`omnichain-py`](https://github.com/getomnichain/omnichain-py).
4
+
5
+ ```bash
6
+ npm install @getomnichain/omnichain decimal.js
7
+ ```
8
+
9
+ `decimal.js` is a required peer install — the package imports it at the root and consumer builds fail at import time if it's missing.
10
+
11
+ ## Quick start
12
+
13
+ ```ts
14
+ import { arbitrumChain, isSuccess, Priority } from '@getomnichain/omnichain';
15
+ import Decimal from 'decimal.js';
16
+
17
+ const chain = arbitrumChain({ rpcUrl: process.env.ARBITRUM_RPC_URL });
18
+
19
+ const unsigned = await chain.createTransferUnsignedTransaction({
20
+ from: senderAddress,
21
+ to: recipientAddress,
22
+ tokenIdentifier: usdcAddress,
23
+ amountHr: new Decimal('1.5'),
24
+ });
25
+
26
+ const status = await chain.getTransactionStatus(txHash);
27
+ if (isSuccess(status)) {
28
+ for (const [wallet, perAsset] of status.balanceChanges) {
29
+ for (const { token, change } of perAsset.values()) {
30
+ console.log(wallet, token.symbol, change.balanceChangeMr, change.balanceChangeHr.toFixed());
31
+ }
32
+ }
33
+ }
34
+
35
+ const gas = await chain.suggestGas(Priority.NORMAL);
36
+ ```
37
+
38
+ Consumer TypeScript setup: `module: "NodeNext"` + `moduleResolution: "NodeNext"`. The package ships compiled `.js` + `.d.ts` under `dist/`; the source is `.ts` on GitHub for anyone who wants to read the implementation.
39
+
40
+ ## What this SDK does NOT do
41
+
42
+ - **Hold keys** — signing happens in the consumer service. The SDK only emits `UnsignedTransaction` objects.
43
+ - **Read environment variables** — every constructor takes an explicit config object. The one exception is RPC URL fallback resolution (`<NAME>_RPC_URL` / `EVM_<chainId>_RPC_URL` / `SOLANA_<chainId>_RPC_URL`), documented per chain.
44
+ - **Decide chain IDs** — non-EVM chains have no universal numeric ID; consumers can seed a synthetic scheme via `registerNonEvmChain(id, family)`.
45
+ - **Ship infrastructure** — RPC URLs, indexer keys, Bitcoin Core / Esplora endpoints are consumer-owned.
46
+
47
+ ## Solana raw-instruction helpers
48
+
49
+ `SolanaChain` exposes two raw-instruction builders alongside `createTransferUnsignedTransaction`, for callers that will compile the transaction downstream:
50
+
51
+ - `buildNativeTransferInstruction(from, to, lamports)` — sync; wraps `SystemProgram.transfer`.
52
+ - `buildSplTransferInstructions({from, to, mint, amount, includeCreateAta?, allowOwnerOffCurve?})` — async; returns `[createATA-idempotent?, transferChecked]`. Uses the idempotent ATA form (not probe-then-create) because the downstream compiler runs instructions blindly and a probe would race with execution. `allowOwnerOffCurve` applies to both source and destination ATA derivation for PDA-owned wallets.
53
+
54
+ `createTransferUnsignedTransaction`'s compiled-tx surface uses probe-then-create for its own end-to-end signing path.
55
+
56
+ ## Documentation
57
+
58
+ - [docs/README.md](./docs/README.md) — full module guide
59
+ - [docs/evm.md](./docs/evm.md) — EVM chains and ERC-20
60
+ - [docs/utxo.md](./docs/utxo.md) — Bitcoin / Litecoin / Dogecoin, fee estimation, BTC asset filtering
61
+ - [docs/solana.md](./docs/solana.md) — Solana, SPL Token, Token-2022, priority-fee model
62
+ - [docs/PUBLISHING.md](./docs/PUBLISHING.md) — release + npm publish workflow
63
+
64
+ ## License
65
+
66
+ MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,31 @@
1
+ import { NetworkType } from './network_type.ts';
2
+ import { FeePriority } from './priority.ts';
3
+ /**
4
+ * Base for chain-specific *explicit* fee overrides — mirrors Python's
5
+ * `AbstractGasPricing(pydantic.BaseModel)` at `base/base.py:141-158`.
6
+ * A subclass declares its `networkType` and carries the concrete fee
7
+ * fields for that chain (`EvmGasPricing`, `SolanaGasPricing`,
8
+ * `UtxoGasPricing`).
9
+ *
10
+ * A caller who wants exact numeric control passes an `AbstractGasPricing`
11
+ * subclass to `createTransferUnsignedTransaction`; passing a
12
+ * `FeePriority` tier (SLOW/NORMAL/FAST) instead defers to each chain's
13
+ * `suggest*` estimator. See `GasPricingType`.
14
+ */
15
+ export declare abstract class AbstractGasPricing {
16
+ abstract readonly networkType: NetworkType;
17
+ }
18
+ /**
19
+ * The gas-pricing argument accepted by every
20
+ * `createTransferUnsignedTransaction`. Mirrors Python's
21
+ * `GasPricingType = Union[FeePriority, AbstractGasPricing]` at
22
+ * `base/base.py:162`. Consumers use `FeePriority.NORMAL` by default;
23
+ * explicit overrides use a per-chain subclass.
24
+ */
25
+ export type GasPricingType = FeePriority | AbstractGasPricing;
26
+ /**
27
+ * Runtime discriminator for `GasPricingType`. `FeePriority` is a
28
+ * string enum; `AbstractGasPricing` is a class instance.
29
+ */
30
+ export declare function isAbstractGasPricing(value: GasPricingType): value is AbstractGasPricing;
31
+ //# sourceMappingURL=abstract_gas_pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract_gas_pricing.d.ts","sourceRoot":"","sources":["../abstract_gas_pricing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;;;;;;;;;;GAWG;AACH,8BAAsB,kBAAkB;IACtC,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;CAC5C;AAED;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,kBAAkB,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,IAAI,kBAAkB,CAEvF"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Base for chain-specific *explicit* fee overrides — mirrors Python's
3
+ * `AbstractGasPricing(pydantic.BaseModel)` at `base/base.py:141-158`.
4
+ * A subclass declares its `networkType` and carries the concrete fee
5
+ * fields for that chain (`EvmGasPricing`, `SolanaGasPricing`,
6
+ * `UtxoGasPricing`).
7
+ *
8
+ * A caller who wants exact numeric control passes an `AbstractGasPricing`
9
+ * subclass to `createTransferUnsignedTransaction`; passing a
10
+ * `FeePriority` tier (SLOW/NORMAL/FAST) instead defers to each chain's
11
+ * `suggest*` estimator. See `GasPricingType`.
12
+ */
13
+ export class AbstractGasPricing {
14
+ }
15
+ /**
16
+ * Runtime discriminator for `GasPricingType`. `FeePriority` is a
17
+ * string enum; `AbstractGasPricing` is a class instance.
18
+ */
19
+ export function isAbstractGasPricing(value) {
20
+ return value instanceof AbstractGasPricing;
21
+ }
22
+ //# sourceMappingURL=abstract_gas_pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract_gas_pricing.js","sourceRoot":"","sources":["../abstract_gas_pricing.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,MAAM,OAAgB,kBAAkB;CAEvC;AAWD;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAqB;IACxD,OAAO,KAAK,YAAY,kBAAkB,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { NetworkType } from './network_type.ts';
2
+ export declare abstract class Address {
3
+ protected readonly raw: string;
4
+ protected constructor(raw: string);
5
+ abstract canonical(): string;
6
+ abstract get networkType(): NetworkType;
7
+ equals(other: Address): boolean;
8
+ toString(): string;
9
+ }
10
+ //# sourceMappingURL=address.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address.d.ts","sourceRoot":"","sources":["../address.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,8BAAsB,OAAO;IACL,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM;IAApD,SAAS,aAAgC,GAAG,EAAE,MAAM;IAEpD,QAAQ,CAAC,SAAS,IAAI,MAAM;IAC5B,QAAQ,KAAK,WAAW,IAAI,WAAW,CAAC;IAExC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO;IAM/B,QAAQ,IAAI,MAAM;CAGnB"}
@@ -0,0 +1,26 @@
1
+ import { Address } from './address.ts';
2
+ export declare function addressFor(chainId: number, raw: string): Address;
3
+ export declare function canonicalizeAddress(chainId: number, raw: string): string;
4
+ /**
5
+ * Total function — never throws. Returns the raw input on any failure
6
+ * (address-format error, unsupported chain, malformed args).
7
+ *
8
+ * Callers that need to fail loudly on stale/unsupported chainIds while
9
+ * still tolerating address-format errors should use
10
+ * `canonicalizeAddressStrict` instead.
11
+ */
12
+ export declare function tryCanonicalizeAddress(chainId: number, raw: string): string;
13
+ /**
14
+ * Swallows address-format errors (returns raw input) but re-throws
15
+ * `ChainError(ChainNotSupported)` so a stale chainId (e.g. un-migrated
16
+ * legacy Solana `-100`) fails loudly rather than passing a bogus routing
17
+ * signal downstream. Use in application code where an unsupported chain
18
+ * is a hard error the caller wants to surface, and address-format
19
+ * errors are reported by a separate validation layer.
20
+ *
21
+ * NOT for class-transformer `@Transform` callbacks — a throw there also
22
+ * fires during response serialization when an entity carries a stale
23
+ * chainId, killing every read of a legacy row.
24
+ */
25
+ export declare function canonicalizeAddressStrict(chainId: number, raw: string): string;
26
+ //# sourceMappingURL=address.factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address.factory.d.ts","sourceRoot":"","sources":["../address.factory.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAOvC,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAiChE;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAExE;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAM3E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAO9E"}
@@ -0,0 +1,75 @@
1
+ import { ChainError, ChainErrorKinds, isChainError } from "./errors.js";
2
+ import { NetworkType, networkTypeOf } from "./network_type.js";
3
+ import { EvmAddress } from "./evm/evm_address.js";
4
+ import { SolanaAddress } from "./solana/solana_address.js";
5
+ import { TonAddress } from "./ton/ton_address.js";
6
+ import { BtcAddress } from "./utxo/btc/btc_address.js";
7
+ import { btcParamsForChainId } from "./utxo/btc/network_params.js";
8
+ export function addressFor(chainId, raw) {
9
+ const family = networkTypeOf(chainId);
10
+ switch (family) {
11
+ case NetworkType.EVM:
12
+ return new EvmAddress(raw);
13
+ case NetworkType.SOLANA:
14
+ return new SolanaAddress(raw);
15
+ case NetworkType.BTC:
16
+ return new BtcAddress(raw, btcParamsForChainId(BigInt(chainId)));
17
+ case NetworkType.TON:
18
+ return new TonAddress(raw);
19
+ // TRON / COSMOS have no in-repo Address class yet. Rather than fall through
20
+ // to EvmAddress (which would silently accept a valid EVM address for a
21
+ // Tron chain and un-canonicalize base58 T… addresses), fail closed until
22
+ // the concrete implementations land.
23
+ case NetworkType.TRON:
24
+ case NetworkType.COSMOS:
25
+ throw new ChainError(ChainErrorKinds.ChainNotSupported, `${family} address parsing is not implemented for chainId ${chainId}`, { chainId });
26
+ default: {
27
+ // Exhaustiveness guard — a new NetworkType value should force this
28
+ // switch to be updated rather than fall through to EVM.
29
+ const exhaustive = family;
30
+ throw new ChainError(ChainErrorKinds.ChainNotSupported, `Unhandled NetworkType ${String(exhaustive)} for chainId ${chainId}`, { chainId });
31
+ }
32
+ }
33
+ }
34
+ export function canonicalizeAddress(chainId, raw) {
35
+ return addressFor(chainId, raw).canonical();
36
+ }
37
+ /**
38
+ * Total function — never throws. Returns the raw input on any failure
39
+ * (address-format error, unsupported chain, malformed args).
40
+ *
41
+ * Callers that need to fail loudly on stale/unsupported chainIds while
42
+ * still tolerating address-format errors should use
43
+ * `canonicalizeAddressStrict` instead.
44
+ */
45
+ export function tryCanonicalizeAddress(chainId, raw) {
46
+ try {
47
+ return canonicalizeAddress(chainId, raw);
48
+ }
49
+ catch {
50
+ return raw;
51
+ }
52
+ }
53
+ /**
54
+ * Swallows address-format errors (returns raw input) but re-throws
55
+ * `ChainError(ChainNotSupported)` so a stale chainId (e.g. un-migrated
56
+ * legacy Solana `-100`) fails loudly rather than passing a bogus routing
57
+ * signal downstream. Use in application code where an unsupported chain
58
+ * is a hard error the caller wants to surface, and address-format
59
+ * errors are reported by a separate validation layer.
60
+ *
61
+ * NOT for class-transformer `@Transform` callbacks — a throw there also
62
+ * fires during response serialization when an entity carries a stale
63
+ * chainId, killing every read of a legacy row.
64
+ */
65
+ export function canonicalizeAddressStrict(chainId, raw) {
66
+ try {
67
+ return canonicalizeAddress(chainId, raw);
68
+ }
69
+ catch (e) {
70
+ if (isChainError(e, ChainErrorKinds.ChainNotSupported))
71
+ throw e;
72
+ return raw;
73
+ }
74
+ }
75
+ //# sourceMappingURL=address.factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address.factory.js","sourceRoot":"","sources":["../address.factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAG/D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,GAAW;IACrD,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,WAAW,CAAC,GAAG;YAClB,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;QAC7B,KAAK,WAAW,CAAC,MAAM;YACrB,OAAO,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC;QAChC,KAAK,WAAW,CAAC,GAAG;YAClB,OAAO,IAAI,UAAU,CAAC,GAAG,EAAE,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACnE,KAAK,WAAW,CAAC,GAAG;YAClB,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;QAC7B,4EAA4E;QAC5E,uEAAuE;QACvE,yEAAyE;QACzE,qCAAqC;QACrC,KAAK,WAAW,CAAC,IAAI,CAAC;QACtB,KAAK,WAAW,CAAC,MAAM;YACrB,MAAM,IAAI,UAAU,CAClB,eAAe,CAAC,iBAAiB,EACjC,GAAG,MAAM,mDAAmD,OAAO,EAAE,EACrE,EAAE,OAAO,EAAE,CACZ,CAAC;QACJ,OAAO,CAAC,CAAC,CAAC;YACR,mEAAmE;YACnE,wDAAwD;YACxD,MAAM,UAAU,GAAU,MAAM,CAAC;YACjC,MAAM,IAAI,UAAU,CAClB,eAAe,CAAC,iBAAiB,EACjC,yBAAyB,MAAM,CAAC,UAAU,CAAC,gBAAgB,OAAO,EAAE,EACpE,EAAE,OAAO,EAAE,CACZ,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,GAAW;IAC9D,OAAO,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC;AAC9C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe,EAAE,GAAW;IACjE,IAAI,CAAC;QACH,OAAO,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAe,EAAE,GAAW;IACpE,IAAI,CAAC;QACH,OAAO,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,YAAY,CAAC,CAAC,EAAE,eAAe,CAAC,iBAAiB,CAAC;YAAE,MAAM,CAAC,CAAC;QAChE,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ export class Address {
2
+ raw;
3
+ constructor(raw) {
4
+ this.raw = raw;
5
+ }
6
+ equals(other) {
7
+ return (this.networkType === other.networkType && this.canonical() === other.canonical());
8
+ }
9
+ toString() {
10
+ return this.canonical();
11
+ }
12
+ }
13
+ //# sourceMappingURL=address.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address.js","sourceRoot":"","sources":["../address.ts"],"names":[],"mappings":"AAEA,MAAM,OAAgB,OAAO;IACc;IAAzC,YAAyC,GAAW;QAAX,QAAG,GAAH,GAAG,CAAQ;IAAG,CAAC;IAKxD,MAAM,CAAC,KAAc;QACnB,OAAO,CACL,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,EAAE,KAAK,KAAK,CAAC,SAAS,EAAE,CACjF,CAAC;IACJ,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC;CACF"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Combines a `class-transformer` `@Transform` that canonicalizes the address
3
+ * value with an `@IsAddress` validator.
4
+ *
5
+ * The transform uses `tryCanonicalizeAddress` — a total function that
6
+ * swallows **every** failure (including `ChainNotSupported`) and returns the
7
+ * raw input. `@IsAddress` is the sole reporter of the failure at DTO
8
+ * validation time. This is deliberate: a `@Transform` also runs during
9
+ * `instanceToPlain` (response serialization), and a throw there would fail
10
+ * every read of a legacy-chainId entity row.
11
+ *
12
+ * For application code outside a class-transformer boundary that wants
13
+ * `ChainNotSupported` to fail loud (e.g. a service layer processing a
14
+ * migration queue), use `canonicalizeAddressStrict` instead.
15
+ */
16
+ export declare function AddressField(chainIdProperty: string): PropertyDecorator;
17
+ //# sourceMappingURL=address_field.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address_field.decorator.d.ts","sourceRoot":"","sources":["../address_field.decorator.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,eAAe,EAAE,MAAM,GAAG,iBAAiB,CAYvE"}
@@ -0,0 +1,34 @@
1
+ import { Transform } from 'class-transformer';
2
+ import { tryCanonicalizeAddress } from "./address.factory.js";
3
+ import { IsAddress } from "./is_address.decorator.js";
4
+ /**
5
+ * Combines a `class-transformer` `@Transform` that canonicalizes the address
6
+ * value with an `@IsAddress` validator.
7
+ *
8
+ * The transform uses `tryCanonicalizeAddress` — a total function that
9
+ * swallows **every** failure (including `ChainNotSupported`) and returns the
10
+ * raw input. `@IsAddress` is the sole reporter of the failure at DTO
11
+ * validation time. This is deliberate: a `@Transform` also runs during
12
+ * `instanceToPlain` (response serialization), and a throw there would fail
13
+ * every read of a legacy-chainId entity row.
14
+ *
15
+ * For application code outside a class-transformer boundary that wants
16
+ * `ChainNotSupported` to fail loud (e.g. a service layer processing a
17
+ * migration queue), use `canonicalizeAddressStrict` instead.
18
+ */
19
+ export function AddressField(chainIdProperty) {
20
+ const transform = Transform(({ obj, value }) => {
21
+ if (typeof value !== 'string')
22
+ return value;
23
+ const chainId = obj[chainIdProperty];
24
+ if (typeof chainId !== 'number')
25
+ return value;
26
+ return tryCanonicalizeAddress(chainId, value);
27
+ });
28
+ const validate = IsAddress(chainIdProperty);
29
+ return (target, propertyKey) => {
30
+ transform(target, propertyKey);
31
+ validate(target, propertyKey);
32
+ };
33
+ }
34
+ //# sourceMappingURL=address_field.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"address_field.decorator.js","sourceRoot":"","sources":["../address_field.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEtD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,YAAY,CAAC,eAAuB;IAClD,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;QAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5C,MAAM,OAAO,GAAI,GAA+B,CAAC,eAAe,CAAC,CAAC;QAClE,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC9C,OAAO,sBAAsB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,SAAS,CAAC,eAAe,CAAC,CAAC;IAC5C,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC7B,SAAS,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAC/B,QAAQ,CAAC,MAAM,EAAE,WAAqB,CAAC,CAAC;IAC1C,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,79 @@
1
+ import { Decimal } from 'decimal.js';
2
+ import { GasPricingType } from './abstract_gas_pricing.ts';
3
+ import { NetworkType } from './network_type.ts';
4
+ import { Token } from './token.ts';
5
+ import { TransactionStatus } from './transaction_status.ts';
6
+ import { UnsignedTransaction } from './unsigned_transaction.ts';
7
+ /**
8
+ * Amount contract — Python parity with `create_transfer_transaction`
9
+ * (base/base.py:529-539) which takes `amount_hr: Decimal` +
10
+ * `is_full_balance: bool`. TS accepts either:
11
+ *
12
+ * - `amount: bigint` — minor units (existing SDK-native form)
13
+ * - `amountHr: Decimal` — human-readable (Python-native form)
14
+ * - `isFullBalance: true` — sweep the sender's whole balance
15
+ *
16
+ * Exactly one of the three must be supplied. `resolveTransferAmount`
17
+ * enforces this and throws `ChainError(InvalidArgument)` on ambiguous
18
+ * input.
19
+ */
20
+ export interface CreateTransferRequest {
21
+ from?: string;
22
+ to: string;
23
+ tokenIdentifier?: string;
24
+ amount?: bigint;
25
+ amountHr?: Decimal;
26
+ isFullBalance?: boolean;
27
+ /**
28
+ * Gas-pricing knob — Python's `gas_pricing: GasPricingType`. The type
29
+ * surface is in place (Python parity) but per-chain builders **do
30
+ * not consume it yet** in Wave 2B — passing ANY value (including
31
+ * `FeePriority.NORMAL`) throws `ChainError(InvalidArgument)`. Wiring
32
+ * to each chain's `suggestGas` / `suggestPriorityFeeMicroLamports` /
33
+ * `suggestFeeRate` estimator lands in a follow-up card. Until then
34
+ * use the existing per-chain option fields (Solana:
35
+ * `priorityFeeMicroLamportsPerCu` / `computeUnitLimit`; UTXO:
36
+ * `feeRateSatsPerVByte` / `feeTargetBlocks`; EVM: `UnsignedEvmTransaction`
37
+ * builder options).
38
+ */
39
+ gasPricing?: GasPricingType;
40
+ memo?: string;
41
+ }
42
+ export type ResolvedTransferAmount = {
43
+ kind: 'exact';
44
+ amountMr: bigint;
45
+ } | {
46
+ kind: 'full';
47
+ };
48
+ /**
49
+ * Validates that exactly one of `{amount, amountHr, isFullBalance}` was
50
+ * supplied and normalizes to a common shape the chain builders consume.
51
+ * Chain-agnostic — the caller supplies `decimals` (from the resolved
52
+ * token). Rounds `amountHr` via `Decimal.trunc()` matching Python's
53
+ * `hr_to_mr`.
54
+ *
55
+ * Non-integer decimals / negative amount / etc. throw
56
+ * `ChainError(InvalidArgument)`.
57
+ */
58
+ export declare function resolveTransferAmount(req: CreateTransferRequest, decimals: number): ResolvedTransferAmount;
59
+ export declare abstract class Chain {
60
+ readonly chainId: number;
61
+ readonly name: string;
62
+ readonly networkType: NetworkType;
63
+ readonly blockTimeSeconds: number;
64
+ readonly nativeSymbol: string;
65
+ readonly explorerBaseUrl: string;
66
+ protected constructor(chainId: number, name: string, networkType: NetworkType, blockTimeSeconds: number, nativeSymbol: string, explorerBaseUrl: string);
67
+ abstract get nativeToken(): Token;
68
+ abstract getWalletExplorerUrl(address: string): string;
69
+ abstract getTokenExplorerUrl(tokenIdentifier?: string): string;
70
+ abstract getTransactionExplorerUrl(txHash: string): string;
71
+ abstract validateAddress(raw: string): boolean;
72
+ abstract validateTokenIdentifier(raw: string | undefined): boolean;
73
+ abstract getBalance(owner: string, tokenIdentifier?: string): Promise<bigint>;
74
+ abstract createTransferUnsignedTransaction(req: CreateTransferRequest): Promise<UnsignedTransaction>;
75
+ abstract getTransactionStatus(txHash: string): Promise<TransactionStatus>;
76
+ abstract getChainTipHeight(): Promise<number>;
77
+ toString(): string;
78
+ }
79
+ //# sourceMappingURL=chain.base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.base.d.ts","sourceRoot":"","sources":["../chain.base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,EAAE,MAAM,GACf,sBAAsB,CA4GxB;AAED,8BAAsB,KAAK;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAEjC,SAAS,aACP,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,MAAM,EACxB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM;IAazB,QAAQ,KAAK,WAAW,IAAI,KAAK,CAAC;IAElC,QAAQ,CAAC,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IACtD,QAAQ,CAAC,mBAAmB,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM;IAC9D,QAAQ,CAAC,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAE1D,QAAQ,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAC9C,QAAQ,CAAC,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;IAElE,QAAQ,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAE7E,QAAQ,CAAC,iCAAiC,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAEpG,QAAQ,CAAC,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAEzE,QAAQ,CAAC,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAE7C,QAAQ,IAAI,MAAM;CAGnB"}
@@ -0,0 +1,113 @@
1
+ import { Decimal } from 'decimal.js';
2
+ import { ChainError, ChainErrorKinds } from "./errors.js";
3
+ import { hrDecimalToMinorUnits } from "./transaction_status.js";
4
+ /**
5
+ * Validates that exactly one of `{amount, amountHr, isFullBalance}` was
6
+ * supplied and normalizes to a common shape the chain builders consume.
7
+ * Chain-agnostic — the caller supplies `decimals` (from the resolved
8
+ * token). Rounds `amountHr` via `Decimal.trunc()` matching Python's
9
+ * `hr_to_mr`.
10
+ *
11
+ * Non-integer decimals / negative amount / etc. throw
12
+ * `ChainError(InvalidArgument)`.
13
+ */
14
+ export function resolveTransferAmount(req, decimals) {
15
+ // Upfront typeof gate for isFullBalance — silently coercing a non-boolean
16
+ // to "unset" here would let `{amount, isFullBalance: 'true'}` (JSON boundary
17
+ // realistic) take the amount branch instead of failing the exactly-one-of.
18
+ if (req.isFullBalance !== undefined && typeof req.isFullBalance !== 'boolean') {
19
+ throw new ChainError(ChainErrorKinds.InvalidArgument, `CreateTransferRequest.isFullBalance must be a boolean (got ${typeof req.isFullBalance})`);
20
+ }
21
+ const provided = [];
22
+ if (req.amount !== undefined)
23
+ provided.push('amount');
24
+ if (req.amountHr !== undefined)
25
+ provided.push('amountHr');
26
+ if (req.isFullBalance === true)
27
+ provided.push('isFullBalance');
28
+ if (provided.length === 0) {
29
+ throw new ChainError(ChainErrorKinds.InvalidArgument, 'CreateTransferRequest: one of {amount, amountHr, isFullBalance} is required');
30
+ }
31
+ if (provided.length > 1) {
32
+ throw new ChainError(ChainErrorKinds.InvalidArgument, `CreateTransferRequest: exactly one of {amount, amountHr, isFullBalance} may be set (got ${provided.join(', ')})`);
33
+ }
34
+ if (req.isFullBalance === true)
35
+ return { kind: 'full' };
36
+ if (req.amount !== undefined) {
37
+ // Explicit typeof check: JS mixed-type comparison lets '1000000' <= 0n
38
+ // return false (`StringToBigInt`), so a string/number amount would
39
+ // otherwise pass this guard and land verbatim in tx.value /
40
+ // lamports / ERC-20 calldata. Realistic vector: consumers
41
+ // deserializing amounts from HTTP/DB JSON.
42
+ if (typeof req.amount !== 'bigint') {
43
+ throw new ChainError(ChainErrorKinds.InvalidArgument, `CreateTransferRequest.amount must be a bigint (got ${typeof req.amount})`);
44
+ }
45
+ if (req.amount <= 0n) {
46
+ throw new ChainError(ChainErrorKinds.InvalidArgument, `CreateTransferRequest.amount must be > 0, got ${req.amount}`);
47
+ }
48
+ return { kind: 'exact', amountMr: req.amount };
49
+ }
50
+ // amountHr branch. Cross-copy-safe structural probe: `instanceof
51
+ // Decimal` and `Decimal.isDecimal` both key off constructor identity
52
+ // in practice (isDecimal's toStringTag branch is dead against the
53
+ // shipped prototype), so a `Decimal` from a nested/duplicated copy of
54
+ // decimal.js in the consumer tree would falsely reject. Instead:
55
+ // probe for the two methods we actually need (`toFixed`, `isFinite`),
56
+ // then normalize via `Decimal.prototype.toString` — an exact,
57
+ // always-reparseable serialization — into our own Decimal instance.
58
+ const rawHr = req.amountHr;
59
+ if (rawHr === null ||
60
+ typeof rawHr !== 'object' ||
61
+ typeof rawHr.toFixed !== 'function' ||
62
+ typeof rawHr.isFinite !== 'function' ||
63
+ typeof rawHr.toString !== 'function') {
64
+ throw new ChainError(ChainErrorKinds.InvalidArgument, 'CreateTransferRequest.amountHr must be a Decimal value (structural probe: needs toFixed + isFinite + toString)');
65
+ }
66
+ let hr;
67
+ try {
68
+ hr = new Decimal(rawHr.toString());
69
+ }
70
+ catch (err) {
71
+ throw new ChainError(ChainErrorKinds.InvalidArgument, 'CreateTransferRequest.amountHr: string round-trip failed', undefined, err instanceof Error ? err : undefined);
72
+ }
73
+ if (!hr.isFinite()) {
74
+ throw new ChainError(ChainErrorKinds.InvalidArgument, `CreateTransferRequest.amountHr must be finite, got ${hr.toString()}`);
75
+ }
76
+ if (!Number.isInteger(decimals) || decimals < 0) {
77
+ throw new ChainError(ChainErrorKinds.InvalidArgument, `CreateTransferRequest.amountHr requires a non-negative integer decimals, got ${decimals}`);
78
+ }
79
+ if (hr.isNegative()) {
80
+ throw new ChainError(ChainErrorKinds.InvalidArgument, `CreateTransferRequest.amountHr must be >= 0, got ${hr.toString()}`);
81
+ }
82
+ // Exact conversion via string-shift (bypasses decimal.js's 20-sig-digit
83
+ // precision limit that would silently round the last wei on 18-decimal
84
+ // amounts ≥ ~100 tokens).
85
+ const amountMr = hrDecimalToMinorUnits(hr, decimals);
86
+ if (amountMr <= 0n) {
87
+ throw new ChainError(ChainErrorKinds.InvalidArgument, `CreateTransferRequest.amountHr must convert to > 0 minor units, got ${amountMr} (from ${hr.toString()} @ ${decimals} decimals)`);
88
+ }
89
+ return { kind: 'exact', amountMr };
90
+ }
91
+ export class Chain {
92
+ chainId;
93
+ name;
94
+ networkType;
95
+ blockTimeSeconds;
96
+ nativeSymbol;
97
+ explorerBaseUrl;
98
+ constructor(chainId, name, networkType, blockTimeSeconds, nativeSymbol, explorerBaseUrl) {
99
+ if (!Number.isInteger(chainId)) {
100
+ throw new Error('Chain chainId must be an integer');
101
+ }
102
+ this.chainId = chainId;
103
+ this.name = name;
104
+ this.networkType = networkType;
105
+ this.blockTimeSeconds = blockTimeSeconds;
106
+ this.nativeSymbol = nativeSymbol;
107
+ this.explorerBaseUrl = explorerBaseUrl.replace(/\/$/, '');
108
+ }
109
+ toString() {
110
+ return `Chain[chainId=${this.chainId}, name=${this.name}, networkType=${this.networkType}]`;
111
+ }
112
+ }
113
+ //# sourceMappingURL=chain.base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.base.js","sourceRoot":"","sources":["../chain.base.ts"],"names":[],"mappings":"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"}