@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,281 @@
1
+ import type { ApiPromise } from "@polkadot/api";
2
+ import type { SubmittableExtrinsic } from "@polkadot/api/types";
3
+ import type { KeyringPair } from "@polkadot/keyring/types";
4
+ import type { Callback, IKeyringPair, ISubmittableResult, Signer } from "@polkadot/types/types";
5
+ import { hexToU8a, isHex, u8aToHex } from "@polkadot/util";
6
+ import { decodeAddress as decodePolkadotAddress, encodeAddress as encodePolkadotAddress } from "@polkadot/util-crypto";
7
+ import {
8
+ AssetValue,
9
+ Chain,
10
+ type DerivationPathArray,
11
+ type GenericCreateTransactionParams,
12
+ getRPCUrl,
13
+ type SubstrateChain,
14
+ SwapKitError,
15
+ SwapKitNumber,
16
+ } from "@uswap/helpers";
17
+
18
+ import { match, P } from "ts-pattern";
19
+ import { createBalanceGetter } from "./balance";
20
+ import { SubstrateNetwork, type SubstrateTransferParams } from "./types";
21
+
22
+ export const PolkadotToolbox = ({ generic = false, ...signerParams }: ToolboxParams = {}) => {
23
+ return createSubstrateToolbox({ chain: Chain.Polkadot, generic, ...signerParams });
24
+ };
25
+
26
+ export const ChainflipToolbox = async ({ generic = false, ...signerParams }: ToolboxParams = {}) => {
27
+ const toolbox = await createSubstrateToolbox({ chain: Chain.Chainflip, generic, ...signerParams });
28
+
29
+ return { ...toolbox };
30
+ };
31
+
32
+ export type SubstrateToolboxes = {
33
+ DOT: Awaited<ReturnType<typeof PolkadotToolbox>>;
34
+ FLIP: Awaited<ReturnType<typeof ChainflipToolbox>>;
35
+ };
36
+
37
+ export function getSubstrateToolbox<T extends SubstrateChain>(chain: T, params?: ToolboxParams) {
38
+ switch (chain) {
39
+ case Chain.Chainflip: {
40
+ return ChainflipToolbox(params);
41
+ }
42
+ case Chain.Polkadot: {
43
+ return PolkadotToolbox(params);
44
+ }
45
+ default:
46
+ throw new SwapKitError("toolbox_substrate_not_supported", { chain });
47
+ }
48
+ }
49
+
50
+ export function isKeyringPair(account: IKeyringPair | Signer): account is IKeyringPair {
51
+ return "address" in account;
52
+ }
53
+
54
+ export async function createKeyring(phrase: string, networkPrefix: number) {
55
+ const { Keyring } = await import("@polkadot/api");
56
+ const { cryptoWaitReady } = await import("@polkadot/util-crypto");
57
+ await cryptoWaitReady();
58
+
59
+ return new Keyring({ ss58Format: networkPrefix, type: "sr25519" }).addFromUri(phrase);
60
+ }
61
+
62
+ const getNonce = (api: ApiPromise, address: string) => api.rpc.system.accountNextIndex(address);
63
+
64
+ const validateAddress = (address: string, networkPrefix: number) => {
65
+ try {
66
+ const decodedAddress = decodeAddress(address, networkPrefix);
67
+
68
+ encodeAddress(decodedAddress, "ss58", networkPrefix);
69
+
70
+ return true;
71
+ } catch {
72
+ return false;
73
+ }
74
+ };
75
+
76
+ const createTransaction = (api: ApiPromise, { recipient, assetValue }: SubstrateTransferParams) =>
77
+ api.tx.balances?.transferAllowDeath?.(recipient, assetValue.getBaseValue("number"));
78
+
79
+ const transfer = async (
80
+ api: ApiPromise,
81
+ signer: IKeyringPair | Signer,
82
+ { recipient, assetValue, sender }: SubstrateTransferParams,
83
+ ) => {
84
+ const transfer = createTransaction(api, { assetValue, recipient });
85
+ if (!transfer) throw new SwapKitError("toolbox_substrate_transfer_error");
86
+
87
+ const isKeyring = isKeyringPair(signer);
88
+
89
+ const address = isKeyring ? (signer as IKeyringPair).address : sender;
90
+ if (!address) throw new SwapKitError("core_transaction_invalid_sender_address");
91
+
92
+ const nonce = await getNonce(api, address);
93
+
94
+ const tx = await transfer.signAndSend(isKeyring ? signer : address, {
95
+ nonce,
96
+ signer: isKeyring ? undefined : signer,
97
+ });
98
+
99
+ return tx.toString();
100
+ };
101
+
102
+ const estimateTransactionFee = async (
103
+ api: ApiPromise,
104
+ signer: IKeyringPair | Signer,
105
+ gasAsset: AssetValue,
106
+ { recipient, assetValue, sender }: SubstrateTransferParams,
107
+ ) => {
108
+ const transfer = createTransaction(api, { assetValue, recipient });
109
+
110
+ const address = isKeyringPair(signer) ? signer.address : sender;
111
+ if (!address) return;
112
+
113
+ const paymentInfo = (await transfer?.paymentInfo(address, { nonce: await getNonce(api, address) })) || {
114
+ partialFee: 0,
115
+ };
116
+ return gasAsset.set(
117
+ SwapKitNumber.fromBigInt(BigInt(paymentInfo.partialFee.toString()), gasAsset.decimal).getValue("string"),
118
+ );
119
+ };
120
+
121
+ const broadcast = async (tx: SubmittableExtrinsic<"promise">, callback?: Callback<ISubmittableResult>) => {
122
+ if (callback) return tx.send(callback);
123
+ const hash = await tx.send();
124
+ return hash.toString();
125
+ };
126
+
127
+ const sign = async (signer: IKeyringPair, tx: SubmittableExtrinsic<"promise">) => {
128
+ const signedTx = await tx.signAsync(signer);
129
+ return signedTx;
130
+ };
131
+
132
+ const signAndBroadcastKeyring = (
133
+ signer: IKeyringPair,
134
+ tx: SubmittableExtrinsic<"promise">,
135
+ callback?: Callback<ISubmittableResult>,
136
+ ) => {
137
+ if (callback) return tx.signAndSend(signer, callback);
138
+ const hash = tx.signAndSend(signer);
139
+ return hash.toString();
140
+ };
141
+
142
+ const signAndBroadcast = async ({
143
+ signer,
144
+ address,
145
+ tx,
146
+ callback,
147
+ api,
148
+ }: {
149
+ signer: Signer;
150
+ address: string;
151
+ tx: SubmittableExtrinsic<"promise">;
152
+ api: ApiPromise;
153
+ callback?: Callback<ISubmittableResult>;
154
+ }) => {
155
+ const nonce = await getNonce(api, address);
156
+ if (callback) {
157
+ tx.signAndSend(address, { nonce, signer }, callback);
158
+ }
159
+ const hash = tx.signAndSend(address, { nonce, signer });
160
+ return hash.toString();
161
+ };
162
+
163
+ function convertAddress(address: string, newPrefix: number) {
164
+ const decodedAddress = decodePolkadotAddress(address);
165
+ const convertedAddress = encodePolkadotAddress(decodedAddress, newPrefix);
166
+ return convertedAddress;
167
+ }
168
+
169
+ function decodeAddress(address: string, networkPrefix?: number) {
170
+ return isHex(address) ? hexToU8a(address) : decodePolkadotAddress(address, undefined, networkPrefix);
171
+ }
172
+
173
+ function encodeAddress(address: Uint8Array, encoding: "ss58" | "hex" = "ss58", networkPrefix?: number) {
174
+ if (encoding === "hex") {
175
+ return u8aToHex(address);
176
+ }
177
+
178
+ return encodePolkadotAddress(address, networkPrefix);
179
+ }
180
+
181
+ export const BaseSubstrateToolbox = ({
182
+ api,
183
+ network,
184
+ gasAsset,
185
+ signer,
186
+ chain,
187
+ }: {
188
+ api: ApiPromise;
189
+ network: SubstrateNetwork;
190
+ gasAsset: AssetValue;
191
+ signer?: IKeyringPair | Signer;
192
+ chain?: SubstrateChain;
193
+ }) => ({
194
+ api,
195
+ broadcast,
196
+ convertAddress,
197
+ createKeyring: (phrase: string) => createKeyring(phrase, network.prefix),
198
+ createTransaction: (params: GenericCreateTransactionParams) => createTransaction(api, params),
199
+ decodeAddress,
200
+ encodeAddress,
201
+ estimateTransactionFee: (params: SubstrateTransferParams) => {
202
+ if (!signer) throw new SwapKitError("core_wallet_not_keypair_wallet");
203
+ return estimateTransactionFee(api, signer, gasAsset, params);
204
+ },
205
+ gasAsset,
206
+ getAddress: (keyring?: IKeyringPair | Signer) => {
207
+ const keyringPair = keyring || signer;
208
+ if (!keyringPair) throw new SwapKitError("core_wallet_not_keypair_wallet");
209
+
210
+ return isKeyringPair(keyringPair) ? keyringPair.address : undefined;
211
+ },
212
+ getBalance: createBalanceGetter(chain || Chain.Polkadot, api),
213
+ network,
214
+ sign: (tx: SubmittableExtrinsic<"promise">) => {
215
+ if (!signer) throw new SwapKitError("core_wallet_not_keypair_wallet");
216
+ if (isKeyringPair(signer)) return sign(signer, tx);
217
+
218
+ throw new SwapKitError(
219
+ "core_wallet_not_keypair_wallet",
220
+ "Signer does not have keyring pair capabilities required for signing.",
221
+ );
222
+ },
223
+ signAndBroadcast: ({
224
+ tx,
225
+ callback,
226
+ address,
227
+ }: {
228
+ tx: SubmittableExtrinsic<"promise">;
229
+ callback?: Callback<ISubmittableResult>;
230
+ address?: string;
231
+ }) => {
232
+ if (!signer) throw new SwapKitError("core_wallet_not_keypair_wallet");
233
+ if (isKeyringPair(signer)) return signAndBroadcastKeyring(signer, tx, callback);
234
+
235
+ if (address) {
236
+ return signAndBroadcast({ address, api, callback, signer, tx });
237
+ }
238
+
239
+ throw new SwapKitError(
240
+ "core_wallet_not_keypair_wallet",
241
+ "Signer does not have keyring pair capabilities required for signing.",
242
+ );
243
+ },
244
+ transfer: (params: SubstrateTransferParams) => {
245
+ if (!signer) throw new SwapKitError("core_wallet_not_keypair_wallet");
246
+ return transfer(api, signer, params);
247
+ },
248
+ validateAddress: (address: string) => validateAddress(address, network.prefix),
249
+ });
250
+
251
+ export const substrateValidateAddress = ({ address, chain }: { address: string; chain: SubstrateChain }) => {
252
+ const { prefix } = chain === Chain.Polkadot ? SubstrateNetwork.DOT : SubstrateNetwork.FLIP;
253
+
254
+ return validateAddress(address, prefix) || validateAddress(address, SubstrateNetwork.GENERIC.prefix);
255
+ };
256
+
257
+ export async function createSubstrateToolbox({
258
+ generic,
259
+ chain,
260
+ ...signerParams
261
+ }: ToolboxParams & { chain: SubstrateChain }) {
262
+ const { ApiPromise, WsProvider } = await import("@polkadot/api");
263
+
264
+ const rpcUrl = await getRPCUrl(chain);
265
+ const provider = new WsProvider(rpcUrl);
266
+ const api = await ApiPromise.create({ noInitWarn: true, provider });
267
+ const gasAsset = AssetValue.from({ chain });
268
+ const network = generic ? SubstrateNetwork.GENERIC : SubstrateNetwork[chain];
269
+
270
+ const signer = await match(signerParams)
271
+ .with({ phrase: P.string }, ({ phrase }) => createKeyring(phrase, SubstrateNetwork[chain].prefix))
272
+ .with({ signer: P.any }, ({ signer }) => signer)
273
+ .otherwise(() => undefined);
274
+
275
+ return BaseSubstrateToolbox({ api, chain, gasAsset, network, signer });
276
+ }
277
+
278
+ export type ToolboxParams = { generic?: boolean } & (
279
+ | { signer?: KeyringPair | Signer }
280
+ | { phrase?: string; derivationPath?: DerivationPathArray; index?: number }
281
+ );
@@ -0,0 +1,115 @@
1
+ import type { Signer as InjectedSigner } from "@polkadot/api/types";
2
+ import type { ProviderInterface } from "@polkadot/rpc-provider/types";
3
+ import type { ExtDef } from "@polkadot/types/extrinsic/signedExtensions/types";
4
+ import type { KeypairType } from "@polkadot/util-crypto/types";
5
+ import type { GenericTransferParams, SubstrateChain } from "@uswap/helpers";
6
+
7
+ const polkadotNetwork = {
8
+ decimals: [10],
9
+ displayName: "Polkadot Relay Chain",
10
+ network: "polkadot",
11
+ prefix: 0,
12
+ standardAccount: "*25519",
13
+ symbols: ["DOT"],
14
+ website: "https://polkadot.network",
15
+ };
16
+
17
+ const chainflipNetwork = {
18
+ decimals: [18],
19
+ displayName: "Chainflip",
20
+ network: "chainflip",
21
+ prefix: 2112,
22
+ standardAccount: "*25519",
23
+ symbols: ["FLIP"],
24
+ website: "https://chainflip.io/",
25
+ };
26
+
27
+ const subtrateNetwork = {
28
+ decimals: [],
29
+ displayName: "Substrate",
30
+ network: "substrate",
31
+ prefix: 42,
32
+ standardAccount: "*25519",
33
+ symbols: [],
34
+ website: "https://substrate.io/",
35
+ };
36
+
37
+ export const SubstrateNetwork: Record<SubstrateChain | "GENERIC", SubstrateNetwork> = {
38
+ DOT: polkadotNetwork,
39
+ FLIP: chainflipNetwork,
40
+ GENERIC: subtrateNetwork,
41
+ };
42
+
43
+ export type SubstrateNetwork = typeof polkadotNetwork | typeof chainflipNetwork | typeof subtrateNetwork;
44
+
45
+ export type SubstrateTransferParams = GenericTransferParams & { sender?: string };
46
+
47
+ type Unsubcall = () => void;
48
+
49
+ interface InjectedAccount {
50
+ address: string;
51
+ genesisHash?: string | null;
52
+ name?: string;
53
+ type?: KeypairType;
54
+ }
55
+
56
+ interface InjectedAccounts {
57
+ get: (anyType?: boolean) => Promise<InjectedAccount[]>;
58
+ subscribe: (cb: (accounts: InjectedAccount[]) => void | Promise<void>) => Unsubcall;
59
+ }
60
+ interface InjectedExtensionInfo {
61
+ name: string;
62
+ version: string;
63
+ }
64
+ interface ProviderMeta {
65
+ network: string;
66
+ node: "full" | "light";
67
+ source: string;
68
+ transport: string;
69
+ }
70
+ interface MetadataDefBase {
71
+ chain: string;
72
+ genesisHash: string;
73
+ icon: string;
74
+ ss58Format: number;
75
+ chainType?: "substrate" | "ethereum";
76
+ }
77
+ interface MetadataDef extends MetadataDefBase {
78
+ color?: string;
79
+ specVersion: number;
80
+ tokenDecimals: number;
81
+ tokenSymbol: string;
82
+ types: Record<string, Record<string, string> | string>;
83
+ metaCalls?: string;
84
+ userExtensions?: ExtDef;
85
+ }
86
+ interface InjectedMetadataKnown {
87
+ genesisHash: string;
88
+ specVersion: number;
89
+ }
90
+ interface InjectedMetadata {
91
+ get: () => Promise<InjectedMetadataKnown[]>;
92
+ provide: (definition: MetadataDef) => Promise<boolean>;
93
+ }
94
+ type ProviderList = Record<string, ProviderMeta>;
95
+
96
+ interface InjectedProvider extends ProviderInterface {
97
+ listProviders: () => Promise<ProviderList>;
98
+ startProvider: (key: string) => Promise<ProviderMeta>;
99
+ }
100
+
101
+ type InjectedWalletData = {
102
+ accounts: InjectedAccounts;
103
+ metadata?: InjectedMetadata;
104
+ provider?: InjectedProvider;
105
+ signer: InjectedSigner;
106
+ };
107
+
108
+ export type SubstrateInjectedExtension = Record<
109
+ string,
110
+ {
111
+ connect?: (origin: string) => Promise<InjectedExtensionInfo & InjectedWalletData>;
112
+ enable?: (origin: string) => Promise<InjectedWalletData>;
113
+ version?: string;
114
+ }
115
+ >;
@@ -0,0 +1,82 @@
1
+ import { beforeAll, describe, expect, test } from "bun:test";
2
+ import { AssetValue, Chain } from "@uswap/helpers";
3
+ import { getSuiToolbox } from "../toolbox";
4
+
5
+ const TEST_PHRASE = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
6
+ const KNOWN_SUI_ADDRESS = "0x57b861db681d8e47b586e6e9a92f6ed210dbbb440670b8122420848cf0e844fb";
7
+
8
+ const context: { toolbox: Awaited<ReturnType<typeof getSuiToolbox>> } = {} as any;
9
+
10
+ beforeAll(async () => {
11
+ context.toolbox = await getSuiToolbox({ phrase: TEST_PHRASE });
12
+ });
13
+
14
+ describe("Sui Toolbox", () => {
15
+ test("should validate valid Sui addresses", () => {
16
+ const validAddresses = [KNOWN_SUI_ADDRESS, "0x02a212de6a9dfa3a69e22387acfbafbb1a9e591bd9d636e7895dcfc8de05f331"];
17
+
18
+ for (const address of validAddresses) {
19
+ expect(context.toolbox.validateAddress(address)).toBe(true);
20
+ }
21
+ });
22
+
23
+ test("should reject invalid Sui addresses", () => {
24
+ const invalidAddresses = [
25
+ "",
26
+ "invalid",
27
+ "0xG2a212de6a9dfa3a69e22387acfbafbb1a9e591bd9d636e7895dcfc8de05f331",
28
+ "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
29
+ "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
30
+ ];
31
+
32
+ for (const address of invalidAddresses) {
33
+ expect(context.toolbox.validateAddress(address)).toBe(false);
34
+ }
35
+ });
36
+
37
+ test("should generate valid Sui address from phrase", () => {
38
+ const address = context.toolbox.getAddress();
39
+ expect(address?.startsWith("0x")).toBe(true);
40
+ if (address) {
41
+ expect(context.toolbox.validateAddress(address)).toBe(true);
42
+ }
43
+ });
44
+
45
+ test("should fetch balance for known address", async () => {
46
+ const balances = await context.toolbox.getBalance(KNOWN_SUI_ADDRESS);
47
+ expect(balances[0]?.chain).toBe(Chain.Sui);
48
+ expect(balances[0]?.symbol).toBe("SUI");
49
+ });
50
+
51
+ test("should estimate transaction fee", async () => {
52
+ const fee = await context.toolbox.estimateTransactionFee();
53
+ expect(fee.chain).toBe(Chain.Sui);
54
+ expect(fee.getValue("number")).toBeGreaterThan(0);
55
+ });
56
+
57
+ test.skip("should create transaction without broadcasting (needs real SUI for gas)", async () => {
58
+ const address = context.toolbox.getAddress();
59
+ if (!address) throw new Error("No address generated");
60
+
61
+ const { txBytes } = await context.toolbox.createTransaction({
62
+ assetValue: AssetValue.from({ chain: Chain.Sui, value: "0.001" }),
63
+ recipient: KNOWN_SUI_ADDRESS,
64
+ sender: address,
65
+ });
66
+
67
+ expect(txBytes.length).toBeGreaterThan(0);
68
+ });
69
+
70
+ test.skip("should sign transaction (needs real SUI for gas)", async () => {
71
+ const address = context.toolbox.getAddress();
72
+ if (!address) throw new Error("No address generated");
73
+
74
+ const signedTx = await context.toolbox.signTransaction({
75
+ assetValue: AssetValue.from({ chain: Chain.Sui, value: "0.001" }),
76
+ recipient: KNOWN_SUI_ADDRESS,
77
+ sender: address,
78
+ });
79
+
80
+ expect(signedTx.bytes.length).toBeGreaterThan(0);
81
+ });
82
+ });
@@ -0,0 +1,2 @@
1
+ export * from "./toolbox";
2
+ export * from "./types";
@@ -0,0 +1,165 @@
1
+ import { AssetValue, Chain, getChainConfig, SwapKitError } from "@uswap/helpers";
2
+ import { match, P } from "ts-pattern";
3
+ import type { SuiCreateTransactionParams, SuiToolboxParams, SuiTransferParams } from "./types";
4
+
5
+ export async function getSuiAddressValidator() {
6
+ const { isValidSuiAddress } = await import("@mysten/sui/utils");
7
+
8
+ return function validateAddress(address: string) {
9
+ try {
10
+ return isValidSuiAddress(address);
11
+ } catch {
12
+ return false;
13
+ }
14
+ };
15
+ }
16
+
17
+ export async function getSuiToolbox({ provider: providerParam, ...signerParams }: SuiToolboxParams = {}) {
18
+ const validateAddress = await getSuiAddressValidator();
19
+
20
+ const signer = await match(signerParams)
21
+ .with({ phrase: P.string }, async ({ phrase }) => {
22
+ const { Ed25519Keypair } = await import("@mysten/sui/keypairs/ed25519");
23
+ return Ed25519Keypair.deriveKeypair(phrase);
24
+ })
25
+ .with({ signer: P.any }, ({ signer }) => signer)
26
+ .otherwise(() => undefined);
27
+
28
+ async function getSuiClient(url = providerParam) {
29
+ const { SuiClient, getFullnodeUrl } = await import("@mysten/sui/client");
30
+ return new SuiClient({ url: url || getFullnodeUrl("mainnet") });
31
+ }
32
+
33
+ function getAddress() {
34
+ return signer?.toSuiAddress() || "";
35
+ }
36
+
37
+ async function getBalance(targetAddress?: string) {
38
+ const addressToQuery = targetAddress || getAddress();
39
+ if (!addressToQuery) {
40
+ throw new SwapKitError("toolbox_sui_address_required" as any);
41
+ }
42
+
43
+ try {
44
+ const suiClient = await getSuiClient();
45
+ const { totalBalance } = await suiClient.getBalance({ owner: addressToQuery });
46
+ const { baseDecimal: fromBaseDecimal, chain } = getChainConfig(Chain.Sui);
47
+
48
+ const suiBalances = [AssetValue.from({ chain, fromBaseDecimal, value: totalBalance })];
49
+
50
+ const coinBalances = await suiClient.getAllBalances({ owner: addressToQuery });
51
+ for (const { coinType, totalBalance } of coinBalances) {
52
+ if (coinType === "0x2::sui::SUI") continue; // Skip SUI as we already added it
53
+
54
+ if (Number(totalBalance) > 0) {
55
+ const symbol = coinType.split("::").pop()?.toUpperCase() || "UNKNOWN";
56
+ const asset = `${chain}.${symbol}-${coinType}`;
57
+ // Default to 9 decimals, should be fetched from coin metadata
58
+ suiBalances.push(AssetValue.from({ asset, fromBaseDecimal, value: totalBalance }));
59
+ }
60
+ }
61
+
62
+ return suiBalances;
63
+ } catch (error) {
64
+ throw new SwapKitError("toolbox_sui_balance_error" as any, { error });
65
+ }
66
+ }
67
+
68
+ async function estimateTransactionFee(params?: SuiCreateTransactionParams) {
69
+ const defaultFee = AssetValue.from({ chain: Chain.Sui, value: "0.01" });
70
+
71
+ if (!params) return defaultFee;
72
+
73
+ try {
74
+ const suiClient = await getSuiClient();
75
+ const { txBytes } = await createTransaction(params);
76
+ const {
77
+ effects: { status, gasUsed },
78
+ } = await suiClient.dryRunTransactionBlock({ transactionBlock: txBytes });
79
+
80
+ if (status.status !== "success") return defaultFee;
81
+
82
+ const totalGas = Number(gasUsed.computationCost) + Number(gasUsed.storageCost) - Number(gasUsed.storageRebate);
83
+
84
+ return AssetValue.from({ chain: Chain.Sui, value: totalGas.toString() });
85
+ } catch {
86
+ return defaultFee;
87
+ }
88
+ }
89
+
90
+ async function createTransaction({ recipient, assetValue, gasBudget, sender }: SuiCreateTransactionParams) {
91
+ const { Transaction } = await import("@mysten/sui/transactions");
92
+
93
+ const senderAddress = sender || getAddress();
94
+
95
+ if (!senderAddress) {
96
+ throw new SwapKitError("toolbox_sui_no_sender");
97
+ }
98
+
99
+ try {
100
+ const tx = new Transaction();
101
+ tx.setSender(senderAddress);
102
+
103
+ if (assetValue.isGasAsset || assetValue.symbol === "SUI") {
104
+ const [suiCoin] = tx.splitCoins(tx.gas, [assetValue.getBaseValue("string")]);
105
+ tx.transferObjects([suiCoin], recipient);
106
+ } else {
107
+ throw new SwapKitError("toolbox_sui_custom_token_transfer_not_implemented" as any);
108
+ }
109
+
110
+ if (gasBudget) {
111
+ tx.setGasBudget(gasBudget);
112
+ }
113
+
114
+ const suiClient = await getSuiClient();
115
+ const txBytes = await tx.build({ client: suiClient });
116
+
117
+ return { tx, txBytes };
118
+ } catch (error) {
119
+ throw new SwapKitError("toolbox_sui_transaction_creation_error" as any, { error });
120
+ }
121
+ }
122
+
123
+ async function signTransaction(
124
+ params: Uint8Array<ArrayBuffer> | SuiCreateTransactionParams | Awaited<ReturnType<typeof createTransaction>>,
125
+ ) {
126
+ if (!signer) {
127
+ throw new SwapKitError("toolbox_sui_no_signer");
128
+ }
129
+
130
+ if (params instanceof Uint8Array) {
131
+ return signer.signTransaction(params);
132
+ }
133
+
134
+ const { txBytes } = "tx" in params ? params : await createTransaction(params);
135
+
136
+ return signer.signTransaction(txBytes);
137
+ }
138
+
139
+ async function transfer({ assetValue, gasBudget, recipient }: SuiTransferParams) {
140
+ if (!signer) {
141
+ throw new SwapKitError("toolbox_sui_no_signer" as any);
142
+ }
143
+
144
+ const sender = signer.toSuiAddress() || getAddress();
145
+ if (!sender) {
146
+ throw new SwapKitError("toolbox_sui_no_sender");
147
+ }
148
+
149
+ const { txBytes } = await createTransaction({ assetValue, gasBudget, recipient, sender });
150
+ const suiClient = await getSuiClient();
151
+ const { digest: txHash } = await suiClient.signAndExecuteTransaction({ signer, transaction: txBytes });
152
+
153
+ return txHash;
154
+ }
155
+
156
+ return {
157
+ createTransaction,
158
+ estimateTransactionFee,
159
+ getAddress,
160
+ getBalance,
161
+ signTransaction,
162
+ transfer,
163
+ validateAddress,
164
+ };
165
+ }
@@ -0,0 +1,11 @@
1
+ import type { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
2
+ import type { GenericCreateTransactionParams, GenericTransferParams } from "@uswap/helpers";
3
+ import type { getSuiToolbox } from "./toolbox";
4
+
5
+ export type SuiWallet = Awaited<ReturnType<typeof getSuiToolbox>>;
6
+
7
+ export type SuiCreateTransactionParams = Omit<GenericCreateTransactionParams, "feeRate"> & { gasBudget?: number };
8
+
9
+ export type SuiTransferParams = Omit<GenericTransferParams, "feeRate"> & { gasBudget?: number };
10
+
11
+ export type SuiToolboxParams = { provider?: string; phrase?: string; signer?: Ed25519Keypair };