@enclave-hq/wallet-sdk 1.0.0 → 1.0.2

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.
@@ -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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "tron" /* TRON */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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 = "evm" /* EVM */;
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: "evm" /* EVM */,
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: this.getViemChain(finalChainId),
441
- transport: viem.http()
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: "evm" /* EVM */,
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 && transaction.gasPrice !== "auto" ? `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
  */
@@ -579,6 +647,16 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
579
647
  throw new Error("Wallet client not initialized");
580
648
  }
581
649
  try {
650
+ console.log("\u{1F50D} [MetaMask writeContract] params.gasPrice:", params.gasPrice, "type:", typeof params.gasPrice);
651
+ let processedGasPrice;
652
+ if (!params.gasPrice) {
653
+ processedGasPrice = void 0;
654
+ } else if (params.gasPrice === "auto") {
655
+ processedGasPrice = void 0;
656
+ } else {
657
+ processedGasPrice = BigInt(params.gasPrice);
658
+ }
659
+ console.log("\u{1F50D} [MetaMask writeContract] processedGasPrice:", processedGasPrice);
582
660
  const txHash = await this.walletClient.writeContract({
583
661
  address: params.address,
584
662
  abi: params.abi,
@@ -586,7 +664,7 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
586
664
  ...params.args ? { args: params.args } : {},
587
665
  value: params.value ? BigInt(params.value) : void 0,
588
666
  gas: params.gas ? BigInt(params.gas) : void 0,
589
- gasPrice: params.gasPrice ? BigInt(params.gasPrice) : void 0
667
+ gasPrice: processedGasPrice
590
668
  });
591
669
  return txHash;
592
670
  } catch (error) {
@@ -729,9 +807,14 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
729
807
  constructor() {
730
808
  super(...arguments);
731
809
  this.type = "tronlink" /* TRONLINK */;
732
- this.chainType = "tron" /* TRON */;
810
+ this.chainType = ChainType.TRON;
733
811
  this.name = "TronLink";
734
812
  this.icon = "https://www.tronlink.org/static/logoIcon.svg";
813
+ /**
814
+ * 轮询检测账户变化(备用方案)
815
+ */
816
+ this.pollingInterval = null;
817
+ this.lastKnownAddress = null;
735
818
  /**
736
819
  * 处理账户变化
737
820
  */
@@ -746,7 +829,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
746
829
  universalAddress: createUniversalAddress(this.currentAccount.chainId, address),
747
830
  nativeAddress: address,
748
831
  chainId: this.currentAccount.chainId,
749
- chainType: "tron" /* TRON */,
832
+ chainType: ChainType.TRON,
750
833
  isActive: true
751
834
  };
752
835
  this.setAccount(account);
@@ -785,7 +868,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
785
868
  universalAddress: createUniversalAddress(tronChainId, address),
786
869
  nativeAddress: address,
787
870
  chainId: tronChainId,
788
- chainType: "tron" /* TRON */,
871
+ chainType: ChainType.TRON,
789
872
  isActive: true
790
873
  };
791
874
  this.setState("connected" /* CONNECTED */);
@@ -803,20 +886,177 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
803
886
  }
804
887
  /**
805
888
  * 签名消息
889
+ *
890
+ * Note: TronLink supports two signing methods:
891
+ * - trx.sign(): Signs a transaction object
892
+ * - trx.signMessageV2(): Signs a plain text message (what we use here)
806
893
  */
807
894
  async signMessage(message) {
808
895
  this.ensureConnected();
809
896
  try {
810
897
  const tronWeb = this.getTronWeb();
811
- const signature = await tronWeb.trx.sign(message);
812
- return signature;
898
+ if (typeof tronWeb.trx.signMessageV2 === "function") {
899
+ const signature = await tronWeb.trx.signMessageV2(message);
900
+ return signature;
901
+ } else {
902
+ console.warn("[TronLink] signMessageV2 not available, falling back to sign()");
903
+ const signature = await tronWeb.trx.sign(message);
904
+ return signature;
905
+ }
813
906
  } catch (error) {
814
907
  if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
815
908
  throw new SignatureRejectedError();
816
909
  }
910
+ if (error.message?.includes("Invalid transaction")) {
911
+ throw new Error("Invalid message format. For transaction signing, use signTransaction() instead.");
912
+ }
913
+ throw error;
914
+ }
915
+ }
916
+ /**
917
+ * 签名交易
918
+ *
919
+ * Note: This uses trx.sign() which is specifically for signing transaction objects.
920
+ * For plain text message signing, use signMessage() instead.
921
+ */
922
+ async signTransaction(transaction) {
923
+ this.ensureConnected();
924
+ try {
925
+ const tronWeb = this.getTronWeb();
926
+ const signature = await tronWeb.trx.sign(transaction);
927
+ return signature;
928
+ } catch (error) {
929
+ if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
930
+ throw new SignatureRejectedError("Transaction signature was rejected by user");
931
+ }
932
+ if (error.message?.includes("Invalid transaction")) {
933
+ throw new Error("Invalid transaction format. Please provide a properly formatted Tron transaction object.");
934
+ }
817
935
  throw error;
818
936
  }
819
937
  }
938
+ /**
939
+ * 读取合约
940
+ */
941
+ async readContract(params) {
942
+ this.ensureConnected();
943
+ try {
944
+ const tronWeb = this.getTronWeb();
945
+ const contract = await tronWeb.contract(params.abi, params.address);
946
+ const result = await contract[params.functionName](...params.args || []).call();
947
+ return result;
948
+ } catch (error) {
949
+ console.error("Read contract error:", error);
950
+ throw new Error(`Failed to read contract: ${error.message}`);
951
+ }
952
+ }
953
+ /**
954
+ * 写入合约
955
+ */
956
+ async writeContract(params) {
957
+ this.ensureConnected();
958
+ try {
959
+ const tronWeb = this.getTronWeb();
960
+ console.log("[TronLink] writeContract params:", {
961
+ address: params.address,
962
+ functionName: params.functionName,
963
+ args: params.args,
964
+ value: params.value,
965
+ gas: params.gas
966
+ });
967
+ if (!params.args || params.args.length === 0) {
968
+ throw new Error("Contract function arguments are required");
969
+ }
970
+ const hasUndefined = params.args.some((arg) => arg === void 0 || arg === null);
971
+ if (hasUndefined) {
972
+ console.error("[TronLink] Invalid args detected:", params.args);
973
+ throw new Error(`Invalid contract arguments: some arguments are undefined or null`);
974
+ }
975
+ const functionAbi = params.abi.find(
976
+ (item) => item.name === params.functionName && item.type === "function"
977
+ );
978
+ if (!functionAbi) {
979
+ throw new Error(`Function ${params.functionName} not found in ABI`);
980
+ }
981
+ console.log("[TronLink] Function ABI:", functionAbi);
982
+ console.log("[TronLink] Calling with args:", params.args);
983
+ const options = {
984
+ feeLimit: params.gas || 1e8,
985
+ // 默认 100 TRX 的能量限制
986
+ callValue: params.value || 0
987
+ // 发送的 TRX 数量(单位:SUN)
988
+ };
989
+ const parameter = functionAbi.inputs.map((input, index) => ({
990
+ type: input.type,
991
+ value: params.args[index]
992
+ }));
993
+ console.log("[TronLink] Transaction options:", options);
994
+ console.log("[TronLink] Parameters:", parameter);
995
+ const transaction = await tronWeb.transactionBuilder.triggerSmartContract(
996
+ params.address,
997
+ params.functionName + "(" + functionAbi.inputs.map((i) => i.type).join(",") + ")",
998
+ options,
999
+ parameter,
1000
+ this.currentAccount.nativeAddress
1001
+ );
1002
+ console.log("[TronLink] Transaction built:", transaction);
1003
+ if (!transaction || !transaction.transaction) {
1004
+ throw new Error("Failed to build transaction");
1005
+ }
1006
+ const signedTx = await tronWeb.trx.sign(transaction.transaction);
1007
+ const broadcast = await tronWeb.trx.sendRawTransaction(signedTx);
1008
+ console.log("[TronLink] Broadcast result:", broadcast);
1009
+ if (!broadcast.result) {
1010
+ throw new Error(broadcast.message || "Transaction broadcast failed");
1011
+ }
1012
+ const txHash = broadcast.txid || broadcast.transaction?.txID;
1013
+ console.log("[TronLink] Transaction hash:", txHash);
1014
+ return txHash || "";
1015
+ } catch (error) {
1016
+ console.error("Write contract error:", error);
1017
+ if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
1018
+ throw new SignatureRejectedError("Transaction was rejected by user");
1019
+ }
1020
+ throw new Error(`Failed to write contract: ${error.message}`);
1021
+ }
1022
+ }
1023
+ /**
1024
+ * 等待交易确认
1025
+ */
1026
+ async waitForTransaction(txHash, _confirmations = 1) {
1027
+ try {
1028
+ const tronWeb = this.getTronWeb();
1029
+ let attempts = 0;
1030
+ const maxAttempts = 60;
1031
+ while (attempts < maxAttempts) {
1032
+ try {
1033
+ const txInfo = await tronWeb.trx.getTransactionInfo(txHash);
1034
+ if (txInfo && txInfo.id) {
1035
+ const receipt = {
1036
+ transactionHash: txHash,
1037
+ blockNumber: txInfo.blockNumber || 0,
1038
+ blockHash: txInfo.blockHash || "",
1039
+ from: this.currentAccount.nativeAddress,
1040
+ to: txInfo.contract_address || "",
1041
+ status: txInfo.receipt?.result === "SUCCESS" ? "success" : "failed",
1042
+ gasUsed: (txInfo.receipt?.energy_usage_total || 0).toString(),
1043
+ logs: txInfo.log || []
1044
+ };
1045
+ if (receipt.status === "failed") {
1046
+ throw new TransactionFailedError(txHash, "Transaction failed on Tron network");
1047
+ }
1048
+ return receipt;
1049
+ }
1050
+ } catch (error) {
1051
+ }
1052
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
1053
+ attempts++;
1054
+ }
1055
+ throw new Error("Transaction confirmation timeout");
1056
+ } catch (error) {
1057
+ throw new Error(`Failed to wait for transaction: ${error.message}`);
1058
+ }
1059
+ }
820
1060
  /**
821
1061
  * 获取 Provider
822
1062
  */
@@ -855,9 +1095,16 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
855
1095
  setupEventListeners() {
856
1096
  if (typeof window === "undefined") return;
857
1097
  const w = window;
858
- if (w.tronLink) {
859
- w.tronLink.on("accountsChanged", this.handleAccountsChanged);
860
- w.tronLink.on("disconnect", this.handleDisconnect);
1098
+ try {
1099
+ if (w.tronLink && typeof w.tronLink.on === "function") {
1100
+ w.tronLink.on("accountsChanged", this.handleAccountsChanged);
1101
+ w.tronLink.on("disconnect", this.handleDisconnect);
1102
+ } else if (w.tronWeb && w.tronWeb.eventServer) {
1103
+ this.startPolling();
1104
+ }
1105
+ } catch (error) {
1106
+ console.warn("TronLink event listener setup failed:", error);
1107
+ this.startPolling();
861
1108
  }
862
1109
  }
863
1110
  /**
@@ -866,9 +1113,38 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
866
1113
  removeEventListeners() {
867
1114
  if (typeof window === "undefined") return;
868
1115
  const w = window;
869
- if (w.tronLink) {
870
- w.tronLink.off("accountsChanged", this.handleAccountsChanged);
871
- w.tronLink.off("disconnect", this.handleDisconnect);
1116
+ try {
1117
+ if (w.tronLink && typeof w.tronLink.off === "function") {
1118
+ w.tronLink.off("accountsChanged", this.handleAccountsChanged);
1119
+ w.tronLink.off("disconnect", this.handleDisconnect);
1120
+ }
1121
+ } catch (error) {
1122
+ console.warn("TronLink event listener removal failed:", error);
1123
+ }
1124
+ this.stopPolling();
1125
+ }
1126
+ startPolling() {
1127
+ if (this.pollingInterval) return;
1128
+ this.lastKnownAddress = this.currentAccount?.nativeAddress || null;
1129
+ this.pollingInterval = setInterval(async () => {
1130
+ try {
1131
+ const tronWeb = this.getTronWeb();
1132
+ const currentAddress = tronWeb.defaultAddress?.base58;
1133
+ if (currentAddress && currentAddress !== this.lastKnownAddress) {
1134
+ this.lastKnownAddress = currentAddress;
1135
+ this.handleAccountsChanged({ address: { base58: currentAddress } });
1136
+ } else if (!currentAddress && this.lastKnownAddress) {
1137
+ this.lastKnownAddress = null;
1138
+ this.handleAccountsChanged(null);
1139
+ }
1140
+ } catch (error) {
1141
+ }
1142
+ }, 2e3);
1143
+ }
1144
+ stopPolling() {
1145
+ if (this.pollingInterval) {
1146
+ clearInterval(this.pollingInterval);
1147
+ this.pollingInterval = null;
872
1148
  }
873
1149
  }
874
1150
  };
@@ -879,7 +1155,7 @@ var EVMPrivateKeyAdapter = class extends WalletAdapter {
879
1155
  constructor() {
880
1156
  super(...arguments);
881
1157
  this.type = "private-key" /* PRIVATE_KEY */;
882
- this.chainType = "evm" /* EVM */;
1158
+ this.chainType = ChainType.EVM;
883
1159
  this.name = "Private Key (EVM)";
884
1160
  this.privateKey = null;
885
1161
  this.walletClient = null;
@@ -909,7 +1185,7 @@ var EVMPrivateKeyAdapter = class extends WalletAdapter {
909
1185
  universalAddress: createUniversalAddress(chainId, address),
910
1186
  nativeAddress: address,
911
1187
  chainId,
912
- chainType: "evm" /* EVM */,
1188
+ chainType: ChainType.EVM,
913
1189
  isActive: true
914
1190
  };
915
1191
  this.setState("connected" /* CONNECTED */);
@@ -1259,9 +1535,10 @@ var WalletManager = class extends TypedEventEmitter {
1259
1535
  if (!this.primaryWallet) {
1260
1536
  return;
1261
1537
  }
1538
+ const chainType = this.primaryWallet.chainType;
1262
1539
  await this.primaryWallet.disconnect();
1263
1540
  this.removeAdapterListeners(this.primaryWallet);
1264
- this.connectedWallets.delete(this.primaryWallet.chainType);
1541
+ this.connectedWallets.delete(chainType);
1265
1542
  this.primaryWallet = null;
1266
1543
  if (this.config.enableStorage) {
1267
1544
  this.saveToStorage();
@@ -1366,6 +1643,34 @@ var WalletManager = class extends TypedEventEmitter {
1366
1643
  }
1367
1644
  return adapter.signTypedData(typedData);
1368
1645
  }
1646
+ /**
1647
+ * 签名交易(使用主钱包)
1648
+ */
1649
+ async signTransaction(transaction) {
1650
+ if (!this.primaryWallet) {
1651
+ throw new WalletNotConnectedError();
1652
+ }
1653
+ if (!this.primaryWallet.signTransaction) {
1654
+ throw new Error(`signTransaction not supported by ${this.primaryWallet.type}`);
1655
+ }
1656
+ return this.primaryWallet.signTransaction(transaction);
1657
+ }
1658
+ /**
1659
+ * 使用指定链类型的钱包签名交易
1660
+ */
1661
+ async signTransactionWithChainType(transaction, chainType) {
1662
+ if (!chainType) {
1663
+ return this.signTransaction(transaction);
1664
+ }
1665
+ const adapter = this.connectedWallets.get(chainType);
1666
+ if (!adapter) {
1667
+ throw new WalletNotConnectedError(`Wallet for chain type ${chainType}`);
1668
+ }
1669
+ if (!adapter.signTransaction) {
1670
+ throw new Error(`signTransaction not supported by ${adapter.type}`);
1671
+ }
1672
+ return adapter.signTransaction(transaction);
1673
+ }
1369
1674
  // ===== 链切换 =====
1370
1675
  /**
1371
1676
  * 请求切换链(仅 EVM)
@@ -1526,6 +1831,7 @@ var WalletManager = class extends TypedEventEmitter {
1526
1831
  * 移除适配器事件监听
1527
1832
  */
1528
1833
  removeAdapterListeners(adapter) {
1834
+ if (!adapter) return;
1529
1835
  adapter.removeAllListeners();
1530
1836
  }
1531
1837
  // ===== 存储 =====
@@ -1623,6 +1929,9 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
1623
1929
  const signMessage = React.useCallback(async (message) => {
1624
1930
  return walletManager.signMessage(message);
1625
1931
  }, [walletManager]);
1932
+ const signTransaction = React.useCallback(async (transaction) => {
1933
+ return walletManager.signTransaction(transaction);
1934
+ }, [walletManager]);
1626
1935
  React.useEffect(() => {
1627
1936
  const handleAccountChanged = (newAccount) => {
1628
1937
  setAccount(newAccount);
@@ -1662,7 +1971,8 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
1662
1971
  connectAdditional,
1663
1972
  disconnect,
1664
1973
  switchPrimaryWallet,
1665
- signMessage
1974
+ signMessage,
1975
+ signTransaction
1666
1976
  };
1667
1977
  return /* @__PURE__ */ React__default.default.createElement(WalletContext.Provider, { value }, children);
1668
1978
  }
@@ -1771,12 +2081,37 @@ function useSignMessage() {
1771
2081
  error
1772
2082
  };
1773
2083
  }
2084
+ function useSignTransaction() {
2085
+ const { signTransaction: contextSignTransaction } = useWallet();
2086
+ const [isSigning, setIsSigning] = React.useState(false);
2087
+ const [error, setError] = React.useState(null);
2088
+ const signTransaction = async (transaction) => {
2089
+ setIsSigning(true);
2090
+ setError(null);
2091
+ try {
2092
+ const signature = await contextSignTransaction(transaction);
2093
+ return signature;
2094
+ } catch (err) {
2095
+ const error2 = err instanceof Error ? err : new Error(String(err));
2096
+ setError(error2);
2097
+ throw error2;
2098
+ } finally {
2099
+ setIsSigning(false);
2100
+ }
2101
+ };
2102
+ return {
2103
+ signTransaction,
2104
+ isSigning,
2105
+ error
2106
+ };
2107
+ }
1774
2108
 
1775
2109
  exports.WalletProvider = WalletProvider;
1776
2110
  exports.useAccount = useAccount;
1777
2111
  exports.useConnect = useConnect;
1778
2112
  exports.useDisconnect = useDisconnect;
1779
2113
  exports.useSignMessage = useSignMessage;
2114
+ exports.useSignTransaction = useSignTransaction;
1780
2115
  exports.useWallet = useWallet;
1781
2116
  //# sourceMappingURL=index.js.map
1782
2117
  //# sourceMappingURL=index.js.map