@t402/wdk 2.0.0 → 2.3.0
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/README.md +117 -112
- package/dist/cjs/index.d.ts +384 -11
- package/dist/cjs/index.js +803 -173
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.d.mts +384 -11
- package/dist/esm/index.mjs +786 -178
- package/dist/esm/index.mjs.map +1 -1
- package/package.json +48 -22
package/dist/esm/index.mjs
CHANGED
|
@@ -6,9 +6,10 @@ var DEFAULT_CACHE_CONFIG = {
|
|
|
6
6
|
refreshOnAccess: false
|
|
7
7
|
};
|
|
8
8
|
var TTLCache = class {
|
|
9
|
+
_cache = /* @__PURE__ */ new Map();
|
|
10
|
+
_config;
|
|
11
|
+
_cleanupInterval = null;
|
|
9
12
|
constructor(config = {}) {
|
|
10
|
-
this._cache = /* @__PURE__ */ new Map();
|
|
11
|
-
this._cleanupInterval = null;
|
|
12
13
|
this._config = { ...DEFAULT_CACHE_CONFIG, ...config };
|
|
13
14
|
if (this._config.maxSize > 0) {
|
|
14
15
|
this._startCleanup();
|
|
@@ -276,6 +277,9 @@ var DEFAULT_BALANCE_CACHE_CONFIG = {
|
|
|
276
277
|
maxSize: 500
|
|
277
278
|
};
|
|
278
279
|
var BalanceCache = class {
|
|
280
|
+
_cache;
|
|
281
|
+
_aggregatedCache;
|
|
282
|
+
_config;
|
|
279
283
|
constructor(config = {}) {
|
|
280
284
|
this._config = { ...DEFAULT_BALANCE_CACHE_CONFIG, ...config };
|
|
281
285
|
this._cache = new TTLCache({
|
|
@@ -684,6 +688,9 @@ var WDKErrorCode = /* @__PURE__ */ ((WDKErrorCode2) => {
|
|
|
684
688
|
return WDKErrorCode2;
|
|
685
689
|
})(WDKErrorCode || {});
|
|
686
690
|
var WDKError = class _WDKError extends Error {
|
|
691
|
+
code;
|
|
692
|
+
cause;
|
|
693
|
+
context;
|
|
687
694
|
constructor(code, message, options) {
|
|
688
695
|
super(message);
|
|
689
696
|
this.name = "WDKError";
|
|
@@ -728,6 +735,7 @@ var WDKInitializationError = class extends WDKError {
|
|
|
728
735
|
}
|
|
729
736
|
};
|
|
730
737
|
var ChainError = class extends WDKError {
|
|
738
|
+
chain;
|
|
731
739
|
constructor(code, message, options) {
|
|
732
740
|
super(code, message, {
|
|
733
741
|
cause: options?.cause,
|
|
@@ -738,6 +746,8 @@ var ChainError = class extends WDKError {
|
|
|
738
746
|
}
|
|
739
747
|
};
|
|
740
748
|
var SignerError = class extends WDKError {
|
|
749
|
+
chain;
|
|
750
|
+
address;
|
|
741
751
|
constructor(code, message, options) {
|
|
742
752
|
super(code, message, {
|
|
743
753
|
cause: options?.cause,
|
|
@@ -749,6 +759,7 @@ var SignerError = class extends WDKError {
|
|
|
749
759
|
}
|
|
750
760
|
};
|
|
751
761
|
var SigningError = class extends WDKError {
|
|
762
|
+
operation;
|
|
752
763
|
constructor(code, message, options) {
|
|
753
764
|
super(code, message, {
|
|
754
765
|
cause: options.cause,
|
|
@@ -759,6 +770,8 @@ var SigningError = class extends WDKError {
|
|
|
759
770
|
}
|
|
760
771
|
};
|
|
761
772
|
var BalanceError = class extends WDKError {
|
|
773
|
+
chain;
|
|
774
|
+
token;
|
|
762
775
|
constructor(code, message, options) {
|
|
763
776
|
super(code, message, {
|
|
764
777
|
cause: options?.cause,
|
|
@@ -770,6 +783,8 @@ var BalanceError = class extends WDKError {
|
|
|
770
783
|
}
|
|
771
784
|
};
|
|
772
785
|
var TransactionError = class extends WDKError {
|
|
786
|
+
chain;
|
|
787
|
+
txHash;
|
|
773
788
|
constructor(code, message, options) {
|
|
774
789
|
super(code, message, {
|
|
775
790
|
cause: options?.cause,
|
|
@@ -781,6 +796,8 @@ var TransactionError = class extends WDKError {
|
|
|
781
796
|
}
|
|
782
797
|
};
|
|
783
798
|
var BridgeError = class extends WDKError {
|
|
799
|
+
fromChain;
|
|
800
|
+
toChain;
|
|
784
801
|
constructor(code, message, options) {
|
|
785
802
|
super(code, message, {
|
|
786
803
|
cause: options?.cause,
|
|
@@ -796,6 +813,8 @@ var BridgeError = class extends WDKError {
|
|
|
796
813
|
}
|
|
797
814
|
};
|
|
798
815
|
var RPCError = class extends WDKError {
|
|
816
|
+
endpoint;
|
|
817
|
+
rpcCode;
|
|
799
818
|
constructor(code, message, options) {
|
|
800
819
|
super(code, message, {
|
|
801
820
|
cause: options?.cause,
|
|
@@ -823,11 +842,10 @@ function wrapError(error, defaultCode = 9999 /* UNKNOWN_ERROR */, defaultMessage
|
|
|
823
842
|
});
|
|
824
843
|
}
|
|
825
844
|
if (msg.includes("rate limit") || msg.includes("too many requests") || msg.includes("429")) {
|
|
826
|
-
return new RPCError(
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
);
|
|
845
|
+
return new RPCError(8003 /* RPC_RATE_LIMITED */, `Rate limited: ${error.message}`, {
|
|
846
|
+
cause: error,
|
|
847
|
+
context
|
|
848
|
+
});
|
|
831
849
|
}
|
|
832
850
|
if (msg.includes("connection") || msg.includes("network") || msg.includes("econnrefused") || msg.includes("enotfound")) {
|
|
833
851
|
return new RPCError(
|
|
@@ -905,12 +923,7 @@ async function withTimeout(promise, timeoutMs, operation = "Operation") {
|
|
|
905
923
|
let timeoutId;
|
|
906
924
|
const timeoutPromise = new Promise((_, reject) => {
|
|
907
925
|
timeoutId = setTimeout(() => {
|
|
908
|
-
reject(
|
|
909
|
-
new RPCError(
|
|
910
|
-
8002 /* RPC_TIMEOUT */,
|
|
911
|
-
`${operation} timed out after ${timeoutMs}ms`
|
|
912
|
-
)
|
|
913
|
-
);
|
|
926
|
+
reject(new RPCError(8002 /* RPC_TIMEOUT */, `${operation} timed out after ${timeoutMs}ms`));
|
|
914
927
|
}, timeoutMs);
|
|
915
928
|
});
|
|
916
929
|
try {
|
|
@@ -927,6 +940,12 @@ var DEFAULT_BALANCE_RETRY = {
|
|
|
927
940
|
baseDelay: 500
|
|
928
941
|
};
|
|
929
942
|
var WDKSigner = class {
|
|
943
|
+
_wdk;
|
|
944
|
+
_chain;
|
|
945
|
+
_accountIndex;
|
|
946
|
+
_account = null;
|
|
947
|
+
_address = null;
|
|
948
|
+
_timeoutMs;
|
|
930
949
|
/**
|
|
931
950
|
* Create a new WDK signer
|
|
932
951
|
*
|
|
@@ -936,14 +955,8 @@ var WDKSigner = class {
|
|
|
936
955
|
* @param timeoutMs - Timeout for operations in milliseconds (default: 30000)
|
|
937
956
|
*/
|
|
938
957
|
constructor(wdk, chain, accountIndex = 0, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
939
|
-
this._account = null;
|
|
940
|
-
this._address = null;
|
|
941
958
|
if (!wdk) {
|
|
942
|
-
throw new SignerError(
|
|
943
|
-
1002 /* WDK_NOT_INITIALIZED */,
|
|
944
|
-
"WDK instance is required",
|
|
945
|
-
{ chain }
|
|
946
|
-
);
|
|
959
|
+
throw new SignerError(1002 /* WDK_NOT_INITIALIZED */, "WDK instance is required", { chain });
|
|
947
960
|
}
|
|
948
961
|
if (!chain || typeof chain !== "string") {
|
|
949
962
|
throw new SignerError(
|
|
@@ -1084,11 +1097,7 @@ var WDKSigner = class {
|
|
|
1084
1097
|
primaryType: message.primaryType,
|
|
1085
1098
|
message: message.message
|
|
1086
1099
|
});
|
|
1087
|
-
const signature = await withTimeout(
|
|
1088
|
-
signPromise,
|
|
1089
|
-
this._timeoutMs,
|
|
1090
|
-
"Signing typed data"
|
|
1091
|
-
);
|
|
1100
|
+
const signature = await withTimeout(signPromise, this._timeoutMs, "Signing typed data");
|
|
1092
1101
|
if (!signature || !signature.startsWith("0x")) {
|
|
1093
1102
|
throw new SigningError(
|
|
1094
1103
|
4001 /* SIGN_TYPED_DATA_FAILED */,
|
|
@@ -1101,19 +1110,20 @@ var WDKSigner = class {
|
|
|
1101
1110
|
if (error instanceof SigningError) {
|
|
1102
1111
|
throw error;
|
|
1103
1112
|
}
|
|
1104
|
-
const wrapped = wrapError(
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
throw new SigningError(
|
|
1109
|
-
wrapped.code,
|
|
1110
|
-
wrapped.message,
|
|
1113
|
+
const wrapped = wrapError(
|
|
1114
|
+
error,
|
|
1115
|
+
4001 /* SIGN_TYPED_DATA_FAILED */,
|
|
1116
|
+
"Failed to sign typed data",
|
|
1111
1117
|
{
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
context: wrapped.context
|
|
1118
|
+
chain: this._chain,
|
|
1119
|
+
primaryType: message.primaryType
|
|
1115
1120
|
}
|
|
1116
1121
|
);
|
|
1122
|
+
throw new SigningError(wrapped.code, wrapped.message, {
|
|
1123
|
+
operation: "signTypedData",
|
|
1124
|
+
cause: wrapped.cause,
|
|
1125
|
+
context: wrapped.context
|
|
1126
|
+
});
|
|
1117
1127
|
}
|
|
1118
1128
|
}
|
|
1119
1129
|
/**
|
|
@@ -1123,11 +1133,10 @@ var WDKSigner = class {
|
|
|
1123
1133
|
*/
|
|
1124
1134
|
async signMessage(message) {
|
|
1125
1135
|
if (message === void 0 || message === null) {
|
|
1126
|
-
throw new SigningError(
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
);
|
|
1136
|
+
throw new SigningError(4004 /* INVALID_MESSAGE */, "Message is required for signing", {
|
|
1137
|
+
operation: "signMessage",
|
|
1138
|
+
context: { chain: this._chain }
|
|
1139
|
+
});
|
|
1131
1140
|
}
|
|
1132
1141
|
if (typeof message !== "string" && !(message instanceof Uint8Array)) {
|
|
1133
1142
|
throw new SigningError(
|
|
@@ -1140,11 +1149,7 @@ var WDKSigner = class {
|
|
|
1140
1149
|
const account = await this.getAccount();
|
|
1141
1150
|
const messageStr = typeof message === "string" ? message : Buffer.from(message).toString("utf-8");
|
|
1142
1151
|
const signPromise = account.signMessage(messageStr);
|
|
1143
|
-
const signature = await withTimeout(
|
|
1144
|
-
signPromise,
|
|
1145
|
-
this._timeoutMs,
|
|
1146
|
-
"Signing message"
|
|
1147
|
-
);
|
|
1152
|
+
const signature = await withTimeout(signPromise, this._timeoutMs, "Signing message");
|
|
1148
1153
|
if (!signature || !signature.startsWith("0x")) {
|
|
1149
1154
|
throw new SigningError(
|
|
1150
1155
|
4002 /* SIGN_MESSAGE_FAILED */,
|
|
@@ -1160,15 +1165,11 @@ var WDKSigner = class {
|
|
|
1160
1165
|
const wrapped = wrapError(error, 4002 /* SIGN_MESSAGE_FAILED */, "Failed to sign message", {
|
|
1161
1166
|
chain: this._chain
|
|
1162
1167
|
});
|
|
1163
|
-
throw new SigningError(
|
|
1164
|
-
|
|
1165
|
-
wrapped.
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
cause: wrapped.cause,
|
|
1169
|
-
context: wrapped.context
|
|
1170
|
-
}
|
|
1171
|
-
);
|
|
1168
|
+
throw new SigningError(wrapped.code, wrapped.message, {
|
|
1169
|
+
operation: "signMessage",
|
|
1170
|
+
cause: wrapped.cause,
|
|
1171
|
+
context: wrapped.context
|
|
1172
|
+
});
|
|
1172
1173
|
}
|
|
1173
1174
|
}
|
|
1174
1175
|
/**
|
|
@@ -1197,13 +1198,10 @@ var WDKSigner = class {
|
|
|
1197
1198
|
async getBalance() {
|
|
1198
1199
|
try {
|
|
1199
1200
|
const account = await this.getAccount();
|
|
1200
|
-
return await withRetry(
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
},
|
|
1205
|
-
DEFAULT_BALANCE_RETRY
|
|
1206
|
-
);
|
|
1201
|
+
return await withRetry(async () => {
|
|
1202
|
+
const balancePromise = account.getBalance();
|
|
1203
|
+
return withTimeout(balancePromise, this._timeoutMs, "Fetching native balance");
|
|
1204
|
+
}, DEFAULT_BALANCE_RETRY);
|
|
1207
1205
|
} catch (error) {
|
|
1208
1206
|
if (error instanceof BalanceError) {
|
|
1209
1207
|
throw error;
|
|
@@ -1233,13 +1231,10 @@ var WDKSigner = class {
|
|
|
1233
1231
|
}
|
|
1234
1232
|
try {
|
|
1235
1233
|
const account = await this.getAccount();
|
|
1236
|
-
return await withRetry(
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
},
|
|
1241
|
-
DEFAULT_BALANCE_RETRY
|
|
1242
|
-
);
|
|
1234
|
+
return await withRetry(async () => {
|
|
1235
|
+
const balancePromise = account.getTokenBalance(tokenAddress);
|
|
1236
|
+
return withTimeout(balancePromise, this._timeoutMs, "Fetching token balance");
|
|
1237
|
+
}, DEFAULT_BALANCE_RETRY);
|
|
1243
1238
|
} catch (error) {
|
|
1244
1239
|
if (error instanceof BalanceError) {
|
|
1245
1240
|
throw error;
|
|
@@ -1270,17 +1265,14 @@ var WDKSigner = class {
|
|
|
1270
1265
|
}
|
|
1271
1266
|
try {
|
|
1272
1267
|
const account = await this.getAccount();
|
|
1273
|
-
return await withRetry(
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
},
|
|
1282
|
-
DEFAULT_BALANCE_RETRY
|
|
1283
|
-
);
|
|
1268
|
+
return await withRetry(async () => {
|
|
1269
|
+
const estimatePromise = account.estimateGas({
|
|
1270
|
+
to: params.to,
|
|
1271
|
+
value: params.value,
|
|
1272
|
+
data: params.data
|
|
1273
|
+
});
|
|
1274
|
+
return withTimeout(estimatePromise, this._timeoutMs, "Estimating gas");
|
|
1275
|
+
}, DEFAULT_BALANCE_RETRY);
|
|
1284
1276
|
} catch (error) {
|
|
1285
1277
|
if (error instanceof TransactionError) {
|
|
1286
1278
|
throw error;
|
|
@@ -1338,15 +1330,11 @@ var WDKSigner = class {
|
|
|
1338
1330
|
chain: this._chain,
|
|
1339
1331
|
to: params.to
|
|
1340
1332
|
});
|
|
1341
|
-
throw new TransactionError(
|
|
1342
|
-
|
|
1343
|
-
wrapped.
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
cause: wrapped.cause,
|
|
1347
|
-
context: wrapped.context
|
|
1348
|
-
}
|
|
1349
|
-
);
|
|
1333
|
+
throw new TransactionError(wrapped.code, wrapped.message, {
|
|
1334
|
+
chain: this._chain,
|
|
1335
|
+
cause: wrapped.cause,
|
|
1336
|
+
context: wrapped.context
|
|
1337
|
+
});
|
|
1350
1338
|
}
|
|
1351
1339
|
}
|
|
1352
1340
|
};
|
|
@@ -1356,9 +1344,9 @@ async function createWDKSigner(wdk, chain, accountIndex = 0, timeoutMs = DEFAULT
|
|
|
1356
1344
|
return signer;
|
|
1357
1345
|
}
|
|
1358
1346
|
var MockWDKSigner = class {
|
|
1359
|
-
|
|
1347
|
+
address;
|
|
1348
|
+
constructor(address, _privateKey) {
|
|
1360
1349
|
this.address = address;
|
|
1361
|
-
this._privateKey = privateKey;
|
|
1362
1350
|
}
|
|
1363
1351
|
async signTypedData(_message) {
|
|
1364
1352
|
return "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
|
@@ -1370,53 +1358,17 @@ var MockWDKSigner = class {
|
|
|
1370
1358
|
|
|
1371
1359
|
// src/t402wdk.ts
|
|
1372
1360
|
import { supportsBridging, getBridgeableChains } from "@t402/evm";
|
|
1373
|
-
var
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
this._normalizedChains = /* @__PURE__ */ new Map();
|
|
1385
|
-
this._signerCache = /* @__PURE__ */ new Map();
|
|
1386
|
-
this._initializationError = null;
|
|
1387
|
-
if (!seedPhrase || typeof seedPhrase !== "string") {
|
|
1388
|
-
throw new WDKInitializationError("Seed phrase is required and must be a string");
|
|
1389
|
-
}
|
|
1390
|
-
const words = seedPhrase.trim().split(/\s+/);
|
|
1391
|
-
const validWordCounts = [12, 15, 18, 21, 24];
|
|
1392
|
-
if (!validWordCounts.includes(words.length)) {
|
|
1393
|
-
throw new WDKInitializationError(
|
|
1394
|
-
`Invalid seed phrase: expected 12, 15, 18, 21, or 24 words, got ${words.length}`,
|
|
1395
|
-
{ context: { wordCount: words.length } }
|
|
1396
|
-
);
|
|
1397
|
-
}
|
|
1398
|
-
this._seedPhrase = seedPhrase;
|
|
1399
|
-
this._config = config;
|
|
1400
|
-
this._options = options;
|
|
1401
|
-
this._balanceCache = new BalanceCache(options.cache);
|
|
1402
|
-
for (const [chain, chainConfig] of Object.entries(config)) {
|
|
1403
|
-
if (chainConfig) {
|
|
1404
|
-
try {
|
|
1405
|
-
this._normalizedChains.set(chain, normalizeChainConfig(chain, chainConfig));
|
|
1406
|
-
} catch (error) {
|
|
1407
|
-
throw new ChainError(
|
|
1408
|
-
2003 /* INVALID_CHAIN_CONFIG */,
|
|
1409
|
-
`Invalid configuration for chain "${chain}": ${error instanceof Error ? error.message : String(error)}`,
|
|
1410
|
-
{ chain, cause: error instanceof Error ? error : void 0 }
|
|
1411
|
-
);
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
this._addDefaultChainsIfNeeded();
|
|
1416
|
-
if (_T402WDK._WDK) {
|
|
1417
|
-
this._initializeWDK();
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1361
|
+
var T402WDK = class _T402WDK {
|
|
1362
|
+
_wdk = null;
|
|
1363
|
+
_normalizedChains = /* @__PURE__ */ new Map();
|
|
1364
|
+
_seedPhrase;
|
|
1365
|
+
_signerCache = /* @__PURE__ */ new Map();
|
|
1366
|
+
_balanceCache;
|
|
1367
|
+
_initializationError = null;
|
|
1368
|
+
// WDK module references (set via registerWDK)
|
|
1369
|
+
static _WDK = null;
|
|
1370
|
+
static _WalletManagerEvm = null;
|
|
1371
|
+
static _BridgeUsdt0Evm = null;
|
|
1420
1372
|
/**
|
|
1421
1373
|
* Register the Tether WDK modules
|
|
1422
1374
|
*
|
|
@@ -1484,6 +1436,46 @@ var _T402WDK = class _T402WDK {
|
|
|
1484
1436
|
);
|
|
1485
1437
|
}
|
|
1486
1438
|
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Create a new T402WDK instance
|
|
1441
|
+
*
|
|
1442
|
+
* @param seedPhrase - BIP-39 mnemonic seed phrase
|
|
1443
|
+
* @param config - Chain configuration (RPC endpoints)
|
|
1444
|
+
* @param options - Additional options (cache configuration, etc.)
|
|
1445
|
+
* @throws {WDKInitializationError} If seed phrase is invalid
|
|
1446
|
+
*/
|
|
1447
|
+
constructor(seedPhrase, config = {}, options = {}) {
|
|
1448
|
+
if (!seedPhrase || typeof seedPhrase !== "string") {
|
|
1449
|
+
throw new WDKInitializationError("Seed phrase is required and must be a string");
|
|
1450
|
+
}
|
|
1451
|
+
const words = seedPhrase.trim().split(/\s+/);
|
|
1452
|
+
const validWordCounts = [12, 15, 18, 21, 24];
|
|
1453
|
+
if (!validWordCounts.includes(words.length)) {
|
|
1454
|
+
throw new WDKInitializationError(
|
|
1455
|
+
`Invalid seed phrase: expected 12, 15, 18, 21, or 24 words, got ${words.length}`,
|
|
1456
|
+
{ context: { wordCount: words.length } }
|
|
1457
|
+
);
|
|
1458
|
+
}
|
|
1459
|
+
this._seedPhrase = seedPhrase;
|
|
1460
|
+
this._balanceCache = new BalanceCache(options.cache);
|
|
1461
|
+
for (const [chain, chainConfig] of Object.entries(config)) {
|
|
1462
|
+
if (chainConfig) {
|
|
1463
|
+
try {
|
|
1464
|
+
this._normalizedChains.set(chain, normalizeChainConfig(chain, chainConfig));
|
|
1465
|
+
} catch (error) {
|
|
1466
|
+
throw new ChainError(
|
|
1467
|
+
2003 /* INVALID_CHAIN_CONFIG */,
|
|
1468
|
+
`Invalid configuration for chain "${chain}": ${error instanceof Error ? error.message : String(error)}`,
|
|
1469
|
+
{ chain, cause: error instanceof Error ? error : void 0 }
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
this._addDefaultChainsIfNeeded();
|
|
1475
|
+
if (_T402WDK._WDK) {
|
|
1476
|
+
this._initializeWDK();
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1487
1479
|
/**
|
|
1488
1480
|
* Add default chain configurations for common chains
|
|
1489
1481
|
*/
|
|
@@ -1491,10 +1483,7 @@ var _T402WDK = class _T402WDK {
|
|
|
1491
1483
|
if (this._normalizedChains.size === 0) {
|
|
1492
1484
|
const defaultEndpoint = DEFAULT_RPC_ENDPOINTS.arbitrum;
|
|
1493
1485
|
if (defaultEndpoint) {
|
|
1494
|
-
this._normalizedChains.set(
|
|
1495
|
-
"arbitrum",
|
|
1496
|
-
normalizeChainConfig("arbitrum", defaultEndpoint)
|
|
1497
|
-
);
|
|
1486
|
+
this._normalizedChains.set("arbitrum", normalizeChainConfig("arbitrum", defaultEndpoint));
|
|
1498
1487
|
}
|
|
1499
1488
|
}
|
|
1500
1489
|
}
|
|
@@ -1725,11 +1714,9 @@ var _T402WDK = class _T402WDK {
|
|
|
1725
1714
|
async getChainBalances(chain, accountIndex = 0) {
|
|
1726
1715
|
const config = this._normalizedChains.get(chain);
|
|
1727
1716
|
if (!config) {
|
|
1728
|
-
throw new ChainError(
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
{ chain }
|
|
1732
|
-
);
|
|
1717
|
+
throw new ChainError(2001 /* CHAIN_NOT_CONFIGURED */, `Chain "${chain}" not configured`, {
|
|
1718
|
+
chain
|
|
1719
|
+
});
|
|
1733
1720
|
}
|
|
1734
1721
|
try {
|
|
1735
1722
|
const signer = await this.getSigner(chain, accountIndex);
|
|
@@ -1879,7 +1866,10 @@ var _T402WDK = class _T402WDK {
|
|
|
1879
1866
|
throw new BalanceError(
|
|
1880
1867
|
5001 /* BALANCE_FETCH_FAILED */,
|
|
1881
1868
|
`Failed to find best chain for payment: ${error instanceof Error ? error.message : String(error)}`,
|
|
1882
|
-
{
|
|
1869
|
+
{
|
|
1870
|
+
cause: error instanceof Error ? error : void 0,
|
|
1871
|
+
context: { amount: amount.toString() }
|
|
1872
|
+
}
|
|
1883
1873
|
);
|
|
1884
1874
|
}
|
|
1885
1875
|
}
|
|
@@ -1901,25 +1891,23 @@ var _T402WDK = class _T402WDK {
|
|
|
1901
1891
|
);
|
|
1902
1892
|
}
|
|
1903
1893
|
if (!params.fromChain || !params.toChain) {
|
|
1904
|
-
throw new BridgeError(
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
);
|
|
1894
|
+
throw new BridgeError(7003 /* BRIDGE_FAILED */, "Both fromChain and toChain are required", {
|
|
1895
|
+
fromChain: params.fromChain,
|
|
1896
|
+
toChain: params.toChain
|
|
1897
|
+
});
|
|
1909
1898
|
}
|
|
1910
1899
|
if (params.fromChain === params.toChain) {
|
|
1911
|
-
throw new BridgeError(
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
);
|
|
1900
|
+
throw new BridgeError(7002 /* BRIDGE_NOT_SUPPORTED */, "Cannot bridge to the same chain", {
|
|
1901
|
+
fromChain: params.fromChain,
|
|
1902
|
+
toChain: params.toChain
|
|
1903
|
+
});
|
|
1916
1904
|
}
|
|
1917
1905
|
if (!params.amount || params.amount <= 0n) {
|
|
1918
|
-
throw new BridgeError(
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
);
|
|
1906
|
+
throw new BridgeError(7003 /* BRIDGE_FAILED */, "Amount must be greater than 0", {
|
|
1907
|
+
fromChain: params.fromChain,
|
|
1908
|
+
toChain: params.toChain,
|
|
1909
|
+
context: { amount: params.amount?.toString() }
|
|
1910
|
+
});
|
|
1923
1911
|
}
|
|
1924
1912
|
if (!this.canBridge(params.fromChain, params.toChain)) {
|
|
1925
1913
|
throw new BridgeError(
|
|
@@ -2048,11 +2036,6 @@ var _T402WDK = class _T402WDK {
|
|
|
2048
2036
|
this._signerCache.clear();
|
|
2049
2037
|
}
|
|
2050
2038
|
};
|
|
2051
|
-
// WDK module references (set via registerWDK)
|
|
2052
|
-
_T402WDK._WDK = null;
|
|
2053
|
-
_T402WDK._WalletManagerEvm = null;
|
|
2054
|
-
_T402WDK._BridgeUsdt0Evm = null;
|
|
2055
|
-
var T402WDK = _T402WDK;
|
|
2056
2039
|
function formatTokenAmount(amount, decimals) {
|
|
2057
2040
|
if (amount === 0n) {
|
|
2058
2041
|
return "0";
|
|
@@ -2069,32 +2052,26 @@ function formatTokenAmount(amount, decimals) {
|
|
|
2069
2052
|
}
|
|
2070
2053
|
|
|
2071
2054
|
// src/bridge.ts
|
|
2072
|
-
import {
|
|
2073
|
-
Usdt0Bridge,
|
|
2074
|
-
supportsBridging as supportsBridging2,
|
|
2075
|
-
getBridgeableChains as getBridgeableChains2
|
|
2076
|
-
} from "@t402/evm";
|
|
2055
|
+
import { Usdt0Bridge, supportsBridging as supportsBridging2, getBridgeableChains as getBridgeableChains2 } from "@t402/evm";
|
|
2077
2056
|
var WdkBridge = class {
|
|
2078
|
-
|
|
2079
|
-
this.bridges = /* @__PURE__ */ new Map();
|
|
2080
|
-
}
|
|
2057
|
+
bridges = /* @__PURE__ */ new Map();
|
|
2081
2058
|
/**
|
|
2082
2059
|
* Create bridge signer adapter from WDK signer
|
|
2083
2060
|
*/
|
|
2084
2061
|
createBridgeSigner(signer) {
|
|
2085
2062
|
return {
|
|
2086
2063
|
address: signer.address,
|
|
2087
|
-
readContract: async (
|
|
2064
|
+
readContract: async (_args) => {
|
|
2088
2065
|
throw new Error(
|
|
2089
2066
|
"readContract not available on WDKSigner. Use T402WDK.bridgeUsdt0() instead."
|
|
2090
2067
|
);
|
|
2091
2068
|
},
|
|
2092
|
-
writeContract: async (
|
|
2069
|
+
writeContract: async (_args) => {
|
|
2093
2070
|
throw new Error(
|
|
2094
2071
|
"writeContract not available on WDKSigner. Use T402WDK.bridgeUsdt0() instead."
|
|
2095
2072
|
);
|
|
2096
2073
|
},
|
|
2097
|
-
waitForTransactionReceipt: async (
|
|
2074
|
+
waitForTransactionReceipt: async (_args) => {
|
|
2098
2075
|
throw new Error(
|
|
2099
2076
|
"waitForTransactionReceipt not available on WDKSigner. Use T402WDK.bridgeUsdt0() instead."
|
|
2100
2077
|
);
|
|
@@ -2145,6 +2122,629 @@ import {
|
|
|
2145
2122
|
USDT0_OFT_ADDRESSES,
|
|
2146
2123
|
Usdt0Bridge as Usdt0Bridge2
|
|
2147
2124
|
} from "@t402/evm";
|
|
2125
|
+
|
|
2126
|
+
// src/hardware/types.ts
|
|
2127
|
+
var HardwareWalletErrorCode = /* @__PURE__ */ ((HardwareWalletErrorCode2) => {
|
|
2128
|
+
HardwareWalletErrorCode2["DEVICE_NOT_FOUND"] = "DEVICE_NOT_FOUND";
|
|
2129
|
+
HardwareWalletErrorCode2["CONNECTION_FAILED"] = "CONNECTION_FAILED";
|
|
2130
|
+
HardwareWalletErrorCode2["DEVICE_LOCKED"] = "DEVICE_LOCKED";
|
|
2131
|
+
HardwareWalletErrorCode2["APP_NOT_OPEN"] = "APP_NOT_OPEN";
|
|
2132
|
+
HardwareWalletErrorCode2["TRANSPORT_ERROR"] = "TRANSPORT_ERROR";
|
|
2133
|
+
HardwareWalletErrorCode2["USER_REJECTED"] = "USER_REJECTED";
|
|
2134
|
+
HardwareWalletErrorCode2["SIGNING_FAILED"] = "SIGNING_FAILED";
|
|
2135
|
+
HardwareWalletErrorCode2["INVALID_DATA"] = "INVALID_DATA";
|
|
2136
|
+
HardwareWalletErrorCode2["NOT_SUPPORTED"] = "NOT_SUPPORTED";
|
|
2137
|
+
HardwareWalletErrorCode2["TIMEOUT"] = "TIMEOUT";
|
|
2138
|
+
HardwareWalletErrorCode2["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
|
|
2139
|
+
return HardwareWalletErrorCode2;
|
|
2140
|
+
})(HardwareWalletErrorCode || {});
|
|
2141
|
+
var HardwareWalletError = class extends Error {
|
|
2142
|
+
code;
|
|
2143
|
+
walletType;
|
|
2144
|
+
cause;
|
|
2145
|
+
constructor(code, message, walletType, cause) {
|
|
2146
|
+
super(message);
|
|
2147
|
+
this.name = "HardwareWalletError";
|
|
2148
|
+
this.code = code;
|
|
2149
|
+
this.walletType = walletType;
|
|
2150
|
+
this.cause = cause;
|
|
2151
|
+
}
|
|
2152
|
+
};
|
|
2153
|
+
|
|
2154
|
+
// src/hardware/ledger.ts
|
|
2155
|
+
var DEFAULT_DERIVATION_PATH = "m/44'/60'/0'/0";
|
|
2156
|
+
var LedgerSigner = class {
|
|
2157
|
+
walletType = "ledger";
|
|
2158
|
+
_address = null;
|
|
2159
|
+
_transport = null;
|
|
2160
|
+
_eth = null;
|
|
2161
|
+
_options;
|
|
2162
|
+
_status = "disconnected";
|
|
2163
|
+
_deviceInfo;
|
|
2164
|
+
constructor(options = {}) {
|
|
2165
|
+
this._options = {
|
|
2166
|
+
transport: options.transport ?? "webusb",
|
|
2167
|
+
accountIndex: options.accountIndex ?? 0,
|
|
2168
|
+
derivationPath: options.derivationPath ?? `${DEFAULT_DERIVATION_PATH}/${options.accountIndex ?? 0}`,
|
|
2169
|
+
timeout: options.timeout ?? 3e4,
|
|
2170
|
+
scrambleKey: options.scrambleKey ?? true,
|
|
2171
|
+
appName: options.appName ?? "Ethereum"
|
|
2172
|
+
};
|
|
2173
|
+
this._deviceInfo = {
|
|
2174
|
+
type: "ledger",
|
|
2175
|
+
isLocked: true,
|
|
2176
|
+
status: "disconnected"
|
|
2177
|
+
};
|
|
2178
|
+
}
|
|
2179
|
+
/**
|
|
2180
|
+
* Get the wallet address
|
|
2181
|
+
*/
|
|
2182
|
+
get address() {
|
|
2183
|
+
if (!this._address) {
|
|
2184
|
+
throw new HardwareWalletError(
|
|
2185
|
+
"CONNECTION_FAILED" /* CONNECTION_FAILED */,
|
|
2186
|
+
"Ledger not connected. Call connect() first.",
|
|
2187
|
+
"ledger"
|
|
2188
|
+
);
|
|
2189
|
+
}
|
|
2190
|
+
return this._address;
|
|
2191
|
+
}
|
|
2192
|
+
/**
|
|
2193
|
+
* Get device info
|
|
2194
|
+
*/
|
|
2195
|
+
get deviceInfo() {
|
|
2196
|
+
return { ...this._deviceInfo };
|
|
2197
|
+
}
|
|
2198
|
+
/**
|
|
2199
|
+
* Check if connected
|
|
2200
|
+
*/
|
|
2201
|
+
get isConnected() {
|
|
2202
|
+
return this._status === "ready" && this._transport !== null;
|
|
2203
|
+
}
|
|
2204
|
+
/**
|
|
2205
|
+
* Get the derivation path
|
|
2206
|
+
*/
|
|
2207
|
+
get derivationPath() {
|
|
2208
|
+
return this._options.derivationPath;
|
|
2209
|
+
}
|
|
2210
|
+
/**
|
|
2211
|
+
* Connect to the Ledger device
|
|
2212
|
+
*/
|
|
2213
|
+
async connect() {
|
|
2214
|
+
if (this.isConnected) {
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
this._status = "connecting";
|
|
2218
|
+
this._deviceInfo.status = "connecting";
|
|
2219
|
+
try {
|
|
2220
|
+
const TransportModule = await this._getTransportModule();
|
|
2221
|
+
const EthModule = await import("@ledgerhq/hw-app-eth");
|
|
2222
|
+
this._transport = await TransportModule.default.create();
|
|
2223
|
+
this._status = "connected";
|
|
2224
|
+
this._deviceInfo.status = "connected";
|
|
2225
|
+
this._eth = new EthModule.default(this._transport);
|
|
2226
|
+
try {
|
|
2227
|
+
const appConfig = await this._eth.getAppConfiguration();
|
|
2228
|
+
this._deviceInfo.firmwareVersion = appConfig.version;
|
|
2229
|
+
} catch {
|
|
2230
|
+
}
|
|
2231
|
+
const result = await this._eth.getAddress(this._options.derivationPath, false);
|
|
2232
|
+
this._address = result.address;
|
|
2233
|
+
this._status = "ready";
|
|
2234
|
+
this._deviceInfo.status = "ready";
|
|
2235
|
+
this._deviceInfo.isLocked = false;
|
|
2236
|
+
} catch (error) {
|
|
2237
|
+
this._status = "disconnected";
|
|
2238
|
+
this._deviceInfo.status = "disconnected";
|
|
2239
|
+
this._transport = null;
|
|
2240
|
+
this._eth = null;
|
|
2241
|
+
throw this._wrapError(error);
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
/**
|
|
2245
|
+
* Disconnect from the Ledger device
|
|
2246
|
+
*/
|
|
2247
|
+
async disconnect() {
|
|
2248
|
+
if (this._transport) {
|
|
2249
|
+
try {
|
|
2250
|
+
await this._transport.close();
|
|
2251
|
+
} catch {
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
this._transport = null;
|
|
2255
|
+
this._eth = null;
|
|
2256
|
+
this._address = null;
|
|
2257
|
+
this._status = "disconnected";
|
|
2258
|
+
this._deviceInfo.status = "disconnected";
|
|
2259
|
+
this._deviceInfo.isLocked = true;
|
|
2260
|
+
}
|
|
2261
|
+
/**
|
|
2262
|
+
* Sign EIP-712 typed data
|
|
2263
|
+
*
|
|
2264
|
+
* Note: Requires Ethereum app version 1.6.0+ for EIP-712 support
|
|
2265
|
+
*/
|
|
2266
|
+
async signTypedData(params) {
|
|
2267
|
+
if (!this.isConnected || !this._eth) {
|
|
2268
|
+
throw new HardwareWalletError(
|
|
2269
|
+
"CONNECTION_FAILED" /* CONNECTION_FAILED */,
|
|
2270
|
+
"Ledger not connected",
|
|
2271
|
+
"ledger"
|
|
2272
|
+
);
|
|
2273
|
+
}
|
|
2274
|
+
try {
|
|
2275
|
+
const result = await this._eth.signEIP712Message(this._options.derivationPath, {
|
|
2276
|
+
domain: params.domain,
|
|
2277
|
+
types: params.types,
|
|
2278
|
+
primaryType: params.primaryType,
|
|
2279
|
+
message: params.message
|
|
2280
|
+
});
|
|
2281
|
+
const r = result.r.padStart(64, "0");
|
|
2282
|
+
const s = result.s.padStart(64, "0");
|
|
2283
|
+
const v = result.v.toString(16).padStart(2, "0");
|
|
2284
|
+
return `0x${r}${s}${v}`;
|
|
2285
|
+
} catch (error) {
|
|
2286
|
+
throw this._wrapError(error);
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
/**
|
|
2290
|
+
* Sign a personal message
|
|
2291
|
+
*/
|
|
2292
|
+
async signMessage(message) {
|
|
2293
|
+
if (!this.isConnected || !this._eth) {
|
|
2294
|
+
throw new HardwareWalletError(
|
|
2295
|
+
"CONNECTION_FAILED" /* CONNECTION_FAILED */,
|
|
2296
|
+
"Ledger not connected",
|
|
2297
|
+
"ledger"
|
|
2298
|
+
);
|
|
2299
|
+
}
|
|
2300
|
+
try {
|
|
2301
|
+
const messageHex = typeof message === "string" ? Buffer.from(message).toString("hex") : Buffer.from(message).toString("hex");
|
|
2302
|
+
const result = await this._eth.signPersonalMessage(this._options.derivationPath, messageHex);
|
|
2303
|
+
const r = result.r.padStart(64, "0");
|
|
2304
|
+
const s = result.s.padStart(64, "0");
|
|
2305
|
+
const v = result.v.toString(16).padStart(2, "0");
|
|
2306
|
+
return `0x${r}${s}${v}`;
|
|
2307
|
+
} catch (error) {
|
|
2308
|
+
throw this._wrapError(error);
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
/**
|
|
2312
|
+
* Get multiple addresses for account selection
|
|
2313
|
+
*/
|
|
2314
|
+
async getAddresses(count = 5, startIndex = 0) {
|
|
2315
|
+
if (!this.isConnected || !this._eth) {
|
|
2316
|
+
throw new HardwareWalletError(
|
|
2317
|
+
"CONNECTION_FAILED" /* CONNECTION_FAILED */,
|
|
2318
|
+
"Ledger not connected",
|
|
2319
|
+
"ledger"
|
|
2320
|
+
);
|
|
2321
|
+
}
|
|
2322
|
+
const addresses = [];
|
|
2323
|
+
for (let i = startIndex; i < startIndex + count; i++) {
|
|
2324
|
+
const path = `${DEFAULT_DERIVATION_PATH}/${i}`;
|
|
2325
|
+
const result = await this._eth.getAddress(path, false);
|
|
2326
|
+
addresses.push(result.address);
|
|
2327
|
+
}
|
|
2328
|
+
return addresses;
|
|
2329
|
+
}
|
|
2330
|
+
/**
|
|
2331
|
+
* Get the appropriate transport module based on options
|
|
2332
|
+
*/
|
|
2333
|
+
async _getTransportModule() {
|
|
2334
|
+
switch (this._options.transport) {
|
|
2335
|
+
case "webhid":
|
|
2336
|
+
return import("@ledgerhq/hw-transport-webhid");
|
|
2337
|
+
case "bluetooth":
|
|
2338
|
+
return import("@ledgerhq/hw-transport-web-ble");
|
|
2339
|
+
case "webusb":
|
|
2340
|
+
default:
|
|
2341
|
+
return import("@ledgerhq/hw-transport-webusb");
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
/**
|
|
2345
|
+
* Wrap errors in HardwareWalletError
|
|
2346
|
+
*/
|
|
2347
|
+
_wrapError(error) {
|
|
2348
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2349
|
+
const message = err.message.toLowerCase();
|
|
2350
|
+
if (message.includes("denied") || message.includes("rejected")) {
|
|
2351
|
+
return new HardwareWalletError(
|
|
2352
|
+
"USER_REJECTED" /* USER_REJECTED */,
|
|
2353
|
+
"User rejected the action on the Ledger device",
|
|
2354
|
+
"ledger",
|
|
2355
|
+
err
|
|
2356
|
+
);
|
|
2357
|
+
}
|
|
2358
|
+
if (message.includes("locked")) {
|
|
2359
|
+
return new HardwareWalletError(
|
|
2360
|
+
"DEVICE_LOCKED" /* DEVICE_LOCKED */,
|
|
2361
|
+
"Ledger device is locked. Please unlock it.",
|
|
2362
|
+
"ledger",
|
|
2363
|
+
err
|
|
2364
|
+
);
|
|
2365
|
+
}
|
|
2366
|
+
if (message.includes("no device") || message.includes("not found")) {
|
|
2367
|
+
return new HardwareWalletError(
|
|
2368
|
+
"DEVICE_NOT_FOUND" /* DEVICE_NOT_FOUND */,
|
|
2369
|
+
"Ledger device not found. Please connect your device.",
|
|
2370
|
+
"ledger",
|
|
2371
|
+
err
|
|
2372
|
+
);
|
|
2373
|
+
}
|
|
2374
|
+
if (message.includes("app") || message.includes("ethereum")) {
|
|
2375
|
+
return new HardwareWalletError(
|
|
2376
|
+
"APP_NOT_OPEN" /* APP_NOT_OPEN */,
|
|
2377
|
+
"Please open the Ethereum app on your Ledger device.",
|
|
2378
|
+
"ledger",
|
|
2379
|
+
err
|
|
2380
|
+
);
|
|
2381
|
+
}
|
|
2382
|
+
if (message.includes("timeout")) {
|
|
2383
|
+
return new HardwareWalletError(
|
|
2384
|
+
"TIMEOUT" /* TIMEOUT */,
|
|
2385
|
+
"Connection timed out",
|
|
2386
|
+
"ledger",
|
|
2387
|
+
err
|
|
2388
|
+
);
|
|
2389
|
+
}
|
|
2390
|
+
return new HardwareWalletError(
|
|
2391
|
+
"UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
|
|
2392
|
+
err.message,
|
|
2393
|
+
"ledger",
|
|
2394
|
+
err
|
|
2395
|
+
);
|
|
2396
|
+
}
|
|
2397
|
+
};
|
|
2398
|
+
async function createLedgerSigner(options) {
|
|
2399
|
+
const signer = new LedgerSigner(options);
|
|
2400
|
+
await signer.connect();
|
|
2401
|
+
return signer;
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
// src/hardware/trezor.ts
|
|
2405
|
+
var DEFAULT_DERIVATION_PATH2 = "m/44'/60'/0'/0";
|
|
2406
|
+
var TrezorConnect = null;
|
|
2407
|
+
var TrezorSigner = class {
|
|
2408
|
+
walletType = "trezor";
|
|
2409
|
+
_address = null;
|
|
2410
|
+
_options;
|
|
2411
|
+
_status = "disconnected";
|
|
2412
|
+
_deviceInfo;
|
|
2413
|
+
_initialized = false;
|
|
2414
|
+
constructor(options) {
|
|
2415
|
+
if (!options.manifest) {
|
|
2416
|
+
throw new HardwareWalletError(
|
|
2417
|
+
"INVALID_DATA" /* INVALID_DATA */,
|
|
2418
|
+
"Trezor manifest is required (email and appUrl)",
|
|
2419
|
+
"trezor"
|
|
2420
|
+
);
|
|
2421
|
+
}
|
|
2422
|
+
this._options = {
|
|
2423
|
+
manifest: options.manifest,
|
|
2424
|
+
transport: options.transport ?? "webusb",
|
|
2425
|
+
accountIndex: options.accountIndex ?? 0,
|
|
2426
|
+
derivationPath: options.derivationPath ?? `${DEFAULT_DERIVATION_PATH2}/${options.accountIndex ?? 0}`,
|
|
2427
|
+
timeout: options.timeout ?? 3e4,
|
|
2428
|
+
popup: options.popup ?? true,
|
|
2429
|
+
debug: options.debug ?? false
|
|
2430
|
+
};
|
|
2431
|
+
this._deviceInfo = {
|
|
2432
|
+
type: "trezor",
|
|
2433
|
+
isLocked: true,
|
|
2434
|
+
status: "disconnected"
|
|
2435
|
+
};
|
|
2436
|
+
}
|
|
2437
|
+
/**
|
|
2438
|
+
* Get the wallet address
|
|
2439
|
+
*/
|
|
2440
|
+
get address() {
|
|
2441
|
+
if (!this._address) {
|
|
2442
|
+
throw new HardwareWalletError(
|
|
2443
|
+
"CONNECTION_FAILED" /* CONNECTION_FAILED */,
|
|
2444
|
+
"Trezor not connected. Call connect() first.",
|
|
2445
|
+
"trezor"
|
|
2446
|
+
);
|
|
2447
|
+
}
|
|
2448
|
+
return this._address;
|
|
2449
|
+
}
|
|
2450
|
+
/**
|
|
2451
|
+
* Get device info
|
|
2452
|
+
*/
|
|
2453
|
+
get deviceInfo() {
|
|
2454
|
+
return { ...this._deviceInfo };
|
|
2455
|
+
}
|
|
2456
|
+
/**
|
|
2457
|
+
* Check if connected
|
|
2458
|
+
*/
|
|
2459
|
+
get isConnected() {
|
|
2460
|
+
return this._status === "ready" && this._address !== null;
|
|
2461
|
+
}
|
|
2462
|
+
/**
|
|
2463
|
+
* Get the derivation path
|
|
2464
|
+
*/
|
|
2465
|
+
get derivationPath() {
|
|
2466
|
+
return this._options.derivationPath;
|
|
2467
|
+
}
|
|
2468
|
+
/**
|
|
2469
|
+
* Initialize Trezor Connect
|
|
2470
|
+
*/
|
|
2471
|
+
async _initTrezorConnect() {
|
|
2472
|
+
if (this._initialized && TrezorConnect) {
|
|
2473
|
+
return;
|
|
2474
|
+
}
|
|
2475
|
+
try {
|
|
2476
|
+
const module = await import("@trezor/connect");
|
|
2477
|
+
TrezorConnect = module.default;
|
|
2478
|
+
await TrezorConnect.init({
|
|
2479
|
+
manifest: {
|
|
2480
|
+
email: this._options.manifest.email,
|
|
2481
|
+
appUrl: this._options.manifest.appUrl,
|
|
2482
|
+
appName: "T402 WDK"
|
|
2483
|
+
},
|
|
2484
|
+
popup: this._options.popup,
|
|
2485
|
+
debug: this._options.debug
|
|
2486
|
+
});
|
|
2487
|
+
this._initialized = true;
|
|
2488
|
+
} catch (error) {
|
|
2489
|
+
throw new HardwareWalletError(
|
|
2490
|
+
"CONNECTION_FAILED" /* CONNECTION_FAILED */,
|
|
2491
|
+
`Failed to initialize Trezor Connect: ${error instanceof Error ? error.message : String(error)}`,
|
|
2492
|
+
"trezor",
|
|
2493
|
+
error instanceof Error ? error : void 0
|
|
2494
|
+
);
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2497
|
+
/**
|
|
2498
|
+
* Connect to the Trezor device
|
|
2499
|
+
*/
|
|
2500
|
+
async connect() {
|
|
2501
|
+
if (this.isConnected) {
|
|
2502
|
+
return;
|
|
2503
|
+
}
|
|
2504
|
+
this._status = "connecting";
|
|
2505
|
+
this._deviceInfo.status = "connecting";
|
|
2506
|
+
try {
|
|
2507
|
+
await this._initTrezorConnect();
|
|
2508
|
+
if (!TrezorConnect) {
|
|
2509
|
+
throw new Error("TrezorConnect not initialized");
|
|
2510
|
+
}
|
|
2511
|
+
const featuresResult = await TrezorConnect.getFeatures();
|
|
2512
|
+
if (featuresResult.success) {
|
|
2513
|
+
const features = featuresResult.payload;
|
|
2514
|
+
this._deviceInfo.model = features.model;
|
|
2515
|
+
this._deviceInfo.firmwareVersion = `${features.major_version}.${features.minor_version}.${features.patch_version}`;
|
|
2516
|
+
}
|
|
2517
|
+
const result = await TrezorConnect.ethereumGetAddress({
|
|
2518
|
+
path: this._options.derivationPath,
|
|
2519
|
+
showOnTrezor: false
|
|
2520
|
+
});
|
|
2521
|
+
if (!result.success) {
|
|
2522
|
+
throw new Error(result.payload.error || "Failed to get address");
|
|
2523
|
+
}
|
|
2524
|
+
this._address = result.payload.address;
|
|
2525
|
+
this._status = "ready";
|
|
2526
|
+
this._deviceInfo.status = "ready";
|
|
2527
|
+
this._deviceInfo.isLocked = false;
|
|
2528
|
+
} catch (error) {
|
|
2529
|
+
this._status = "disconnected";
|
|
2530
|
+
this._deviceInfo.status = "disconnected";
|
|
2531
|
+
this._address = null;
|
|
2532
|
+
throw this._wrapError(error);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
/**
|
|
2536
|
+
* Disconnect from the Trezor device
|
|
2537
|
+
*/
|
|
2538
|
+
async disconnect() {
|
|
2539
|
+
if (TrezorConnect) {
|
|
2540
|
+
try {
|
|
2541
|
+
TrezorConnect.dispose();
|
|
2542
|
+
} catch {
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
this._address = null;
|
|
2546
|
+
this._status = "disconnected";
|
|
2547
|
+
this._deviceInfo.status = "disconnected";
|
|
2548
|
+
this._deviceInfo.isLocked = true;
|
|
2549
|
+
this._initialized = false;
|
|
2550
|
+
TrezorConnect = null;
|
|
2551
|
+
}
|
|
2552
|
+
/**
|
|
2553
|
+
* Sign EIP-712 typed data
|
|
2554
|
+
*/
|
|
2555
|
+
async signTypedData(params) {
|
|
2556
|
+
if (!this.isConnected) {
|
|
2557
|
+
throw new HardwareWalletError(
|
|
2558
|
+
"CONNECTION_FAILED" /* CONNECTION_FAILED */,
|
|
2559
|
+
"Trezor not connected",
|
|
2560
|
+
"trezor"
|
|
2561
|
+
);
|
|
2562
|
+
}
|
|
2563
|
+
await this._initTrezorConnect();
|
|
2564
|
+
if (!TrezorConnect) {
|
|
2565
|
+
throw new Error("TrezorConnect not initialized");
|
|
2566
|
+
}
|
|
2567
|
+
try {
|
|
2568
|
+
const trezorTypes = this._convertTypesToTrezorFormat(params.types);
|
|
2569
|
+
if (!trezorTypes.EIP712Domain) {
|
|
2570
|
+
trezorTypes.EIP712Domain = [
|
|
2571
|
+
{ name: "name", type: "string" },
|
|
2572
|
+
{ name: "version", type: "string" },
|
|
2573
|
+
{ name: "chainId", type: "uint256" },
|
|
2574
|
+
{ name: "verifyingContract", type: "address" }
|
|
2575
|
+
];
|
|
2576
|
+
}
|
|
2577
|
+
const result = await TrezorConnect.ethereumSignTypedData({
|
|
2578
|
+
path: this._options.derivationPath,
|
|
2579
|
+
data: {
|
|
2580
|
+
domain: params.domain,
|
|
2581
|
+
types: trezorTypes,
|
|
2582
|
+
primaryType: params.primaryType,
|
|
2583
|
+
message: params.message
|
|
2584
|
+
},
|
|
2585
|
+
metamask_v4_compat: true
|
|
2586
|
+
});
|
|
2587
|
+
if (!result.success) {
|
|
2588
|
+
throw new Error(result.payload.error || "Failed to sign typed data");
|
|
2589
|
+
}
|
|
2590
|
+
return result.payload.signature;
|
|
2591
|
+
} catch (error) {
|
|
2592
|
+
throw this._wrapError(error);
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
/**
|
|
2596
|
+
* Sign a personal message
|
|
2597
|
+
*/
|
|
2598
|
+
async signMessage(message) {
|
|
2599
|
+
if (!this.isConnected) {
|
|
2600
|
+
throw new HardwareWalletError(
|
|
2601
|
+
"CONNECTION_FAILED" /* CONNECTION_FAILED */,
|
|
2602
|
+
"Trezor not connected",
|
|
2603
|
+
"trezor"
|
|
2604
|
+
);
|
|
2605
|
+
}
|
|
2606
|
+
await this._initTrezorConnect();
|
|
2607
|
+
if (!TrezorConnect) {
|
|
2608
|
+
throw new Error("TrezorConnect not initialized");
|
|
2609
|
+
}
|
|
2610
|
+
try {
|
|
2611
|
+
const messageHex = typeof message === "string" ? `0x${Buffer.from(message).toString("hex")}` : `0x${Buffer.from(message).toString("hex")}`;
|
|
2612
|
+
const result = await TrezorConnect.ethereumSignMessage({
|
|
2613
|
+
path: this._options.derivationPath,
|
|
2614
|
+
message: messageHex,
|
|
2615
|
+
hex: true
|
|
2616
|
+
});
|
|
2617
|
+
if (!result.success) {
|
|
2618
|
+
throw new Error(result.payload.error || "Failed to sign message");
|
|
2619
|
+
}
|
|
2620
|
+
return `0x${result.payload.signature}`;
|
|
2621
|
+
} catch (error) {
|
|
2622
|
+
throw this._wrapError(error);
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
/**
|
|
2626
|
+
* Get multiple addresses for account selection
|
|
2627
|
+
*/
|
|
2628
|
+
async getAddresses(count = 5, startIndex = 0) {
|
|
2629
|
+
if (!this.isConnected) {
|
|
2630
|
+
throw new HardwareWalletError(
|
|
2631
|
+
"CONNECTION_FAILED" /* CONNECTION_FAILED */,
|
|
2632
|
+
"Trezor not connected",
|
|
2633
|
+
"trezor"
|
|
2634
|
+
);
|
|
2635
|
+
}
|
|
2636
|
+
await this._initTrezorConnect();
|
|
2637
|
+
if (!TrezorConnect) {
|
|
2638
|
+
throw new Error("TrezorConnect not initialized");
|
|
2639
|
+
}
|
|
2640
|
+
const addresses = [];
|
|
2641
|
+
const bundle = [];
|
|
2642
|
+
for (let i = startIndex; i < startIndex + count; i++) {
|
|
2643
|
+
bundle.push({
|
|
2644
|
+
path: `${DEFAULT_DERIVATION_PATH2}/${i}`,
|
|
2645
|
+
showOnTrezor: false
|
|
2646
|
+
});
|
|
2647
|
+
}
|
|
2648
|
+
const result = await TrezorConnect.ethereumGetAddress({ bundle });
|
|
2649
|
+
if (!result.success) {
|
|
2650
|
+
throw this._wrapError(new Error(result.payload.error || "Failed to get addresses"));
|
|
2651
|
+
}
|
|
2652
|
+
for (const item of result.payload) {
|
|
2653
|
+
addresses.push(item.address);
|
|
2654
|
+
}
|
|
2655
|
+
return addresses;
|
|
2656
|
+
}
|
|
2657
|
+
/**
|
|
2658
|
+
* Convert EIP-712 types to Trezor format
|
|
2659
|
+
*/
|
|
2660
|
+
_convertTypesToTrezorFormat(types) {
|
|
2661
|
+
const result = {};
|
|
2662
|
+
for (const [typeName, fields] of Object.entries(types)) {
|
|
2663
|
+
if (Array.isArray(fields)) {
|
|
2664
|
+
result[typeName] = fields.map((field) => ({
|
|
2665
|
+
name: String(field.name),
|
|
2666
|
+
type: String(field.type)
|
|
2667
|
+
}));
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
return result;
|
|
2671
|
+
}
|
|
2672
|
+
/**
|
|
2673
|
+
* Wrap errors in HardwareWalletError
|
|
2674
|
+
*/
|
|
2675
|
+
_wrapError(error) {
|
|
2676
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2677
|
+
const message = err.message.toLowerCase();
|
|
2678
|
+
if (message.includes("cancelled") || message.includes("rejected") || message.includes("denied")) {
|
|
2679
|
+
return new HardwareWalletError(
|
|
2680
|
+
"USER_REJECTED" /* USER_REJECTED */,
|
|
2681
|
+
"User cancelled the action on the Trezor device",
|
|
2682
|
+
"trezor",
|
|
2683
|
+
err
|
|
2684
|
+
);
|
|
2685
|
+
}
|
|
2686
|
+
if (message.includes("pin")) {
|
|
2687
|
+
return new HardwareWalletError(
|
|
2688
|
+
"DEVICE_LOCKED" /* DEVICE_LOCKED */,
|
|
2689
|
+
"Trezor device requires PIN entry",
|
|
2690
|
+
"trezor",
|
|
2691
|
+
err
|
|
2692
|
+
);
|
|
2693
|
+
}
|
|
2694
|
+
if (message.includes("passphrase")) {
|
|
2695
|
+
return new HardwareWalletError(
|
|
2696
|
+
"DEVICE_LOCKED" /* DEVICE_LOCKED */,
|
|
2697
|
+
"Trezor device requires passphrase entry",
|
|
2698
|
+
"trezor",
|
|
2699
|
+
err
|
|
2700
|
+
);
|
|
2701
|
+
}
|
|
2702
|
+
if (message.includes("device") && message.includes("not found")) {
|
|
2703
|
+
return new HardwareWalletError(
|
|
2704
|
+
"DEVICE_NOT_FOUND" /* DEVICE_NOT_FOUND */,
|
|
2705
|
+
"Trezor device not found. Please connect your device.",
|
|
2706
|
+
"trezor",
|
|
2707
|
+
err
|
|
2708
|
+
);
|
|
2709
|
+
}
|
|
2710
|
+
if (message.includes("timeout")) {
|
|
2711
|
+
return new HardwareWalletError(
|
|
2712
|
+
"TIMEOUT" /* TIMEOUT */,
|
|
2713
|
+
"Connection timed out",
|
|
2714
|
+
"trezor",
|
|
2715
|
+
err
|
|
2716
|
+
);
|
|
2717
|
+
}
|
|
2718
|
+
return new HardwareWalletError(
|
|
2719
|
+
"UNKNOWN_ERROR" /* UNKNOWN_ERROR */,
|
|
2720
|
+
err.message,
|
|
2721
|
+
"trezor",
|
|
2722
|
+
err
|
|
2723
|
+
);
|
|
2724
|
+
}
|
|
2725
|
+
};
|
|
2726
|
+
async function createTrezorSigner(options) {
|
|
2727
|
+
const signer = new TrezorSigner(options);
|
|
2728
|
+
await signer.connect();
|
|
2729
|
+
return signer;
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
// src/hardware/index.ts
|
|
2733
|
+
function detectHardwareWalletSupport() {
|
|
2734
|
+
const hasNavigator = typeof navigator !== "undefined";
|
|
2735
|
+
return {
|
|
2736
|
+
ledger: {
|
|
2737
|
+
webusb: hasNavigator && "usb" in navigator,
|
|
2738
|
+
webhid: hasNavigator && "hid" in navigator,
|
|
2739
|
+
bluetooth: hasNavigator && "bluetooth" in navigator
|
|
2740
|
+
},
|
|
2741
|
+
trezor: hasNavigator && "usb" in navigator
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
function isHardwareWalletSupported() {
|
|
2745
|
+
const support = detectHardwareWalletSupport();
|
|
2746
|
+
return support.ledger.webusb || support.ledger.webhid || support.ledger.bluetooth || support.trezor;
|
|
2747
|
+
}
|
|
2148
2748
|
export {
|
|
2149
2749
|
BalanceCache,
|
|
2150
2750
|
BalanceError,
|
|
@@ -2156,7 +2756,10 @@ export {
|
|
|
2156
2756
|
DEFAULT_CHAINS,
|
|
2157
2757
|
DEFAULT_RETRY_CONFIG,
|
|
2158
2758
|
DEFAULT_RPC_ENDPOINTS,
|
|
2759
|
+
HardwareWalletError,
|
|
2760
|
+
HardwareWalletErrorCode,
|
|
2159
2761
|
LAYERZERO_ENDPOINT_IDS,
|
|
2762
|
+
LedgerSigner,
|
|
2160
2763
|
MockWDKSigner,
|
|
2161
2764
|
RPCError,
|
|
2162
2765
|
SignerError,
|
|
@@ -2164,6 +2767,7 @@ export {
|
|
|
2164
2767
|
T402WDK,
|
|
2165
2768
|
TTLCache,
|
|
2166
2769
|
TransactionError,
|
|
2770
|
+
TrezorSigner,
|
|
2167
2771
|
USDC_ADDRESSES,
|
|
2168
2772
|
USDT0_ADDRESSES,
|
|
2169
2773
|
USDT0_OFT_ADDRESSES,
|
|
@@ -2175,7 +2779,10 @@ export {
|
|
|
2175
2779
|
WDKSigner,
|
|
2176
2780
|
WdkBridge,
|
|
2177
2781
|
createDirectBridge,
|
|
2782
|
+
createLedgerSigner,
|
|
2783
|
+
createTrezorSigner,
|
|
2178
2784
|
createWDKSigner,
|
|
2785
|
+
detectHardwareWalletSupport,
|
|
2179
2786
|
getBridgeableChains3 as getBridgeableChains,
|
|
2180
2787
|
getChainFromNetwork,
|
|
2181
2788
|
getChainId,
|
|
@@ -2183,6 +2790,7 @@ export {
|
|
|
2183
2790
|
getPreferredToken,
|
|
2184
2791
|
getUsdt0Chains,
|
|
2185
2792
|
hasErrorCode,
|
|
2793
|
+
isHardwareWalletSupported,
|
|
2186
2794
|
isWDKError,
|
|
2187
2795
|
normalizeChainConfig,
|
|
2188
2796
|
supportsBridging3 as supportsBridging,
|