@zubari/sdk 0.4.5 → 0.5.1
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/{TransactionService-Djonkbp4.d.ts → TransactionService-BtWUjKt_.d.ts} +14 -2
- package/dist/{TransactionService-1Jt8ZRqO.d.mts → TransactionService-Lr_WS6iR.d.mts} +14 -2
- package/dist/{WalletManager-DfvFJ-mk.d.ts → WalletManager-DQQwVkoa.d.ts} +4 -0
- package/dist/{WalletManager-j0tgNIKi.d.mts → WalletManager-Sbpx4E1-.d.mts} +4 -0
- package/dist/{contracts-BahTuxZj.d.mts → contracts-B842YprC.d.mts} +2 -2
- package/dist/{contracts-D7rVmNJy.d.ts → contracts-s_CDIruh.d.ts} +2 -2
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +305 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +306 -24
- package/dist/index.mjs.map +1 -1
- package/dist/protocols/index.js +2 -2
- package/dist/protocols/index.js.map +1 -1
- package/dist/protocols/index.mjs +2 -2
- package/dist/protocols/index.mjs.map +1 -1
- package/dist/react/index.d.mts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +303 -21
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +304 -22
- package/dist/react/index.mjs.map +1 -1
- package/dist/services/index.d.mts +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.js +132 -8
- package/dist/services/index.js.map +1 -1
- package/dist/services/index.mjs +132 -8
- package/dist/services/index.mjs.map +1 -1
- package/dist/wallet/index.d.mts +2 -2
- package/dist/wallet/index.d.ts +2 -2
- package/dist/wallet/index.js +303 -21
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +304 -22
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/wallet/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { HDKey } from '@scure/bip32';
|
|
|
5
5
|
import { bech32, base58check } from '@scure/base';
|
|
6
6
|
import { sha256 } from '@noble/hashes/sha256';
|
|
7
7
|
import { ripemd160 } from '@noble/hashes/ripemd160';
|
|
8
|
-
import { createPublicClient, http, formatEther } from 'viem';
|
|
8
|
+
import { createPublicClient, http, formatEther, getAddress } from 'viem';
|
|
9
9
|
import { mainnet, sepolia } from 'viem/chains';
|
|
10
10
|
|
|
11
11
|
// src/config/networks.ts
|
|
@@ -113,6 +113,38 @@ var TESTNET_NETWORKS = {
|
|
|
113
113
|
name: "Solana Devnet",
|
|
114
114
|
rpcUrl: "https://api.devnet.solana.com",
|
|
115
115
|
explorerUrl: "https://solscan.io?cluster=devnet"
|
|
116
|
+
},
|
|
117
|
+
tron: {
|
|
118
|
+
name: "TRON Nile Testnet",
|
|
119
|
+
chainId: 3448148188,
|
|
120
|
+
rpcUrl: "https://nile.trongrid.io",
|
|
121
|
+
explorerUrl: "https://nile.tronscan.org"
|
|
122
|
+
},
|
|
123
|
+
ton: {
|
|
124
|
+
name: "TON Testnet",
|
|
125
|
+
rpcUrl: "https://testnet.toncenter.com/api/v2",
|
|
126
|
+
explorerUrl: "https://testnet.tonscan.org"
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
var USDT_ADDRESSES = {
|
|
130
|
+
ethereum: {
|
|
131
|
+
mainnet: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
132
|
+
testnet: "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
133
|
+
// Sepolia (Test Tether USD)
|
|
134
|
+
},
|
|
135
|
+
tron: {
|
|
136
|
+
mainnet: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
137
|
+
testnet: "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf"
|
|
138
|
+
// Nile testnet
|
|
139
|
+
},
|
|
140
|
+
solana: {
|
|
141
|
+
mainnet: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
|
142
|
+
testnet: ""
|
|
143
|
+
// No official USDT on devnet
|
|
144
|
+
},
|
|
145
|
+
ton: {
|
|
146
|
+
mainnet: "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs",
|
|
147
|
+
testnet: "kQD0GKBM8ZbryVk2aESmzfU6b9b_8era_IkvBSELujFZPsyy"
|
|
116
148
|
}
|
|
117
149
|
};
|
|
118
150
|
var DERIVATION_PATHS = {
|
|
@@ -534,6 +566,60 @@ function generateSeedPhrase() {
|
|
|
534
566
|
|
|
535
567
|
// src/services/ZubariWdkService.ts
|
|
536
568
|
var DEFAULT_API_URL2 = "https://ckgwifsxka.us-east-2.awsapprunner.com";
|
|
569
|
+
var CHAIN_ERROR_MESSAGES = {
|
|
570
|
+
ethereum: {
|
|
571
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
572
|
+
"nonce too low": "NONCE_TOO_LOW",
|
|
573
|
+
"gas too low": "GAS_TOO_LOW",
|
|
574
|
+
"replacement transaction underpriced": "GAS_TOO_LOW",
|
|
575
|
+
"transaction underpriced": "GAS_TOO_LOW",
|
|
576
|
+
"invalid address": "INVALID_ADDRESS"
|
|
577
|
+
},
|
|
578
|
+
bitcoin: {
|
|
579
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
580
|
+
"dust": "DUST_AMOUNT",
|
|
581
|
+
"mempool": "MEMPOOL_FULL",
|
|
582
|
+
"invalid address": "INVALID_ADDRESS"
|
|
583
|
+
},
|
|
584
|
+
solana: {
|
|
585
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
586
|
+
"invalid account": "INVALID_ADDRESS",
|
|
587
|
+
"blockhash not found": "NETWORK_ERROR"
|
|
588
|
+
},
|
|
589
|
+
ton: {
|
|
590
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
591
|
+
"invalid address": "INVALID_ADDRESS"
|
|
592
|
+
},
|
|
593
|
+
tron: {
|
|
594
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
595
|
+
"invalid address": "INVALID_ADDRESS",
|
|
596
|
+
"bandwidth": "GAS_TOO_LOW"
|
|
597
|
+
},
|
|
598
|
+
spark: {
|
|
599
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
600
|
+
"invoice expired": "TIMEOUT",
|
|
601
|
+
"no route": "NETWORK_ERROR"
|
|
602
|
+
}
|
|
603
|
+
};
|
|
604
|
+
function parseChainError(chain, errorMessage) {
|
|
605
|
+
const errorLower = errorMessage.toLowerCase();
|
|
606
|
+
const chainErrors = CHAIN_ERROR_MESSAGES[chain];
|
|
607
|
+
for (const [pattern, code] of Object.entries(chainErrors)) {
|
|
608
|
+
if (errorLower.includes(pattern)) {
|
|
609
|
+
return code;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
if (errorLower.includes("timeout") || errorLower.includes("timed out")) {
|
|
613
|
+
return "TIMEOUT";
|
|
614
|
+
}
|
|
615
|
+
if (errorLower.includes("network") || errorLower.includes("connection")) {
|
|
616
|
+
return "NETWORK_ERROR";
|
|
617
|
+
}
|
|
618
|
+
if (errorLower.includes("rejected") || errorLower.includes("denied")) {
|
|
619
|
+
return "REJECTED";
|
|
620
|
+
}
|
|
621
|
+
return "UNKNOWN";
|
|
622
|
+
}
|
|
537
623
|
function isBrowser() {
|
|
538
624
|
return typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
539
625
|
}
|
|
@@ -808,47 +894,117 @@ var ZubariWdkService = class {
|
|
|
808
894
|
return { fee: "0", symbol: this.getChainSymbol(chain) };
|
|
809
895
|
}
|
|
810
896
|
/**
|
|
811
|
-
* Send a transaction
|
|
897
|
+
* Send a transaction on any supported chain
|
|
898
|
+
*
|
|
899
|
+
* @param seed - BIP-39 seed phrase
|
|
900
|
+
* @param chain - Target blockchain (ethereum, bitcoin, solana, ton, tron, spark)
|
|
901
|
+
* @param to - Recipient address
|
|
902
|
+
* @param amount - Amount to send (in native units: ETH, BTC, SOL, etc.)
|
|
903
|
+
* @returns Transaction result with hash on success, or error details on failure
|
|
812
904
|
*/
|
|
813
905
|
async sendTransaction(seed, chain, to, amount) {
|
|
814
906
|
await this.initialize();
|
|
907
|
+
const startTime = Date.now();
|
|
908
|
+
console.log(`[ZubariWdkService] Sending ${chain} transaction`, {
|
|
909
|
+
to: `${to.slice(0, 10)}...${to.slice(-6)}`,
|
|
910
|
+
amount,
|
|
911
|
+
network: this.config.network
|
|
912
|
+
});
|
|
815
913
|
try {
|
|
816
914
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
|
|
817
915
|
method: "POST",
|
|
818
916
|
headers: { "Content-Type": "application/json" },
|
|
819
917
|
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
820
918
|
});
|
|
919
|
+
const elapsed = Date.now() - startTime;
|
|
821
920
|
if (response.ok) {
|
|
822
921
|
const data = await response.json();
|
|
823
922
|
let txHash = data.txHash || data.transactionHash || data.hash;
|
|
824
923
|
if (txHash && typeof txHash === "object" && "hash" in txHash) {
|
|
825
924
|
txHash = txHash.hash;
|
|
826
925
|
}
|
|
827
|
-
if (
|
|
828
|
-
|
|
926
|
+
if (txHash) {
|
|
927
|
+
const isValid = this.validateTxHash(chain, txHash);
|
|
928
|
+
if (!isValid) {
|
|
929
|
+
console.warn(`[ZubariWdkService] Invalid ${chain} tx hash format:`, txHash);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
console.log(`[ZubariWdkService] ${chain} transaction ${data.success ? "SUCCESS" : "FAILED"}`, {
|
|
933
|
+
txHash: txHash ? `${txHash.slice(0, 16)}...` : "N/A",
|
|
934
|
+
elapsed: `${elapsed}ms`
|
|
935
|
+
});
|
|
936
|
+
if (!data.success) {
|
|
937
|
+
const errorCode2 = parseChainError(chain, data.error || "");
|
|
938
|
+
return {
|
|
939
|
+
success: false,
|
|
940
|
+
error: data.error,
|
|
941
|
+
errorCode: errorCode2,
|
|
942
|
+
chain
|
|
943
|
+
};
|
|
829
944
|
}
|
|
830
945
|
return {
|
|
831
|
-
success:
|
|
946
|
+
success: true,
|
|
832
947
|
txHash,
|
|
833
948
|
from: data.from,
|
|
834
949
|
to: data.to,
|
|
835
950
|
amount: data.amount,
|
|
836
|
-
chain: data.chain,
|
|
837
|
-
network: data.network
|
|
951
|
+
chain: data.chain || chain,
|
|
952
|
+
network: data.network || this.config.network
|
|
838
953
|
};
|
|
839
954
|
}
|
|
840
955
|
const errorData = await response.json().catch(() => ({}));
|
|
956
|
+
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
957
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
958
|
+
console.error(`[ZubariWdkService] ${chain} transaction FAILED`, {
|
|
959
|
+
status: response.status,
|
|
960
|
+
error: errorMessage,
|
|
961
|
+
errorCode,
|
|
962
|
+
elapsed: `${elapsed}ms`
|
|
963
|
+
});
|
|
841
964
|
return {
|
|
842
965
|
success: false,
|
|
843
|
-
error:
|
|
966
|
+
error: errorMessage,
|
|
967
|
+
errorCode,
|
|
968
|
+
chain
|
|
844
969
|
};
|
|
845
970
|
} catch (error) {
|
|
971
|
+
const elapsed = Date.now() - startTime;
|
|
972
|
+
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
973
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
974
|
+
console.error(`[ZubariWdkService] ${chain} transaction ERROR`, {
|
|
975
|
+
error: errorMessage,
|
|
976
|
+
errorCode,
|
|
977
|
+
elapsed: `${elapsed}ms`
|
|
978
|
+
});
|
|
846
979
|
return {
|
|
847
980
|
success: false,
|
|
848
|
-
error:
|
|
981
|
+
error: errorMessage,
|
|
982
|
+
errorCode,
|
|
983
|
+
chain
|
|
849
984
|
};
|
|
850
985
|
}
|
|
851
986
|
}
|
|
987
|
+
/**
|
|
988
|
+
* Validate transaction hash format for a specific chain
|
|
989
|
+
*/
|
|
990
|
+
validateTxHash(chain, txHash) {
|
|
991
|
+
switch (chain) {
|
|
992
|
+
case "ethereum":
|
|
993
|
+
return /^0x[a-fA-F0-9]{64}$/.test(txHash);
|
|
994
|
+
case "bitcoin":
|
|
995
|
+
return /^[a-fA-F0-9]{64}$/.test(txHash);
|
|
996
|
+
case "solana":
|
|
997
|
+
return /^[1-9A-HJ-NP-Za-km-z]{80,90}$/.test(txHash);
|
|
998
|
+
case "ton":
|
|
999
|
+
return txHash.length >= 40;
|
|
1000
|
+
case "tron":
|
|
1001
|
+
return /^[a-fA-F0-9]{64}$/.test(txHash);
|
|
1002
|
+
case "spark":
|
|
1003
|
+
return txHash.length >= 32;
|
|
1004
|
+
default:
|
|
1005
|
+
return true;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
852
1008
|
/**
|
|
853
1009
|
* Get the network configuration
|
|
854
1010
|
*/
|
|
@@ -1835,6 +1991,19 @@ async function getPriceForChain(chain) {
|
|
|
1835
1991
|
const prices = await fetchPrices();
|
|
1836
1992
|
return prices[chain] || 0;
|
|
1837
1993
|
}
|
|
1994
|
+
function tonFriendlyToRaw(addr) {
|
|
1995
|
+
if (addr.includes(":")) return addr;
|
|
1996
|
+
try {
|
|
1997
|
+
const b64 = addr.replace(/-/g, "+").replace(/_/g, "/");
|
|
1998
|
+
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
1999
|
+
if (bytes.length !== 36) return addr;
|
|
2000
|
+
const workchain = bytes[1] === 255 ? -1 : bytes[1];
|
|
2001
|
+
const hash = Array.from(bytes.slice(2, 34)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2002
|
+
return `${workchain}:${hash}`;
|
|
2003
|
+
} catch {
|
|
2004
|
+
return addr;
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
1838
2007
|
var STORAGE_KEYS = {
|
|
1839
2008
|
ENCRYPTED_SEED: "encrypted_seed",
|
|
1840
2009
|
ACTIVE_WALLET: "active_wallet",
|
|
@@ -2339,26 +2508,53 @@ var WalletManager = class _WalletManager {
|
|
|
2339
2508
|
}
|
|
2340
2509
|
const networkConfig = this.getChainConfig(chain);
|
|
2341
2510
|
let balance = "0";
|
|
2511
|
+
const tokenBalances = {};
|
|
2342
2512
|
if (chain === "ethereum") {
|
|
2343
2513
|
const viemChain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
2344
|
-
|
|
2514
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
2345
2515
|
const client = createPublicClient({
|
|
2346
2516
|
chain: viemChain,
|
|
2347
2517
|
transport: http(this.config.rpcUrl, {
|
|
2348
2518
|
timeout: 15e3,
|
|
2349
|
-
// 15 second timeout
|
|
2350
2519
|
retryCount: 2,
|
|
2351
2520
|
retryDelay: 1e3
|
|
2352
2521
|
})
|
|
2353
2522
|
});
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2523
|
+
const usdtAddr = USDT_ADDRESSES.ethereum?.[isTestnet ? "testnet" : "mainnet"];
|
|
2524
|
+
const erc20BalanceOfAbi = [{
|
|
2525
|
+
type: "function",
|
|
2526
|
+
name: "balanceOf",
|
|
2527
|
+
stateMutability: "view",
|
|
2528
|
+
inputs: [{ name: "account", type: "address" }],
|
|
2529
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
2530
|
+
}];
|
|
2531
|
+
const checksumAddr = getAddress(address);
|
|
2532
|
+
const [ethResult, usdtResult] = await Promise.allSettled([
|
|
2533
|
+
client.getBalance({ address: checksumAddr }),
|
|
2534
|
+
usdtAddr ? client.readContract({
|
|
2535
|
+
address: getAddress(usdtAddr),
|
|
2536
|
+
abi: erc20BalanceOfAbi,
|
|
2537
|
+
functionName: "balanceOf",
|
|
2538
|
+
args: [checksumAddr]
|
|
2539
|
+
}) : Promise.resolve(null)
|
|
2540
|
+
]);
|
|
2541
|
+
if (ethResult.status === "fulfilled") {
|
|
2542
|
+
balance = formatEther(ethResult.value);
|
|
2543
|
+
} else {
|
|
2544
|
+
console.error(`[WalletManager] Failed to fetch ETH balance:`, ethResult.reason);
|
|
2545
|
+
}
|
|
2546
|
+
if (usdtResult.status === "fulfilled" && usdtResult.value != null) {
|
|
2547
|
+
try {
|
|
2548
|
+
const rawUsdt = BigInt(usdtResult.value);
|
|
2549
|
+
const usdtAmount = Number(rawUsdt) / 1e6;
|
|
2550
|
+
if (usdtAmount > 0) {
|
|
2551
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2552
|
+
}
|
|
2553
|
+
} catch (err) {
|
|
2554
|
+
console.warn("[WalletManager] Failed to parse ETH USDT balance:", err);
|
|
2555
|
+
}
|
|
2556
|
+
} else if (usdtResult.status === "rejected") {
|
|
2557
|
+
console.warn("[WalletManager] Failed to fetch ETH USDT balance:", usdtResult.reason);
|
|
2362
2558
|
}
|
|
2363
2559
|
} else if (chain === "bitcoin") {
|
|
2364
2560
|
const isMainnet = this.config.network === "mainnet" || address.startsWith("bc1") || address.startsWith("1") || address.startsWith("3");
|
|
@@ -2414,8 +2610,41 @@ var WalletManager = class _WalletManager {
|
|
|
2414
2610
|
} catch (error) {
|
|
2415
2611
|
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2416
2612
|
}
|
|
2613
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
2614
|
+
const usdtMint = USDT_ADDRESSES.solana?.[isTestnet ? "testnet" : "mainnet"];
|
|
2615
|
+
if (usdtMint) {
|
|
2616
|
+
try {
|
|
2617
|
+
const tokenResponse = await fetch(rpcUrl, {
|
|
2618
|
+
method: "POST",
|
|
2619
|
+
headers: { "Content-Type": "application/json" },
|
|
2620
|
+
body: JSON.stringify({
|
|
2621
|
+
jsonrpc: "2.0",
|
|
2622
|
+
id: 2,
|
|
2623
|
+
method: "getTokenAccountsByOwner",
|
|
2624
|
+
params: [
|
|
2625
|
+
address,
|
|
2626
|
+
{ mint: usdtMint },
|
|
2627
|
+
{ encoding: "jsonParsed" }
|
|
2628
|
+
]
|
|
2629
|
+
})
|
|
2630
|
+
});
|
|
2631
|
+
if (tokenResponse.ok) {
|
|
2632
|
+
const tokenData = await tokenResponse.json();
|
|
2633
|
+
const accounts = tokenData.result?.value;
|
|
2634
|
+
if (accounts && accounts.length > 0) {
|
|
2635
|
+
const uiAmount = accounts[0].account?.data?.parsed?.info?.tokenAmount?.uiAmount;
|
|
2636
|
+
if (uiAmount && uiAmount > 0) {
|
|
2637
|
+
tokenBalances.USDT = { balance: uiAmount.toFixed(6), balanceUsd: uiAmount };
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
} catch (error) {
|
|
2642
|
+
console.warn("Failed to fetch Solana USDT balance:", error);
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2417
2645
|
} else if (chain === "tron") {
|
|
2418
|
-
const
|
|
2646
|
+
const tronConfig = getNetworkConfig("tron", this.config.network !== "mainnet");
|
|
2647
|
+
const baseUrl = tronConfig.rpcUrl;
|
|
2419
2648
|
try {
|
|
2420
2649
|
const response = await fetch(`${baseUrl}/v1/accounts/${address}`, {
|
|
2421
2650
|
headers: { "Accept": "application/json" }
|
|
@@ -2425,12 +2654,28 @@ var WalletManager = class _WalletManager {
|
|
|
2425
2654
|
if (data.data?.[0]?.balance !== void 0) {
|
|
2426
2655
|
balance = (data.data[0].balance / 1e6).toFixed(6);
|
|
2427
2656
|
}
|
|
2657
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
2658
|
+
const usdtAddr = USDT_ADDRESSES.tron?.[isTestnet ? "testnet" : "mainnet"];
|
|
2659
|
+
if (usdtAddr && data.data?.[0]?.trc20) {
|
|
2660
|
+
const trc20List = data.data[0].trc20;
|
|
2661
|
+
for (const tokenObj of trc20List) {
|
|
2662
|
+
if (tokenObj[usdtAddr]) {
|
|
2663
|
+
const rawUsdtBalance = BigInt(tokenObj[usdtAddr]);
|
|
2664
|
+
const usdtAmount = Number(rawUsdtBalance) / 1e6;
|
|
2665
|
+
if (usdtAmount > 0) {
|
|
2666
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2667
|
+
}
|
|
2668
|
+
break;
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2428
2672
|
}
|
|
2429
2673
|
} catch (error) {
|
|
2430
2674
|
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2431
2675
|
}
|
|
2432
2676
|
} else if (chain === "ton") {
|
|
2433
|
-
const
|
|
2677
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
2678
|
+
const baseUrl = isTestnet ? "https://testnet.toncenter.com/api/v2" : "https://toncenter.com/api/v2";
|
|
2434
2679
|
try {
|
|
2435
2680
|
const response = await fetch(`${baseUrl}/getAddressBalance?address=${address}`, {
|
|
2436
2681
|
headers: { "Accept": "application/json" }
|
|
@@ -2446,6 +2691,42 @@ var WalletManager = class _WalletManager {
|
|
|
2446
2691
|
} catch (error) {
|
|
2447
2692
|
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
2448
2693
|
}
|
|
2694
|
+
const usdtJetton = USDT_ADDRESSES.ton?.[isTestnet ? "testnet" : "mainnet"];
|
|
2695
|
+
if (usdtJetton) {
|
|
2696
|
+
const tonapiBaseUrl = isTestnet ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
2697
|
+
try {
|
|
2698
|
+
const rawAddr = tonFriendlyToRaw(address);
|
|
2699
|
+
const jettonResponse = await fetch(
|
|
2700
|
+
`${tonapiBaseUrl}/accounts/${encodeURIComponent(rawAddr)}/jettons?currencies=usd`,
|
|
2701
|
+
{ headers: { "Accept": "application/json" } }
|
|
2702
|
+
);
|
|
2703
|
+
if (jettonResponse.ok) {
|
|
2704
|
+
const jettonData = await jettonResponse.json();
|
|
2705
|
+
const balances = jettonData.balances;
|
|
2706
|
+
if (balances && balances.length > 0) {
|
|
2707
|
+
for (const jb of balances) {
|
|
2708
|
+
const jettonAddr = jb.jetton?.address;
|
|
2709
|
+
if (jettonAddr) {
|
|
2710
|
+
const usdtRaw = tonFriendlyToRaw(usdtJetton);
|
|
2711
|
+
if (jettonAddr.toLowerCase() === usdtRaw.toLowerCase()) {
|
|
2712
|
+
const rawBalance = jb.balance;
|
|
2713
|
+
if (rawBalance) {
|
|
2714
|
+
const decimals = jb.jetton?.decimals || 6;
|
|
2715
|
+
const usdtAmount = Number(BigInt(rawBalance)) / Math.pow(10, decimals);
|
|
2716
|
+
if (usdtAmount > 0) {
|
|
2717
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
break;
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
} catch (error) {
|
|
2727
|
+
console.warn("Failed to fetch TON USDT jetton balance:", error);
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2449
2730
|
} else if (chain === "spark") {
|
|
2450
2731
|
try {
|
|
2451
2732
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balance`, {
|
|
@@ -2477,7 +2758,8 @@ var WalletManager = class _WalletManager {
|
|
|
2477
2758
|
balance,
|
|
2478
2759
|
balanceUsd,
|
|
2479
2760
|
address,
|
|
2480
|
-
decimals: networkConfig.nativeCurrency.decimals
|
|
2761
|
+
decimals: networkConfig.nativeCurrency.decimals,
|
|
2762
|
+
...Object.keys(tokenBalances).length > 0 ? { tokenBalances } : {}
|
|
2481
2763
|
};
|
|
2482
2764
|
}
|
|
2483
2765
|
/**
|