@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.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
4
|
var EventEmitter = require('eventemitter3');
|
|
5
|
+
var chainUtils = require('@enclave-hq/chain-utils');
|
|
5
6
|
var viem = require('viem');
|
|
6
7
|
var accounts = require('viem/accounts');
|
|
7
8
|
|
|
@@ -39,6 +40,7 @@ var TypedEventEmitter = class {
|
|
|
39
40
|
return this;
|
|
40
41
|
}
|
|
41
42
|
};
|
|
43
|
+
var ChainType = chainUtils.ChainType;
|
|
42
44
|
|
|
43
45
|
// src/core/errors.ts
|
|
44
46
|
var WalletSDKError = class _WalletSDKError extends Error {
|
|
@@ -219,14 +221,15 @@ function formatEVMAddress(address) {
|
|
|
219
221
|
}
|
|
220
222
|
return viem.getAddress(address);
|
|
221
223
|
}
|
|
222
|
-
|
|
223
|
-
// src/utils/chain-info.ts
|
|
224
224
|
var CHAIN_INFO = {
|
|
225
225
|
// EVM Mainnet
|
|
226
226
|
1: {
|
|
227
227
|
id: 1,
|
|
228
|
+
slip44: 60,
|
|
229
|
+
// Ethereum SLIP-44
|
|
228
230
|
name: "Ethereum Mainnet",
|
|
229
|
-
chainType:
|
|
231
|
+
chainType: chainUtils.ChainType.EVM,
|
|
232
|
+
symbol: "ETH",
|
|
230
233
|
nativeCurrency: {
|
|
231
234
|
name: "Ether",
|
|
232
235
|
symbol: "ETH",
|
|
@@ -239,7 +242,8 @@ var CHAIN_INFO = {
|
|
|
239
242
|
11155111: {
|
|
240
243
|
id: 11155111,
|
|
241
244
|
name: "Sepolia Testnet",
|
|
242
|
-
chainType:
|
|
245
|
+
chainType: chainUtils.ChainType.EVM,
|
|
246
|
+
symbol: "ETH",
|
|
243
247
|
nativeCurrency: {
|
|
244
248
|
name: "Sepolia Ether",
|
|
245
249
|
symbol: "ETH",
|
|
@@ -251,8 +255,11 @@ var CHAIN_INFO = {
|
|
|
251
255
|
// Binance Smart Chain
|
|
252
256
|
56: {
|
|
253
257
|
id: 56,
|
|
258
|
+
slip44: 714,
|
|
259
|
+
// BSC SLIP-44
|
|
254
260
|
name: "BNB Smart Chain",
|
|
255
|
-
chainType:
|
|
261
|
+
chainType: chainUtils.ChainType.EVM,
|
|
262
|
+
symbol: "BNB",
|
|
256
263
|
nativeCurrency: {
|
|
257
264
|
name: "BNB",
|
|
258
265
|
symbol: "BNB",
|
|
@@ -264,7 +271,8 @@ var CHAIN_INFO = {
|
|
|
264
271
|
97: {
|
|
265
272
|
id: 97,
|
|
266
273
|
name: "BNB Smart Chain Testnet",
|
|
267
|
-
chainType:
|
|
274
|
+
chainType: chainUtils.ChainType.EVM,
|
|
275
|
+
symbol: "BNB",
|
|
268
276
|
nativeCurrency: {
|
|
269
277
|
name: "BNB",
|
|
270
278
|
symbol: "BNB",
|
|
@@ -276,8 +284,11 @@ var CHAIN_INFO = {
|
|
|
276
284
|
// Polygon
|
|
277
285
|
137: {
|
|
278
286
|
id: 137,
|
|
287
|
+
slip44: 966,
|
|
288
|
+
// Polygon SLIP-44
|
|
279
289
|
name: "Polygon Mainnet",
|
|
280
|
-
chainType:
|
|
290
|
+
chainType: chainUtils.ChainType.EVM,
|
|
291
|
+
symbol: "MATIC",
|
|
281
292
|
nativeCurrency: {
|
|
282
293
|
name: "MATIC",
|
|
283
294
|
symbol: "MATIC",
|
|
@@ -289,7 +300,8 @@ var CHAIN_INFO = {
|
|
|
289
300
|
80002: {
|
|
290
301
|
id: 80002,
|
|
291
302
|
name: "Polygon Amoy Testnet",
|
|
292
|
-
chainType:
|
|
303
|
+
chainType: chainUtils.ChainType.EVM,
|
|
304
|
+
symbol: "MATIC",
|
|
293
305
|
nativeCurrency: {
|
|
294
306
|
name: "MATIC",
|
|
295
307
|
symbol: "MATIC",
|
|
@@ -301,8 +313,11 @@ var CHAIN_INFO = {
|
|
|
301
313
|
// Tron
|
|
302
314
|
195: {
|
|
303
315
|
id: 195,
|
|
316
|
+
slip44: 195,
|
|
317
|
+
// Tron SLIP-44
|
|
304
318
|
name: "Tron Mainnet",
|
|
305
|
-
chainType:
|
|
319
|
+
chainType: chainUtils.ChainType.TRON,
|
|
320
|
+
symbol: "TRX",
|
|
306
321
|
nativeCurrency: {
|
|
307
322
|
name: "TRX",
|
|
308
323
|
symbol: "TRX",
|
|
@@ -314,8 +329,11 @@ var CHAIN_INFO = {
|
|
|
314
329
|
// Arbitrum
|
|
315
330
|
42161: {
|
|
316
331
|
id: 42161,
|
|
332
|
+
slip44: 1042161,
|
|
333
|
+
// Custom SLIP-44 (1000000 + 42161)
|
|
317
334
|
name: "Arbitrum One",
|
|
318
|
-
chainType:
|
|
335
|
+
chainType: chainUtils.ChainType.EVM,
|
|
336
|
+
symbol: "ETH",
|
|
319
337
|
nativeCurrency: {
|
|
320
338
|
name: "Ether",
|
|
321
339
|
symbol: "ETH",
|
|
@@ -327,8 +345,11 @@ var CHAIN_INFO = {
|
|
|
327
345
|
// Optimism
|
|
328
346
|
10: {
|
|
329
347
|
id: 10,
|
|
348
|
+
slip44: 1000010,
|
|
349
|
+
// Custom SLIP-44 (1000000 + 10)
|
|
330
350
|
name: "Optimism",
|
|
331
|
-
chainType:
|
|
351
|
+
chainType: chainUtils.ChainType.EVM,
|
|
352
|
+
symbol: "ETH",
|
|
332
353
|
nativeCurrency: {
|
|
333
354
|
name: "Ether",
|
|
334
355
|
symbol: "ETH",
|
|
@@ -340,8 +361,11 @@ var CHAIN_INFO = {
|
|
|
340
361
|
// Avalanche
|
|
341
362
|
43114: {
|
|
342
363
|
id: 43114,
|
|
364
|
+
slip44: 9e3,
|
|
365
|
+
// Avalanche SLIP-44
|
|
343
366
|
name: "Avalanche C-Chain",
|
|
344
|
-
chainType:
|
|
367
|
+
chainType: chainUtils.ChainType.EVM,
|
|
368
|
+
symbol: "AVAX",
|
|
345
369
|
nativeCurrency: {
|
|
346
370
|
name: "AVAX",
|
|
347
371
|
symbol: "AVAX",
|
|
@@ -360,26 +384,34 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
|
|
|
360
384
|
constructor() {
|
|
361
385
|
super(...arguments);
|
|
362
386
|
this.type = "metamask" /* METAMASK */;
|
|
363
|
-
this.chainType =
|
|
387
|
+
this.chainType = ChainType.EVM;
|
|
364
388
|
this.name = "MetaMask";
|
|
365
389
|
this.icon = "https://upload.wikimedia.org/wikipedia/commons/3/36/MetaMask_Fox.svg";
|
|
366
390
|
this.walletClient = null;
|
|
367
391
|
this.publicClient = null;
|
|
368
392
|
/**
|
|
369
393
|
* 处理账户变化
|
|
394
|
+
*
|
|
395
|
+
* 注意:MetaMask 的行为
|
|
396
|
+
* - 切换到已连接的账户:触发事件,返回新账户 ['0xNewAddress']
|
|
397
|
+
* - 切换到未连接的账户:不触发事件(用户需要手动断开和重新连接)
|
|
398
|
+
* - 锁定钱包:触发事件,返回空数组 []
|
|
370
399
|
*/
|
|
371
400
|
this.handleAccountsChanged = (accounts) => {
|
|
401
|
+
console.log("[MetaMask] accountsChanged event triggered:", accounts);
|
|
372
402
|
if (accounts.length === 0) {
|
|
403
|
+
console.log("[MetaMask] Disconnecting: wallet locked or manually disconnected");
|
|
373
404
|
this.setState("disconnected" /* DISCONNECTED */);
|
|
374
405
|
this.setAccount(null);
|
|
375
406
|
this.emitAccountChanged(null);
|
|
376
407
|
} else {
|
|
377
408
|
const address = formatEVMAddress(accounts[0]);
|
|
409
|
+
console.log("[MetaMask] Account changed to:", address);
|
|
378
410
|
const account = {
|
|
379
411
|
universalAddress: createUniversalAddress(this.currentAccount.chainId, address),
|
|
380
412
|
nativeAddress: address,
|
|
381
413
|
chainId: this.currentAccount.chainId,
|
|
382
|
-
chainType:
|
|
414
|
+
chainType: ChainType.EVM,
|
|
383
415
|
isActive: true
|
|
384
416
|
};
|
|
385
417
|
this.setAccount(account);
|
|
@@ -431,21 +463,23 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
|
|
|
431
463
|
if (chainId && chainId !== parsedChainId) {
|
|
432
464
|
await this.switchChain(chainId);
|
|
433
465
|
}
|
|
466
|
+
const finalChainId = chainId || parsedChainId;
|
|
467
|
+
const viemChain = this.getViemChain(finalChainId);
|
|
434
468
|
this.walletClient = viem.createWalletClient({
|
|
435
469
|
account: accounts[0],
|
|
470
|
+
chain: viemChain,
|
|
436
471
|
transport: viem.custom(provider)
|
|
437
472
|
});
|
|
438
|
-
const finalChainId = chainId || parsedChainId;
|
|
439
473
|
this.publicClient = viem.createPublicClient({
|
|
440
|
-
chain:
|
|
441
|
-
transport: viem.
|
|
474
|
+
chain: viemChain,
|
|
475
|
+
transport: viem.custom(provider)
|
|
442
476
|
});
|
|
443
477
|
const address = formatEVMAddress(accounts[0]);
|
|
444
478
|
const account = {
|
|
445
479
|
universalAddress: createUniversalAddress(finalChainId, address),
|
|
446
480
|
nativeAddress: address,
|
|
447
481
|
chainId: finalChainId,
|
|
448
|
-
chainType:
|
|
482
|
+
chainType: ChainType.EVM,
|
|
449
483
|
isActive: true
|
|
450
484
|
};
|
|
451
485
|
this.setState("connected" /* CONNECTED */);
|
|
@@ -499,6 +533,40 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
|
|
|
499
533
|
throw error;
|
|
500
534
|
}
|
|
501
535
|
}
|
|
536
|
+
/**
|
|
537
|
+
* 签名交易
|
|
538
|
+
*
|
|
539
|
+
* Note: This signs a raw transaction without sending it.
|
|
540
|
+
* The transaction can be broadcast later using the returned signature.
|
|
541
|
+
*/
|
|
542
|
+
async signTransaction(transaction) {
|
|
543
|
+
this.ensureConnected();
|
|
544
|
+
try {
|
|
545
|
+
const provider = this.getBrowserProvider();
|
|
546
|
+
const tx = {
|
|
547
|
+
from: this.currentAccount.nativeAddress,
|
|
548
|
+
to: transaction.to,
|
|
549
|
+
value: transaction.value ? `0x${BigInt(transaction.value).toString(16)}` : void 0,
|
|
550
|
+
data: transaction.data || "0x",
|
|
551
|
+
gas: transaction.gas ? `0x${BigInt(transaction.gas).toString(16)}` : void 0,
|
|
552
|
+
gasPrice: transaction.gasPrice ? `0x${BigInt(transaction.gasPrice).toString(16)}` : void 0,
|
|
553
|
+
maxFeePerGas: transaction.maxFeePerGas ? `0x${BigInt(transaction.maxFeePerGas).toString(16)}` : void 0,
|
|
554
|
+
maxPriorityFeePerGas: transaction.maxPriorityFeePerGas ? `0x${BigInt(transaction.maxPriorityFeePerGas).toString(16)}` : void 0,
|
|
555
|
+
nonce: transaction.nonce !== void 0 ? `0x${transaction.nonce.toString(16)}` : void 0,
|
|
556
|
+
chainId: transaction.chainId || this.currentAccount.chainId
|
|
557
|
+
};
|
|
558
|
+
const signature = await provider.request({
|
|
559
|
+
method: "eth_signTransaction",
|
|
560
|
+
params: [tx]
|
|
561
|
+
});
|
|
562
|
+
return signature;
|
|
563
|
+
} catch (error) {
|
|
564
|
+
if (error.code === 4001) {
|
|
565
|
+
throw new SignatureRejectedError("Transaction signature was rejected by user");
|
|
566
|
+
}
|
|
567
|
+
throw error;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
502
570
|
/**
|
|
503
571
|
* 切换链
|
|
504
572
|
*/
|
|
@@ -729,9 +797,14 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
729
797
|
constructor() {
|
|
730
798
|
super(...arguments);
|
|
731
799
|
this.type = "tronlink" /* TRONLINK */;
|
|
732
|
-
this.chainType =
|
|
800
|
+
this.chainType = ChainType.TRON;
|
|
733
801
|
this.name = "TronLink";
|
|
734
802
|
this.icon = "https://www.tronlink.org/static/logoIcon.svg";
|
|
803
|
+
/**
|
|
804
|
+
* 轮询检测账户变化(备用方案)
|
|
805
|
+
*/
|
|
806
|
+
this.pollingInterval = null;
|
|
807
|
+
this.lastKnownAddress = null;
|
|
735
808
|
/**
|
|
736
809
|
* 处理账户变化
|
|
737
810
|
*/
|
|
@@ -746,7 +819,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
746
819
|
universalAddress: createUniversalAddress(this.currentAccount.chainId, address),
|
|
747
820
|
nativeAddress: address,
|
|
748
821
|
chainId: this.currentAccount.chainId,
|
|
749
|
-
chainType:
|
|
822
|
+
chainType: ChainType.TRON,
|
|
750
823
|
isActive: true
|
|
751
824
|
};
|
|
752
825
|
this.setAccount(account);
|
|
@@ -785,7 +858,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
785
858
|
universalAddress: createUniversalAddress(tronChainId, address),
|
|
786
859
|
nativeAddress: address,
|
|
787
860
|
chainId: tronChainId,
|
|
788
|
-
chainType:
|
|
861
|
+
chainType: ChainType.TRON,
|
|
789
862
|
isActive: true
|
|
790
863
|
};
|
|
791
864
|
this.setState("connected" /* CONNECTED */);
|
|
@@ -803,20 +876,177 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
803
876
|
}
|
|
804
877
|
/**
|
|
805
878
|
* 签名消息
|
|
879
|
+
*
|
|
880
|
+
* Note: TronLink supports two signing methods:
|
|
881
|
+
* - trx.sign(): Signs a transaction object
|
|
882
|
+
* - trx.signMessageV2(): Signs a plain text message (what we use here)
|
|
806
883
|
*/
|
|
807
884
|
async signMessage(message) {
|
|
808
885
|
this.ensureConnected();
|
|
809
886
|
try {
|
|
810
887
|
const tronWeb = this.getTronWeb();
|
|
811
|
-
|
|
812
|
-
|
|
888
|
+
if (typeof tronWeb.trx.signMessageV2 === "function") {
|
|
889
|
+
const signature = await tronWeb.trx.signMessageV2(message);
|
|
890
|
+
return signature;
|
|
891
|
+
} else {
|
|
892
|
+
console.warn("[TronLink] signMessageV2 not available, falling back to sign()");
|
|
893
|
+
const signature = await tronWeb.trx.sign(message);
|
|
894
|
+
return signature;
|
|
895
|
+
}
|
|
813
896
|
} catch (error) {
|
|
814
897
|
if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
|
|
815
898
|
throw new SignatureRejectedError();
|
|
816
899
|
}
|
|
900
|
+
if (error.message?.includes("Invalid transaction")) {
|
|
901
|
+
throw new Error("Invalid message format. For transaction signing, use signTransaction() instead.");
|
|
902
|
+
}
|
|
817
903
|
throw error;
|
|
818
904
|
}
|
|
819
905
|
}
|
|
906
|
+
/**
|
|
907
|
+
* 签名交易
|
|
908
|
+
*
|
|
909
|
+
* Note: This uses trx.sign() which is specifically for signing transaction objects.
|
|
910
|
+
* For plain text message signing, use signMessage() instead.
|
|
911
|
+
*/
|
|
912
|
+
async signTransaction(transaction) {
|
|
913
|
+
this.ensureConnected();
|
|
914
|
+
try {
|
|
915
|
+
const tronWeb = this.getTronWeb();
|
|
916
|
+
const signature = await tronWeb.trx.sign(transaction);
|
|
917
|
+
return signature;
|
|
918
|
+
} catch (error) {
|
|
919
|
+
if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
|
|
920
|
+
throw new SignatureRejectedError("Transaction signature was rejected by user");
|
|
921
|
+
}
|
|
922
|
+
if (error.message?.includes("Invalid transaction")) {
|
|
923
|
+
throw new Error("Invalid transaction format. Please provide a properly formatted Tron transaction object.");
|
|
924
|
+
}
|
|
925
|
+
throw error;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* 读取合约
|
|
930
|
+
*/
|
|
931
|
+
async readContract(params) {
|
|
932
|
+
this.ensureConnected();
|
|
933
|
+
try {
|
|
934
|
+
const tronWeb = this.getTronWeb();
|
|
935
|
+
const contract = await tronWeb.contract(params.abi, params.address);
|
|
936
|
+
const result = await contract[params.functionName](...params.args || []).call();
|
|
937
|
+
return result;
|
|
938
|
+
} catch (error) {
|
|
939
|
+
console.error("Read contract error:", error);
|
|
940
|
+
throw new Error(`Failed to read contract: ${error.message}`);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* 写入合约
|
|
945
|
+
*/
|
|
946
|
+
async writeContract(params) {
|
|
947
|
+
this.ensureConnected();
|
|
948
|
+
try {
|
|
949
|
+
const tronWeb = this.getTronWeb();
|
|
950
|
+
console.log("[TronLink] writeContract params:", {
|
|
951
|
+
address: params.address,
|
|
952
|
+
functionName: params.functionName,
|
|
953
|
+
args: params.args,
|
|
954
|
+
value: params.value,
|
|
955
|
+
gas: params.gas
|
|
956
|
+
});
|
|
957
|
+
if (!params.args || params.args.length === 0) {
|
|
958
|
+
throw new Error("Contract function arguments are required");
|
|
959
|
+
}
|
|
960
|
+
const hasUndefined = params.args.some((arg) => arg === void 0 || arg === null);
|
|
961
|
+
if (hasUndefined) {
|
|
962
|
+
console.error("[TronLink] Invalid args detected:", params.args);
|
|
963
|
+
throw new Error(`Invalid contract arguments: some arguments are undefined or null`);
|
|
964
|
+
}
|
|
965
|
+
const functionAbi = params.abi.find(
|
|
966
|
+
(item) => item.name === params.functionName && item.type === "function"
|
|
967
|
+
);
|
|
968
|
+
if (!functionAbi) {
|
|
969
|
+
throw new Error(`Function ${params.functionName} not found in ABI`);
|
|
970
|
+
}
|
|
971
|
+
console.log("[TronLink] Function ABI:", functionAbi);
|
|
972
|
+
console.log("[TronLink] Calling with args:", params.args);
|
|
973
|
+
const options = {
|
|
974
|
+
feeLimit: params.gas || 1e8,
|
|
975
|
+
// 默认 100 TRX 的能量限制
|
|
976
|
+
callValue: params.value || 0
|
|
977
|
+
// 发送的 TRX 数量(单位:SUN)
|
|
978
|
+
};
|
|
979
|
+
const parameter = functionAbi.inputs.map((input, index) => ({
|
|
980
|
+
type: input.type,
|
|
981
|
+
value: params.args[index]
|
|
982
|
+
}));
|
|
983
|
+
console.log("[TronLink] Transaction options:", options);
|
|
984
|
+
console.log("[TronLink] Parameters:", parameter);
|
|
985
|
+
const transaction = await tronWeb.transactionBuilder.triggerSmartContract(
|
|
986
|
+
params.address,
|
|
987
|
+
params.functionName + "(" + functionAbi.inputs.map((i) => i.type).join(",") + ")",
|
|
988
|
+
options,
|
|
989
|
+
parameter,
|
|
990
|
+
this.currentAccount.nativeAddress
|
|
991
|
+
);
|
|
992
|
+
console.log("[TronLink] Transaction built:", transaction);
|
|
993
|
+
if (!transaction || !transaction.transaction) {
|
|
994
|
+
throw new Error("Failed to build transaction");
|
|
995
|
+
}
|
|
996
|
+
const signedTx = await tronWeb.trx.sign(transaction.transaction);
|
|
997
|
+
const broadcast = await tronWeb.trx.sendRawTransaction(signedTx);
|
|
998
|
+
console.log("[TronLink] Broadcast result:", broadcast);
|
|
999
|
+
if (!broadcast.result) {
|
|
1000
|
+
throw new Error(broadcast.message || "Transaction broadcast failed");
|
|
1001
|
+
}
|
|
1002
|
+
const txHash = broadcast.txid || broadcast.transaction?.txID;
|
|
1003
|
+
console.log("[TronLink] Transaction hash:", txHash);
|
|
1004
|
+
return txHash || "";
|
|
1005
|
+
} catch (error) {
|
|
1006
|
+
console.error("Write contract error:", error);
|
|
1007
|
+
if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
|
|
1008
|
+
throw new SignatureRejectedError("Transaction was rejected by user");
|
|
1009
|
+
}
|
|
1010
|
+
throw new Error(`Failed to write contract: ${error.message}`);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* 等待交易确认
|
|
1015
|
+
*/
|
|
1016
|
+
async waitForTransaction(txHash, _confirmations = 1) {
|
|
1017
|
+
try {
|
|
1018
|
+
const tronWeb = this.getTronWeb();
|
|
1019
|
+
let attempts = 0;
|
|
1020
|
+
const maxAttempts = 60;
|
|
1021
|
+
while (attempts < maxAttempts) {
|
|
1022
|
+
try {
|
|
1023
|
+
const txInfo = await tronWeb.trx.getTransactionInfo(txHash);
|
|
1024
|
+
if (txInfo && txInfo.id) {
|
|
1025
|
+
const receipt = {
|
|
1026
|
+
transactionHash: txHash,
|
|
1027
|
+
blockNumber: txInfo.blockNumber || 0,
|
|
1028
|
+
blockHash: txInfo.blockHash || "",
|
|
1029
|
+
from: this.currentAccount.nativeAddress,
|
|
1030
|
+
to: txInfo.contract_address || "",
|
|
1031
|
+
status: txInfo.receipt?.result === "SUCCESS" ? "success" : "failed",
|
|
1032
|
+
gasUsed: (txInfo.receipt?.energy_usage_total || 0).toString(),
|
|
1033
|
+
logs: txInfo.log || []
|
|
1034
|
+
};
|
|
1035
|
+
if (receipt.status === "failed") {
|
|
1036
|
+
throw new TransactionFailedError(txHash, "Transaction failed on Tron network");
|
|
1037
|
+
}
|
|
1038
|
+
return receipt;
|
|
1039
|
+
}
|
|
1040
|
+
} catch (error) {
|
|
1041
|
+
}
|
|
1042
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
1043
|
+
attempts++;
|
|
1044
|
+
}
|
|
1045
|
+
throw new Error("Transaction confirmation timeout");
|
|
1046
|
+
} catch (error) {
|
|
1047
|
+
throw new Error(`Failed to wait for transaction: ${error.message}`);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
820
1050
|
/**
|
|
821
1051
|
* 获取 Provider
|
|
822
1052
|
*/
|
|
@@ -855,9 +1085,16 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
855
1085
|
setupEventListeners() {
|
|
856
1086
|
if (typeof window === "undefined") return;
|
|
857
1087
|
const w = window;
|
|
858
|
-
|
|
859
|
-
w.tronLink.on
|
|
860
|
-
|
|
1088
|
+
try {
|
|
1089
|
+
if (w.tronLink && typeof w.tronLink.on === "function") {
|
|
1090
|
+
w.tronLink.on("accountsChanged", this.handleAccountsChanged);
|
|
1091
|
+
w.tronLink.on("disconnect", this.handleDisconnect);
|
|
1092
|
+
} else if (w.tronWeb && w.tronWeb.eventServer) {
|
|
1093
|
+
this.startPolling();
|
|
1094
|
+
}
|
|
1095
|
+
} catch (error) {
|
|
1096
|
+
console.warn("TronLink event listener setup failed:", error);
|
|
1097
|
+
this.startPolling();
|
|
861
1098
|
}
|
|
862
1099
|
}
|
|
863
1100
|
/**
|
|
@@ -866,9 +1103,38 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
|
|
|
866
1103
|
removeEventListeners() {
|
|
867
1104
|
if (typeof window === "undefined") return;
|
|
868
1105
|
const w = window;
|
|
869
|
-
|
|
870
|
-
w.tronLink.off
|
|
871
|
-
|
|
1106
|
+
try {
|
|
1107
|
+
if (w.tronLink && typeof w.tronLink.off === "function") {
|
|
1108
|
+
w.tronLink.off("accountsChanged", this.handleAccountsChanged);
|
|
1109
|
+
w.tronLink.off("disconnect", this.handleDisconnect);
|
|
1110
|
+
}
|
|
1111
|
+
} catch (error) {
|
|
1112
|
+
console.warn("TronLink event listener removal failed:", error);
|
|
1113
|
+
}
|
|
1114
|
+
this.stopPolling();
|
|
1115
|
+
}
|
|
1116
|
+
startPolling() {
|
|
1117
|
+
if (this.pollingInterval) return;
|
|
1118
|
+
this.lastKnownAddress = this.currentAccount?.nativeAddress || null;
|
|
1119
|
+
this.pollingInterval = setInterval(async () => {
|
|
1120
|
+
try {
|
|
1121
|
+
const tronWeb = this.getTronWeb();
|
|
1122
|
+
const currentAddress = tronWeb.defaultAddress?.base58;
|
|
1123
|
+
if (currentAddress && currentAddress !== this.lastKnownAddress) {
|
|
1124
|
+
this.lastKnownAddress = currentAddress;
|
|
1125
|
+
this.handleAccountsChanged({ address: { base58: currentAddress } });
|
|
1126
|
+
} else if (!currentAddress && this.lastKnownAddress) {
|
|
1127
|
+
this.lastKnownAddress = null;
|
|
1128
|
+
this.handleAccountsChanged(null);
|
|
1129
|
+
}
|
|
1130
|
+
} catch (error) {
|
|
1131
|
+
}
|
|
1132
|
+
}, 2e3);
|
|
1133
|
+
}
|
|
1134
|
+
stopPolling() {
|
|
1135
|
+
if (this.pollingInterval) {
|
|
1136
|
+
clearInterval(this.pollingInterval);
|
|
1137
|
+
this.pollingInterval = null;
|
|
872
1138
|
}
|
|
873
1139
|
}
|
|
874
1140
|
};
|
|
@@ -879,7 +1145,7 @@ var EVMPrivateKeyAdapter = class extends WalletAdapter {
|
|
|
879
1145
|
constructor() {
|
|
880
1146
|
super(...arguments);
|
|
881
1147
|
this.type = "private-key" /* PRIVATE_KEY */;
|
|
882
|
-
this.chainType =
|
|
1148
|
+
this.chainType = ChainType.EVM;
|
|
883
1149
|
this.name = "Private Key (EVM)";
|
|
884
1150
|
this.privateKey = null;
|
|
885
1151
|
this.walletClient = null;
|
|
@@ -909,7 +1175,7 @@ var EVMPrivateKeyAdapter = class extends WalletAdapter {
|
|
|
909
1175
|
universalAddress: createUniversalAddress(chainId, address),
|
|
910
1176
|
nativeAddress: address,
|
|
911
1177
|
chainId,
|
|
912
|
-
chainType:
|
|
1178
|
+
chainType: ChainType.EVM,
|
|
913
1179
|
isActive: true
|
|
914
1180
|
};
|
|
915
1181
|
this.setState("connected" /* CONNECTED */);
|
|
@@ -1259,9 +1525,10 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
1259
1525
|
if (!this.primaryWallet) {
|
|
1260
1526
|
return;
|
|
1261
1527
|
}
|
|
1528
|
+
const chainType = this.primaryWallet.chainType;
|
|
1262
1529
|
await this.primaryWallet.disconnect();
|
|
1263
1530
|
this.removeAdapterListeners(this.primaryWallet);
|
|
1264
|
-
this.connectedWallets.delete(
|
|
1531
|
+
this.connectedWallets.delete(chainType);
|
|
1265
1532
|
this.primaryWallet = null;
|
|
1266
1533
|
if (this.config.enableStorage) {
|
|
1267
1534
|
this.saveToStorage();
|
|
@@ -1366,6 +1633,34 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
1366
1633
|
}
|
|
1367
1634
|
return adapter.signTypedData(typedData);
|
|
1368
1635
|
}
|
|
1636
|
+
/**
|
|
1637
|
+
* 签名交易(使用主钱包)
|
|
1638
|
+
*/
|
|
1639
|
+
async signTransaction(transaction) {
|
|
1640
|
+
if (!this.primaryWallet) {
|
|
1641
|
+
throw new WalletNotConnectedError();
|
|
1642
|
+
}
|
|
1643
|
+
if (!this.primaryWallet.signTransaction) {
|
|
1644
|
+
throw new Error(`signTransaction not supported by ${this.primaryWallet.type}`);
|
|
1645
|
+
}
|
|
1646
|
+
return this.primaryWallet.signTransaction(transaction);
|
|
1647
|
+
}
|
|
1648
|
+
/**
|
|
1649
|
+
* 使用指定链类型的钱包签名交易
|
|
1650
|
+
*/
|
|
1651
|
+
async signTransactionWithChainType(transaction, chainType) {
|
|
1652
|
+
if (!chainType) {
|
|
1653
|
+
return this.signTransaction(transaction);
|
|
1654
|
+
}
|
|
1655
|
+
const adapter = this.connectedWallets.get(chainType);
|
|
1656
|
+
if (!adapter) {
|
|
1657
|
+
throw new WalletNotConnectedError(`Wallet for chain type ${chainType}`);
|
|
1658
|
+
}
|
|
1659
|
+
if (!adapter.signTransaction) {
|
|
1660
|
+
throw new Error(`signTransaction not supported by ${adapter.type}`);
|
|
1661
|
+
}
|
|
1662
|
+
return adapter.signTransaction(transaction);
|
|
1663
|
+
}
|
|
1369
1664
|
// ===== 链切换 =====
|
|
1370
1665
|
/**
|
|
1371
1666
|
* 请求切换链(仅 EVM)
|
|
@@ -1526,6 +1821,7 @@ var WalletManager = class extends TypedEventEmitter {
|
|
|
1526
1821
|
* 移除适配器事件监听
|
|
1527
1822
|
*/
|
|
1528
1823
|
removeAdapterListeners(adapter) {
|
|
1824
|
+
if (!adapter) return;
|
|
1529
1825
|
adapter.removeAllListeners();
|
|
1530
1826
|
}
|
|
1531
1827
|
// ===== 存储 =====
|
|
@@ -1623,6 +1919,9 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
|
|
|
1623
1919
|
const signMessage = React.useCallback(async (message) => {
|
|
1624
1920
|
return walletManager.signMessage(message);
|
|
1625
1921
|
}, [walletManager]);
|
|
1922
|
+
const signTransaction = React.useCallback(async (transaction) => {
|
|
1923
|
+
return walletManager.signTransaction(transaction);
|
|
1924
|
+
}, [walletManager]);
|
|
1626
1925
|
React.useEffect(() => {
|
|
1627
1926
|
const handleAccountChanged = (newAccount) => {
|
|
1628
1927
|
setAccount(newAccount);
|
|
@@ -1662,7 +1961,8 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
|
|
|
1662
1961
|
connectAdditional,
|
|
1663
1962
|
disconnect,
|
|
1664
1963
|
switchPrimaryWallet,
|
|
1665
|
-
signMessage
|
|
1964
|
+
signMessage,
|
|
1965
|
+
signTransaction
|
|
1666
1966
|
};
|
|
1667
1967
|
return /* @__PURE__ */ React__default.default.createElement(WalletContext.Provider, { value }, children);
|
|
1668
1968
|
}
|
|
@@ -1771,12 +2071,37 @@ function useSignMessage() {
|
|
|
1771
2071
|
error
|
|
1772
2072
|
};
|
|
1773
2073
|
}
|
|
2074
|
+
function useSignTransaction() {
|
|
2075
|
+
const { signTransaction: contextSignTransaction } = useWallet();
|
|
2076
|
+
const [isSigning, setIsSigning] = React.useState(false);
|
|
2077
|
+
const [error, setError] = React.useState(null);
|
|
2078
|
+
const signTransaction = async (transaction) => {
|
|
2079
|
+
setIsSigning(true);
|
|
2080
|
+
setError(null);
|
|
2081
|
+
try {
|
|
2082
|
+
const signature = await contextSignTransaction(transaction);
|
|
2083
|
+
return signature;
|
|
2084
|
+
} catch (err) {
|
|
2085
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
2086
|
+
setError(error2);
|
|
2087
|
+
throw error2;
|
|
2088
|
+
} finally {
|
|
2089
|
+
setIsSigning(false);
|
|
2090
|
+
}
|
|
2091
|
+
};
|
|
2092
|
+
return {
|
|
2093
|
+
signTransaction,
|
|
2094
|
+
isSigning,
|
|
2095
|
+
error
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
1774
2098
|
|
|
1775
2099
|
exports.WalletProvider = WalletProvider;
|
|
1776
2100
|
exports.useAccount = useAccount;
|
|
1777
2101
|
exports.useConnect = useConnect;
|
|
1778
2102
|
exports.useDisconnect = useDisconnect;
|
|
1779
2103
|
exports.useSignMessage = useSignMessage;
|
|
2104
|
+
exports.useSignTransaction = useSignTransaction;
|
|
1780
2105
|
exports.useWallet = useWallet;
|
|
1781
2106
|
//# sourceMappingURL=index.js.map
|
|
1782
2107
|
//# sourceMappingURL=index.js.map
|