@enclave-hq/wallet-sdk 1.0.0 → 1.0.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/index.d.mts +62 -37
- package/dist/index.d.ts +62 -37
- package/dist/index.js +347 -60
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +347 -60
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +33 -8
- package/dist/react/index.d.ts +33 -8
- package/dist/react/index.js +358 -33
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +358 -34
- package/dist/react/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/react/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { createContext, useState, useCallback, useEffect, useContext } from 'react';
|
|
2
2
|
import EventEmitter from 'eventemitter3';
|
|
3
|
+
import { ChainType as ChainType$1 } from '@enclave-hq/chain-utils';
|
|
3
4
|
import { createWalletClient, http, createPublicClient, custom, isAddress, getAddress } from 'viem';
|
|
4
5
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
5
6
|
|
|
@@ -32,6 +33,7 @@ var TypedEventEmitter = class {
|
|
|
32
33
|
return this;
|
|
33
34
|
}
|
|
34
35
|
};
|
|
36
|
+
var ChainType = ChainType$1;
|
|
35
37
|
|
|
36
38
|
// src/core/errors.ts
|
|
37
39
|
var WalletSDKError = class _WalletSDKError extends Error {
|
|
@@ -212,14 +214,15 @@ function formatEVMAddress(address) {
|
|
|
212
214
|
}
|
|
213
215
|
return getAddress(address);
|
|
214
216
|
}
|
|
215
|
-
|
|
216
|
-
// src/utils/chain-info.ts
|
|
217
217
|
var CHAIN_INFO = {
|
|
218
218
|
// EVM Mainnet
|
|
219
219
|
1: {
|
|
220
220
|
id: 1,
|
|
221
|
+
slip44: 60,
|
|
222
|
+
// Ethereum SLIP-44
|
|
221
223
|
name: "Ethereum Mainnet",
|
|
222
|
-
chainType:
|
|
224
|
+
chainType: ChainType$1.EVM,
|
|
225
|
+
symbol: "ETH",
|
|
223
226
|
nativeCurrency: {
|
|
224
227
|
name: "Ether",
|
|
225
228
|
symbol: "ETH",
|
|
@@ -232,7 +235,8 @@ var CHAIN_INFO = {
|
|
|
232
235
|
11155111: {
|
|
233
236
|
id: 11155111,
|
|
234
237
|
name: "Sepolia Testnet",
|
|
235
|
-
chainType:
|
|
238
|
+
chainType: ChainType$1.EVM,
|
|
239
|
+
symbol: "ETH",
|
|
236
240
|
nativeCurrency: {
|
|
237
241
|
name: "Sepolia Ether",
|
|
238
242
|
symbol: "ETH",
|
|
@@ -244,8 +248,11 @@ var CHAIN_INFO = {
|
|
|
244
248
|
// Binance Smart Chain
|
|
245
249
|
56: {
|
|
246
250
|
id: 56,
|
|
251
|
+
slip44: 714,
|
|
252
|
+
// BSC SLIP-44
|
|
247
253
|
name: "BNB Smart Chain",
|
|
248
|
-
chainType:
|
|
254
|
+
chainType: ChainType$1.EVM,
|
|
255
|
+
symbol: "BNB",
|
|
249
256
|
nativeCurrency: {
|
|
250
257
|
name: "BNB",
|
|
251
258
|
symbol: "BNB",
|
|
@@ -257,7 +264,8 @@ var CHAIN_INFO = {
|
|
|
257
264
|
97: {
|
|
258
265
|
id: 97,
|
|
259
266
|
name: "BNB Smart Chain Testnet",
|
|
260
|
-
chainType:
|
|
267
|
+
chainType: ChainType$1.EVM,
|
|
268
|
+
symbol: "BNB",
|
|
261
269
|
nativeCurrency: {
|
|
262
270
|
name: "BNB",
|
|
263
271
|
symbol: "BNB",
|
|
@@ -269,8 +277,11 @@ var CHAIN_INFO = {
|
|
|
269
277
|
// Polygon
|
|
270
278
|
137: {
|
|
271
279
|
id: 137,
|
|
280
|
+
slip44: 966,
|
|
281
|
+
// Polygon SLIP-44
|
|
272
282
|
name: "Polygon Mainnet",
|
|
273
|
-
chainType:
|
|
283
|
+
chainType: ChainType$1.EVM,
|
|
284
|
+
symbol: "MATIC",
|
|
274
285
|
nativeCurrency: {
|
|
275
286
|
name: "MATIC",
|
|
276
287
|
symbol: "MATIC",
|
|
@@ -282,7 +293,8 @@ var CHAIN_INFO = {
|
|
|
282
293
|
80002: {
|
|
283
294
|
id: 80002,
|
|
284
295
|
name: "Polygon Amoy Testnet",
|
|
285
|
-
chainType:
|
|
296
|
+
chainType: ChainType$1.EVM,
|
|
297
|
+
symbol: "MATIC",
|
|
286
298
|
nativeCurrency: {
|
|
287
299
|
name: "MATIC",
|
|
288
300
|
symbol: "MATIC",
|
|
@@ -294,8 +306,11 @@ var CHAIN_INFO = {
|
|
|
294
306
|
// Tron
|
|
295
307
|
195: {
|
|
296
308
|
id: 195,
|
|
309
|
+
slip44: 195,
|
|
310
|
+
// Tron SLIP-44
|
|
297
311
|
name: "Tron Mainnet",
|
|
298
|
-
chainType:
|
|
312
|
+
chainType: ChainType$1.TRON,
|
|
313
|
+
symbol: "TRX",
|
|
299
314
|
nativeCurrency: {
|
|
300
315
|
name: "TRX",
|
|
301
316
|
symbol: "TRX",
|
|
@@ -307,8 +322,11 @@ var CHAIN_INFO = {
|
|
|
307
322
|
// Arbitrum
|
|
308
323
|
42161: {
|
|
309
324
|
id: 42161,
|
|
325
|
+
slip44: 1042161,
|
|
326
|
+
// Custom SLIP-44 (1000000 + 42161)
|
|
310
327
|
name: "Arbitrum One",
|
|
311
|
-
chainType:
|
|
328
|
+
chainType: ChainType$1.EVM,
|
|
329
|
+
symbol: "ETH",
|
|
312
330
|
nativeCurrency: {
|
|
313
331
|
name: "Ether",
|
|
314
332
|
symbol: "ETH",
|
|
@@ -320,8 +338,11 @@ var CHAIN_INFO = {
|
|
|
320
338
|
// Optimism
|
|
321
339
|
10: {
|
|
322
340
|
id: 10,
|
|
341
|
+
slip44: 1000010,
|
|
342
|
+
// Custom SLIP-44 (1000000 + 10)
|
|
323
343
|
name: "Optimism",
|
|
324
|
-
chainType:
|
|
344
|
+
chainType: ChainType$1.EVM,
|
|
345
|
+
symbol: "ETH",
|
|
325
346
|
nativeCurrency: {
|
|
326
347
|
name: "Ether",
|
|
327
348
|
symbol: "ETH",
|
|
@@ -333,8 +354,11 @@ var CHAIN_INFO = {
|
|
|
333
354
|
// Avalanche
|
|
334
355
|
43114: {
|
|
335
356
|
id: 43114,
|
|
357
|
+
slip44: 9e3,
|
|
358
|
+
// Avalanche SLIP-44
|
|
336
359
|
name: "Avalanche C-Chain",
|
|
337
|
-
chainType:
|
|
360
|
+
chainType: ChainType$1.EVM,
|
|
361
|
+
symbol: "AVAX",
|
|
338
362
|
nativeCurrency: {
|
|
339
363
|
name: "AVAX",
|
|
340
364
|
symbol: "AVAX",
|
|
@@ -353,26 +377,34 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
|
|
|
353
377
|
constructor() {
|
|
354
378
|
super(...arguments);
|
|
355
379
|
this.type = "metamask" /* METAMASK */;
|
|
356
|
-
this.chainType =
|
|
380
|
+
this.chainType = ChainType.EVM;
|
|
357
381
|
this.name = "MetaMask";
|
|
358
382
|
this.icon = "https://upload.wikimedia.org/wikipedia/commons/3/36/MetaMask_Fox.svg";
|
|
359
383
|
this.walletClient = null;
|
|
360
384
|
this.publicClient = null;
|
|
361
385
|
/**
|
|
362
386
|
* 处理账户变化
|
|
387
|
+
*
|
|
388
|
+
* 注意:MetaMask 的行为
|
|
389
|
+
* - 切换到已连接的账户:触发事件,返回新账户 ['0xNewAddress']
|
|
390
|
+
* - 切换到未连接的账户:不触发事件(用户需要手动断开和重新连接)
|
|
391
|
+
* - 锁定钱包:触发事件,返回空数组 []
|
|
363
392
|
*/
|
|
364
393
|
this.handleAccountsChanged = (accounts) => {
|
|
394
|
+
console.log("[MetaMask] accountsChanged event triggered:", accounts);
|
|
365
395
|
if (accounts.length === 0) {
|
|
396
|
+
console.log("[MetaMask] Disconnecting: wallet locked or manually disconnected");
|
|
366
397
|
this.setState("disconnected" /* DISCONNECTED */);
|
|
367
398
|
this.setAccount(null);
|
|
368
399
|
this.emitAccountChanged(null);
|
|
369
400
|
} else {
|
|
370
401
|
const address = formatEVMAddress(accounts[0]);
|
|
402
|
+
console.log("[MetaMask] Account changed to:", address);
|
|
371
403
|
const account = {
|
|
372
404
|
universalAddress: createUniversalAddress(this.currentAccount.chainId, address),
|
|
373
405
|
nativeAddress: address,
|
|
374
406
|
chainId: this.currentAccount.chainId,
|
|
375
|
-
chainType:
|
|
407
|
+
chainType: ChainType.EVM,
|
|
376
408
|
isActive: true
|
|
377
409
|
};
|
|
378
410
|
this.setAccount(account);
|
|
@@ -424,21 +456,23 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
|
|
|
424
456
|
if (chainId && chainId !== parsedChainId) {
|
|
425
457
|
await this.switchChain(chainId);
|
|
426
458
|
}
|
|
459
|
+
const finalChainId = chainId || parsedChainId;
|
|
460
|
+
const viemChain = this.getViemChain(finalChainId);
|
|
427
461
|
this.walletClient = createWalletClient({
|
|
428
462
|
account: accounts[0],
|
|
463
|
+
chain: viemChain,
|
|
429
464
|
transport: custom(provider)
|
|
430
465
|
});
|
|
431
|
-
const finalChainId = chainId || parsedChainId;
|
|
432
466
|
this.publicClient = createPublicClient({
|
|
433
|
-
chain:
|
|
434
|
-
transport:
|
|
467
|
+
chain: viemChain,
|
|
468
|
+
transport: custom(provider)
|
|
435
469
|
});
|
|
436
470
|
const address = formatEVMAddress(accounts[0]);
|
|
437
471
|
const account = {
|
|
438
472
|
universalAddress: createUniversalAddress(finalChainId, address),
|
|
439
473
|
nativeAddress: address,
|
|
440
474
|
chainId: finalChainId,
|
|
441
|
-
chainType:
|
|
475
|
+
chainType: ChainType.EVM,
|
|
442
476
|
isActive: true
|
|
443
477
|
};
|
|
444
478
|
this.setState("connected" /* CONNECTED */);
|
|
@@ -492,6 +526,40 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
|
|
|
492
526
|
throw error;
|
|
493
527
|
}
|
|
494
528
|
}
|
|
529
|
+
/**
|
|
530
|
+
* 签名交易
|
|
531
|
+
*
|
|
532
|
+
* Note: This signs a raw transaction without sending it.
|
|
533
|
+
* The transaction can be broadcast later using the returned signature.
|
|
534
|
+
*/
|
|
535
|
+
async signTransaction(transaction) {
|
|
536
|
+
this.ensureConnected();
|
|
537
|
+
try {
|
|
538
|
+
const provider = this.getBrowserProvider();
|
|
539
|
+
const tx = {
|
|
540
|
+
from: this.currentAccount.nativeAddress,
|
|
541
|
+
to: transaction.to,
|
|
542
|
+
value: transaction.value ? `0x${BigInt(transaction.value).toString(16)}` : void 0,
|
|
543
|
+
data: transaction.data || "0x",
|
|
544
|
+
gas: transaction.gas ? `0x${BigInt(transaction.gas).toString(16)}` : void 0,
|
|
545
|
+
gasPrice: transaction.gasPrice ? `0x${BigInt(transaction.gasPrice).toString(16)}` : void 0,
|
|
546
|
+
maxFeePerGas: transaction.maxFeePerGas ? `0x${BigInt(transaction.maxFeePerGas).toString(16)}` : void 0,
|
|
547
|
+
maxPriorityFeePerGas: transaction.maxPriorityFeePerGas ? `0x${BigInt(transaction.maxPriorityFeePerGas).toString(16)}` : void 0,
|
|
548
|
+
nonce: transaction.nonce !== void 0 ? `0x${transaction.nonce.toString(16)}` : void 0,
|
|
549
|
+
chainId: transaction.chainId || this.currentAccount.chainId
|
|
550
|
+
};
|
|
551
|
+
const signature = await provider.request({
|
|
552
|
+
method: "eth_signTransaction",
|
|
553
|
+
params: [tx]
|
|
554
|
+
});
|
|
555
|
+
return signature;
|
|
556
|
+
} catch (error) {
|
|
557
|
+
if (error.code === 4001) {
|
|
558
|
+
throw new SignatureRejectedError("Transaction signature was rejected by user");
|
|
559
|
+
}
|
|
560
|
+
throw error;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
495
563
|
/**
|
|
496
564
|
* 切换链
|
|
497
565
|
*/
|
|
@@ -722,9 +790,14 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
722
790
|
constructor() {
|
|
723
791
|
super(...arguments);
|
|
724
792
|
this.type = "tronlink" /* TRONLINK */;
|
|
725
|
-
this.chainType =
|
|
793
|
+
this.chainType = ChainType.TRON;
|
|
726
794
|
this.name = "TronLink";
|
|
727
795
|
this.icon = "https://www.tronlink.org/static/logoIcon.svg";
|
|
796
|
+
/**
|
|
797
|
+
* 轮询检测账户变化(备用方案)
|
|
798
|
+
*/
|
|
799
|
+
this.pollingInterval = null;
|
|
800
|
+
this.lastKnownAddress = null;
|
|
728
801
|
/**
|
|
729
802
|
* 处理账户变化
|
|
730
803
|
*/
|
|
@@ -739,7 +812,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
739
812
|
universalAddress: createUniversalAddress(this.currentAccount.chainId, address),
|
|
740
813
|
nativeAddress: address,
|
|
741
814
|
chainId: this.currentAccount.chainId,
|
|
742
|
-
chainType:
|
|
815
|
+
chainType: ChainType.TRON,
|
|
743
816
|
isActive: true
|
|
744
817
|
};
|
|
745
818
|
this.setAccount(account);
|
|
@@ -778,7 +851,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
778
851
|
universalAddress: createUniversalAddress(tronChainId, address),
|
|
779
852
|
nativeAddress: address,
|
|
780
853
|
chainId: tronChainId,
|
|
781
|
-
chainType:
|
|
854
|
+
chainType: ChainType.TRON,
|
|
782
855
|
isActive: true
|
|
783
856
|
};
|
|
784
857
|
this.setState("connected" /* CONNECTED */);
|
|
@@ -796,20 +869,177 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
796
869
|
}
|
|
797
870
|
/**
|
|
798
871
|
* 签名消息
|
|
872
|
+
*
|
|
873
|
+
* Note: TronLink supports two signing methods:
|
|
874
|
+
* - trx.sign(): Signs a transaction object
|
|
875
|
+
* - trx.signMessageV2(): Signs a plain text message (what we use here)
|
|
799
876
|
*/
|
|
800
877
|
async signMessage(message) {
|
|
801
878
|
this.ensureConnected();
|
|
802
879
|
try {
|
|
803
880
|
const tronWeb = this.getTronWeb();
|
|
804
|
-
|
|
805
|
-
|
|
881
|
+
if (typeof tronWeb.trx.signMessageV2 === "function") {
|
|
882
|
+
const signature = await tronWeb.trx.signMessageV2(message);
|
|
883
|
+
return signature;
|
|
884
|
+
} else {
|
|
885
|
+
console.warn("[TronLink] signMessageV2 not available, falling back to sign()");
|
|
886
|
+
const signature = await tronWeb.trx.sign(message);
|
|
887
|
+
return signature;
|
|
888
|
+
}
|
|
806
889
|
} catch (error) {
|
|
807
890
|
if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
|
|
808
891
|
throw new SignatureRejectedError();
|
|
809
892
|
}
|
|
893
|
+
if (error.message?.includes("Invalid transaction")) {
|
|
894
|
+
throw new Error("Invalid message format. For transaction signing, use signTransaction() instead.");
|
|
895
|
+
}
|
|
810
896
|
throw error;
|
|
811
897
|
}
|
|
812
898
|
}
|
|
899
|
+
/**
|
|
900
|
+
* 签名交易
|
|
901
|
+
*
|
|
902
|
+
* Note: This uses trx.sign() which is specifically for signing transaction objects.
|
|
903
|
+
* For plain text message signing, use signMessage() instead.
|
|
904
|
+
*/
|
|
905
|
+
async signTransaction(transaction) {
|
|
906
|
+
this.ensureConnected();
|
|
907
|
+
try {
|
|
908
|
+
const tronWeb = this.getTronWeb();
|
|
909
|
+
const signature = await tronWeb.trx.sign(transaction);
|
|
910
|
+
return signature;
|
|
911
|
+
} catch (error) {
|
|
912
|
+
if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
|
|
913
|
+
throw new SignatureRejectedError("Transaction signature was rejected by user");
|
|
914
|
+
}
|
|
915
|
+
if (error.message?.includes("Invalid transaction")) {
|
|
916
|
+
throw new Error("Invalid transaction format. Please provide a properly formatted Tron transaction object.");
|
|
917
|
+
}
|
|
918
|
+
throw error;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
/**
|
|
922
|
+
* 读取合约
|
|
923
|
+
*/
|
|
924
|
+
async readContract(params) {
|
|
925
|
+
this.ensureConnected();
|
|
926
|
+
try {
|
|
927
|
+
const tronWeb = this.getTronWeb();
|
|
928
|
+
const contract = await tronWeb.contract(params.abi, params.address);
|
|
929
|
+
const result = await contract[params.functionName](...params.args || []).call();
|
|
930
|
+
return result;
|
|
931
|
+
} catch (error) {
|
|
932
|
+
console.error("Read contract error:", error);
|
|
933
|
+
throw new Error(`Failed to read contract: ${error.message}`);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* 写入合约
|
|
938
|
+
*/
|
|
939
|
+
async writeContract(params) {
|
|
940
|
+
this.ensureConnected();
|
|
941
|
+
try {
|
|
942
|
+
const tronWeb = this.getTronWeb();
|
|
943
|
+
console.log("[TronLink] writeContract params:", {
|
|
944
|
+
address: params.address,
|
|
945
|
+
functionName: params.functionName,
|
|
946
|
+
args: params.args,
|
|
947
|
+
value: params.value,
|
|
948
|
+
gas: params.gas
|
|
949
|
+
});
|
|
950
|
+
if (!params.args || params.args.length === 0) {
|
|
951
|
+
throw new Error("Contract function arguments are required");
|
|
952
|
+
}
|
|
953
|
+
const hasUndefined = params.args.some((arg) => arg === void 0 || arg === null);
|
|
954
|
+
if (hasUndefined) {
|
|
955
|
+
console.error("[TronLink] Invalid args detected:", params.args);
|
|
956
|
+
throw new Error(`Invalid contract arguments: some arguments are undefined or null`);
|
|
957
|
+
}
|
|
958
|
+
const functionAbi = params.abi.find(
|
|
959
|
+
(item) => item.name === params.functionName && item.type === "function"
|
|
960
|
+
);
|
|
961
|
+
if (!functionAbi) {
|
|
962
|
+
throw new Error(`Function ${params.functionName} not found in ABI`);
|
|
963
|
+
}
|
|
964
|
+
console.log("[TronLink] Function ABI:", functionAbi);
|
|
965
|
+
console.log("[TronLink] Calling with args:", params.args);
|
|
966
|
+
const options = {
|
|
967
|
+
feeLimit: params.gas || 1e8,
|
|
968
|
+
// 默认 100 TRX 的能量限制
|
|
969
|
+
callValue: params.value || 0
|
|
970
|
+
// 发送的 TRX 数量(单位:SUN)
|
|
971
|
+
};
|
|
972
|
+
const parameter = functionAbi.inputs.map((input, index) => ({
|
|
973
|
+
type: input.type,
|
|
974
|
+
value: params.args[index]
|
|
975
|
+
}));
|
|
976
|
+
console.log("[TronLink] Transaction options:", options);
|
|
977
|
+
console.log("[TronLink] Parameters:", parameter);
|
|
978
|
+
const transaction = await tronWeb.transactionBuilder.triggerSmartContract(
|
|
979
|
+
params.address,
|
|
980
|
+
params.functionName + "(" + functionAbi.inputs.map((i) => i.type).join(",") + ")",
|
|
981
|
+
options,
|
|
982
|
+
parameter,
|
|
983
|
+
this.currentAccount.nativeAddress
|
|
984
|
+
);
|
|
985
|
+
console.log("[TronLink] Transaction built:", transaction);
|
|
986
|
+
if (!transaction || !transaction.transaction) {
|
|
987
|
+
throw new Error("Failed to build transaction");
|
|
988
|
+
}
|
|
989
|
+
const signedTx = await tronWeb.trx.sign(transaction.transaction);
|
|
990
|
+
const broadcast = await tronWeb.trx.sendRawTransaction(signedTx);
|
|
991
|
+
console.log("[TronLink] Broadcast result:", broadcast);
|
|
992
|
+
if (!broadcast.result) {
|
|
993
|
+
throw new Error(broadcast.message || "Transaction broadcast failed");
|
|
994
|
+
}
|
|
995
|
+
const txHash = broadcast.txid || broadcast.transaction?.txID;
|
|
996
|
+
console.log("[TronLink] Transaction hash:", txHash);
|
|
997
|
+
return txHash || "";
|
|
998
|
+
} catch (error) {
|
|
999
|
+
console.error("Write contract error:", error);
|
|
1000
|
+
if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
|
|
1001
|
+
throw new SignatureRejectedError("Transaction was rejected by user");
|
|
1002
|
+
}
|
|
1003
|
+
throw new Error(`Failed to write contract: ${error.message}`);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* 等待交易确认
|
|
1008
|
+
*/
|
|
1009
|
+
async waitForTransaction(txHash, _confirmations = 1) {
|
|
1010
|
+
try {
|
|
1011
|
+
const tronWeb = this.getTronWeb();
|
|
1012
|
+
let attempts = 0;
|
|
1013
|
+
const maxAttempts = 60;
|
|
1014
|
+
while (attempts < maxAttempts) {
|
|
1015
|
+
try {
|
|
1016
|
+
const txInfo = await tronWeb.trx.getTransactionInfo(txHash);
|
|
1017
|
+
if (txInfo && txInfo.id) {
|
|
1018
|
+
const receipt = {
|
|
1019
|
+
transactionHash: txHash,
|
|
1020
|
+
blockNumber: txInfo.blockNumber || 0,
|
|
1021
|
+
blockHash: txInfo.blockHash || "",
|
|
1022
|
+
from: this.currentAccount.nativeAddress,
|
|
1023
|
+
to: txInfo.contract_address || "",
|
|
1024
|
+
status: txInfo.receipt?.result === "SUCCESS" ? "success" : "failed",
|
|
1025
|
+
gasUsed: (txInfo.receipt?.energy_usage_total || 0).toString(),
|
|
1026
|
+
logs: txInfo.log || []
|
|
1027
|
+
};
|
|
1028
|
+
if (receipt.status === "failed") {
|
|
1029
|
+
throw new TransactionFailedError(txHash, "Transaction failed on Tron network");
|
|
1030
|
+
}
|
|
1031
|
+
return receipt;
|
|
1032
|
+
}
|
|
1033
|
+
} catch (error) {
|
|
1034
|
+
}
|
|
1035
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
1036
|
+
attempts++;
|
|
1037
|
+
}
|
|
1038
|
+
throw new Error("Transaction confirmation timeout");
|
|
1039
|
+
} catch (error) {
|
|
1040
|
+
throw new Error(`Failed to wait for transaction: ${error.message}`);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
813
1043
|
/**
|
|
814
1044
|
* 获取 Provider
|
|
815
1045
|
*/
|
|
@@ -848,9 +1078,16 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
848
1078
|
setupEventListeners() {
|
|
849
1079
|
if (typeof window === "undefined") return;
|
|
850
1080
|
const w = window;
|
|
851
|
-
|
|
852
|
-
w.tronLink.on
|
|
853
|
-
|
|
1081
|
+
try {
|
|
1082
|
+
if (w.tronLink && typeof w.tronLink.on === "function") {
|
|
1083
|
+
w.tronLink.on("accountsChanged", this.handleAccountsChanged);
|
|
1084
|
+
w.tronLink.on("disconnect", this.handleDisconnect);
|
|
1085
|
+
} else if (w.tronWeb && w.tronWeb.eventServer) {
|
|
1086
|
+
this.startPolling();
|
|
1087
|
+
}
|
|
1088
|
+
} catch (error) {
|
|
1089
|
+
console.warn("TronLink event listener setup failed:", error);
|
|
1090
|
+
this.startPolling();
|
|
854
1091
|
}
|
|
855
1092
|
}
|
|
856
1093
|
/**
|
|
@@ -859,9 +1096,38 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
859
1096
|
removeEventListeners() {
|
|
860
1097
|
if (typeof window === "undefined") return;
|
|
861
1098
|
const w = window;
|
|
862
|
-
|
|
863
|
-
w.tronLink.off
|
|
864
|
-
|
|
1099
|
+
try {
|
|
1100
|
+
if (w.tronLink && typeof w.tronLink.off === "function") {
|
|
1101
|
+
w.tronLink.off("accountsChanged", this.handleAccountsChanged);
|
|
1102
|
+
w.tronLink.off("disconnect", this.handleDisconnect);
|
|
1103
|
+
}
|
|
1104
|
+
} catch (error) {
|
|
1105
|
+
console.warn("TronLink event listener removal failed:", error);
|
|
1106
|
+
}
|
|
1107
|
+
this.stopPolling();
|
|
1108
|
+
}
|
|
1109
|
+
startPolling() {
|
|
1110
|
+
if (this.pollingInterval) return;
|
|
1111
|
+
this.lastKnownAddress = this.currentAccount?.nativeAddress || null;
|
|
1112
|
+
this.pollingInterval = setInterval(async () => {
|
|
1113
|
+
try {
|
|
1114
|
+
const tronWeb = this.getTronWeb();
|
|
1115
|
+
const currentAddress = tronWeb.defaultAddress?.base58;
|
|
1116
|
+
if (currentAddress && currentAddress !== this.lastKnownAddress) {
|
|
1117
|
+
this.lastKnownAddress = currentAddress;
|
|
1118
|
+
this.handleAccountsChanged({ address: { base58: currentAddress } });
|
|
1119
|
+
} else if (!currentAddress && this.lastKnownAddress) {
|
|
1120
|
+
this.lastKnownAddress = null;
|
|
1121
|
+
this.handleAccountsChanged(null);
|
|
1122
|
+
}
|
|
1123
|
+
} catch (error) {
|
|
1124
|
+
}
|
|
1125
|
+
}, 2e3);
|
|
1126
|
+
}
|
|
1127
|
+
stopPolling() {
|
|
1128
|
+
if (this.pollingInterval) {
|
|
1129
|
+
clearInterval(this.pollingInterval);
|
|
1130
|
+
this.pollingInterval = null;
|
|
865
1131
|
}
|
|
866
1132
|
}
|
|
867
1133
|
};
|
|
@@ -872,7 +1138,7 @@ var EVMPrivateKeyAdapter = class extends WalletAdapter {
|
|
|
872
1138
|
constructor() {
|
|
873
1139
|
super(...arguments);
|
|
874
1140
|
this.type = "private-key" /* PRIVATE_KEY */;
|
|
875
|
-
this.chainType =
|
|
1141
|
+
this.chainType = ChainType.EVM;
|
|
876
1142
|
this.name = "Private Key (EVM)";
|
|
877
1143
|
this.privateKey = null;
|
|
878
1144
|
this.walletClient = null;
|
|
@@ -902,7 +1168,7 @@ var EVMPrivateKeyAdapter = class extends WalletAdapter {
|
|
|
902
1168
|
universalAddress: createUniversalAddress(chainId, address),
|
|
903
1169
|
nativeAddress: address,
|
|
904
1170
|
chainId,
|
|
905
|
-
chainType:
|
|
1171
|
+
chainType: ChainType.EVM,
|
|
906
1172
|
isActive: true
|
|
907
1173
|
};
|
|
908
1174
|
this.setState("connected" /* CONNECTED */);
|
|
@@ -1252,9 +1518,10 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
1252
1518
|
if (!this.primaryWallet) {
|
|
1253
1519
|
return;
|
|
1254
1520
|
}
|
|
1521
|
+
const chainType = this.primaryWallet.chainType;
|
|
1255
1522
|
await this.primaryWallet.disconnect();
|
|
1256
1523
|
this.removeAdapterListeners(this.primaryWallet);
|
|
1257
|
-
this.connectedWallets.delete(
|
|
1524
|
+
this.connectedWallets.delete(chainType);
|
|
1258
1525
|
this.primaryWallet = null;
|
|
1259
1526
|
if (this.config.enableStorage) {
|
|
1260
1527
|
this.saveToStorage();
|
|
@@ -1359,6 +1626,34 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
1359
1626
|
}
|
|
1360
1627
|
return adapter.signTypedData(typedData);
|
|
1361
1628
|
}
|
|
1629
|
+
/**
|
|
1630
|
+
* 签名交易(使用主钱包)
|
|
1631
|
+
*/
|
|
1632
|
+
async signTransaction(transaction) {
|
|
1633
|
+
if (!this.primaryWallet) {
|
|
1634
|
+
throw new WalletNotConnectedError();
|
|
1635
|
+
}
|
|
1636
|
+
if (!this.primaryWallet.signTransaction) {
|
|
1637
|
+
throw new Error(`signTransaction not supported by ${this.primaryWallet.type}`);
|
|
1638
|
+
}
|
|
1639
|
+
return this.primaryWallet.signTransaction(transaction);
|
|
1640
|
+
}
|
|
1641
|
+
/**
|
|
1642
|
+
* 使用指定链类型的钱包签名交易
|
|
1643
|
+
*/
|
|
1644
|
+
async signTransactionWithChainType(transaction, chainType) {
|
|
1645
|
+
if (!chainType) {
|
|
1646
|
+
return this.signTransaction(transaction);
|
|
1647
|
+
}
|
|
1648
|
+
const adapter = this.connectedWallets.get(chainType);
|
|
1649
|
+
if (!adapter) {
|
|
1650
|
+
throw new WalletNotConnectedError(`Wallet for chain type ${chainType}`);
|
|
1651
|
+
}
|
|
1652
|
+
if (!adapter.signTransaction) {
|
|
1653
|
+
throw new Error(`signTransaction not supported by ${adapter.type}`);
|
|
1654
|
+
}
|
|
1655
|
+
return adapter.signTransaction(transaction);
|
|
1656
|
+
}
|
|
1362
1657
|
// ===== 链切换 =====
|
|
1363
1658
|
/**
|
|
1364
1659
|
* 请求切换链(仅 EVM)
|
|
@@ -1519,6 +1814,7 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
1519
1814
|
* 移除适配器事件监听
|
|
1520
1815
|
*/
|
|
1521
1816
|
removeAdapterListeners(adapter) {
|
|
1817
|
+
if (!adapter) return;
|
|
1522
1818
|
adapter.removeAllListeners();
|
|
1523
1819
|
}
|
|
1524
1820
|
// ===== 存储 =====
|
|
@@ -1616,6 +1912,9 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
|
|
|
1616
1912
|
const signMessage = useCallback(async (message) => {
|
|
1617
1913
|
return walletManager.signMessage(message);
|
|
1618
1914
|
}, [walletManager]);
|
|
1915
|
+
const signTransaction = useCallback(async (transaction) => {
|
|
1916
|
+
return walletManager.signTransaction(transaction);
|
|
1917
|
+
}, [walletManager]);
|
|
1619
1918
|
useEffect(() => {
|
|
1620
1919
|
const handleAccountChanged = (newAccount) => {
|
|
1621
1920
|
setAccount(newAccount);
|
|
@@ -1655,7 +1954,8 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
|
|
|
1655
1954
|
connectAdditional,
|
|
1656
1955
|
disconnect,
|
|
1657
1956
|
switchPrimaryWallet,
|
|
1658
|
-
signMessage
|
|
1957
|
+
signMessage,
|
|
1958
|
+
signTransaction
|
|
1659
1959
|
};
|
|
1660
1960
|
return /* @__PURE__ */ React.createElement(WalletContext.Provider, { value }, children);
|
|
1661
1961
|
}
|
|
@@ -1764,7 +2064,31 @@ function useSignMessage() {
|
|
|
1764
2064
|
error
|
|
1765
2065
|
};
|
|
1766
2066
|
}
|
|
2067
|
+
function useSignTransaction() {
|
|
2068
|
+
const { signTransaction: contextSignTransaction } = useWallet();
|
|
2069
|
+
const [isSigning, setIsSigning] = useState(false);
|
|
2070
|
+
const [error, setError] = useState(null);
|
|
2071
|
+
const signTransaction = async (transaction) => {
|
|
2072
|
+
setIsSigning(true);
|
|
2073
|
+
setError(null);
|
|
2074
|
+
try {
|
|
2075
|
+
const signature = await contextSignTransaction(transaction);
|
|
2076
|
+
return signature;
|
|
2077
|
+
} catch (err) {
|
|
2078
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
2079
|
+
setError(error2);
|
|
2080
|
+
throw error2;
|
|
2081
|
+
} finally {
|
|
2082
|
+
setIsSigning(false);
|
|
2083
|
+
}
|
|
2084
|
+
};
|
|
2085
|
+
return {
|
|
2086
|
+
signTransaction,
|
|
2087
|
+
isSigning,
|
|
2088
|
+
error
|
|
2089
|
+
};
|
|
2090
|
+
}
|
|
1767
2091
|
|
|
1768
|
-
export { WalletProvider, useAccount, useConnect, useDisconnect, useSignMessage, useWallet };
|
|
2092
|
+
export { WalletProvider, useAccount, useConnect, useDisconnect, useSignMessage, useSignTransaction, useWallet };
|
|
1769
2093
|
//# sourceMappingURL=index.mjs.map
|
|
1770
2094
|
//# sourceMappingURL=index.mjs.map
|