@enclave-hq/wallet-sdk 1.2.4 → 1.2.7
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/index.d.mts +9 -227
- package/dist/index.js +336 -745
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +339 -54
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +5 -1
- package/dist/react/index.d.ts +5 -1
- package/dist/react/index.js +347 -54
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +348 -55
- package/dist/react/index.mjs.map +1 -1
- package/dist/tron.d.mts +36 -0
- package/dist/tron.js +852 -0
- package/dist/tron.js.map +1 -0
- package/dist/tron.mjs +846 -0
- package/dist/tron.mjs.map +1 -0
- package/dist/wallet-adapter-DRd0xm3N.d.mts +197 -0
- package/package.json +8 -3
- package/dist/index.d.ts +0 -880
package/dist/react/index.d.mts
CHANGED
|
@@ -58,6 +58,7 @@ interface IWalletAdapter extends ISigner {
|
|
|
58
58
|
signTypedData?(typedData: any): Promise<string>;
|
|
59
59
|
switchChain?(chainId: number): Promise<void>;
|
|
60
60
|
addChain?(chainConfig: AddChainParams): Promise<void>;
|
|
61
|
+
requestSwitchAccount?(targetAddress?: string): Promise<Account>;
|
|
61
62
|
readContract?<T = any>(params: ContractReadParams): Promise<T>;
|
|
62
63
|
writeContract?(params: ContractWriteParams): Promise<string>;
|
|
63
64
|
estimateGas?(params: ContractWriteParams): Promise<bigint>;
|
|
@@ -225,6 +226,8 @@ declare class WalletManager extends TypedEventEmitter<WalletManagerEvents> {
|
|
|
225
226
|
addChainIfNotExists?: boolean;
|
|
226
227
|
chainConfig?: AddChainParams;
|
|
227
228
|
}): Promise<Account>;
|
|
229
|
+
requestSwitchAccount(targetAddress?: string): Promise<Account>;
|
|
230
|
+
ensureAccount(targetAddress: string): Promise<Account>;
|
|
228
231
|
readContract<T = any>(address: string, abi: any[], functionName: string, args?: any[], chainType?: ChainType): Promise<T>;
|
|
229
232
|
writeContract(address: string, abi: any[], functionName: string, args?: any[], options?: {
|
|
230
233
|
value?: string;
|
|
@@ -263,8 +266,9 @@ interface WalletContextValue {
|
|
|
263
266
|
interface WalletProviderProps {
|
|
264
267
|
children: ReactNode;
|
|
265
268
|
walletManager?: WalletManager;
|
|
269
|
+
autoRestoreFromStorage?: boolean;
|
|
266
270
|
}
|
|
267
|
-
declare function WalletProvider({ children, walletManager: externalWalletManager }: WalletProviderProps): React.JSX.Element;
|
|
271
|
+
declare function WalletProvider({ children, walletManager: externalWalletManager, autoRestoreFromStorage, }: WalletProviderProps): React.JSX.Element;
|
|
268
272
|
declare function useWallet(): WalletContextValue;
|
|
269
273
|
|
|
270
274
|
interface UseAccountResult {
|
package/dist/react/index.d.ts
CHANGED
|
@@ -58,6 +58,7 @@ interface IWalletAdapter extends ISigner {
|
|
|
58
58
|
signTypedData?(typedData: any): Promise<string>;
|
|
59
59
|
switchChain?(chainId: number): Promise<void>;
|
|
60
60
|
addChain?(chainConfig: AddChainParams): Promise<void>;
|
|
61
|
+
requestSwitchAccount?(targetAddress?: string): Promise<Account>;
|
|
61
62
|
readContract?<T = any>(params: ContractReadParams): Promise<T>;
|
|
62
63
|
writeContract?(params: ContractWriteParams): Promise<string>;
|
|
63
64
|
estimateGas?(params: ContractWriteParams): Promise<bigint>;
|
|
@@ -225,6 +226,8 @@ declare class WalletManager extends TypedEventEmitter<WalletManagerEvents> {
|
|
|
225
226
|
addChainIfNotExists?: boolean;
|
|
226
227
|
chainConfig?: AddChainParams;
|
|
227
228
|
}): Promise<Account>;
|
|
229
|
+
requestSwitchAccount(targetAddress?: string): Promise<Account>;
|
|
230
|
+
ensureAccount(targetAddress: string): Promise<Account>;
|
|
228
231
|
readContract<T = any>(address: string, abi: any[], functionName: string, args?: any[], chainType?: ChainType): Promise<T>;
|
|
229
232
|
writeContract(address: string, abi: any[], functionName: string, args?: any[], options?: {
|
|
230
233
|
value?: string;
|
|
@@ -263,8 +266,9 @@ interface WalletContextValue {
|
|
|
263
266
|
interface WalletProviderProps {
|
|
264
267
|
children: ReactNode;
|
|
265
268
|
walletManager?: WalletManager;
|
|
269
|
+
autoRestoreFromStorage?: boolean;
|
|
266
270
|
}
|
|
267
|
-
declare function WalletProvider({ children, walletManager: externalWalletManager }: WalletProviderProps): React.JSX.Element;
|
|
271
|
+
declare function WalletProvider({ children, walletManager: externalWalletManager, autoRestoreFromStorage, }: WalletProviderProps): React.JSX.Element;
|
|
268
272
|
declare function useWallet(): WalletContextValue;
|
|
269
273
|
|
|
270
274
|
interface UseAccountResult {
|
package/dist/react/index.js
CHANGED
|
@@ -846,7 +846,12 @@ var CHAIN_INFO = {
|
|
|
846
846
|
symbol: "ETH",
|
|
847
847
|
decimals: 18
|
|
848
848
|
},
|
|
849
|
-
|
|
849
|
+
// 使用支持浏览器 CORS 的公共 RPC,避免 dapp 域名被跨域拦截(如 eth.llamarpc.com 无 CORS 头)
|
|
850
|
+
rpcUrls: [
|
|
851
|
+
"https://cloudflare-eth.com",
|
|
852
|
+
"https://rpc.ankr.com/eth",
|
|
853
|
+
"https://eth.llamarpc.com"
|
|
854
|
+
],
|
|
850
855
|
blockExplorerUrls: ["https://etherscan.io"]
|
|
851
856
|
},
|
|
852
857
|
// EVM Testnets
|
|
@@ -1245,6 +1250,56 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
|
|
|
1245
1250
|
}]
|
|
1246
1251
|
});
|
|
1247
1252
|
}
|
|
1253
|
+
/**
|
|
1254
|
+
* 请求切换账户
|
|
1255
|
+
* 弹出 MetaMask 账户选择界面,让用户选择或切换到目标地址
|
|
1256
|
+
* @param targetAddress 目标地址(可选),如果提供,会在切换后验证是否匹配
|
|
1257
|
+
* @returns 切换后的账户信息
|
|
1258
|
+
*/
|
|
1259
|
+
async requestSwitchAccount(targetAddress) {
|
|
1260
|
+
const provider = this.getBrowserProvider();
|
|
1261
|
+
if (!provider) {
|
|
1262
|
+
throw new Error("MetaMask provider not available");
|
|
1263
|
+
}
|
|
1264
|
+
try {
|
|
1265
|
+
await provider.request({
|
|
1266
|
+
method: "wallet_requestPermissions",
|
|
1267
|
+
params: [{ eth_accounts: {} }]
|
|
1268
|
+
});
|
|
1269
|
+
const accounts = await provider.request({
|
|
1270
|
+
method: "eth_accounts"
|
|
1271
|
+
});
|
|
1272
|
+
if (!accounts || accounts.length === 0) {
|
|
1273
|
+
throw new ConnectionRejectedError(this.type);
|
|
1274
|
+
}
|
|
1275
|
+
const address = formatEVMAddress(accounts[0]);
|
|
1276
|
+
if (targetAddress && address.toLowerCase() !== targetAddress.toLowerCase()) {
|
|
1277
|
+
throw new Error(`\u8BF7\u5728 MetaMask \u4E2D\u9009\u62E9\u5730\u5740 ${targetAddress.slice(0, 6)}...${targetAddress.slice(-4)}\uFF0C\u5F53\u524D\u9009\u62E9\u7684\u662F ${address.slice(0, 6)}...${address.slice(-4)}`);
|
|
1278
|
+
}
|
|
1279
|
+
const chainId = this.currentAccount?.chainId || 1;
|
|
1280
|
+
const account = {
|
|
1281
|
+
universalAddress: createUniversalAddress(chainId, address),
|
|
1282
|
+
nativeAddress: address,
|
|
1283
|
+
chainId,
|
|
1284
|
+
chainType: ChainType.EVM,
|
|
1285
|
+
isActive: true
|
|
1286
|
+
};
|
|
1287
|
+
this.setAccount(account);
|
|
1288
|
+
this.emitAccountChanged(account);
|
|
1289
|
+
const viemChain = this.getViemChain(chainId);
|
|
1290
|
+
this.walletClient = viem.createWalletClient({
|
|
1291
|
+
account: address,
|
|
1292
|
+
chain: viemChain,
|
|
1293
|
+
transport: viem.custom(provider)
|
|
1294
|
+
});
|
|
1295
|
+
return account;
|
|
1296
|
+
} catch (error) {
|
|
1297
|
+
if (error.code === 4001) {
|
|
1298
|
+
throw new ConnectionRejectedError(this.type);
|
|
1299
|
+
}
|
|
1300
|
+
throw error;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1248
1303
|
/**
|
|
1249
1304
|
* 读取合约
|
|
1250
1305
|
*/
|
|
@@ -1470,6 +1525,46 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
|
|
|
1470
1525
|
|
|
1471
1526
|
// src/adapters/tron/tronlink.ts
|
|
1472
1527
|
init_types();
|
|
1528
|
+
var TronApiRateLimiter = class {
|
|
1529
|
+
constructor(minIntervalMs = 600) {
|
|
1530
|
+
this.lastCallTime = 0;
|
|
1531
|
+
this.minInterval = minIntervalMs;
|
|
1532
|
+
}
|
|
1533
|
+
/**
|
|
1534
|
+
* 等待直到可以进行下一次 API 调用
|
|
1535
|
+
*/
|
|
1536
|
+
async waitForNextCall() {
|
|
1537
|
+
const now = Date.now();
|
|
1538
|
+
const timeSinceLastCall = now - this.lastCallTime;
|
|
1539
|
+
if (timeSinceLastCall < this.minInterval) {
|
|
1540
|
+
const waitTime = this.minInterval - timeSinceLastCall;
|
|
1541
|
+
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
1542
|
+
}
|
|
1543
|
+
this.lastCallTime = Date.now();
|
|
1544
|
+
}
|
|
1545
|
+
};
|
|
1546
|
+
var tronApiRateLimiter = new TronApiRateLimiter(600);
|
|
1547
|
+
async function retryWithBackoff(fn, maxRetries = 3, initialDelay = 500) {
|
|
1548
|
+
let lastError;
|
|
1549
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
1550
|
+
try {
|
|
1551
|
+
return await fn();
|
|
1552
|
+
} catch (error) {
|
|
1553
|
+
lastError = error;
|
|
1554
|
+
const errorMsg = error?.message || String(error);
|
|
1555
|
+
const errorLower = errorMsg.toLowerCase();
|
|
1556
|
+
const isRateLimitError = error?.response?.status === 429 || error?.status === 429 || errorLower.includes("429") || errorLower.includes("rate limit") || errorLower.includes("too many requests") || error?.code === "ERR_BAD_REQUEST" && error?.response?.status === 429;
|
|
1557
|
+
if (isRateLimitError && attempt < maxRetries - 1) {
|
|
1558
|
+
const delay = initialDelay * Math.pow(2, attempt);
|
|
1559
|
+
console.warn(`[TronLink] \u9047\u5230\u901F\u7387\u9650\u5236 (429)\uFF0C\u7B49\u5F85 ${delay}ms \u540E\u91CD\u8BD5 (${attempt + 1}/${maxRetries})...`);
|
|
1560
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1561
|
+
continue;
|
|
1562
|
+
}
|
|
1563
|
+
throw error;
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
throw lastError;
|
|
1567
|
+
}
|
|
1473
1568
|
var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
1474
1569
|
constructor() {
|
|
1475
1570
|
super(...arguments);
|
|
@@ -1647,10 +1742,12 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
1647
1742
|
/**
|
|
1648
1743
|
* 读取合约
|
|
1649
1744
|
* 参考 webserver 的实现,使用 TronWeb 合约实例的标准 call() 方法
|
|
1745
|
+
* 带 TronGrid 限流 + 429 重试
|
|
1650
1746
|
*/
|
|
1651
1747
|
async readContract(params) {
|
|
1652
1748
|
this.ensureConnected();
|
|
1653
|
-
|
|
1749
|
+
await tronApiRateLimiter.waitForNextCall();
|
|
1750
|
+
const doRead = async () => {
|
|
1654
1751
|
const tronWeb = this.getTronWeb();
|
|
1655
1752
|
if (!this.currentAccount) {
|
|
1656
1753
|
throw new Error("No account connected");
|
|
@@ -1665,19 +1762,17 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
1665
1762
|
return result;
|
|
1666
1763
|
} catch (method1Error) {
|
|
1667
1764
|
console.warn("\u26A0\uFE0F [\u65B9\u6CD51] TronWeb\u6807\u51C6\u65B9\u6CD5\u5931\u8D25\uFF0C\u5C1D\u8BD5\u65B9\u6CD52:", method1Error.message);
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
throw new Error(`Function ${params.functionName} not found in contract`);
|
|
1673
|
-
}
|
|
1674
|
-
const result = await method2(...params.args || []).call();
|
|
1675
|
-
return result;
|
|
1676
|
-
} catch (method2Error) {
|
|
1677
|
-
console.error("\u26A0\uFE0F [\u65B9\u6CD52] \u4E5F\u5931\u8D25:", method2Error.message);
|
|
1678
|
-
throw method1Error;
|
|
1765
|
+
const contract2 = await tronWeb.contract().at(params.address);
|
|
1766
|
+
const method2 = contract2[params.functionName];
|
|
1767
|
+
if (!method2 || typeof method2 !== "function") {
|
|
1768
|
+
throw new Error(`Function ${params.functionName} not found in contract`);
|
|
1679
1769
|
}
|
|
1770
|
+
const result = await method2(...params.args || []).call();
|
|
1771
|
+
return result;
|
|
1680
1772
|
}
|
|
1773
|
+
};
|
|
1774
|
+
try {
|
|
1775
|
+
return await retryWithBackoff(doRead, 3, 800);
|
|
1681
1776
|
} catch (error) {
|
|
1682
1777
|
console.error("Read contract error:", error);
|
|
1683
1778
|
throw new Error(`Failed to read contract: ${error.message || "Unknown error"}`);
|
|
@@ -1688,6 +1783,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
1688
1783
|
*/
|
|
1689
1784
|
async writeContract(params) {
|
|
1690
1785
|
this.ensureConnected();
|
|
1786
|
+
await tronApiRateLimiter.waitForNextCall();
|
|
1691
1787
|
try {
|
|
1692
1788
|
const tronWeb = this.getTronWeb();
|
|
1693
1789
|
console.log("[TronLink] writeContract params:", {
|
|
@@ -1713,29 +1809,171 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
1713
1809
|
}
|
|
1714
1810
|
console.log("[TronLink] Function ABI:", functionAbi);
|
|
1715
1811
|
console.log("[TronLink] Calling with args:", params.args);
|
|
1812
|
+
const TRON_FEE_LIMIT = 1e8;
|
|
1716
1813
|
const options = {
|
|
1717
|
-
feeLimit:
|
|
1718
|
-
//
|
|
1814
|
+
feeLimit: TRON_FEE_LIMIT,
|
|
1815
|
+
// 固定为 100 TRX 的能量限制
|
|
1719
1816
|
callValue: params.value || 0
|
|
1720
1817
|
// 发送的 TRX 数量(单位:SUN)
|
|
1721
1818
|
};
|
|
1722
|
-
const
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1819
|
+
const hasTupleArray = functionAbi.inputs.some((input) => input.type === "tuple[]");
|
|
1820
|
+
console.log("[TronLink] \u68C0\u67E5 tuple[] \u7C7B\u578B:", {
|
|
1821
|
+
hasTupleArray,
|
|
1822
|
+
inputs: functionAbi.inputs.map((i) => ({ name: i.name, type: i.type }))
|
|
1823
|
+
});
|
|
1824
|
+
let tx;
|
|
1825
|
+
if (hasTupleArray) {
|
|
1826
|
+
console.log("[TronLink] \u68C0\u6D4B\u5230 tuple[] \u53C2\u6570\uFF0C\u4F7F\u7528\u624B\u52A8\u7F16\u7801\u65B9\u5F0F");
|
|
1827
|
+
const processedArgs = params.args.map((argValue, index) => {
|
|
1828
|
+
const input = functionAbi.inputs[index];
|
|
1829
|
+
if (input.type === "address" && typeof argValue === "string") {
|
|
1830
|
+
if (argValue.startsWith("T") && argValue.length === 34) {
|
|
1831
|
+
const hexAddress = tronWeb.address.toHex(argValue);
|
|
1832
|
+
return hexAddress.startsWith("0x") ? hexAddress : `0x${hexAddress}`;
|
|
1833
|
+
}
|
|
1834
|
+
return argValue.startsWith("0x") ? argValue : `0x${argValue}`;
|
|
1835
|
+
}
|
|
1836
|
+
if (input.type === "tuple[]" && Array.isArray(argValue)) {
|
|
1837
|
+
return argValue.map((tupleItem) => {
|
|
1838
|
+
if (input.components && Array.isArray(input.components)) {
|
|
1839
|
+
const processedTuple = {};
|
|
1840
|
+
input.components.forEach((component) => {
|
|
1841
|
+
let value = tupleItem[component.name];
|
|
1842
|
+
if (component.type === "address" && typeof value === "string") {
|
|
1843
|
+
if (value.startsWith("T") && value.length === 34) {
|
|
1844
|
+
const hexAddress = tronWeb.address.toHex(value);
|
|
1845
|
+
value = hexAddress.startsWith("0x") ? hexAddress : `0x${hexAddress}`;
|
|
1846
|
+
} else if (!value.startsWith("0x")) {
|
|
1847
|
+
value = `0x${value}`;
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
processedTuple[component.name] = value;
|
|
1851
|
+
});
|
|
1852
|
+
return processedTuple;
|
|
1853
|
+
}
|
|
1854
|
+
return tupleItem;
|
|
1855
|
+
});
|
|
1856
|
+
}
|
|
1857
|
+
if (input.type === "tuple" && typeof argValue === "object" && !Array.isArray(argValue)) {
|
|
1858
|
+
if (input.components && Array.isArray(input.components)) {
|
|
1859
|
+
const processedTuple = {};
|
|
1860
|
+
input.components.forEach((component) => {
|
|
1861
|
+
let value = argValue[component.name];
|
|
1862
|
+
if (component.type === "address" && typeof value === "string") {
|
|
1863
|
+
if (value.startsWith("T") && value.length === 34) {
|
|
1864
|
+
const hexAddress = tronWeb.address.toHex(value);
|
|
1865
|
+
value = hexAddress.startsWith("0x") ? hexAddress : `0x${hexAddress}`;
|
|
1866
|
+
} else if (!value.startsWith("0x")) {
|
|
1867
|
+
value = `0x${value}`;
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
processedTuple[component.name] = value;
|
|
1871
|
+
});
|
|
1872
|
+
return processedTuple;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
return argValue;
|
|
1876
|
+
});
|
|
1877
|
+
console.log("[TronLink] \u5904\u7406\u540E\u7684\u53C2\u6570\uFF08\u7528\u4E8E viem \u7F16\u7801\uFF09:", processedArgs);
|
|
1878
|
+
const encodedData = viem.encodeFunctionData({
|
|
1879
|
+
abi: [functionAbi],
|
|
1880
|
+
functionName: params.functionName,
|
|
1881
|
+
args: processedArgs
|
|
1882
|
+
});
|
|
1883
|
+
console.log("[TronLink] \u7F16\u7801\u540E\u7684\u6570\u636E:", encodedData);
|
|
1884
|
+
const functionSelector = encodedData.slice(0, 10);
|
|
1885
|
+
const parameterData = encodedData.slice(10);
|
|
1886
|
+
console.log("[TronLink] \u51FD\u6570\u9009\u62E9\u5668:", functionSelector);
|
|
1887
|
+
console.log("[TronLink] \u53C2\u6570\u6570\u636E:", parameterData);
|
|
1888
|
+
const functionSignature = params.functionName + "(" + functionAbi.inputs.map((i) => i.type).join(",") + ")";
|
|
1889
|
+
const parameterHexClean = parameterData.startsWith("0x") ? parameterData.slice(2) : parameterData;
|
|
1890
|
+
console.log("[TronLink] \u4F7F\u7528 TronWeb triggerSmartContract (rawParameter)...", {
|
|
1891
|
+
contractAddress: params.address,
|
|
1892
|
+
functionSelector: functionSignature,
|
|
1893
|
+
encodedDataLength: parameterHexClean.length
|
|
1894
|
+
});
|
|
1895
|
+
tx = await retryWithBackoff(
|
|
1896
|
+
() => tronWeb.transactionBuilder.triggerSmartContract(
|
|
1897
|
+
params.address,
|
|
1898
|
+
// Base58 格式的合约地址
|
|
1899
|
+
functionSignature,
|
|
1900
|
+
// 函数签名(用于识别函数)
|
|
1901
|
+
{
|
|
1902
|
+
feeLimit: options.feeLimit,
|
|
1903
|
+
callValue: options.callValue,
|
|
1904
|
+
rawParameter: parameterHexClean
|
|
1905
|
+
// 使用 rawParameter 直接提供编码后的数据
|
|
1906
|
+
},
|
|
1907
|
+
[],
|
|
1908
|
+
// parameter 留空(因为使用 rawParameter)
|
|
1909
|
+
this.currentAccount.nativeAddress
|
|
1910
|
+
// Base58 格式的发送地址
|
|
1911
|
+
),
|
|
1912
|
+
3,
|
|
1913
|
+
// 最多重试 3 次
|
|
1914
|
+
500
|
|
1915
|
+
// 初始延迟 500ms
|
|
1916
|
+
);
|
|
1917
|
+
console.log("[TronLink] \u4F7F\u7528 TronWeb API \u6784\u5EFA\u7684\u4EA4\u6613:", tx);
|
|
1918
|
+
} else {
|
|
1919
|
+
const parameter = functionAbi.inputs.map((input, index) => {
|
|
1920
|
+
const argValue = params.args[index];
|
|
1921
|
+
if (input.type === "tuple" && typeof argValue === "object" && !Array.isArray(argValue)) {
|
|
1922
|
+
if (input.components && Array.isArray(input.components)) {
|
|
1923
|
+
return {
|
|
1924
|
+
type: input.type,
|
|
1925
|
+
value: input.components.map((component) => ({
|
|
1926
|
+
type: component.type,
|
|
1927
|
+
value: argValue[component.name]
|
|
1928
|
+
}))
|
|
1929
|
+
};
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
if (input.type === "address" && typeof argValue === "string") {
|
|
1933
|
+
if (argValue.startsWith("T") && argValue.length === 34) {
|
|
1934
|
+
return {
|
|
1935
|
+
type: input.type,
|
|
1936
|
+
value: argValue
|
|
1937
|
+
};
|
|
1938
|
+
}
|
|
1939
|
+
try {
|
|
1940
|
+
const base58Address = tronWeb.address.fromHex(argValue.startsWith("0x") ? argValue : `0x${argValue}`);
|
|
1941
|
+
return {
|
|
1942
|
+
type: input.type,
|
|
1943
|
+
value: base58Address
|
|
1944
|
+
};
|
|
1945
|
+
} catch (e) {
|
|
1946
|
+
return {
|
|
1947
|
+
type: input.type,
|
|
1948
|
+
value: argValue
|
|
1949
|
+
};
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
return {
|
|
1953
|
+
type: input.type,
|
|
1954
|
+
value: argValue
|
|
1955
|
+
};
|
|
1956
|
+
});
|
|
1957
|
+
console.log("[TronLink] Transaction options:", options);
|
|
1958
|
+
console.log("[TronLink] Parameters:", parameter);
|
|
1959
|
+
const functionSelector = params.functionName + "(" + functionAbi.inputs.map((i) => i.type).join(",") + ")";
|
|
1960
|
+
console.log("[TronLink] Function selector:", functionSelector);
|
|
1961
|
+
console.log("[TronLink] Transaction options:", options);
|
|
1962
|
+
console.log("[TronLink] Parameters:", parameter);
|
|
1963
|
+
tx = await retryWithBackoff(
|
|
1964
|
+
() => tronWeb.transactionBuilder.triggerSmartContract(
|
|
1965
|
+
params.address,
|
|
1966
|
+
functionSelector,
|
|
1967
|
+
options,
|
|
1968
|
+
parameter,
|
|
1969
|
+
this.currentAccount.nativeAddress
|
|
1970
|
+
),
|
|
1971
|
+
3,
|
|
1972
|
+
// 最多重试 3 次
|
|
1973
|
+
500
|
|
1974
|
+
// 初始延迟 500ms
|
|
1975
|
+
);
|
|
1976
|
+
}
|
|
1739
1977
|
console.log("[TronLink] Transaction built:", tx);
|
|
1740
1978
|
if (!tx || !tx.transaction) {
|
|
1741
1979
|
throw new Error("Failed to build transaction");
|
|
@@ -1775,6 +2013,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
1775
2013
|
const maxAttempts = 60;
|
|
1776
2014
|
while (attempts < maxAttempts) {
|
|
1777
2015
|
try {
|
|
2016
|
+
await tronApiRateLimiter.waitForNextCall();
|
|
1778
2017
|
const txInfo = await tronWeb.trx.getTransactionInfo(txHash);
|
|
1779
2018
|
if (txInfo && txInfo.id) {
|
|
1780
2019
|
const receipt = {
|
|
@@ -3192,6 +3431,12 @@ _WalletConnectAdapter.providerChains = null;
|
|
|
3192
3431
|
_WalletConnectAdapter.isInitializing = false;
|
|
3193
3432
|
_WalletConnectAdapter.initPromise = null;
|
|
3194
3433
|
var WalletConnectAdapter = _WalletConnectAdapter;
|
|
3434
|
+
|
|
3435
|
+
// src/adapters/tron/wallet-connect.ts
|
|
3436
|
+
var wallet_connect_exports = {};
|
|
3437
|
+
__export(wallet_connect_exports, {
|
|
3438
|
+
WalletConnectTronAdapter: () => WalletConnectTronAdapter
|
|
3439
|
+
});
|
|
3195
3440
|
init_types();
|
|
3196
3441
|
var _WalletConnectTronAdapter = class _WalletConnectTronAdapter extends WalletAdapter {
|
|
3197
3442
|
constructor(projectId) {
|
|
@@ -3884,6 +4129,11 @@ _WalletConnectTronAdapter.walletInstance = null;
|
|
|
3884
4129
|
_WalletConnectTronAdapter.walletProjectId = null;
|
|
3885
4130
|
var WalletConnectTronAdapter = _WalletConnectTronAdapter;
|
|
3886
4131
|
|
|
4132
|
+
// src/internal/walletconnect-tron-loader.esm.ts
|
|
4133
|
+
function loadWalletConnectTronModule() {
|
|
4134
|
+
return wallet_connect_exports;
|
|
4135
|
+
}
|
|
4136
|
+
|
|
3887
4137
|
// src/adapters/deep-link/adapter.ts
|
|
3888
4138
|
init_types();
|
|
3889
4139
|
var _DeepLinkAdapter = class _DeepLinkAdapter extends WalletAdapter {
|
|
@@ -4190,10 +4440,10 @@ var AdapterRegistry = class {
|
|
|
4190
4440
|
"walletconnect" /* WALLETCONNECT */,
|
|
4191
4441
|
() => new WalletConnectAdapter(this.config.walletConnectProjectId)
|
|
4192
4442
|
);
|
|
4193
|
-
this.register(
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
);
|
|
4443
|
+
this.register("walletconnect-tron" /* WALLETCONNECT_TRON */, () => {
|
|
4444
|
+
const { WalletConnectTronAdapter: WalletConnectTronAdapter2 } = loadWalletConnectTronModule();
|
|
4445
|
+
return new WalletConnectTronAdapter2(this.config.walletConnectProjectId);
|
|
4446
|
+
});
|
|
4197
4447
|
}
|
|
4198
4448
|
this.register("tronlink" /* TRONLINK */, () => new TronLinkAdapter());
|
|
4199
4449
|
this.register(
|
|
@@ -4708,6 +4958,41 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
4708
4958
|
throw error;
|
|
4709
4959
|
}
|
|
4710
4960
|
}
|
|
4961
|
+
/**
|
|
4962
|
+
* Request account switch (opens wallet account selector)
|
|
4963
|
+
* @param targetAddress Optional target address to verify after switching
|
|
4964
|
+
* @returns The new account after switching
|
|
4965
|
+
*/
|
|
4966
|
+
async requestSwitchAccount(targetAddress) {
|
|
4967
|
+
if (!this.primaryWallet) {
|
|
4968
|
+
throw new WalletNotConnectedError();
|
|
4969
|
+
}
|
|
4970
|
+
if (!this.primaryWallet.requestSwitchAccount) {
|
|
4971
|
+
throw new Error(`Account switching not supported by ${this.primaryWallet.type}`);
|
|
4972
|
+
}
|
|
4973
|
+
const account = await this.primaryWallet.requestSwitchAccount(targetAddress);
|
|
4974
|
+
if (this.config.enableStorage) {
|
|
4975
|
+
this.saveToStorage();
|
|
4976
|
+
}
|
|
4977
|
+
return account;
|
|
4978
|
+
}
|
|
4979
|
+
/**
|
|
4980
|
+
* Ensure the current account matches the target address
|
|
4981
|
+
* If not matching, request account switch
|
|
4982
|
+
* @param targetAddress The address that should be active
|
|
4983
|
+
* @returns The account (either existing or after switch)
|
|
4984
|
+
*/
|
|
4985
|
+
async ensureAccount(targetAddress) {
|
|
4986
|
+
const currentAccount = this.getPrimaryAccount();
|
|
4987
|
+
if (!currentAccount) {
|
|
4988
|
+
throw new WalletNotConnectedError();
|
|
4989
|
+
}
|
|
4990
|
+
if (currentAccount.nativeAddress.toLowerCase() === targetAddress.toLowerCase()) {
|
|
4991
|
+
return currentAccount;
|
|
4992
|
+
}
|
|
4993
|
+
console.log(`[WalletManager] Current account ${currentAccount.nativeAddress} doesn't match target ${targetAddress}, requesting switch...`);
|
|
4994
|
+
return this.requestSwitchAccount(targetAddress);
|
|
4995
|
+
}
|
|
4711
4996
|
// ===== Contract Calls =====
|
|
4712
4997
|
/**
|
|
4713
4998
|
* Read contract
|
|
@@ -4917,13 +5202,13 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
4917
5202
|
if (currentAddress === savedAddress.toLowerCase()) {
|
|
4918
5203
|
console.debug("[WalletManager] Address matches, attempting connect (should be silent if already authorized)");
|
|
4919
5204
|
try {
|
|
4920
|
-
const
|
|
5205
|
+
const account = await adapter.connect(data.primaryChainId);
|
|
4921
5206
|
this.setPrimaryWallet(adapter);
|
|
4922
5207
|
this.connectedWallets.set(adapter.chainType, adapter);
|
|
4923
5208
|
this.setupAdapterListeners(adapter, true);
|
|
4924
|
-
this.emit("accountChanged",
|
|
5209
|
+
this.emit("accountChanged", account);
|
|
4925
5210
|
console.debug("[WalletManager] Connect successful");
|
|
4926
|
-
return
|
|
5211
|
+
return account;
|
|
4927
5212
|
} catch (connectError) {
|
|
4928
5213
|
console.debug("[WalletManager] Connect failed (might be user rejection):", connectError?.message);
|
|
4929
5214
|
return null;
|
|
@@ -4943,12 +5228,12 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
4943
5228
|
try {
|
|
4944
5229
|
const tronWeb = adapter.getTronWeb?.();
|
|
4945
5230
|
if (tronWeb && tronWeb.defaultAddress?.base58) {
|
|
4946
|
-
const
|
|
5231
|
+
const account = await adapter.connect(data.primaryChainId);
|
|
4947
5232
|
this.setPrimaryWallet(adapter);
|
|
4948
5233
|
this.connectedWallets.set(adapter.chainType, adapter);
|
|
4949
5234
|
this.setupAdapterListeners(adapter, true);
|
|
4950
|
-
this.emit("accountChanged",
|
|
4951
|
-
return
|
|
5235
|
+
this.emit("accountChanged", account);
|
|
5236
|
+
return account;
|
|
4952
5237
|
}
|
|
4953
5238
|
} catch (silentError) {
|
|
4954
5239
|
console.debug("Silent TronLink connection failed:", silentError);
|
|
@@ -4959,14 +5244,14 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
4959
5244
|
const wcAdapter = adapter;
|
|
4960
5245
|
if (typeof wcAdapter.restoreSession === "function") {
|
|
4961
5246
|
console.debug("[WalletManager] Attempting to restore WalletConnect Tron session...");
|
|
4962
|
-
const
|
|
4963
|
-
if (
|
|
5247
|
+
const account = await wcAdapter.restoreSession(data.primaryChainId);
|
|
5248
|
+
if (account) {
|
|
4964
5249
|
console.debug("[WalletManager] WalletConnect Tron session restored successfully");
|
|
4965
5250
|
this.setPrimaryWallet(adapter);
|
|
4966
5251
|
this.connectedWallets.set(adapter.chainType, adapter);
|
|
4967
5252
|
this.setupAdapterListeners(adapter, true);
|
|
4968
|
-
this.emit("accountChanged",
|
|
4969
|
-
return
|
|
5253
|
+
this.emit("accountChanged", account);
|
|
5254
|
+
return account;
|
|
4970
5255
|
} else {
|
|
4971
5256
|
console.debug("[WalletManager] No valid WalletConnect Tron session found");
|
|
4972
5257
|
return null;
|
|
@@ -4977,12 +5262,12 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
4977
5262
|
return null;
|
|
4978
5263
|
}
|
|
4979
5264
|
}
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
return
|
|
5265
|
+
console.debug(
|
|
5266
|
+
"[WalletManager] restoreFromStorage: no silent session; skipping interactive connect (type:",
|
|
5267
|
+
data.primaryWalletType,
|
|
5268
|
+
")"
|
|
5269
|
+
);
|
|
5270
|
+
return null;
|
|
4986
5271
|
} catch (error) {
|
|
4987
5272
|
console.debug("Failed to restore wallet from storage:", error);
|
|
4988
5273
|
return null;
|
|
@@ -5025,7 +5310,11 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
5025
5310
|
|
|
5026
5311
|
// src/react/WalletContext.tsx
|
|
5027
5312
|
var WalletContext = React2.createContext(null);
|
|
5028
|
-
function WalletProvider({
|
|
5313
|
+
function WalletProvider({
|
|
5314
|
+
children,
|
|
5315
|
+
walletManager: externalWalletManager,
|
|
5316
|
+
autoRestoreFromStorage = true
|
|
5317
|
+
}) {
|
|
5029
5318
|
const [walletManager] = React2.useState(() => externalWalletManager || new WalletManager());
|
|
5030
5319
|
const [account, setAccount] = React2.useState(null);
|
|
5031
5320
|
const [connectedWallets, setConnectedWallets] = React2.useState([]);
|
|
@@ -5062,6 +5351,10 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
|
|
|
5062
5351
|
return walletManager.signTransaction(transaction);
|
|
5063
5352
|
}, [walletManager]);
|
|
5064
5353
|
React2.useEffect(() => {
|
|
5354
|
+
if (!autoRestoreFromStorage) {
|
|
5355
|
+
setIsRestoring(false);
|
|
5356
|
+
return;
|
|
5357
|
+
}
|
|
5065
5358
|
const restoreConnection = async () => {
|
|
5066
5359
|
try {
|
|
5067
5360
|
const restoredAccount = await walletManager.restoreFromStorage();
|
|
@@ -5076,7 +5369,7 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
|
|
|
5076
5369
|
}
|
|
5077
5370
|
};
|
|
5078
5371
|
restoreConnection();
|
|
5079
|
-
}, [walletManager, updateConnectedWallets]);
|
|
5372
|
+
}, [walletManager, updateConnectedWallets, autoRestoreFromStorage]);
|
|
5080
5373
|
React2.useEffect(() => {
|
|
5081
5374
|
const handleAccountChanged = (newAccount) => {
|
|
5082
5375
|
setAccount(newAccount);
|