@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.
@@ -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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "tron" /* TRON */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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: "evm" /* EVM */,
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 = "evm" /* EVM */;
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: "evm" /* EVM */,
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: this.getViemChain(finalChainId),
434
- transport: http()
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: "evm" /* EVM */,
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 && transaction.gasPrice !== "auto" ? `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
  */
@@ -572,6 +640,16 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
572
640
  throw new Error("Wallet client not initialized");
573
641
  }
574
642
  try {
643
+ console.log("\u{1F50D} [MetaMask writeContract] params.gasPrice:", params.gasPrice, "type:", typeof params.gasPrice);
644
+ let processedGasPrice;
645
+ if (!params.gasPrice) {
646
+ processedGasPrice = void 0;
647
+ } else if (params.gasPrice === "auto") {
648
+ processedGasPrice = void 0;
649
+ } else {
650
+ processedGasPrice = BigInt(params.gasPrice);
651
+ }
652
+ console.log("\u{1F50D} [MetaMask writeContract] processedGasPrice:", processedGasPrice);
575
653
  const txHash = await this.walletClient.writeContract({
576
654
  address: params.address,
577
655
  abi: params.abi,
@@ -579,7 +657,7 @@ var MetaMaskAdapter = class extends BrowserWalletAdapter {
579
657
  ...params.args ? { args: params.args } : {},
580
658
  value: params.value ? BigInt(params.value) : void 0,
581
659
  gas: params.gas ? BigInt(params.gas) : void 0,
582
- gasPrice: params.gasPrice ? BigInt(params.gasPrice) : void 0
660
+ gasPrice: processedGasPrice
583
661
  });
584
662
  return txHash;
585
663
  } catch (error) {
@@ -722,9 +800,14 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
722
800
  constructor() {
723
801
  super(...arguments);
724
802
  this.type = "tronlink" /* TRONLINK */;
725
- this.chainType = "tron" /* TRON */;
803
+ this.chainType = ChainType.TRON;
726
804
  this.name = "TronLink";
727
805
  this.icon = "https://www.tronlink.org/static/logoIcon.svg";
806
+ /**
807
+ * 轮询检测账户变化(备用方案)
808
+ */
809
+ this.pollingInterval = null;
810
+ this.lastKnownAddress = null;
728
811
  /**
729
812
  * 处理账户变化
730
813
  */
@@ -739,7 +822,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
739
822
  universalAddress: createUniversalAddress(this.currentAccount.chainId, address),
740
823
  nativeAddress: address,
741
824
  chainId: this.currentAccount.chainId,
742
- chainType: "tron" /* TRON */,
825
+ chainType: ChainType.TRON,
743
826
  isActive: true
744
827
  };
745
828
  this.setAccount(account);
@@ -778,7 +861,7 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
778
861
  universalAddress: createUniversalAddress(tronChainId, address),
779
862
  nativeAddress: address,
780
863
  chainId: tronChainId,
781
- chainType: "tron" /* TRON */,
864
+ chainType: ChainType.TRON,
782
865
  isActive: true
783
866
  };
784
867
  this.setState("connected" /* CONNECTED */);
@@ -796,20 +879,177 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
796
879
  }
797
880
  /**
798
881
  * 签名消息
882
+ *
883
+ * Note: TronLink supports two signing methods:
884
+ * - trx.sign(): Signs a transaction object
885
+ * - trx.signMessageV2(): Signs a plain text message (what we use here)
799
886
  */
800
887
  async signMessage(message) {
801
888
  this.ensureConnected();
802
889
  try {
803
890
  const tronWeb = this.getTronWeb();
804
- const signature = await tronWeb.trx.sign(message);
805
- return signature;
891
+ if (typeof tronWeb.trx.signMessageV2 === "function") {
892
+ const signature = await tronWeb.trx.signMessageV2(message);
893
+ return signature;
894
+ } else {
895
+ console.warn("[TronLink] signMessageV2 not available, falling back to sign()");
896
+ const signature = await tronWeb.trx.sign(message);
897
+ return signature;
898
+ }
806
899
  } catch (error) {
807
900
  if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
808
901
  throw new SignatureRejectedError();
809
902
  }
903
+ if (error.message?.includes("Invalid transaction")) {
904
+ throw new Error("Invalid message format. For transaction signing, use signTransaction() instead.");
905
+ }
906
+ throw error;
907
+ }
908
+ }
909
+ /**
910
+ * 签名交易
911
+ *
912
+ * Note: This uses trx.sign() which is specifically for signing transaction objects.
913
+ * For plain text message signing, use signMessage() instead.
914
+ */
915
+ async signTransaction(transaction) {
916
+ this.ensureConnected();
917
+ try {
918
+ const tronWeb = this.getTronWeb();
919
+ const signature = await tronWeb.trx.sign(transaction);
920
+ return signature;
921
+ } catch (error) {
922
+ if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
923
+ throw new SignatureRejectedError("Transaction signature was rejected by user");
924
+ }
925
+ if (error.message?.includes("Invalid transaction")) {
926
+ throw new Error("Invalid transaction format. Please provide a properly formatted Tron transaction object.");
927
+ }
810
928
  throw error;
811
929
  }
812
930
  }
931
+ /**
932
+ * 读取合约
933
+ */
934
+ async readContract(params) {
935
+ this.ensureConnected();
936
+ try {
937
+ const tronWeb = this.getTronWeb();
938
+ const contract = await tronWeb.contract(params.abi, params.address);
939
+ const result = await contract[params.functionName](...params.args || []).call();
940
+ return result;
941
+ } catch (error) {
942
+ console.error("Read contract error:", error);
943
+ throw new Error(`Failed to read contract: ${error.message}`);
944
+ }
945
+ }
946
+ /**
947
+ * 写入合约
948
+ */
949
+ async writeContract(params) {
950
+ this.ensureConnected();
951
+ try {
952
+ const tronWeb = this.getTronWeb();
953
+ console.log("[TronLink] writeContract params:", {
954
+ address: params.address,
955
+ functionName: params.functionName,
956
+ args: params.args,
957
+ value: params.value,
958
+ gas: params.gas
959
+ });
960
+ if (!params.args || params.args.length === 0) {
961
+ throw new Error("Contract function arguments are required");
962
+ }
963
+ const hasUndefined = params.args.some((arg) => arg === void 0 || arg === null);
964
+ if (hasUndefined) {
965
+ console.error("[TronLink] Invalid args detected:", params.args);
966
+ throw new Error(`Invalid contract arguments: some arguments are undefined or null`);
967
+ }
968
+ const functionAbi = params.abi.find(
969
+ (item) => item.name === params.functionName && item.type === "function"
970
+ );
971
+ if (!functionAbi) {
972
+ throw new Error(`Function ${params.functionName} not found in ABI`);
973
+ }
974
+ console.log("[TronLink] Function ABI:", functionAbi);
975
+ console.log("[TronLink] Calling with args:", params.args);
976
+ const options = {
977
+ feeLimit: params.gas || 1e8,
978
+ // 默认 100 TRX 的能量限制
979
+ callValue: params.value || 0
980
+ // 发送的 TRX 数量(单位:SUN)
981
+ };
982
+ const parameter = functionAbi.inputs.map((input, index) => ({
983
+ type: input.type,
984
+ value: params.args[index]
985
+ }));
986
+ console.log("[TronLink] Transaction options:", options);
987
+ console.log("[TronLink] Parameters:", parameter);
988
+ const transaction = await tronWeb.transactionBuilder.triggerSmartContract(
989
+ params.address,
990
+ params.functionName + "(" + functionAbi.inputs.map((i) => i.type).join(",") + ")",
991
+ options,
992
+ parameter,
993
+ this.currentAccount.nativeAddress
994
+ );
995
+ console.log("[TronLink] Transaction built:", transaction);
996
+ if (!transaction || !transaction.transaction) {
997
+ throw new Error("Failed to build transaction");
998
+ }
999
+ const signedTx = await tronWeb.trx.sign(transaction.transaction);
1000
+ const broadcast = await tronWeb.trx.sendRawTransaction(signedTx);
1001
+ console.log("[TronLink] Broadcast result:", broadcast);
1002
+ if (!broadcast.result) {
1003
+ throw new Error(broadcast.message || "Transaction broadcast failed");
1004
+ }
1005
+ const txHash = broadcast.txid || broadcast.transaction?.txID;
1006
+ console.log("[TronLink] Transaction hash:", txHash);
1007
+ return txHash || "";
1008
+ } catch (error) {
1009
+ console.error("Write contract error:", error);
1010
+ if (error.message?.includes("User rejected") || error.message?.includes("Confirmation declined")) {
1011
+ throw new SignatureRejectedError("Transaction was rejected by user");
1012
+ }
1013
+ throw new Error(`Failed to write contract: ${error.message}`);
1014
+ }
1015
+ }
1016
+ /**
1017
+ * 等待交易确认
1018
+ */
1019
+ async waitForTransaction(txHash, _confirmations = 1) {
1020
+ try {
1021
+ const tronWeb = this.getTronWeb();
1022
+ let attempts = 0;
1023
+ const maxAttempts = 60;
1024
+ while (attempts < maxAttempts) {
1025
+ try {
1026
+ const txInfo = await tronWeb.trx.getTransactionInfo(txHash);
1027
+ if (txInfo && txInfo.id) {
1028
+ const receipt = {
1029
+ transactionHash: txHash,
1030
+ blockNumber: txInfo.blockNumber || 0,
1031
+ blockHash: txInfo.blockHash || "",
1032
+ from: this.currentAccount.nativeAddress,
1033
+ to: txInfo.contract_address || "",
1034
+ status: txInfo.receipt?.result === "SUCCESS" ? "success" : "failed",
1035
+ gasUsed: (txInfo.receipt?.energy_usage_total || 0).toString(),
1036
+ logs: txInfo.log || []
1037
+ };
1038
+ if (receipt.status === "failed") {
1039
+ throw new TransactionFailedError(txHash, "Transaction failed on Tron network");
1040
+ }
1041
+ return receipt;
1042
+ }
1043
+ } catch (error) {
1044
+ }
1045
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
1046
+ attempts++;
1047
+ }
1048
+ throw new Error("Transaction confirmation timeout");
1049
+ } catch (error) {
1050
+ throw new Error(`Failed to wait for transaction: ${error.message}`);
1051
+ }
1052
+ }
813
1053
  /**
814
1054
  * 获取 Provider
815
1055
  */
@@ -848,9 +1088,16 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
848
1088
  setupEventListeners() {
849
1089
  if (typeof window === "undefined") return;
850
1090
  const w = window;
851
- if (w.tronLink) {
852
- w.tronLink.on("accountsChanged", this.handleAccountsChanged);
853
- w.tronLink.on("disconnect", this.handleDisconnect);
1091
+ try {
1092
+ if (w.tronLink && typeof w.tronLink.on === "function") {
1093
+ w.tronLink.on("accountsChanged", this.handleAccountsChanged);
1094
+ w.tronLink.on("disconnect", this.handleDisconnect);
1095
+ } else if (w.tronWeb && w.tronWeb.eventServer) {
1096
+ this.startPolling();
1097
+ }
1098
+ } catch (error) {
1099
+ console.warn("TronLink event listener setup failed:", error);
1100
+ this.startPolling();
854
1101
  }
855
1102
  }
856
1103
  /**
@@ -859,9 +1106,38 @@ var _TronLinkAdapter = class _TronLinkAdapter extends BrowserWalletAdapter {
859
1106
  removeEventListeners() {
860
1107
  if (typeof window === "undefined") return;
861
1108
  const w = window;
862
- if (w.tronLink) {
863
- w.tronLink.off("accountsChanged", this.handleAccountsChanged);
864
- w.tronLink.off("disconnect", this.handleDisconnect);
1109
+ try {
1110
+ if (w.tronLink && typeof w.tronLink.off === "function") {
1111
+ w.tronLink.off("accountsChanged", this.handleAccountsChanged);
1112
+ w.tronLink.off("disconnect", this.handleDisconnect);
1113
+ }
1114
+ } catch (error) {
1115
+ console.warn("TronLink event listener removal failed:", error);
1116
+ }
1117
+ this.stopPolling();
1118
+ }
1119
+ startPolling() {
1120
+ if (this.pollingInterval) return;
1121
+ this.lastKnownAddress = this.currentAccount?.nativeAddress || null;
1122
+ this.pollingInterval = setInterval(async () => {
1123
+ try {
1124
+ const tronWeb = this.getTronWeb();
1125
+ const currentAddress = tronWeb.defaultAddress?.base58;
1126
+ if (currentAddress && currentAddress !== this.lastKnownAddress) {
1127
+ this.lastKnownAddress = currentAddress;
1128
+ this.handleAccountsChanged({ address: { base58: currentAddress } });
1129
+ } else if (!currentAddress && this.lastKnownAddress) {
1130
+ this.lastKnownAddress = null;
1131
+ this.handleAccountsChanged(null);
1132
+ }
1133
+ } catch (error) {
1134
+ }
1135
+ }, 2e3);
1136
+ }
1137
+ stopPolling() {
1138
+ if (this.pollingInterval) {
1139
+ clearInterval(this.pollingInterval);
1140
+ this.pollingInterval = null;
865
1141
  }
866
1142
  }
867
1143
  };
@@ -872,7 +1148,7 @@ var EVMPrivateKeyAdapter = class extends WalletAdapter {
872
1148
  constructor() {
873
1149
  super(...arguments);
874
1150
  this.type = "private-key" /* PRIVATE_KEY */;
875
- this.chainType = "evm" /* EVM */;
1151
+ this.chainType = ChainType.EVM;
876
1152
  this.name = "Private Key (EVM)";
877
1153
  this.privateKey = null;
878
1154
  this.walletClient = null;
@@ -902,7 +1178,7 @@ var EVMPrivateKeyAdapter = class extends WalletAdapter {
902
1178
  universalAddress: createUniversalAddress(chainId, address),
903
1179
  nativeAddress: address,
904
1180
  chainId,
905
- chainType: "evm" /* EVM */,
1181
+ chainType: ChainType.EVM,
906
1182
  isActive: true
907
1183
  };
908
1184
  this.setState("connected" /* CONNECTED */);
@@ -1252,9 +1528,10 @@ var WalletManager = class extends TypedEventEmitter {
1252
1528
  if (!this.primaryWallet) {
1253
1529
  return;
1254
1530
  }
1531
+ const chainType = this.primaryWallet.chainType;
1255
1532
  await this.primaryWallet.disconnect();
1256
1533
  this.removeAdapterListeners(this.primaryWallet);
1257
- this.connectedWallets.delete(this.primaryWallet.chainType);
1534
+ this.connectedWallets.delete(chainType);
1258
1535
  this.primaryWallet = null;
1259
1536
  if (this.config.enableStorage) {
1260
1537
  this.saveToStorage();
@@ -1359,6 +1636,34 @@ var WalletManager = class extends TypedEventEmitter {
1359
1636
  }
1360
1637
  return adapter.signTypedData(typedData);
1361
1638
  }
1639
+ /**
1640
+ * 签名交易(使用主钱包)
1641
+ */
1642
+ async signTransaction(transaction) {
1643
+ if (!this.primaryWallet) {
1644
+ throw new WalletNotConnectedError();
1645
+ }
1646
+ if (!this.primaryWallet.signTransaction) {
1647
+ throw new Error(`signTransaction not supported by ${this.primaryWallet.type}`);
1648
+ }
1649
+ return this.primaryWallet.signTransaction(transaction);
1650
+ }
1651
+ /**
1652
+ * 使用指定链类型的钱包签名交易
1653
+ */
1654
+ async signTransactionWithChainType(transaction, chainType) {
1655
+ if (!chainType) {
1656
+ return this.signTransaction(transaction);
1657
+ }
1658
+ const adapter = this.connectedWallets.get(chainType);
1659
+ if (!adapter) {
1660
+ throw new WalletNotConnectedError(`Wallet for chain type ${chainType}`);
1661
+ }
1662
+ if (!adapter.signTransaction) {
1663
+ throw new Error(`signTransaction not supported by ${adapter.type}`);
1664
+ }
1665
+ return adapter.signTransaction(transaction);
1666
+ }
1362
1667
  // ===== 链切换 =====
1363
1668
  /**
1364
1669
  * 请求切换链(仅 EVM)
@@ -1519,6 +1824,7 @@ var WalletManager = class extends TypedEventEmitter {
1519
1824
  * 移除适配器事件监听
1520
1825
  */
1521
1826
  removeAdapterListeners(adapter) {
1827
+ if (!adapter) return;
1522
1828
  adapter.removeAllListeners();
1523
1829
  }
1524
1830
  // ===== 存储 =====
@@ -1616,6 +1922,9 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
1616
1922
  const signMessage = useCallback(async (message) => {
1617
1923
  return walletManager.signMessage(message);
1618
1924
  }, [walletManager]);
1925
+ const signTransaction = useCallback(async (transaction) => {
1926
+ return walletManager.signTransaction(transaction);
1927
+ }, [walletManager]);
1619
1928
  useEffect(() => {
1620
1929
  const handleAccountChanged = (newAccount) => {
1621
1930
  setAccount(newAccount);
@@ -1655,7 +1964,8 @@ function WalletProvider({ children, walletManager: externalWalletManager }) {
1655
1964
  connectAdditional,
1656
1965
  disconnect,
1657
1966
  switchPrimaryWallet,
1658
- signMessage
1967
+ signMessage,
1968
+ signTransaction
1659
1969
  };
1660
1970
  return /* @__PURE__ */ React.createElement(WalletContext.Provider, { value }, children);
1661
1971
  }
@@ -1764,7 +2074,31 @@ function useSignMessage() {
1764
2074
  error
1765
2075
  };
1766
2076
  }
2077
+ function useSignTransaction() {
2078
+ const { signTransaction: contextSignTransaction } = useWallet();
2079
+ const [isSigning, setIsSigning] = useState(false);
2080
+ const [error, setError] = useState(null);
2081
+ const signTransaction = async (transaction) => {
2082
+ setIsSigning(true);
2083
+ setError(null);
2084
+ try {
2085
+ const signature = await contextSignTransaction(transaction);
2086
+ return signature;
2087
+ } catch (err) {
2088
+ const error2 = err instanceof Error ? err : new Error(String(err));
2089
+ setError(error2);
2090
+ throw error2;
2091
+ } finally {
2092
+ setIsSigning(false);
2093
+ }
2094
+ };
2095
+ return {
2096
+ signTransaction,
2097
+ isSigning,
2098
+ error
2099
+ };
2100
+ }
1767
2101
 
1768
- export { WalletProvider, useAccount, useConnect, useDisconnect, useSignMessage, useWallet };
2102
+ export { WalletProvider, useAccount, useConnect, useDisconnect, useSignMessage, useSignTransaction, useWallet };
1769
2103
  //# sourceMappingURL=index.mjs.map
1770
2104
  //# sourceMappingURL=index.mjs.map