@uswap/toolboxes 4.3.7 → 4.3.10
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.
- package/dist/src/cardano/index.cjs +2 -2
- package/dist/src/cardano/index.cjs.map +3 -3
- package/dist/src/cardano/index.js +2 -2
- package/dist/src/cardano/index.js.map +3 -3
- package/dist/src/cosmos/index.cjs +2 -2
- package/dist/src/cosmos/index.cjs.map +8 -8
- package/dist/src/cosmos/index.js +2 -2
- package/dist/src/cosmos/index.js.map +8 -8
- package/dist/src/evm/index.cjs +2 -2
- package/dist/src/evm/index.cjs.map +7 -7
- package/dist/src/evm/index.js +2 -2
- package/dist/src/evm/index.js.map +7 -7
- package/dist/src/index.cjs +3 -3
- package/dist/src/index.cjs.map +34 -34
- package/dist/src/index.js +3 -3
- package/dist/src/index.js.map +34 -34
- package/dist/src/near/index.cjs +2 -2
- package/dist/src/near/index.cjs.map +5 -5
- package/dist/src/near/index.js +2 -2
- package/dist/src/near/index.js.map +5 -5
- package/dist/src/radix/index.cjs +2 -2
- package/dist/src/radix/index.cjs.map +3 -3
- package/dist/src/radix/index.js +2 -2
- package/dist/src/radix/index.js.map +3 -3
- package/dist/src/ripple/index.cjs +2 -2
- package/dist/src/ripple/index.cjs.map +3 -3
- package/dist/src/ripple/index.js +2 -2
- package/dist/src/ripple/index.js.map +3 -3
- package/dist/src/solana/index.cjs +2 -2
- package/dist/src/solana/index.cjs.map +3 -3
- package/dist/src/solana/index.js +2 -2
- package/dist/src/solana/index.js.map +3 -3
- package/dist/src/substrate/index.cjs +2 -2
- package/dist/src/substrate/index.cjs.map +4 -4
- package/dist/src/substrate/index.js +2 -2
- package/dist/src/substrate/index.js.map +4 -4
- package/dist/src/sui/index.cjs +2 -2
- package/dist/src/sui/index.cjs.map +3 -3
- package/dist/src/sui/index.js +2 -2
- package/dist/src/sui/index.js.map +3 -3
- package/dist/src/ton/index.cjs +2 -2
- package/dist/src/ton/index.cjs.map +3 -3
- package/dist/src/ton/index.js +2 -2
- package/dist/src/ton/index.js.map +3 -3
- package/dist/src/tron/index.cjs +2 -2
- package/dist/src/tron/index.cjs.map +4 -4
- package/dist/src/tron/index.js +2 -2
- package/dist/src/tron/index.js.map +4 -4
- package/dist/src/utxo/index.cjs +3 -3
- package/dist/src/utxo/index.cjs.map +11 -11
- package/dist/src/utxo/index.js +3 -3
- package/dist/src/utxo/index.js.map +11 -11
- package/dist/types/cardano/toolbox.d.ts +5 -0
- package/dist/types/cardano/toolbox.d.ts.map +1 -1
- package/dist/types/cosmos/thorchainUtils/addressFormat.d.ts +5 -0
- package/dist/types/cosmos/thorchainUtils/addressFormat.d.ts.map +1 -1
- package/dist/types/cosmos/thorchainUtils/messages.d.ts +5 -0
- package/dist/types/cosmos/thorchainUtils/messages.d.ts.map +1 -1
- package/dist/types/cosmos/toolbox/cosmos.d.ts +5 -0
- package/dist/types/cosmos/toolbox/cosmos.d.ts.map +1 -1
- package/dist/types/cosmos/toolbox/index.d.ts +5 -0
- package/dist/types/cosmos/toolbox/index.d.ts.map +1 -1
- package/dist/types/cosmos/toolbox/thorchain.d.ts +5 -0
- package/dist/types/cosmos/toolbox/thorchain.d.ts.map +1 -1
- package/dist/types/cosmos/util.d.ts +5 -0
- package/dist/types/cosmos/util.d.ts.map +1 -1
- package/dist/types/evm/helpers.d.ts +1 -1
- package/dist/types/evm/helpers.d.ts.map +1 -1
- package/dist/types/evm/toolbox/baseEVMToolbox.d.ts +7 -0
- package/dist/types/evm/toolbox/baseEVMToolbox.d.ts.map +1 -1
- package/dist/types/evm/toolbox/evm.d.ts +38 -38
- package/dist/types/evm/toolbox/evm.d.ts.map +1 -1
- package/dist/types/evm/toolbox/op.d.ts +7 -14
- package/dist/types/evm/toolbox/op.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/near/helpers/core.d.ts +5 -0
- package/dist/types/near/helpers/core.d.ts.map +1 -1
- package/dist/types/near/toolbox.d.ts +5 -0
- package/dist/types/near/toolbox.d.ts.map +1 -1
- package/dist/types/radix/index.d.ts +5 -0
- package/dist/types/radix/index.d.ts.map +1 -1
- package/dist/types/ripple/index.d.ts +5 -0
- package/dist/types/ripple/index.d.ts.map +1 -1
- package/dist/types/solana/toolbox.d.ts +5 -0
- package/dist/types/solana/toolbox.d.ts.map +1 -1
- package/dist/types/substrate/substrate.d.ts +5 -0
- package/dist/types/substrate/substrate.d.ts.map +1 -1
- package/dist/types/sui/toolbox.d.ts +5 -0
- package/dist/types/sui/toolbox.d.ts.map +1 -1
- package/dist/types/ton/toolbox.d.ts +5 -0
- package/dist/types/ton/toolbox.d.ts.map +1 -1
- package/dist/types/tron/helpers/trongrid.d.ts +5 -0
- package/dist/types/tron/helpers/trongrid.d.ts.map +1 -1
- package/dist/types/tron/toolbox.d.ts +5 -0
- package/dist/types/tron/toolbox.d.ts.map +1 -1
- package/dist/types/utils.d.ts.map +1 -1
- package/dist/types/utxo/helpers/api.d.ts +5 -0
- package/dist/types/utxo/helpers/api.d.ts.map +1 -1
- package/dist/types/utxo/helpers/bchaddrjs.d.ts +5 -0
- package/dist/types/utxo/helpers/bchaddrjs.d.ts.map +1 -1
- package/dist/types/utxo/helpers/coinselect.d.ts +5 -0
- package/dist/types/utxo/helpers/coinselect.d.ts.map +1 -1
- package/dist/types/utxo/helpers/txSize.d.ts +5 -0
- package/dist/types/utxo/helpers/txSize.d.ts.map +1 -1
- package/dist/types/utxo/toolbox/bitcoinCash.d.ts +5 -0
- package/dist/types/utxo/toolbox/bitcoinCash.d.ts.map +1 -1
- package/dist/types/utxo/toolbox/index.d.ts +5 -0
- package/dist/types/utxo/toolbox/index.d.ts.map +1 -1
- package/dist/types/utxo/toolbox/utxo.d.ts +5 -0
- package/dist/types/utxo/toolbox/utxo.d.ts.map +1 -1
- package/dist/types/utxo/toolbox/zcash.d.ts +6 -1
- package/dist/types/utxo/toolbox/zcash.d.ts.map +1 -1
- package/package.json +13 -7
- package/src/cardano/toolbox.ts +12 -6
- package/src/cosmos/__tests__/toolbox.test.ts +8 -4
- package/src/cosmos/thorchainUtils/addressFormat.ts +8 -2
- package/src/cosmos/thorchainUtils/messages.ts +8 -2
- package/src/cosmos/toolbox/cosmos.ts +11 -5
- package/src/cosmos/toolbox/index.ts +8 -2
- package/src/cosmos/toolbox/thorchain.ts +9 -3
- package/src/cosmos/util.ts +9 -3
- package/src/evm/helpers.ts +7 -9
- package/src/evm/toolbox/baseEVMToolbox.ts +34 -26
- package/src/evm/toolbox/evm.ts +2 -3
- package/src/evm/toolbox/op.ts +10 -17
- package/src/index.ts +8 -2
- package/src/near/helpers/core.ts +8 -2
- package/src/near/toolbox.ts +21 -15
- package/src/radix/index.ts +15 -3
- package/src/ripple/index.ts +15 -12
- package/src/solana/toolbox.ts +16 -16
- package/src/substrate/balance.ts +2 -2
- package/src/substrate/substrate.ts +17 -11
- package/src/sui/__tests__/toolbox.test.ts +9 -5
- package/src/sui/toolbox.ts +18 -11
- package/src/ton/__tests__/toolbox.test.ts +9 -5
- package/src/ton/toolbox.ts +14 -8
- package/src/tron/helpers/trongrid.ts +8 -2
- package/src/tron/toolbox.ts +21 -15
- package/src/utils.ts +8 -1
- package/src/utxo/helpers/api.ts +15 -9
- package/src/utxo/helpers/bchaddrjs.ts +9 -3
- package/src/utxo/helpers/coinselect.ts +8 -2
- package/src/utxo/helpers/txSize.ts +8 -2
- package/src/utxo/toolbox/bitcoinCash.ts +13 -7
- package/src/utxo/toolbox/index.ts +8 -2
- package/src/utxo/toolbox/utxo.ts +16 -10
- package/src/utxo/toolbox/zcash.ts +24 -21
package/src/solana/toolbox.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on code from SwapKit (https://github.com/swapkit/SwapKit),
|
|
3
|
+
* licensed under the Apache License 2.0.
|
|
4
|
+
* Modifications © 2025 Horizontal Systems.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import type {
|
|
2
8
|
Connection,
|
|
3
9
|
PublicKey,
|
|
@@ -16,7 +22,7 @@ import {
|
|
|
16
22
|
getChainConfig,
|
|
17
23
|
getRPCUrl,
|
|
18
24
|
NetworkDerivationPath,
|
|
19
|
-
|
|
25
|
+
USwapError,
|
|
20
26
|
updateDerivationPath,
|
|
21
27
|
} from "@uswap/helpers";
|
|
22
28
|
import { match, P } from "ts-pattern";
|
|
@@ -67,17 +73,11 @@ async function getSolanaBalance(address: string) {
|
|
|
67
73
|
const { PublicKey } = await import("@solana/web3.js");
|
|
68
74
|
const { TOKEN_PROGRAM_ID } = await import("@solana/spl-token");
|
|
69
75
|
const publicKey = new PublicKey(address);
|
|
76
|
+
const { baseDecimal } = getChainConfig(Chain.Solana);
|
|
70
77
|
|
|
71
|
-
const balances: AssetValue[] = [];
|
|
72
|
-
|
|
73
|
-
// Get SOL balance
|
|
74
78
|
const solBalance = await connection.getBalance(publicKey);
|
|
75
|
-
|
|
76
|
-
const { baseDecimal } = getChainConfig(Chain.Solana);
|
|
77
|
-
balances.push(AssetValue.from({ chain: Chain.Solana, fromBaseDecimal: baseDecimal, value: solBalance }));
|
|
78
|
-
}
|
|
79
|
+
const balances = [AssetValue.from({ chain: Chain.Solana, fromBaseDecimal: baseDecimal, value: solBalance || 0 })];
|
|
79
80
|
|
|
80
|
-
// Get token balances
|
|
81
81
|
const tokenAccounts = await connection.getParsedTokenAccountsByOwner(publicKey, { programId: TOKEN_PROGRAM_ID });
|
|
82
82
|
|
|
83
83
|
for (const { account } of tokenAccounts.value) {
|
|
@@ -133,7 +133,7 @@ export async function getSolanaToolbox(
|
|
|
133
133
|
|
|
134
134
|
function getBalance(addressParam?: string) {
|
|
135
135
|
const address = addressParam || getAddress();
|
|
136
|
-
if (!address) throw new
|
|
136
|
+
if (!address) throw new USwapError("core_wallet_connection_not_found");
|
|
137
137
|
return getSolanaBalance(address);
|
|
138
138
|
}
|
|
139
139
|
|
|
@@ -176,7 +176,7 @@ function estimateTransactionFee(getConnection: () => Promise<Connection>) {
|
|
|
176
176
|
const feeInLamports = await connection.getFeeForMessage(message);
|
|
177
177
|
|
|
178
178
|
if (feeInLamports.value === null) {
|
|
179
|
-
throw new
|
|
179
|
+
throw new USwapError("toolbox_solana_fee_estimation_failed", "Could not estimate Solana fee.");
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
const { baseDecimal } = getChainConfig(Chain.Solana);
|
|
@@ -289,7 +289,7 @@ function createTransaction(getConnection: () => Promise<Connection>) {
|
|
|
289
289
|
const validateAddress = await getSolanaAddressValidator();
|
|
290
290
|
|
|
291
291
|
if (!(isProgramDerivedAddress || validateAddress(recipient))) {
|
|
292
|
-
throw new
|
|
292
|
+
throw new USwapError("core_transaction_invalid_recipient_address");
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
const connection = await getConnection();
|
|
@@ -301,7 +301,7 @@ function createTransaction(getConnection: () => Promise<Connection>) {
|
|
|
301
301
|
});
|
|
302
302
|
|
|
303
303
|
if (!transaction) {
|
|
304
|
-
throw new
|
|
304
|
+
throw new USwapError("core_transaction_invalid_sender_address");
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
if (memo) transaction.add(createMemoInstruction(memo));
|
|
@@ -324,7 +324,7 @@ async function createTransactionFromInstructions({
|
|
|
324
324
|
const transaction = new Transaction().add(...instructions);
|
|
325
325
|
|
|
326
326
|
if (!transaction) {
|
|
327
|
-
throw new
|
|
327
|
+
throw new USwapError("core_transaction_invalid_sender_address");
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
return transaction;
|
|
@@ -333,7 +333,7 @@ async function createTransactionFromInstructions({
|
|
|
333
333
|
function transfer(getConnection: () => Promise<Connection>, signer?: SolanaSigner) {
|
|
334
334
|
return async ({ recipient, assetValue, memo, isProgramDerivedAddress }: SolanaTransferParams) => {
|
|
335
335
|
if (!signer) {
|
|
336
|
-
throw new
|
|
336
|
+
throw new USwapError("core_transaction_invalid_sender_address");
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
const sender = signer.publicKey?.toString() ?? (await (signer as SolanaProvider).connect()).publicKey.toString();
|
|
@@ -368,7 +368,7 @@ function signTransaction(getConnection: () => Promise<Connection>, signer?: Sola
|
|
|
368
368
|
return async (transaction: Transaction | VersionedTransaction) => {
|
|
369
369
|
const { VersionedTransaction } = await import("@solana/web3.js");
|
|
370
370
|
if (!signer) {
|
|
371
|
-
throw new
|
|
371
|
+
throw new USwapError("toolbox_solana_no_signer");
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
if (!(transaction instanceof VersionedTransaction)) {
|
package/src/substrate/balance.ts
CHANGED
|
@@ -29,7 +29,7 @@ export async function getSubstrateBalance(
|
|
|
29
29
|
} catch (error) {
|
|
30
30
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
31
31
|
console.error(`Error fetching substrate balance: ${errorMessage}`);
|
|
32
|
-
return [];
|
|
32
|
+
return [gasAsset.set(0)];
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -66,7 +66,7 @@ export async function getChainflipBalance(
|
|
|
66
66
|
} catch (error) {
|
|
67
67
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
68
68
|
console.error(`Error fetching chainflip balance: ${errorMessage}`);
|
|
69
|
-
return [];
|
|
69
|
+
return [gasAsset.set(0)];
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on code from SwapKit (https://github.com/swapkit/SwapKit),
|
|
3
|
+
* licensed under the Apache License 2.0.
|
|
4
|
+
* Modifications © 2025 Horizontal Systems.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import type { ApiPromise } from "@polkadot/api";
|
|
2
8
|
import type { SubmittableExtrinsic } from "@polkadot/api/types";
|
|
3
9
|
import type { KeyringPair } from "@polkadot/keyring/types";
|
|
@@ -11,8 +17,8 @@ import {
|
|
|
11
17
|
type GenericCreateTransactionParams,
|
|
12
18
|
getRPCUrl,
|
|
13
19
|
type SubstrateChain,
|
|
14
|
-
SwapKitError,
|
|
15
20
|
SwapKitNumber,
|
|
21
|
+
USwapError,
|
|
16
22
|
} from "@uswap/helpers";
|
|
17
23
|
|
|
18
24
|
import { match, P } from "ts-pattern";
|
|
@@ -43,7 +49,7 @@ export function getSubstrateToolbox<T extends SubstrateChain>(chain: T, params?:
|
|
|
43
49
|
return PolkadotToolbox(params);
|
|
44
50
|
}
|
|
45
51
|
default:
|
|
46
|
-
throw new
|
|
52
|
+
throw new USwapError("toolbox_substrate_not_supported", { chain });
|
|
47
53
|
}
|
|
48
54
|
}
|
|
49
55
|
|
|
@@ -82,12 +88,12 @@ const transfer = async (
|
|
|
82
88
|
{ recipient, assetValue, sender }: SubstrateTransferParams,
|
|
83
89
|
) => {
|
|
84
90
|
const transfer = createTransaction(api, { assetValue, recipient });
|
|
85
|
-
if (!transfer) throw new
|
|
91
|
+
if (!transfer) throw new USwapError("toolbox_substrate_transfer_error");
|
|
86
92
|
|
|
87
93
|
const isKeyring = isKeyringPair(signer);
|
|
88
94
|
|
|
89
95
|
const address = isKeyring ? (signer as IKeyringPair).address : sender;
|
|
90
|
-
if (!address) throw new
|
|
96
|
+
if (!address) throw new USwapError("core_transaction_invalid_sender_address");
|
|
91
97
|
|
|
92
98
|
const nonce = await getNonce(api, address);
|
|
93
99
|
|
|
@@ -199,23 +205,23 @@ export const BaseSubstrateToolbox = ({
|
|
|
199
205
|
decodeAddress,
|
|
200
206
|
encodeAddress,
|
|
201
207
|
estimateTransactionFee: (params: SubstrateTransferParams) => {
|
|
202
|
-
if (!signer) throw new
|
|
208
|
+
if (!signer) throw new USwapError("core_wallet_not_keypair_wallet");
|
|
203
209
|
return estimateTransactionFee(api, signer, gasAsset, params);
|
|
204
210
|
},
|
|
205
211
|
gasAsset,
|
|
206
212
|
getAddress: (keyring?: IKeyringPair | Signer) => {
|
|
207
213
|
const keyringPair = keyring || signer;
|
|
208
|
-
if (!keyringPair) throw new
|
|
214
|
+
if (!keyringPair) throw new USwapError("core_wallet_not_keypair_wallet");
|
|
209
215
|
|
|
210
216
|
return isKeyringPair(keyringPair) ? keyringPair.address : undefined;
|
|
211
217
|
},
|
|
212
218
|
getBalance: createBalanceGetter(chain || Chain.Polkadot, api),
|
|
213
219
|
network,
|
|
214
220
|
sign: (tx: SubmittableExtrinsic<"promise">) => {
|
|
215
|
-
if (!signer) throw new
|
|
221
|
+
if (!signer) throw new USwapError("core_wallet_not_keypair_wallet");
|
|
216
222
|
if (isKeyringPair(signer)) return sign(signer, tx);
|
|
217
223
|
|
|
218
|
-
throw new
|
|
224
|
+
throw new USwapError(
|
|
219
225
|
"core_wallet_not_keypair_wallet",
|
|
220
226
|
"Signer does not have keyring pair capabilities required for signing.",
|
|
221
227
|
);
|
|
@@ -229,20 +235,20 @@ export const BaseSubstrateToolbox = ({
|
|
|
229
235
|
callback?: Callback<ISubmittableResult>;
|
|
230
236
|
address?: string;
|
|
231
237
|
}) => {
|
|
232
|
-
if (!signer) throw new
|
|
238
|
+
if (!signer) throw new USwapError("core_wallet_not_keypair_wallet");
|
|
233
239
|
if (isKeyringPair(signer)) return signAndBroadcastKeyring(signer, tx, callback);
|
|
234
240
|
|
|
235
241
|
if (address) {
|
|
236
242
|
return signAndBroadcast({ address, api, callback, signer, tx });
|
|
237
243
|
}
|
|
238
244
|
|
|
239
|
-
throw new
|
|
245
|
+
throw new USwapError(
|
|
240
246
|
"core_wallet_not_keypair_wallet",
|
|
241
247
|
"Signer does not have keyring pair capabilities required for signing.",
|
|
242
248
|
);
|
|
243
249
|
},
|
|
244
250
|
transfer: (params: SubstrateTransferParams) => {
|
|
245
|
-
if (!signer) throw new
|
|
251
|
+
if (!signer) throw new USwapError("core_wallet_not_keypair_wallet");
|
|
246
252
|
return transfer(api, signer, params);
|
|
247
253
|
},
|
|
248
254
|
validateAddress: (address: string) => validateAddress(address, network.prefix),
|
|
@@ -42,11 +42,15 @@ describe("Sui Toolbox", () => {
|
|
|
42
42
|
}
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
test(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
test(
|
|
46
|
+
"should fetch balance for known address",
|
|
47
|
+
async () => {
|
|
48
|
+
const balances = await context.toolbox.getBalance(KNOWN_SUI_ADDRESS);
|
|
49
|
+
expect(balances[0]?.chain).toBe(Chain.Sui);
|
|
50
|
+
expect(balances[0]?.symbol).toBe("SUI");
|
|
51
|
+
},
|
|
52
|
+
{ retry: 3, timeout: 10000 },
|
|
53
|
+
);
|
|
50
54
|
|
|
51
55
|
test("should estimate transaction fee", async () => {
|
|
52
56
|
const fee = await context.toolbox.estimateTransactionFee();
|
package/src/sui/toolbox.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Based on code from SwapKit (https://github.com/swapkit/SwapKit),
|
|
3
|
+
* licensed under the Apache License 2.0.
|
|
4
|
+
* Modifications © 2025 Horizontal Systems.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { AssetValue, Chain, getChainConfig, USwapError } from "@uswap/helpers";
|
|
2
8
|
import { match, P } from "ts-pattern";
|
|
3
9
|
import type { SuiCreateTransactionParams, SuiToolboxParams, SuiTransferParams } from "./types";
|
|
4
10
|
|
|
@@ -37,13 +43,14 @@ export async function getSuiToolbox({ provider: providerParam, ...signerParams }
|
|
|
37
43
|
async function getBalance(targetAddress?: string) {
|
|
38
44
|
const addressToQuery = targetAddress || getAddress();
|
|
39
45
|
if (!addressToQuery) {
|
|
40
|
-
throw new
|
|
46
|
+
throw new USwapError("toolbox_sui_address_required" as any);
|
|
41
47
|
}
|
|
42
48
|
|
|
49
|
+
const { baseDecimal: fromBaseDecimal, chain } = getChainConfig(Chain.Sui);
|
|
50
|
+
|
|
43
51
|
try {
|
|
44
52
|
const suiClient = await getSuiClient();
|
|
45
53
|
const { totalBalance } = await suiClient.getBalance({ owner: addressToQuery });
|
|
46
|
-
const { baseDecimal: fromBaseDecimal, chain } = getChainConfig(Chain.Sui);
|
|
47
54
|
|
|
48
55
|
const suiBalances = [AssetValue.from({ chain, fromBaseDecimal, value: totalBalance })];
|
|
49
56
|
|
|
@@ -60,8 +67,8 @@ export async function getSuiToolbox({ provider: providerParam, ...signerParams }
|
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
return suiBalances;
|
|
63
|
-
} catch
|
|
64
|
-
|
|
70
|
+
} catch {
|
|
71
|
+
return [AssetValue.from({ chain })];
|
|
65
72
|
}
|
|
66
73
|
}
|
|
67
74
|
|
|
@@ -93,7 +100,7 @@ export async function getSuiToolbox({ provider: providerParam, ...signerParams }
|
|
|
93
100
|
const senderAddress = sender || getAddress();
|
|
94
101
|
|
|
95
102
|
if (!senderAddress) {
|
|
96
|
-
throw new
|
|
103
|
+
throw new USwapError("toolbox_sui_no_sender");
|
|
97
104
|
}
|
|
98
105
|
|
|
99
106
|
try {
|
|
@@ -104,7 +111,7 @@ export async function getSuiToolbox({ provider: providerParam, ...signerParams }
|
|
|
104
111
|
const [suiCoin] = tx.splitCoins(tx.gas, [assetValue.getBaseValue("string")]);
|
|
105
112
|
tx.transferObjects([suiCoin], recipient);
|
|
106
113
|
} else {
|
|
107
|
-
throw new
|
|
114
|
+
throw new USwapError("toolbox_sui_custom_token_transfer_not_implemented" as any);
|
|
108
115
|
}
|
|
109
116
|
|
|
110
117
|
if (gasBudget) {
|
|
@@ -116,7 +123,7 @@ export async function getSuiToolbox({ provider: providerParam, ...signerParams }
|
|
|
116
123
|
|
|
117
124
|
return { tx, txBytes };
|
|
118
125
|
} catch (error) {
|
|
119
|
-
throw new
|
|
126
|
+
throw new USwapError("toolbox_sui_transaction_creation_error" as any, { error });
|
|
120
127
|
}
|
|
121
128
|
}
|
|
122
129
|
|
|
@@ -124,7 +131,7 @@ export async function getSuiToolbox({ provider: providerParam, ...signerParams }
|
|
|
124
131
|
params: Uint8Array<ArrayBuffer> | SuiCreateTransactionParams | Awaited<ReturnType<typeof createTransaction>>,
|
|
125
132
|
) {
|
|
126
133
|
if (!signer) {
|
|
127
|
-
throw new
|
|
134
|
+
throw new USwapError("toolbox_sui_no_signer");
|
|
128
135
|
}
|
|
129
136
|
|
|
130
137
|
if (params instanceof Uint8Array) {
|
|
@@ -138,12 +145,12 @@ export async function getSuiToolbox({ provider: providerParam, ...signerParams }
|
|
|
138
145
|
|
|
139
146
|
async function transfer({ assetValue, gasBudget, recipient }: SuiTransferParams) {
|
|
140
147
|
if (!signer) {
|
|
141
|
-
throw new
|
|
148
|
+
throw new USwapError("toolbox_sui_no_signer" as any);
|
|
142
149
|
}
|
|
143
150
|
|
|
144
151
|
const sender = signer.toSuiAddress() || getAddress();
|
|
145
152
|
if (!sender) {
|
|
146
|
-
throw new
|
|
153
|
+
throw new USwapError("toolbox_sui_no_sender");
|
|
147
154
|
}
|
|
148
155
|
|
|
149
156
|
const { txBytes } = await createTransaction({ assetValue, gasBudget, recipient, sender });
|
|
@@ -39,11 +39,15 @@ describe("TON Toolbox", () => {
|
|
|
39
39
|
expect(context.toolbox.validateAddress(address)).toBe(true);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
test(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
test(
|
|
43
|
+
"should fetch balance for known address",
|
|
44
|
+
async () => {
|
|
45
|
+
const balances = await context.toolbox.getBalance(KNOWN_TON_ADDRESS);
|
|
46
|
+
expect(balances[0]?.chain).toBe(Chain.Ton);
|
|
47
|
+
expect(balances[0]?.symbol).toBe("TON");
|
|
48
|
+
},
|
|
49
|
+
{ retry: 3, timeout: 10000 },
|
|
50
|
+
);
|
|
47
51
|
|
|
48
52
|
test("should estimate transaction fee", async () => {
|
|
49
53
|
const fee = await context.toolbox.estimateTransactionFee();
|
package/src/ton/toolbox.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on code from SwapKit (https://github.com/swapkit/SwapKit),
|
|
3
|
+
* licensed under the Apache License 2.0.
|
|
4
|
+
* Modifications © 2025 Horizontal Systems.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import type { Cell, OpenedContract, TonClient, WalletContractV4 } from "@ton/ton";
|
|
2
|
-
import { AssetValue, Chain, getChainConfig,
|
|
8
|
+
import { AssetValue, Chain, getChainConfig, SwapKitNumber, USwapError } from "@uswap/helpers";
|
|
3
9
|
import { match, P } from "ts-pattern";
|
|
4
10
|
|
|
5
11
|
import type { TONSigner, TONToolboxParams, TONTransferParams } from "./types";
|
|
@@ -33,7 +39,7 @@ export async function getTONToolbox(toolboxParams: TONToolboxParams = {}) {
|
|
|
33
39
|
const walletSigner = paramSigner || signer;
|
|
34
40
|
|
|
35
41
|
if (!walletSigner) {
|
|
36
|
-
throw new
|
|
42
|
+
throw new USwapError("core_wallet_connection_not_found");
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
const walletContract = WalletContractV4.create({ publicKey: walletSigner.publicKey, workchain: 0 });
|
|
@@ -52,15 +58,15 @@ export async function getTONToolbox(toolboxParams: TONToolboxParams = {}) {
|
|
|
52
58
|
try {
|
|
53
59
|
const balance = await client.getBalance(Address.parse(address));
|
|
54
60
|
return [AssetValue.from({ chain: Chain.Ton, value: SwapKitNumber.fromBigInt(balance, baseDecimal) })];
|
|
55
|
-
} catch
|
|
56
|
-
|
|
61
|
+
} catch {
|
|
62
|
+
return [AssetValue.from({ chain: Chain.Ton })];
|
|
57
63
|
}
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
async function createTransaction({ assetValue, recipient, memo }: TONTransferParams) {
|
|
61
67
|
const wallet = getWallet();
|
|
62
68
|
if (!wallet || !signer) {
|
|
63
|
-
throw new
|
|
69
|
+
throw new USwapError("core_wallet_connection_not_found");
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
const { toNano, comment, internal } = await import("@ton/ton");
|
|
@@ -80,7 +86,7 @@ export async function getTONToolbox(toolboxParams: TONToolboxParams = {}) {
|
|
|
80
86
|
async function transfer({ assetValue, recipient, memo }: TONTransferParams) {
|
|
81
87
|
const wallet = getWallet();
|
|
82
88
|
if (!wallet || !signer) {
|
|
83
|
-
throw new
|
|
89
|
+
throw new USwapError("core_wallet_connection_not_found");
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
const transfer = await createTransaction({ assetValue, memo, recipient });
|
|
@@ -92,14 +98,14 @@ export async function getTONToolbox(toolboxParams: TONToolboxParams = {}) {
|
|
|
92
98
|
async function sendTransaction(transferCell: Cell) {
|
|
93
99
|
const wallet = getWallet();
|
|
94
100
|
if (!wallet) {
|
|
95
|
-
throw new
|
|
101
|
+
throw new USwapError("core_wallet_connection_not_found");
|
|
96
102
|
}
|
|
97
103
|
|
|
98
104
|
try {
|
|
99
105
|
await wallet.send(transferCell);
|
|
100
106
|
return transferCell.hash().toString("hex");
|
|
101
107
|
} catch (error) {
|
|
102
|
-
throw new
|
|
108
|
+
throw new USwapError("core_wallet_connection_not_found", { error });
|
|
103
109
|
}
|
|
104
110
|
}
|
|
105
111
|
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Based on code from SwapKit (https://github.com/swapkit/SwapKit),
|
|
3
|
+
* licensed under the Apache License 2.0.
|
|
4
|
+
* Modifications © 2025 Horizontal Systems.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { USwapError } from "@uswap/helpers";
|
|
2
8
|
import type { TronGridAccountResponse } from "../types";
|
|
3
9
|
|
|
4
10
|
const TRONGRID_API_BASE = "https://api.trongrid.io";
|
|
@@ -45,7 +51,7 @@ export async function fetchAccountFromTronGrid(address: string) {
|
|
|
45
51
|
// Return simplified object with balance and trc20 array
|
|
46
52
|
return { balance: account.balance, trc20: account.trc20 || [] };
|
|
47
53
|
} catch (error) {
|
|
48
|
-
throw new
|
|
54
|
+
throw new USwapError("toolbox_tron_trongrid_api_error", {
|
|
49
55
|
address,
|
|
50
56
|
message: error instanceof Error ? error.message : "Unknown error",
|
|
51
57
|
});
|
package/src/tron/toolbox.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on code from SwapKit (https://github.com/swapkit/SwapKit),
|
|
3
|
+
* licensed under the Apache License 2.0.
|
|
4
|
+
* Modifications © 2025 Horizontal Systems.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import {
|
|
2
8
|
AssetValue,
|
|
3
9
|
BaseDecimal,
|
|
@@ -5,7 +11,7 @@ import {
|
|
|
5
11
|
derivationPathToString,
|
|
6
12
|
getRPCUrl,
|
|
7
13
|
NetworkDerivationPath,
|
|
8
|
-
|
|
14
|
+
USwapError,
|
|
9
15
|
updateDerivationPath,
|
|
10
16
|
warnOnce,
|
|
11
17
|
} from "@uswap/helpers";
|
|
@@ -65,7 +71,7 @@ export async function getTronPrivateKeyFromMnemonic({
|
|
|
65
71
|
const derived = hdKey.derive(derivationPathToUse);
|
|
66
72
|
|
|
67
73
|
if (!derived.privateKey) {
|
|
68
|
-
throw new
|
|
74
|
+
throw new USwapError("toolbox_tron_no_signer");
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
return Buffer.from(derived.privateKey).toString("hex");
|
|
@@ -88,7 +94,7 @@ async function createKeysForPath({
|
|
|
88
94
|
const derived = hdKey.derive(derivationPath);
|
|
89
95
|
|
|
90
96
|
if (!derived.privateKey) {
|
|
91
|
-
throw new
|
|
97
|
+
throw new USwapError("toolbox_tron_no_signer");
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
// Convert private key to hex string for TronWeb
|
|
@@ -147,7 +153,7 @@ export const createTronToolbox = async (
|
|
|
147
153
|
.otherwise(() => Promise.resolve(undefined));
|
|
148
154
|
|
|
149
155
|
const getAddress = async () => {
|
|
150
|
-
if (!signer) throw new
|
|
156
|
+
if (!signer) throw new USwapError("toolbox_tron_no_signer");
|
|
151
157
|
return await signer.getAddress();
|
|
152
158
|
};
|
|
153
159
|
|
|
@@ -338,7 +344,7 @@ export const createTronToolbox = async (
|
|
|
338
344
|
};
|
|
339
345
|
|
|
340
346
|
const transfer = async ({ recipient, assetValue, memo, expiration }: TronTransferParams) => {
|
|
341
|
-
if (!signer) throw new
|
|
347
|
+
if (!signer) throw new USwapError("toolbox_tron_no_signer");
|
|
342
348
|
|
|
343
349
|
const from = await getAddress();
|
|
344
350
|
tronWeb.setAddress(from);
|
|
@@ -348,7 +354,7 @@ export const createTronToolbox = async (
|
|
|
348
354
|
const { txid } = await tronWeb.trx.sendRawTransaction(signedTx);
|
|
349
355
|
|
|
350
356
|
if (!txid) {
|
|
351
|
-
throw new
|
|
357
|
+
throw new USwapError("toolbox_tron_token_transfer_failed");
|
|
352
358
|
}
|
|
353
359
|
|
|
354
360
|
return txid;
|
|
@@ -422,7 +428,7 @@ export const createTronToolbox = async (
|
|
|
422
428
|
}`,
|
|
423
429
|
});
|
|
424
430
|
|
|
425
|
-
throw new
|
|
431
|
+
throw new USwapError("toolbox_tron_fee_estimation_failed", { error });
|
|
426
432
|
}
|
|
427
433
|
};
|
|
428
434
|
|
|
@@ -464,7 +470,7 @@ export const createTronToolbox = async (
|
|
|
464
470
|
tronWeb.setAddress(sender);
|
|
465
471
|
const contractAddress = assetValue.address;
|
|
466
472
|
if (!contractAddress) {
|
|
467
|
-
throw new
|
|
473
|
+
throw new USwapError("toolbox_tron_invalid_token_identifier", { identifier: assetValue.toString() });
|
|
468
474
|
}
|
|
469
475
|
|
|
470
476
|
try {
|
|
@@ -487,7 +493,7 @@ export const createTronToolbox = async (
|
|
|
487
493
|
const txWithData = addTxData({ expiration, memo, transaction });
|
|
488
494
|
return txWithData;
|
|
489
495
|
} catch (error) {
|
|
490
|
-
throw new
|
|
496
|
+
throw new USwapError("toolbox_tron_transaction_creation_failed", {
|
|
491
497
|
message: "Failed to create TRC20 transaction.",
|
|
492
498
|
originalError: error instanceof Error ? error.message : String(error),
|
|
493
499
|
});
|
|
@@ -495,7 +501,7 @@ export const createTronToolbox = async (
|
|
|
495
501
|
};
|
|
496
502
|
|
|
497
503
|
const signTransaction = async (transaction: TronTransaction) => {
|
|
498
|
-
if (!signer) throw new
|
|
504
|
+
if (!signer) throw new USwapError("toolbox_tron_no_signer");
|
|
499
505
|
return await signer.signTransaction(transaction);
|
|
500
506
|
};
|
|
501
507
|
|
|
@@ -509,14 +515,14 @@ export const createTronToolbox = async (
|
|
|
509
515
|
const contract = tronWeb.contract(trc20ABI, assetAddress);
|
|
510
516
|
|
|
511
517
|
if (!contract.methods?.allowance) {
|
|
512
|
-
throw new
|
|
518
|
+
throw new USwapError("toolbox_tron_invalid_token_contract");
|
|
513
519
|
}
|
|
514
520
|
|
|
515
521
|
const [allowance] = await contract.methods.allowance(from, spenderAddress).call();
|
|
516
522
|
|
|
517
523
|
return allowance ? (typeof allowance === "bigint" ? allowance : BigInt(allowance)) : 0n;
|
|
518
524
|
} catch (error) {
|
|
519
|
-
throw new
|
|
525
|
+
throw new USwapError("toolbox_tron_allowance_check_failed", { error });
|
|
520
526
|
}
|
|
521
527
|
};
|
|
522
528
|
|
|
@@ -532,7 +538,7 @@ export const createTronToolbox = async (
|
|
|
532
538
|
};
|
|
533
539
|
|
|
534
540
|
const approve = async ({ assetAddress, spenderAddress, amount, from }: TronApproveParams) => {
|
|
535
|
-
if (!signer) throw new
|
|
541
|
+
if (!signer) throw new USwapError("toolbox_tron_no_signer");
|
|
536
542
|
|
|
537
543
|
const fromAddress = from || (await getAddress());
|
|
538
544
|
const approvalAmount = amount !== undefined ? BigInt(amount).toString() : MAX_APPROVAL;
|
|
@@ -559,12 +565,12 @@ export const createTronToolbox = async (
|
|
|
559
565
|
const { txid } = await tronWeb.trx.sendRawTransaction(signedTx);
|
|
560
566
|
|
|
561
567
|
if (!txid) {
|
|
562
|
-
throw new
|
|
568
|
+
throw new USwapError("toolbox_tron_approve_failed");
|
|
563
569
|
}
|
|
564
570
|
|
|
565
571
|
return txid;
|
|
566
572
|
} catch (error) {
|
|
567
|
-
throw new
|
|
573
|
+
throw new USwapError("toolbox_tron_approve_failed", { error });
|
|
568
574
|
}
|
|
569
575
|
};
|
|
570
576
|
|
package/src/utils.ts
CHANGED
|
@@ -20,8 +20,15 @@ export function getBalance<T extends Chain>(chain: T) {
|
|
|
20
20
|
return async function getBalance(address: string, scamFilter = true) {
|
|
21
21
|
const balances = await SwapKitApi.getChainBalance({ address, chain, scamFilter });
|
|
22
22
|
const { baseDecimal } = getChainConfig(chain);
|
|
23
|
-
|
|
23
|
+
const assetValues = balances.map(({ identifier, value, decimal }) => {
|
|
24
24
|
return new AssetValue({ decimal: decimal || baseDecimal, identifier, value });
|
|
25
25
|
});
|
|
26
|
+
|
|
27
|
+
const hasNativeAsset = assetValues.some((asset) => asset.isGasAsset);
|
|
28
|
+
if (!hasNativeAsset) {
|
|
29
|
+
return [AssetValue.from({ chain }), ...assetValues];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return assetValues;
|
|
26
33
|
};
|
|
27
34
|
}
|
package/src/utxo/helpers/api.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on code from SwapKit (https://github.com/swapkit/SwapKit),
|
|
3
|
+
* licensed under the Apache License 2.0.
|
|
4
|
+
* Modifications © 2025 Horizontal Systems.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import { networks as zcashNetworks } from "@bitgo/utxo-lib";
|
|
2
|
-
import { Chain, getRPCUrl, RequestClient, SKConfig,
|
|
8
|
+
import { Chain, getRPCUrl, RequestClient, SKConfig, USwapError, type UTXOChain, warnOnce } from "@uswap/helpers";
|
|
3
9
|
import { networks } from "bitcoinjs-lib";
|
|
4
10
|
// @ts-expect-error
|
|
5
11
|
import coininfo from "coininfo";
|
|
@@ -26,7 +32,7 @@ async function broadcastUTXOTx({ chain, txHash }: { chain: Chain; txHash: string
|
|
|
26
32
|
}>(url, { body, headers: { "Content-Type": "application/json" } });
|
|
27
33
|
|
|
28
34
|
if (response.context.code !== 200) {
|
|
29
|
-
throw new
|
|
35
|
+
throw new USwapError("toolbox_utxo_broadcast_failed", {
|
|
30
36
|
error: response.context.error || "Transaction broadcast failed",
|
|
31
37
|
});
|
|
32
38
|
}
|
|
@@ -45,11 +51,11 @@ async function broadcastUTXOTx({ chain, txHash }: { chain: Chain; txHash: string
|
|
|
45
51
|
}>(rpcUrl, { body: rpcBody, headers: { "Content-Type": "application/json" } });
|
|
46
52
|
|
|
47
53
|
if (rpcResponse.error) {
|
|
48
|
-
throw new
|
|
54
|
+
throw new USwapError("toolbox_utxo_broadcast_failed", { error: rpcResponse.error?.message });
|
|
49
55
|
}
|
|
50
56
|
|
|
51
57
|
if (rpcResponse.result.includes('"code":-26')) {
|
|
52
|
-
throw new
|
|
58
|
+
throw new USwapError("toolbox_utxo_invalid_transaction", { error: "Transaction amount was too low" });
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
return rpcResponse.result;
|
|
@@ -121,13 +127,13 @@ async function blockchairRequest<T>(url: string, apiKey?: string): Promise<T> {
|
|
|
121
127
|
);
|
|
122
128
|
|
|
123
129
|
if (!response || response.context.code !== 200)
|
|
124
|
-
throw new
|
|
130
|
+
throw new USwapError("toolbox_utxo_api_error", { error: `Failed to query ${url}` });
|
|
125
131
|
|
|
126
132
|
return response.data as T;
|
|
127
133
|
}
|
|
128
134
|
|
|
129
135
|
async function getAddressData({ address, chain, apiKey }: BlockchairParams<{ address?: string }>) {
|
|
130
|
-
if (!address) throw new
|
|
136
|
+
if (!address) throw new USwapError("toolbox_utxo_invalid_params", { error: "Address is required" });
|
|
131
137
|
|
|
132
138
|
try {
|
|
133
139
|
const response = await blockchairRequest<BlockchairAddressResponse>(
|
|
@@ -148,7 +154,7 @@ async function getUnconfirmedBalance({ address, chain, apiKey }: BlockchairParam
|
|
|
148
154
|
}
|
|
149
155
|
|
|
150
156
|
async function getRawTx({ chain, apiKey, txHash }: BlockchairParams<{ txHash?: string }>) {
|
|
151
|
-
if (!txHash) throw new
|
|
157
|
+
if (!txHash) throw new USwapError("toolbox_utxo_invalid_params", { error: "TxHash is required" });
|
|
152
158
|
|
|
153
159
|
try {
|
|
154
160
|
const rawTxResponse = await blockchairRequest<BlockchairRawTransactionResponse>(
|
|
@@ -223,7 +229,7 @@ async function getUnspentUtxos({
|
|
|
223
229
|
offset = 0,
|
|
224
230
|
limit = 30,
|
|
225
231
|
}: BlockchairFetchUnspentUtxoParams): Promise<Awaited<ReturnType<typeof fetchUtxosBatch>>> {
|
|
226
|
-
if (!address) throw new
|
|
232
|
+
if (!address) throw new USwapError("toolbox_utxo_invalid_params", { error: "Address is required" });
|
|
227
233
|
|
|
228
234
|
try {
|
|
229
235
|
const utxos = await fetchUtxosBatch({ address, apiKey, chain, limit, offset, targetValue });
|
|
@@ -340,7 +346,7 @@ export function getUtxoNetwork() {
|
|
|
340
346
|
}
|
|
341
347
|
|
|
342
348
|
default:
|
|
343
|
-
throw new
|
|
349
|
+
throw new USwapError("toolbox_utxo_not_supported", { chain });
|
|
344
350
|
}
|
|
345
351
|
};
|
|
346
352
|
}
|