@zubari/sdk 0.5.0 → 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-BJaLBfX5.d.ts → WalletManager-DQQwVkoa.d.ts} +52 -131
- package/dist/{WalletManager-pVFpurEi.d.mts → WalletManager-Sbpx4E1-.d.mts} +52 -131
- package/dist/{index-Da7SaweH.d.mts → contracts-B842YprC.d.mts} +152 -82
- package/dist/{index-ARbXbNI-.d.ts → contracts-s_CDIruh.d.ts} +152 -82
- package/dist/index.d.mts +65 -6
- package/dist/index.d.ts +65 -6
- package/dist/index.js +531 -73
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +515 -75
- package/dist/index.mjs.map +1 -1
- package/dist/protocols/index.js +23 -5
- package/dist/protocols/index.js.map +1 -1
- package/dist/protocols/index.mjs +23 -5
- package/dist/protocols/index.mjs.map +1 -1
- package/dist/react/index.d.mts +3 -4
- package/dist/react/index.d.ts +3 -4
- package/dist/react/index.js +324 -34
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +325 -35
- 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 +151 -19
- package/dist/services/index.js.map +1 -1
- package/dist/services/index.mjs +151 -19
- package/dist/services/index.mjs.map +1 -1
- package/dist/wallet/index.d.mts +3 -4
- package/dist/wallet/index.d.ts +3 -4
- package/dist/wallet/index.js +354 -53
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +355 -54
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +16 -14
package/dist/react/index.d.mts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { b as NetworkType } from '../index-CTyZlHKg.mjs';
|
|
2
|
-
import { W as WalletManagerConfig, a as WalletState, C as ChainBalance, M as MultiChainAddresses, b as WalletManager } from '../WalletManager-
|
|
3
|
-
export { S as SUPPORTED_CHAINS } from '../WalletManager-
|
|
4
|
-
import '
|
|
5
|
-
import 'node_modules/viem/_types/utils/ccip';
|
|
2
|
+
import { W as WalletManagerConfig, a as WalletState, C as ChainBalance, M as MultiChainAddresses, b as WalletManager } from '../WalletManager-Sbpx4E1-.mjs';
|
|
3
|
+
export { S as SUPPORTED_CHAINS } from '../WalletManager-Sbpx4E1-.mjs';
|
|
4
|
+
import 'abitype';
|
|
6
5
|
import 'viem';
|
|
7
6
|
import 'ethers';
|
|
8
7
|
import '../SecureStorage-jO783AhC.mjs';
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { b as NetworkType } from '../index-CTyZlHKg.js';
|
|
2
|
-
import { W as WalletManagerConfig, a as WalletState, C as ChainBalance, M as MultiChainAddresses, b as WalletManager } from '../WalletManager-
|
|
3
|
-
export { S as SUPPORTED_CHAINS } from '../WalletManager-
|
|
4
|
-
import '
|
|
5
|
-
import 'node_modules/viem/_types/utils/ccip';
|
|
2
|
+
import { W as WalletManagerConfig, a as WalletState, C as ChainBalance, M as MultiChainAddresses, b as WalletManager } from '../WalletManager-DQQwVkoa.js';
|
|
3
|
+
export { S as SUPPORTED_CHAINS } from '../WalletManager-DQQwVkoa.js';
|
|
4
|
+
import 'abitype';
|
|
6
5
|
import 'viem';
|
|
7
6
|
import 'ethers';
|
|
8
7
|
import '../SecureStorage-jO783AhC.js';
|
package/dist/react/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var NETWORKS = {
|
|
|
34
34
|
chainId: 1,
|
|
35
35
|
coinType: 60,
|
|
36
36
|
// m/44'/60'
|
|
37
|
-
rpcUrl: "https://
|
|
37
|
+
rpcUrl: "https://ethereum-rpc.publicnode.com",
|
|
38
38
|
explorerUrl: "https://etherscan.io",
|
|
39
39
|
nativeCurrency: {
|
|
40
40
|
name: "Ether",
|
|
@@ -118,6 +118,38 @@ var TESTNET_NETWORKS = {
|
|
|
118
118
|
name: "Solana Devnet",
|
|
119
119
|
rpcUrl: "https://api.devnet.solana.com",
|
|
120
120
|
explorerUrl: "https://solscan.io?cluster=devnet"
|
|
121
|
+
},
|
|
122
|
+
tron: {
|
|
123
|
+
name: "TRON Nile Testnet",
|
|
124
|
+
chainId: 3448148188,
|
|
125
|
+
rpcUrl: "https://nile.trongrid.io",
|
|
126
|
+
explorerUrl: "https://nile.tronscan.org"
|
|
127
|
+
},
|
|
128
|
+
ton: {
|
|
129
|
+
name: "TON Testnet",
|
|
130
|
+
rpcUrl: "https://testnet.toncenter.com/api/v2",
|
|
131
|
+
explorerUrl: "https://testnet.tonscan.org"
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
var USDT_ADDRESSES = {
|
|
135
|
+
ethereum: {
|
|
136
|
+
mainnet: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
137
|
+
testnet: "0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
138
|
+
// Sepolia (Test Tether USD)
|
|
139
|
+
},
|
|
140
|
+
tron: {
|
|
141
|
+
mainnet: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
142
|
+
testnet: "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf"
|
|
143
|
+
// Nile testnet
|
|
144
|
+
},
|
|
145
|
+
solana: {
|
|
146
|
+
mainnet: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
|
147
|
+
testnet: ""
|
|
148
|
+
// No official USDT on devnet
|
|
149
|
+
},
|
|
150
|
+
ton: {
|
|
151
|
+
mainnet: "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs",
|
|
152
|
+
testnet: "kQD0GKBM8ZbryVk2aESmzfU6b9b_8era_IkvBSELujFZPsyy"
|
|
121
153
|
}
|
|
122
154
|
};
|
|
123
155
|
var DERIVATION_PATHS = {
|
|
@@ -184,7 +216,7 @@ var WdkApiClient = class {
|
|
|
184
216
|
/**
|
|
185
217
|
* Derive address for a specific chain using Tether WDK
|
|
186
218
|
*/
|
|
187
|
-
async deriveAddress(seed, chain, network = "
|
|
219
|
+
async deriveAddress(seed, chain, network = "mainnet") {
|
|
188
220
|
try {
|
|
189
221
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-address`, {
|
|
190
222
|
method: "POST",
|
|
@@ -204,7 +236,7 @@ var WdkApiClient = class {
|
|
|
204
236
|
/**
|
|
205
237
|
* Derive addresses for all chains using Tether WDK
|
|
206
238
|
*/
|
|
207
|
-
async deriveAllAddresses(seed, network = "
|
|
239
|
+
async deriveAllAddresses(seed, network = "mainnet") {
|
|
208
240
|
try {
|
|
209
241
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/derive-all`, {
|
|
210
242
|
method: "POST",
|
|
@@ -224,7 +256,7 @@ var WdkApiClient = class {
|
|
|
224
256
|
/**
|
|
225
257
|
* Send a transaction on a specific chain using Tether WDK
|
|
226
258
|
*/
|
|
227
|
-
async sendTransaction(seed, chain, to, amount, network = "
|
|
259
|
+
async sendTransaction(seed, chain, to, amount, network = "mainnet") {
|
|
228
260
|
try {
|
|
229
261
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/send`, {
|
|
230
262
|
method: "POST",
|
|
@@ -245,7 +277,7 @@ var WdkApiClient = class {
|
|
|
245
277
|
* Get transaction history for an address on a specific chain
|
|
246
278
|
* Fetches from blockchain explorers (Etherscan, mempool.space, etc.)
|
|
247
279
|
*/
|
|
248
|
-
async getTransactionHistory(seed, chain, network = "
|
|
280
|
+
async getTransactionHistory(seed, chain, network = "mainnet", limit = 10) {
|
|
249
281
|
try {
|
|
250
282
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/history`, {
|
|
251
283
|
method: "POST",
|
|
@@ -266,7 +298,7 @@ var WdkApiClient = class {
|
|
|
266
298
|
* Get transaction status by hash
|
|
267
299
|
* Fetches from blockchain explorers to check confirmation status
|
|
268
300
|
*/
|
|
269
|
-
async getTransactionStatus(txHash, chain, network = "
|
|
301
|
+
async getTransactionStatus(txHash, chain, network = "mainnet") {
|
|
270
302
|
try {
|
|
271
303
|
const response = await fetch(`${this.config.baseUrl}/api/wallets/wdk/tx-status`, {
|
|
272
304
|
method: "POST",
|
|
@@ -307,7 +339,7 @@ function deriveEthereumAddress(seed) {
|
|
|
307
339
|
const hdNode = ethers.HDNodeWallet.fromPhrase(seed, void 0, DERIVATION_PATHS2.ethereum);
|
|
308
340
|
return hdNode.address;
|
|
309
341
|
}
|
|
310
|
-
function deriveBitcoinAddress(seed, network = "
|
|
342
|
+
function deriveBitcoinAddress(seed, network = "mainnet") {
|
|
311
343
|
try {
|
|
312
344
|
const seedBytes = bip39.mnemonicToSeedSync(seed);
|
|
313
345
|
const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
|
|
@@ -401,7 +433,7 @@ function deriveTronAddress(seed) {
|
|
|
401
433
|
throw error;
|
|
402
434
|
}
|
|
403
435
|
}
|
|
404
|
-
function deriveSparkAddress(seed, network = "
|
|
436
|
+
function deriveSparkAddress(seed, network = "mainnet") {
|
|
405
437
|
try {
|
|
406
438
|
const seedBytes = bip39.mnemonicToSeedSync(seed);
|
|
407
439
|
const hdKey = bip32.HDKey.fromMasterSeed(seedBytes);
|
|
@@ -421,7 +453,7 @@ function deriveSparkAddress(seed, network = "testnet") {
|
|
|
421
453
|
throw error;
|
|
422
454
|
}
|
|
423
455
|
}
|
|
424
|
-
async function deriveAllAddresses(seed, network = "
|
|
456
|
+
async function deriveAllAddresses(seed, network = "mainnet") {
|
|
425
457
|
const addresses = {
|
|
426
458
|
ethereum: null,
|
|
427
459
|
bitcoin: null,
|
|
@@ -475,6 +507,60 @@ function generateSeedPhrase() {
|
|
|
475
507
|
|
|
476
508
|
// src/services/ZubariWdkService.ts
|
|
477
509
|
var DEFAULT_API_URL2 = "https://ckgwifsxka.us-east-2.awsapprunner.com";
|
|
510
|
+
var CHAIN_ERROR_MESSAGES = {
|
|
511
|
+
ethereum: {
|
|
512
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
513
|
+
"nonce too low": "NONCE_TOO_LOW",
|
|
514
|
+
"gas too low": "GAS_TOO_LOW",
|
|
515
|
+
"replacement transaction underpriced": "GAS_TOO_LOW",
|
|
516
|
+
"transaction underpriced": "GAS_TOO_LOW",
|
|
517
|
+
"invalid address": "INVALID_ADDRESS"
|
|
518
|
+
},
|
|
519
|
+
bitcoin: {
|
|
520
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
521
|
+
"dust": "DUST_AMOUNT",
|
|
522
|
+
"mempool": "MEMPOOL_FULL",
|
|
523
|
+
"invalid address": "INVALID_ADDRESS"
|
|
524
|
+
},
|
|
525
|
+
solana: {
|
|
526
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
527
|
+
"invalid account": "INVALID_ADDRESS",
|
|
528
|
+
"blockhash not found": "NETWORK_ERROR"
|
|
529
|
+
},
|
|
530
|
+
ton: {
|
|
531
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
532
|
+
"invalid address": "INVALID_ADDRESS"
|
|
533
|
+
},
|
|
534
|
+
tron: {
|
|
535
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
536
|
+
"invalid address": "INVALID_ADDRESS",
|
|
537
|
+
"bandwidth": "GAS_TOO_LOW"
|
|
538
|
+
},
|
|
539
|
+
spark: {
|
|
540
|
+
"insufficient funds": "INSUFFICIENT_FUNDS",
|
|
541
|
+
"invoice expired": "TIMEOUT",
|
|
542
|
+
"no route": "NETWORK_ERROR"
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
function parseChainError(chain, errorMessage) {
|
|
546
|
+
const errorLower = errorMessage.toLowerCase();
|
|
547
|
+
const chainErrors = CHAIN_ERROR_MESSAGES[chain];
|
|
548
|
+
for (const [pattern, code] of Object.entries(chainErrors)) {
|
|
549
|
+
if (errorLower.includes(pattern)) {
|
|
550
|
+
return code;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
if (errorLower.includes("timeout") || errorLower.includes("timed out")) {
|
|
554
|
+
return "TIMEOUT";
|
|
555
|
+
}
|
|
556
|
+
if (errorLower.includes("network") || errorLower.includes("connection")) {
|
|
557
|
+
return "NETWORK_ERROR";
|
|
558
|
+
}
|
|
559
|
+
if (errorLower.includes("rejected") || errorLower.includes("denied")) {
|
|
560
|
+
return "REJECTED";
|
|
561
|
+
}
|
|
562
|
+
return "UNKNOWN";
|
|
563
|
+
}
|
|
478
564
|
function isBrowser() {
|
|
479
565
|
return typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
480
566
|
}
|
|
@@ -498,7 +584,7 @@ var ZubariWdkService = class {
|
|
|
498
584
|
useNativeWdk = false;
|
|
499
585
|
constructor(config = {}) {
|
|
500
586
|
this.config = {
|
|
501
|
-
network: config.network || "
|
|
587
|
+
network: config.network || "mainnet",
|
|
502
588
|
apiUrl: config.apiUrl || process.env.NEXT_PUBLIC_API_URL || DEFAULT_API_URL2,
|
|
503
589
|
forceApi: config.forceApi ?? false,
|
|
504
590
|
timeout: config.timeout || 3e4
|
|
@@ -649,7 +735,7 @@ var ZubariWdkService = class {
|
|
|
649
735
|
}
|
|
650
736
|
return null;
|
|
651
737
|
};
|
|
652
|
-
|
|
738
|
+
const addresses = {
|
|
653
739
|
ethereum: extractAddress(response.addresses.ethereum),
|
|
654
740
|
bitcoin: extractAddress(response.addresses.bitcoin),
|
|
655
741
|
ton: extractAddress(response.addresses.ton),
|
|
@@ -657,6 +743,14 @@ var ZubariWdkService = class {
|
|
|
657
743
|
solana: extractAddress(response.addresses.solana),
|
|
658
744
|
spark: extractAddress(response.addresses.spark)
|
|
659
745
|
};
|
|
746
|
+
if (!addresses.spark) {
|
|
747
|
+
try {
|
|
748
|
+
addresses.spark = deriveSparkAddress(seed, this.config.network);
|
|
749
|
+
} catch (e) {
|
|
750
|
+
console.warn("Browser Spark derivation fallback failed:", e);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
return addresses;
|
|
660
754
|
}
|
|
661
755
|
} catch (error) {
|
|
662
756
|
console.warn("API address derivation failed:", error);
|
|
@@ -741,47 +835,117 @@ var ZubariWdkService = class {
|
|
|
741
835
|
return { fee: "0", symbol: this.getChainSymbol(chain) };
|
|
742
836
|
}
|
|
743
837
|
/**
|
|
744
|
-
* Send a transaction
|
|
838
|
+
* Send a transaction on any supported chain
|
|
839
|
+
*
|
|
840
|
+
* @param seed - BIP-39 seed phrase
|
|
841
|
+
* @param chain - Target blockchain (ethereum, bitcoin, solana, ton, tron, spark)
|
|
842
|
+
* @param to - Recipient address
|
|
843
|
+
* @param amount - Amount to send (in native units: ETH, BTC, SOL, etc.)
|
|
844
|
+
* @returns Transaction result with hash on success, or error details on failure
|
|
745
845
|
*/
|
|
746
846
|
async sendTransaction(seed, chain, to, amount) {
|
|
747
847
|
await this.initialize();
|
|
848
|
+
const startTime = Date.now();
|
|
849
|
+
console.log(`[ZubariWdkService] Sending ${chain} transaction`, {
|
|
850
|
+
to: `${to.slice(0, 10)}...${to.slice(-6)}`,
|
|
851
|
+
amount,
|
|
852
|
+
network: this.config.network
|
|
853
|
+
});
|
|
748
854
|
try {
|
|
749
855
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/send`, {
|
|
750
856
|
method: "POST",
|
|
751
857
|
headers: { "Content-Type": "application/json" },
|
|
752
858
|
body: JSON.stringify({ seed, chain, to, amount, network: this.config.network })
|
|
753
859
|
});
|
|
860
|
+
const elapsed = Date.now() - startTime;
|
|
754
861
|
if (response.ok) {
|
|
755
862
|
const data = await response.json();
|
|
756
863
|
let txHash = data.txHash || data.transactionHash || data.hash;
|
|
757
864
|
if (txHash && typeof txHash === "object" && "hash" in txHash) {
|
|
758
865
|
txHash = txHash.hash;
|
|
759
866
|
}
|
|
760
|
-
if (
|
|
761
|
-
|
|
867
|
+
if (txHash) {
|
|
868
|
+
const isValid = this.validateTxHash(chain, txHash);
|
|
869
|
+
if (!isValid) {
|
|
870
|
+
console.warn(`[ZubariWdkService] Invalid ${chain} tx hash format:`, txHash);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
console.log(`[ZubariWdkService] ${chain} transaction ${data.success ? "SUCCESS" : "FAILED"}`, {
|
|
874
|
+
txHash: txHash ? `${txHash.slice(0, 16)}...` : "N/A",
|
|
875
|
+
elapsed: `${elapsed}ms`
|
|
876
|
+
});
|
|
877
|
+
if (!data.success) {
|
|
878
|
+
const errorCode2 = parseChainError(chain, data.error || "");
|
|
879
|
+
return {
|
|
880
|
+
success: false,
|
|
881
|
+
error: data.error,
|
|
882
|
+
errorCode: errorCode2,
|
|
883
|
+
chain
|
|
884
|
+
};
|
|
762
885
|
}
|
|
763
886
|
return {
|
|
764
|
-
success:
|
|
887
|
+
success: true,
|
|
765
888
|
txHash,
|
|
766
889
|
from: data.from,
|
|
767
890
|
to: data.to,
|
|
768
891
|
amount: data.amount,
|
|
769
|
-
chain: data.chain,
|
|
770
|
-
network: data.network
|
|
892
|
+
chain: data.chain || chain,
|
|
893
|
+
network: data.network || this.config.network
|
|
771
894
|
};
|
|
772
895
|
}
|
|
773
896
|
const errorData = await response.json().catch(() => ({}));
|
|
897
|
+
const errorMessage = errorData.error || `HTTP ${response.status}`;
|
|
898
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
899
|
+
console.error(`[ZubariWdkService] ${chain} transaction FAILED`, {
|
|
900
|
+
status: response.status,
|
|
901
|
+
error: errorMessage,
|
|
902
|
+
errorCode,
|
|
903
|
+
elapsed: `${elapsed}ms`
|
|
904
|
+
});
|
|
774
905
|
return {
|
|
775
906
|
success: false,
|
|
776
|
-
error:
|
|
907
|
+
error: errorMessage,
|
|
908
|
+
errorCode,
|
|
909
|
+
chain
|
|
777
910
|
};
|
|
778
911
|
} catch (error) {
|
|
912
|
+
const elapsed = Date.now() - startTime;
|
|
913
|
+
const errorMessage = error instanceof Error ? error.message : "Transaction failed";
|
|
914
|
+
const errorCode = parseChainError(chain, errorMessage);
|
|
915
|
+
console.error(`[ZubariWdkService] ${chain} transaction ERROR`, {
|
|
916
|
+
error: errorMessage,
|
|
917
|
+
errorCode,
|
|
918
|
+
elapsed: `${elapsed}ms`
|
|
919
|
+
});
|
|
779
920
|
return {
|
|
780
921
|
success: false,
|
|
781
|
-
error:
|
|
922
|
+
error: errorMessage,
|
|
923
|
+
errorCode,
|
|
924
|
+
chain
|
|
782
925
|
};
|
|
783
926
|
}
|
|
784
927
|
}
|
|
928
|
+
/**
|
|
929
|
+
* Validate transaction hash format for a specific chain
|
|
930
|
+
*/
|
|
931
|
+
validateTxHash(chain, txHash) {
|
|
932
|
+
switch (chain) {
|
|
933
|
+
case "ethereum":
|
|
934
|
+
return /^0x[a-fA-F0-9]{64}$/.test(txHash);
|
|
935
|
+
case "bitcoin":
|
|
936
|
+
return /^[a-fA-F0-9]{64}$/.test(txHash);
|
|
937
|
+
case "solana":
|
|
938
|
+
return /^[1-9A-HJ-NP-Za-km-z]{80,90}$/.test(txHash);
|
|
939
|
+
case "ton":
|
|
940
|
+
return txHash.length >= 40;
|
|
941
|
+
case "tron":
|
|
942
|
+
return /^[a-fA-F0-9]{64}$/.test(txHash);
|
|
943
|
+
case "spark":
|
|
944
|
+
return txHash.length >= 32;
|
|
945
|
+
default:
|
|
946
|
+
return true;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
785
949
|
/**
|
|
786
950
|
* Get the network configuration
|
|
787
951
|
*/
|
|
@@ -1267,6 +1431,19 @@ async function getPriceForChain(chain) {
|
|
|
1267
1431
|
const prices = await fetchPrices();
|
|
1268
1432
|
return prices[chain] || 0;
|
|
1269
1433
|
}
|
|
1434
|
+
function tonFriendlyToRaw(addr) {
|
|
1435
|
+
if (addr.includes(":")) return addr;
|
|
1436
|
+
try {
|
|
1437
|
+
const b64 = addr.replace(/-/g, "+").replace(/_/g, "/");
|
|
1438
|
+
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
|
|
1439
|
+
if (bytes.length !== 36) return addr;
|
|
1440
|
+
const workchain = bytes[1] === 255 ? -1 : bytes[1];
|
|
1441
|
+
const hash = Array.from(bytes.slice(2, 34)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1442
|
+
return `${workchain}:${hash}`;
|
|
1443
|
+
} catch {
|
|
1444
|
+
return addr;
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1270
1447
|
var STORAGE_KEYS = {
|
|
1271
1448
|
ENCRYPTED_SEED: "encrypted_seed",
|
|
1272
1449
|
ACTIVE_WALLET: "active_wallet",
|
|
@@ -1285,7 +1462,7 @@ var WalletManager = class _WalletManager {
|
|
|
1285
1462
|
const isTestnet = config.network !== "mainnet";
|
|
1286
1463
|
const ethereumConfig = getNetworkConfig("ethereum", isTestnet);
|
|
1287
1464
|
this.config = {
|
|
1288
|
-
network: config.network || "
|
|
1465
|
+
network: config.network || "mainnet",
|
|
1289
1466
|
rpcUrl: config.rpcUrl || ethereumConfig.rpcUrl,
|
|
1290
1467
|
storage: config.storage || createSecureStorage(),
|
|
1291
1468
|
enabledChains: config.enabledChains || SUPPORTED_CHAINS,
|
|
@@ -1551,7 +1728,7 @@ var WalletManager = class _WalletManager {
|
|
|
1551
1728
|
*
|
|
1552
1729
|
* No fallback to placeholder addresses - WDK API is required for real addresses.
|
|
1553
1730
|
*/
|
|
1554
|
-
static async deriveAddressForChainAsync(seed, chain, network = "
|
|
1731
|
+
static async deriveAddressForChainAsync(seed, chain, network = "mainnet", apiUrl) {
|
|
1555
1732
|
if (chain === "ethereum") {
|
|
1556
1733
|
try {
|
|
1557
1734
|
const wdkService2 = getZubariWdkService({ network, apiUrl });
|
|
@@ -1771,26 +1948,53 @@ var WalletManager = class _WalletManager {
|
|
|
1771
1948
|
}
|
|
1772
1949
|
const networkConfig = this.getChainConfig(chain);
|
|
1773
1950
|
let balance = "0";
|
|
1951
|
+
const tokenBalances = {};
|
|
1774
1952
|
if (chain === "ethereum") {
|
|
1775
1953
|
const viemChain = this.config.network === "mainnet" ? chains.mainnet : chains.sepolia;
|
|
1776
|
-
|
|
1954
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
1777
1955
|
const client = viem.createPublicClient({
|
|
1778
1956
|
chain: viemChain,
|
|
1779
1957
|
transport: viem.http(this.config.rpcUrl, {
|
|
1780
1958
|
timeout: 15e3,
|
|
1781
|
-
// 15 second timeout
|
|
1782
1959
|
retryCount: 2,
|
|
1783
1960
|
retryDelay: 1e3
|
|
1784
1961
|
})
|
|
1785
1962
|
});
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1963
|
+
const usdtAddr = USDT_ADDRESSES.ethereum?.[isTestnet ? "testnet" : "mainnet"];
|
|
1964
|
+
const erc20BalanceOfAbi = [{
|
|
1965
|
+
type: "function",
|
|
1966
|
+
name: "balanceOf",
|
|
1967
|
+
stateMutability: "view",
|
|
1968
|
+
inputs: [{ name: "account", type: "address" }],
|
|
1969
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
1970
|
+
}];
|
|
1971
|
+
const checksumAddr = viem.getAddress(address);
|
|
1972
|
+
const [ethResult, usdtResult] = await Promise.allSettled([
|
|
1973
|
+
client.getBalance({ address: checksumAddr }),
|
|
1974
|
+
usdtAddr ? client.readContract({
|
|
1975
|
+
address: viem.getAddress(usdtAddr),
|
|
1976
|
+
abi: erc20BalanceOfAbi,
|
|
1977
|
+
functionName: "balanceOf",
|
|
1978
|
+
args: [checksumAddr]
|
|
1979
|
+
}) : Promise.resolve(null)
|
|
1980
|
+
]);
|
|
1981
|
+
if (ethResult.status === "fulfilled") {
|
|
1982
|
+
balance = viem.formatEther(ethResult.value);
|
|
1983
|
+
} else {
|
|
1984
|
+
console.error(`[WalletManager] Failed to fetch ETH balance:`, ethResult.reason);
|
|
1985
|
+
}
|
|
1986
|
+
if (usdtResult.status === "fulfilled" && usdtResult.value != null) {
|
|
1987
|
+
try {
|
|
1988
|
+
const rawUsdt = BigInt(usdtResult.value);
|
|
1989
|
+
const usdtAmount = Number(rawUsdt) / 1e6;
|
|
1990
|
+
if (usdtAmount > 0) {
|
|
1991
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
1992
|
+
}
|
|
1993
|
+
} catch (err) {
|
|
1994
|
+
console.warn("[WalletManager] Failed to parse ETH USDT balance:", err);
|
|
1995
|
+
}
|
|
1996
|
+
} else if (usdtResult.status === "rejected") {
|
|
1997
|
+
console.warn("[WalletManager] Failed to fetch ETH USDT balance:", usdtResult.reason);
|
|
1794
1998
|
}
|
|
1795
1999
|
} else if (chain === "bitcoin") {
|
|
1796
2000
|
const isMainnet = this.config.network === "mainnet" || address.startsWith("bc1") || address.startsWith("1") || address.startsWith("3");
|
|
@@ -1846,8 +2050,41 @@ var WalletManager = class _WalletManager {
|
|
|
1846
2050
|
} catch (error) {
|
|
1847
2051
|
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
1848
2052
|
}
|
|
2053
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
2054
|
+
const usdtMint = USDT_ADDRESSES.solana?.[isTestnet ? "testnet" : "mainnet"];
|
|
2055
|
+
if (usdtMint) {
|
|
2056
|
+
try {
|
|
2057
|
+
const tokenResponse = await fetch(rpcUrl, {
|
|
2058
|
+
method: "POST",
|
|
2059
|
+
headers: { "Content-Type": "application/json" },
|
|
2060
|
+
body: JSON.stringify({
|
|
2061
|
+
jsonrpc: "2.0",
|
|
2062
|
+
id: 2,
|
|
2063
|
+
method: "getTokenAccountsByOwner",
|
|
2064
|
+
params: [
|
|
2065
|
+
address,
|
|
2066
|
+
{ mint: usdtMint },
|
|
2067
|
+
{ encoding: "jsonParsed" }
|
|
2068
|
+
]
|
|
2069
|
+
})
|
|
2070
|
+
});
|
|
2071
|
+
if (tokenResponse.ok) {
|
|
2072
|
+
const tokenData = await tokenResponse.json();
|
|
2073
|
+
const accounts = tokenData.result?.value;
|
|
2074
|
+
if (accounts && accounts.length > 0) {
|
|
2075
|
+
const uiAmount = accounts[0].account?.data?.parsed?.info?.tokenAmount?.uiAmount;
|
|
2076
|
+
if (uiAmount && uiAmount > 0) {
|
|
2077
|
+
tokenBalances.USDT = { balance: uiAmount.toFixed(6), balanceUsd: uiAmount };
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
} catch (error) {
|
|
2082
|
+
console.warn("Failed to fetch Solana USDT balance:", error);
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
1849
2085
|
} else if (chain === "tron") {
|
|
1850
|
-
const
|
|
2086
|
+
const tronConfig = getNetworkConfig("tron", this.config.network !== "mainnet");
|
|
2087
|
+
const baseUrl = tronConfig.rpcUrl;
|
|
1851
2088
|
try {
|
|
1852
2089
|
const response = await fetch(`${baseUrl}/v1/accounts/${address}`, {
|
|
1853
2090
|
headers: { "Accept": "application/json" }
|
|
@@ -1857,12 +2094,28 @@ var WalletManager = class _WalletManager {
|
|
|
1857
2094
|
if (data.data?.[0]?.balance !== void 0) {
|
|
1858
2095
|
balance = (data.data[0].balance / 1e6).toFixed(6);
|
|
1859
2096
|
}
|
|
2097
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
2098
|
+
const usdtAddr = USDT_ADDRESSES.tron?.[isTestnet ? "testnet" : "mainnet"];
|
|
2099
|
+
if (usdtAddr && data.data?.[0]?.trc20) {
|
|
2100
|
+
const trc20List = data.data[0].trc20;
|
|
2101
|
+
for (const tokenObj of trc20List) {
|
|
2102
|
+
if (tokenObj[usdtAddr]) {
|
|
2103
|
+
const rawUsdtBalance = BigInt(tokenObj[usdtAddr]);
|
|
2104
|
+
const usdtAmount = Number(rawUsdtBalance) / 1e6;
|
|
2105
|
+
if (usdtAmount > 0) {
|
|
2106
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2107
|
+
}
|
|
2108
|
+
break;
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
1860
2112
|
}
|
|
1861
2113
|
} catch (error) {
|
|
1862
2114
|
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
1863
2115
|
}
|
|
1864
2116
|
} else if (chain === "ton") {
|
|
1865
|
-
const
|
|
2117
|
+
const isTestnet = this.config.network !== "mainnet";
|
|
2118
|
+
const baseUrl = isTestnet ? "https://testnet.toncenter.com/api/v2" : "https://toncenter.com/api/v2";
|
|
1866
2119
|
try {
|
|
1867
2120
|
const response = await fetch(`${baseUrl}/getAddressBalance?address=${address}`, {
|
|
1868
2121
|
headers: { "Accept": "application/json" }
|
|
@@ -1878,6 +2131,42 @@ var WalletManager = class _WalletManager {
|
|
|
1878
2131
|
} catch (error) {
|
|
1879
2132
|
console.warn(`Failed to fetch ${chain} balance:`, error);
|
|
1880
2133
|
}
|
|
2134
|
+
const usdtJetton = USDT_ADDRESSES.ton?.[isTestnet ? "testnet" : "mainnet"];
|
|
2135
|
+
if (usdtJetton) {
|
|
2136
|
+
const tonapiBaseUrl = isTestnet ? "https://testnet.tonapi.io/v2" : "https://tonapi.io/v2";
|
|
2137
|
+
try {
|
|
2138
|
+
const rawAddr = tonFriendlyToRaw(address);
|
|
2139
|
+
const jettonResponse = await fetch(
|
|
2140
|
+
`${tonapiBaseUrl}/accounts/${encodeURIComponent(rawAddr)}/jettons?currencies=usd`,
|
|
2141
|
+
{ headers: { "Accept": "application/json" } }
|
|
2142
|
+
);
|
|
2143
|
+
if (jettonResponse.ok) {
|
|
2144
|
+
const jettonData = await jettonResponse.json();
|
|
2145
|
+
const balances = jettonData.balances;
|
|
2146
|
+
if (balances && balances.length > 0) {
|
|
2147
|
+
for (const jb of balances) {
|
|
2148
|
+
const jettonAddr = jb.jetton?.address;
|
|
2149
|
+
if (jettonAddr) {
|
|
2150
|
+
const usdtRaw = tonFriendlyToRaw(usdtJetton);
|
|
2151
|
+
if (jettonAddr.toLowerCase() === usdtRaw.toLowerCase()) {
|
|
2152
|
+
const rawBalance = jb.balance;
|
|
2153
|
+
if (rawBalance) {
|
|
2154
|
+
const decimals = jb.jetton?.decimals || 6;
|
|
2155
|
+
const usdtAmount = Number(BigInt(rawBalance)) / Math.pow(10, decimals);
|
|
2156
|
+
if (usdtAmount > 0) {
|
|
2157
|
+
tokenBalances.USDT = { balance: usdtAmount.toFixed(6), balanceUsd: usdtAmount };
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
break;
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
} catch (error) {
|
|
2167
|
+
console.warn("Failed to fetch TON USDT jetton balance:", error);
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
1881
2170
|
} else if (chain === "spark") {
|
|
1882
2171
|
try {
|
|
1883
2172
|
const response = await fetch(`${this.config.apiUrl}/api/wallets/wdk/balance`, {
|
|
@@ -1909,7 +2198,8 @@ var WalletManager = class _WalletManager {
|
|
|
1909
2198
|
balance,
|
|
1910
2199
|
balanceUsd,
|
|
1911
2200
|
address,
|
|
1912
|
-
decimals: networkConfig.nativeCurrency.decimals
|
|
2201
|
+
decimals: networkConfig.nativeCurrency.decimals,
|
|
2202
|
+
...Object.keys(tokenBalances).length > 0 ? { tokenBalances } : {}
|
|
1913
2203
|
};
|
|
1914
2204
|
}
|
|
1915
2205
|
/**
|