@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/react/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { HDKey } from '@scure/bip32';
|
|
|
6
6
|
import { bech32, base58check } from '@scure/base';
|
|
7
7
|
import { sha256 } from '@noble/hashes/sha256';
|
|
8
8
|
import { ripemd160 } from '@noble/hashes/ripemd160';
|
|
9
|
-
import { createPublicClient, http, formatEther } from 'viem';
|
|
9
|
+
import { createPublicClient, http, formatEther, getAddress } from 'viem';
|
|
10
10
|
import { mainnet, sepolia } from 'viem/chains';
|
|
11
11
|
|
|
12
12
|
// src/react/useWalletManager.ts
|
|
@@ -116,6 +116,38 @@ var TESTNET_NETWORKS = {
|
|
|
116
116
|
name: "Solana Devnet",
|
|
117
117
|
rpcUrl: "https://api.devnet.solana.com",
|
|
118
118
|
explorerUrl: "https://solscan.io?cluster=devnet"
|
|
119
|
+
},
|
|
120
|
+
tron: {
|
|
121
|
+
name: "TRON Nile Testnet",
|
|
122
|
+
chainId: 3448148188,
|
|
123
|
+
rpcUrl: "https://nile.trongrid.io",
|
|
124
|
+
explorerUrl: "https://nile.tronscan.org"
|
|
125
|
+
},
|
|
126
|
+
ton: {
|
|
127
|
+
name: "TON Testnet",
|
|
128
|
+
rpcUrl: "https://testnet.toncenter.com/api/v2",
|
|
129
|
+
explorerUrl: "https://testnet.tonscan.org"
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
var USDT_ADDRESSES = {
|
|
133
|
+
ethereum: {
|
|
134
|
+
mainnet: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
135
|
+
testnet: "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
136
|
+
// Sepolia (Test Tether USD)
|
|
137
|
+
},
|
|
138
|
+
tron: {
|
|
139
|
+
mainnet: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
140
|
+
testnet: "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf"
|
|
141
|
+
// Nile testnet
|
|
142
|
+
},
|
|
143
|
+
solana: {
|
|
144
|
+
mainnet: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
|
145
|
+
testnet: ""
|
|
146
|
+
// No official USDT on devnet
|
|
147
|
+
},
|
|
148
|
+
ton: {
|
|
149
|
+
mainnet: "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs",
|
|
150
|
+
testnet: "kQD0GKBM8ZbryVk2aESmzfU6b9b_8era_IkvBSELujFZPsyy"
|
|
119
151
|
}
|
|
120
152
|
};
|
|
121
153
|
var DERIVATION_PATHS = {
|
|
@@ -473,6 +505,60 @@ function generateSeedPhrase() {
|
|
|
473
505
|
|
|
474
506
|
// src/services/ZubariWdkService.ts
|
|
475
507
|
var DEFAULT_API_URL2 = "https://ckgwifsxka.us-east-2.awsapprunner.com";
|
|
508
|
+
var CHAIN_ERROR_MESSAGES = {
|
|
509
|
+
ethereum: {
|
|
510
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
511
|
+
"nonce too low": "NONCE_TOO_LOW",
|
|
512
|
+
"gas too low": "GAS_TOO_LOW",
|
|
513
|
+
"replacement transaction underpriced": "GAS_TOO_LOW",
|
|
514
|
+
"transaction underpriced": "GAS_TOO_LOW",
|
|
515
|
+
"invalid address": "INVALID_ADDRESS"
|
|
516
|
+
},
|
|
517
|
+
bitcoin: {
|
|
518
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
519
|
+
"dust": "DUST_AMOUNT",
|
|
520
|
+
"mempool": "MEMPOOL_FULL",
|
|
521
|
+
"invalid address": "INVALID_ADDRESS"
|
|
522
|
+
},
|
|
523
|
+
solana: {
|
|
524
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
525
|
+
"invalid account": "INVALID_ADDRESS",
|
|
526
|
+
"blockhash not found": "NETWORK_ERROR"
|
|
527
|
+
},
|
|
528
|
+
ton: {
|
|
529
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
530
|
+
"invalid address": "INVALID_ADDRESS"
|
|
531
|
+
},
|
|
532
|
+
tron: {
|
|
533
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
534
|
+
"invalid address": "INVALID_ADDRESS",
|
|
535
|
+
"bandwidth": "GAS_TOO_LOW"
|
|
536
|
+
},
|
|
537
|
+
spark: {
|
|
538
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
539
|
+
"invoice expired": "TIMEOUT",
|
|
540
|
+
"no route": "NETWORK_ERROR"
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
function parseChainError(chain, errorMessage) {
|
|
544
|
+
const errorLower = errorMessage.toLowerCase();
|
|
545
|
+
const chainErrors = CHAIN_ERROR_MESSAGES[chain];
|
|
546
|
+
for (const [pattern, code] of Object.entries(chainErrors)) {
|
|
547
|
+
if (errorLower.includes(pattern)) {
|
|
548
|
+
return code;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
if (errorLower.includes("timeout") || errorLower.includes("timed out")) {
|
|
552
|
+
return "TIMEOUT";
|
|
553
|
+
}
|
|
554
|
+
if (errorLower.includes("network") || errorLower.includes("connection")) {
|
|
555
|
+
return "NETWORK_ERROR";
|
|
556
|
+
}
|
|
557
|
+
if (errorLower.includes("rejected") || errorLower.includes("denied")) {
|
|
558
|
+
return "REJECTED";
|
|
559
|
+
}
|
|
560
|
+
return "UNKNOWN";
|
|
561
|
+
}
|
|
476
562
|
function isBrowser() {
|
|
477
563
|
return typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
478
564
|
}
|
|
@@ -747,47 +833,117 @@ var ZubariWdkService = class {
|
|
|
747
833
|
return { fee: "0", symbol: this.getChainSymbol(chain) };
|
|
748
834
|
}
|
|
749
835
|
/**
|
|
750
|
-
* Send a transaction
|
|
836
|
+
* Send a transaction on any supported chain
|
|
837
|
+
*
|
|
838
|
+
* @param seed - BIP-39 seed phrase
|
|
839
|
+
* @param chain - Target blockchain (ethereum, bitcoin, solana, ton, tron, spark)
|
|
840
|
+
* @param to - Recipient address
|
|
841
|
+
* @param amount - Amount to send (in native units: ETH, BTC, SOL, etc.)
|
|
842
|
+
* @returns Transaction result with hash on success, or error details on failure
|
|
751
843
|
*/
|
|
752
844
|
async sendTransaction(seed, chain, to, amount) {
|
|
753
845
|
await this.initialize();
|
|
846
|
+
const startTime = Date.now();
|
|
847
|
+
console.log(`[ZubariWdkService] Sending ${chain} transaction`, {
|
|
848
|
+
to: `${to.slice(0, 10)}...${to.slice(-6)}`,
|
|
849
|
+
amount,
|
|
850
|
+
network: this.config.network
|
|
851
|
+
});
|
|
754
852
|
try {
|
|
755
853
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
|
|
756
854
|
method: "POST",
|
|
757
855
|
headers: { "Content-Type": "application/json" },
|
|
758
856
|
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
759
857
|
});
|
|
858
|
+
const elapsed = Date.now() - startTime;
|
|
760
859
|
if (response.ok) {
|
|
761
860
|
const data = await response.json();
|
|
762
861
|
let txHash = data.txHash || data.transactionHash || data.hash;
|
|
763
862
|
if (txHash && typeof txHash === "object" && "hash" in txHash) {
|
|
764
863
|
txHash = txHash.hash;
|
|
765
864
|
}
|
|
766
|
-
if (
|
|
767
|
-
|
|
865
|
+
if (txHash) {
|
|
866
|
+
const isValid = this.validateTxHash(chain, txHash);
|
|
867
|
+
if (!isValid) {
|
|
868
|
+
console.warn(`[ZubariWdkService] Invalid ${chain} tx hash format:`, txHash);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
console.log(`[ZubariWdkService] ${chain} transaction ${data.success ? "SUCCESS" : "FAILED"}`, {
|
|
872
|
+
txHash: txHash ? `${txHash.slice(0, 16)}...` : "N/A",
|
|
873
|
+
elapsed: `${elapsed}ms`
|
|
874
|
+
});
|
|
875
|
+
if (!data.success) {
|
|
876
|
+
const errorCode2 = parseChainError(chain, data.error || "");
|
|
877
|
+
return {
|
|
878
|
+
success: false,
|
|
879
|
+
error: data.error,
|
|
880
|
+
errorCode: errorCode2,
|
|
881
|
+
chain
|
|
882
|
+
};
|
|
768
883
|
}
|
|
769
884
|
return {
|
|
770
|
-
success:
|
|
885
|
+
success: true,
|
|
771
886
|
txHash,
|
|
772
887
|
from: data.from,
|
|
773
888
|
to: data.to,
|
|
774
889
|
amount: data.amount,
|
|
775
|
-
chain: data.chain,
|
|
776
|
-
network: data.network
|
|
890
|
+
chain: data.chain || chain,
|
|
891
|
+
network: data.network || this.config.network
|
|
777
892
|
};
|
|
778
893
|
}
|
|
779
894
|
const errorData = await response.json().catch(() => ({}));
|
|
895
|
+
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
896
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
897
|
+
console.error(`[ZubariWdkService] ${chain} transaction FAILED`, {
|
|
898
|
+
status: response.status,
|
|
899
|
+
error: errorMessage,
|
|
900
|
+
errorCode,
|
|
901
|
+
elapsed: `${elapsed}ms`
|
|
902
|
+
});
|
|
780
903
|
return {
|
|
781
904
|
success: false,
|
|
782
|
-
error:
|
|
905
|
+
error: errorMessage,
|
|
906
|
+
errorCode,
|
|
907
|
+
chain
|
|
783
908
|
};
|
|
784
909
|
} catch (error) {
|
|
910
|
+
const elapsed = Date.now() - startTime;
|
|
911
|
+
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
912
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
913
|
+
console.error(`[ZubariWdkService] ${chain} transaction ERROR`, {
|
|
914
|
+
error: errorMessage,
|
|
915
|
+
errorCode,
|
|
916
|
+
elapsed: `${elapsed}ms`
|
|
917
|
+
});
|
|
785
918
|
return {
|
|
786
919
|
success: false,
|
|
787
|
-
error:
|
|
920
|
+
error: errorMessage,
|
|
921
|
+
errorCode,
|
|
922
|
+
chain
|
|
788
923
|
};
|
|
789
924
|
}
|
|
790
925
|
}
|
|
926
|
+
/**
|
|
927
|
+
* Validate transaction hash format for a specific chain
|
|
928
|
+
*/
|
|
929
|
+
validateTxHash(chain, txHash) {
|
|
930
|
+
switch (chain) {
|
|
931
|
+
case "ethereum":
|
|
932
|
+
return /^0x[a-fA-F0-9]{64}$/.test(txHash);
|
|
933
|
+
case "bitcoin":
|
|
934
|
+
return /^[a-fA-F0-9]{64}$/.test(txHash);
|
|
935
|
+
case "solana":
|
|
936
|
+
return /^[1-9A-HJ-NP-Za-km-z]{80,90}$/.test(txHash);
|
|
937
|
+
case "ton":
|
|
938
|
+
return txHash.length >= 40;
|
|
939
|
+
case "tron":
|
|
940
|
+
return /^[a-fA-F0-9]{64}$/.test(txHash);
|
|
941
|
+
case "spark":
|
|
942
|
+
return txHash.length >= 32;
|
|
943
|
+
default:
|
|
944
|
+
return true;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
791
947
|
/**
|
|
792
948
|
* Get the network configuration
|
|
793
949
|
*/
|
|
@@ -1273,6 +1429,19 @@ async function getPriceForChain(chain) {
|
|
|
1273
1429
|
const prices = await fetchPrices();
|
|
1274
1430
|
return prices[chain] || 0;
|
|
1275
1431
|
}
|
|
1432
|
+
function tonFriendlyToRaw(addr) {
|
|
1433
|
+
if (addr.includes(":")) return addr;
|
|
1434
|
+
try {
|
|
1435
|
+
const b64 = addr.replace(/-/g, "+").replace(/_/g, "/");
|
|
1436
|
+
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
1437
|
+
if (bytes.length !== 36) return addr;
|
|
1438
|
+
const workchain = bytes[1] === 255 ? -1 : bytes[1];
|
|
1439
|
+
const hash = Array.from(bytes.slice(2, 34)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1440
|
+
return `${workchain}:${hash}`;
|
|
1441
|
+
} catch {
|
|
1442
|
+
return addr;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1276
1445
|
var STORAGE_KEYS = {
|
|
1277
1446
|
ENCRYPTED_SEED: "encrypted_seed",
|
|
1278
1447
|
ACTIVE_WALLET: "active_wallet",
|
|
@@ -1777,26 +1946,53 @@ var WalletManager = class _WalletManager {
|
|
|
1777
1946
|
}
|
|
1778
1947
|
const networkConfig = this.getChainConfig(chain);
|
|
1779
1948
|
let balance = "0";
|
|
1949
|
+
const tokenBalances = {};
|
|
1780
1950
|
if (chain === "ethereum") {
|
|
1781
1951
|
const viemChain = this.config.network === "mainnet" ? mainnet : sepolia;
|
|
1782
|
-
|
|
1952
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
1783
1953
|
const client = createPublicClient({
|
|
1784
1954
|
chain: viemChain,
|
|
1785
1955
|
transport: http(this.config.rpcUrl, {
|
|
1786
1956
|
timeout: 15e3,
|
|
1787
|
-
// 15 second timeout
|
|
1788
1957
|
retryCount: 2,
|
|
1789
1958
|
retryDelay: 1e3
|
|
1790
1959
|
})
|
|
1791
1960
|
});
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1961
|
+
const usdtAddr = USDT_ADDRESSES.ethereum?.[isTestnet ? "testnet" : "mainnet"];
|
|
1962
|
+
const erc20BalanceOfAbi = [{
|
|
1963
|
+
type: "function",
|
|
1964
|
+
name: "balanceOf",
|
|
1965
|
+
stateMutability: "view",
|
|
1966
|
+
inputs: [{ name: "account", type: "address" }],
|
|
1967
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
1968
|
+
}];
|
|
1969
|
+
const checksumAddr = getAddress(address);
|
|
1970
|
+
const [ethResult, usdtResult] = await Promise.allSettled([
|
|
1971
|
+
client.getBalance({ address: checksumAddr }),
|
|
1972
|
+
usdtAddr ? client.readContract({
|
|
1973
|
+
address: getAddress(usdtAddr),
|
|
1974
|
+
abi: erc20BalanceOfAbi,
|
|
1975
|
+
functionName: "balanceOf",
|
|
1976
|
+
args: [checksumAddr]
|
|
1977
|
+
}) : Promise.resolve(null)
|
|
1978
|
+
]);
|
|
1979
|
+
if (ethResult.status === "fulfilled") {
|
|
1980
|
+
balance = formatEther(ethResult.value);
|
|
1981
|
+
} else {
|
|
1982
|
+
console.error(`[WalletManager] Failed to fetch ETH balance:`, ethResult.reason);
|
|
1983
|
+
}
|
|
1984
|
+
if (usdtResult.status === "fulfilled" && usdtResult.value != null) {
|
|
1985
|
+
try {
|
|
1986
|
+
const rawUsdt = BigInt(usdtResult.value);
|
|
1987
|
+
const usdtAmount = Number(rawUsdt) / 1e6;
|
|
1988
|
+
if (usdtAmount > 0) {
|
|
1989
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
1990
|
+
}
|
|
1991
|
+
} catch (err) {
|
|
1992
|
+
console.warn("[WalletManager] Failed to parse ETH USDT balance:", err);
|
|
1993
|
+
}
|
|
1994
|
+
} else if (usdtResult.status === "rejected") {
|
|
1995
|
+
console.warn("[WalletManager] Failed to fetch ETH USDT balance:", usdtResult.reason);
|
|
1800
1996
|
}
|
|
1801
1997
|
} else if (chain === "bitcoin") {
|
|
1802
1998
|
const isMainnet = this.config.network === "mainnet" || address.startsWith("bc1") || address.startsWith("1") || address.startsWith("3");
|
|
@@ -1852,8 +2048,41 @@ var WalletManager = class _WalletManager {
|
|
|
1852
2048
|
} catch (error) {
|
|
1853
2049
|
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
1854
2050
|
}
|
|
2051
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
2052
|
+
const usdtMint = USDT_ADDRESSES.solana?.[isTestnet ? "testnet" : "mainnet"];
|
|
2053
|
+
if (usdtMint) {
|
|
2054
|
+
try {
|
|
2055
|
+
const tokenResponse = await fetch(rpcUrl, {
|
|
2056
|
+
method: "POST",
|
|
2057
|
+
headers: { "Content-Type": "application/json" },
|
|
2058
|
+
body: JSON.stringify({
|
|
2059
|
+
jsonrpc: "2.0",
|
|
2060
|
+
id: 2,
|
|
2061
|
+
method: "getTokenAccountsByOwner",
|
|
2062
|
+
params: [
|
|
2063
|
+
address,
|
|
2064
|
+
{ mint: usdtMint },
|
|
2065
|
+
{ encoding: "jsonParsed" }
|
|
2066
|
+
]
|
|
2067
|
+
})
|
|
2068
|
+
});
|
|
2069
|
+
if (tokenResponse.ok) {
|
|
2070
|
+
const tokenData = await tokenResponse.json();
|
|
2071
|
+
const accounts = tokenData.result?.value;
|
|
2072
|
+
if (accounts && accounts.length > 0) {
|
|
2073
|
+
const uiAmount = accounts[0].account?.data?.parsed?.info?.tokenAmount?.uiAmount;
|
|
2074
|
+
if (uiAmount && uiAmount > 0) {
|
|
2075
|
+
tokenBalances.USDT = { balance: uiAmount.toFixed(6), balanceUsd: uiAmount };
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
} catch (error) {
|
|
2080
|
+
console.warn("Failed to fetch Solana USDT balance:", error);
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
1855
2083
|
} else if (chain === "tron") {
|
|
1856
|
-
const
|
|
2084
|
+
const tronConfig = getNetworkConfig("tron", this.config.network !== "mainnet");
|
|
2085
|
+
const baseUrl = tronConfig.rpcUrl;
|
|
1857
2086
|
try {
|
|
1858
2087
|
const response = await fetch(`${baseUrl}/v1/accounts/${address}`, {
|
|
1859
2088
|
headers: { "Accept": "application/json" }
|
|
@@ -1863,12 +2092,28 @@ var WalletManager = class _WalletManager {
|
|
|
1863
2092
|
if (data.data?.[0]?.balance !== void 0) {
|
|
1864
2093
|
balance = (data.data[0].balance / 1e6).toFixed(6);
|
|
1865
2094
|
}
|
|
2095
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
2096
|
+
const usdtAddr = USDT_ADDRESSES.tron?.[isTestnet ? "testnet" : "mainnet"];
|
|
2097
|
+
if (usdtAddr && data.data?.[0]?.trc20) {
|
|
2098
|
+
const trc20List = data.data[0].trc20;
|
|
2099
|
+
for (const tokenObj of trc20List) {
|
|
2100
|
+
if (tokenObj[usdtAddr]) {
|
|
2101
|
+
const rawUsdtBalance = BigInt(tokenObj[usdtAddr]);
|
|
2102
|
+
const usdtAmount = Number(rawUsdtBalance) / 1e6;
|
|
2103
|
+
if (usdtAmount > 0) {
|
|
2104
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2105
|
+
}
|
|
2106
|
+
break;
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
1866
2110
|
}
|
|
1867
2111
|
} catch (error) {
|
|
1868
2112
|
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
1869
2113
|
}
|
|
1870
2114
|
} else if (chain === "ton") {
|
|
1871
|
-
const
|
|
2115
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
2116
|
+
const baseUrl = isTestnet ? "https://testnet.toncenter.com/api/v2" : "https://toncenter.com/api/v2";
|
|
1872
2117
|
try {
|
|
1873
2118
|
const response = await fetch(`${baseUrl}/getAddressBalance?address=${address}`, {
|
|
1874
2119
|
headers: { "Accept": "application/json" }
|
|
@@ -1884,6 +2129,42 @@ var WalletManager = class _WalletManager {
|
|
|
1884
2129
|
} catch (error) {
|
|
1885
2130
|
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
1886
2131
|
}
|
|
2132
|
+
const usdtJetton = USDT_ADDRESSES.ton?.[isTestnet ? "testnet" : "mainnet"];
|
|
2133
|
+
if (usdtJetton) {
|
|
2134
|
+
const tonapiBaseUrl = isTestnet ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
2135
|
+
try {
|
|
2136
|
+
const rawAddr = tonFriendlyToRaw(address);
|
|
2137
|
+
const jettonResponse = await fetch(
|
|
2138
|
+
`${tonapiBaseUrl}/accounts/${encodeURIComponent(rawAddr)}/jettons?currencies=usd`,
|
|
2139
|
+
{ headers: { "Accept": "application/json" } }
|
|
2140
|
+
);
|
|
2141
|
+
if (jettonResponse.ok) {
|
|
2142
|
+
const jettonData = await jettonResponse.json();
|
|
2143
|
+
const balances = jettonData.balances;
|
|
2144
|
+
if (balances && balances.length > 0) {
|
|
2145
|
+
for (const jb of balances) {
|
|
2146
|
+
const jettonAddr = jb.jetton?.address;
|
|
2147
|
+
if (jettonAddr) {
|
|
2148
|
+
const usdtRaw = tonFriendlyToRaw(usdtJetton);
|
|
2149
|
+
if (jettonAddr.toLowerCase() === usdtRaw.toLowerCase()) {
|
|
2150
|
+
const rawBalance = jb.balance;
|
|
2151
|
+
if (rawBalance) {
|
|
2152
|
+
const decimals = jb.jetton?.decimals || 6;
|
|
2153
|
+
const usdtAmount = Number(BigInt(rawBalance)) / Math.pow(10, decimals);
|
|
2154
|
+
if (usdtAmount > 0) {
|
|
2155
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
break;
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
} catch (error) {
|
|
2165
|
+
console.warn("Failed to fetch TON USDT jetton balance:", error);
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
1887
2168
|
} else if (chain === "spark") {
|
|
1888
2169
|
try {
|
|
1889
2170
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balance`, {
|
|
@@ -1915,7 +2196,8 @@ var WalletManager = class _WalletManager {
|
|
|
1915
2196
|
balance,
|
|
1916
2197
|
balanceUsd,
|
|
1917
2198
|
address,
|
|
1918
|
-
decimals: networkConfig.nativeCurrency.decimals
|
|
2199
|
+
decimals: networkConfig.nativeCurrency.decimals,
|
|
2200
|
+
...Object.keys(tokenBalances).length > 0 ? { tokenBalances } : {}
|
|
1919
2201
|
};
|
|
1920
2202
|
}
|
|
1921
2203
|
/**
|