@t402/wdk 2.3.0 → 2.4.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 +8 -0
- package/dist/cjs/adapters/index.d.ts +5 -0
- package/dist/cjs/adapters/index.js +455 -0
- package/dist/cjs/adapters/index.js.map +1 -0
- package/dist/cjs/adapters/svm-adapter.d.ts +125 -0
- package/dist/cjs/adapters/svm-adapter.js +132 -0
- package/dist/cjs/adapters/svm-adapter.js.map +1 -0
- package/dist/cjs/adapters/ton-adapter.d.ts +139 -0
- package/dist/cjs/adapters/ton-adapter.js +152 -0
- package/dist/cjs/adapters/ton-adapter.js.map +1 -0
- package/dist/cjs/adapters/tron-adapter.d.ts +139 -0
- package/dist/cjs/adapters/tron-adapter.js +221 -0
- package/dist/cjs/adapters/tron-adapter.js.map +1 -0
- package/dist/cjs/index.d.ts +292 -217
- package/dist/cjs/index.js +1042 -23
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types-V7c-qhn6.d.ts +489 -0
- package/dist/esm/adapters/index.d.mts +5 -0
- package/dist/esm/adapters/index.mjs +21 -0
- package/dist/esm/adapters/index.mjs.map +1 -0
- package/dist/esm/adapters/svm-adapter.d.mts +125 -0
- package/dist/esm/adapters/svm-adapter.mjs +9 -0
- package/dist/esm/adapters/svm-adapter.mjs.map +1 -0
- package/dist/esm/adapters/ton-adapter.d.mts +139 -0
- package/dist/esm/adapters/ton-adapter.mjs +9 -0
- package/dist/esm/adapters/ton-adapter.mjs.map +1 -0
- package/dist/esm/adapters/tron-adapter.d.mts +139 -0
- package/dist/esm/adapters/tron-adapter.mjs +9 -0
- package/dist/esm/adapters/tron-adapter.mjs.map +1 -0
- package/dist/esm/chunk-HB2DGKQ3.mjs +196 -0
- package/dist/esm/chunk-HB2DGKQ3.mjs.map +1 -0
- package/dist/esm/chunk-MCFHZSF7.mjs +107 -0
- package/dist/esm/chunk-MCFHZSF7.mjs.map +1 -0
- package/dist/esm/chunk-YWBJJV5M.mjs +117 -0
- package/dist/esm/chunk-YWBJJV5M.mjs.map +1 -0
- package/dist/esm/index.d.mts +292 -217
- package/dist/esm/index.mjs +640 -23
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/types-V7c-qhn6.d.mts +489 -0
- package/package.json +70 -6
package/dist/cjs/index.js
CHANGED
|
@@ -61,11 +61,20 @@ __export(index_exports, {
|
|
|
61
61
|
WDKErrorCode: () => WDKErrorCode,
|
|
62
62
|
WDKInitializationError: () => WDKInitializationError,
|
|
63
63
|
WDKSigner: () => WDKSigner,
|
|
64
|
+
WDKSvmSignerAdapter: () => WDKSvmSignerAdapter,
|
|
65
|
+
WDKTonSignerAdapter: () => WDKTonSignerAdapter,
|
|
66
|
+
WDKTronSignerAdapter: () => WDKTronSignerAdapter,
|
|
67
|
+
WDK_COMPATIBILITY: () => WDK_COMPATIBILITY,
|
|
64
68
|
WdkBridge: () => WdkBridge,
|
|
69
|
+
checkWalletEvmCompatibility: () => checkWalletEvmCompatibility,
|
|
70
|
+
checkWdkCompatibility: () => checkWdkCompatibility,
|
|
65
71
|
createDirectBridge: () => createDirectBridge,
|
|
66
72
|
createLedgerSigner: () => createLedgerSigner,
|
|
67
73
|
createTrezorSigner: () => createTrezorSigner,
|
|
68
74
|
createWDKSigner: () => createWDKSigner,
|
|
75
|
+
createWDKSvmSigner: () => createWDKSvmSigner,
|
|
76
|
+
createWDKTonSigner: () => createWDKTonSigner,
|
|
77
|
+
createWDKTronSigner: () => createWDKTronSigner,
|
|
69
78
|
detectHardwareWalletSupport: () => detectHardwareWalletSupport,
|
|
70
79
|
getBridgeableChains: () => import_evm3.getBridgeableChains,
|
|
71
80
|
getChainFromNetwork: () => getChainFromNetwork,
|
|
@@ -73,6 +82,7 @@ __export(index_exports, {
|
|
|
73
82
|
getNetworkFromChain: () => getNetworkFromChain,
|
|
74
83
|
getPreferredToken: () => getPreferredToken,
|
|
75
84
|
getUsdt0Chains: () => getUsdt0Chains,
|
|
85
|
+
getWalletModuleMinVersion: () => getWalletModuleMinVersion,
|
|
76
86
|
hasErrorCode: () => hasErrorCode,
|
|
77
87
|
isHardwareWalletSupported: () => isHardwareWalletSupported,
|
|
78
88
|
isWDKError: () => isWDKError,
|
|
@@ -84,6 +94,411 @@ __export(index_exports, {
|
|
|
84
94
|
});
|
|
85
95
|
module.exports = __toCommonJS(index_exports);
|
|
86
96
|
|
|
97
|
+
// src/adapters/ton-adapter.ts
|
|
98
|
+
var WDKTonAddress = class {
|
|
99
|
+
constructor(_address) {
|
|
100
|
+
this._address = _address;
|
|
101
|
+
}
|
|
102
|
+
toString() {
|
|
103
|
+
return this._address;
|
|
104
|
+
}
|
|
105
|
+
toRawString() {
|
|
106
|
+
return this._address;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var WDKTonSignerAdapter = class {
|
|
110
|
+
_account;
|
|
111
|
+
_address = null;
|
|
112
|
+
_initialized = false;
|
|
113
|
+
constructor(account) {
|
|
114
|
+
if (!account) {
|
|
115
|
+
throw new Error("WDK TON account is required");
|
|
116
|
+
}
|
|
117
|
+
this._account = account;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get the wallet address
|
|
121
|
+
* @throws Error if not initialized
|
|
122
|
+
*/
|
|
123
|
+
get address() {
|
|
124
|
+
if (!this._address) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
"TON signer not initialized. Call initialize() first or use createWDKTonSigner()."
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
return this._address;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if the adapter is initialized
|
|
133
|
+
*/
|
|
134
|
+
get isInitialized() {
|
|
135
|
+
return this._initialized;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Initialize the adapter by fetching the address
|
|
139
|
+
* Must be called before using the signer
|
|
140
|
+
*/
|
|
141
|
+
async initialize() {
|
|
142
|
+
if (this._initialized) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const addressStr = await this._account.getAddress();
|
|
146
|
+
this._address = new WDKTonAddress(addressStr);
|
|
147
|
+
this._initialized = true;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Sign an internal message for Jetton transfer
|
|
151
|
+
*
|
|
152
|
+
* Attempts to build a proper signed Cell using @ton/core if available.
|
|
153
|
+
* Falls back to a simplified wrapper that embeds the raw signature.
|
|
154
|
+
*
|
|
155
|
+
* @param params - Message parameters
|
|
156
|
+
* @returns Signed external message as Cell (BOC)
|
|
157
|
+
*/
|
|
158
|
+
async signMessage(params) {
|
|
159
|
+
const msgHash = params.body.hash();
|
|
160
|
+
const signature = await this._account.signMessage(msgHash);
|
|
161
|
+
try {
|
|
162
|
+
const tonCore = await import("@ton/core");
|
|
163
|
+
const sigBuffer = Buffer.from(signature.buffer, signature.byteOffset, signature.byteLength);
|
|
164
|
+
const bodyBoc = params.body.toBoc();
|
|
165
|
+
const bocBuffer = Buffer.from(bodyBoc.buffer, bodyBoc.byteOffset, bodyBoc.byteLength);
|
|
166
|
+
const signedCell = tonCore.beginCell().storeBuffer(sigBuffer).storeSlice(tonCore.Cell.fromBoc(bocBuffer)[0].beginParse()).endCell();
|
|
167
|
+
return signedCell;
|
|
168
|
+
} catch {
|
|
169
|
+
return {
|
|
170
|
+
hash: () => msgHash,
|
|
171
|
+
toBoc: () => signature
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get current seqno for the wallet
|
|
177
|
+
* Used for replay protection
|
|
178
|
+
*/
|
|
179
|
+
async getSeqno() {
|
|
180
|
+
return this._account.getSeqno();
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get TON balance in nanoTON
|
|
184
|
+
*/
|
|
185
|
+
async getBalance() {
|
|
186
|
+
return this._account.getBalance();
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get Jetton balance
|
|
190
|
+
* @param jettonMaster - Jetton master contract address
|
|
191
|
+
*/
|
|
192
|
+
async getJettonBalance(jettonMaster) {
|
|
193
|
+
return this._account.getJettonBalance(jettonMaster);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get the underlying WDK account
|
|
197
|
+
* Useful for advanced operations not covered by this adapter
|
|
198
|
+
*/
|
|
199
|
+
getWDKAccount() {
|
|
200
|
+
return this._account;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
async function createWDKTonSigner(account) {
|
|
204
|
+
const adapter = new WDKTonSignerAdapter(account);
|
|
205
|
+
await adapter.initialize();
|
|
206
|
+
return adapter;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// src/adapters/svm-adapter.ts
|
|
210
|
+
var WDKSvmSignerAdapter = class {
|
|
211
|
+
_account;
|
|
212
|
+
_address = null;
|
|
213
|
+
_initialized = false;
|
|
214
|
+
constructor(account) {
|
|
215
|
+
if (!account) {
|
|
216
|
+
throw new Error("WDK Solana account is required");
|
|
217
|
+
}
|
|
218
|
+
this._account = account;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Get the wallet address (base58)
|
|
222
|
+
* @throws Error if not initialized
|
|
223
|
+
*/
|
|
224
|
+
get address() {
|
|
225
|
+
if (!this._address) {
|
|
226
|
+
throw new Error(
|
|
227
|
+
"Solana signer not initialized. Call initialize() first or use createWDKSvmSigner()."
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
return this._address;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Check if the adapter is initialized
|
|
234
|
+
*/
|
|
235
|
+
get isInitialized() {
|
|
236
|
+
return this._initialized;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Initialize the adapter by fetching the address
|
|
240
|
+
* Must be called before using the signer
|
|
241
|
+
*/
|
|
242
|
+
async initialize() {
|
|
243
|
+
if (this._initialized) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const addressStr = await this._account.getAddress();
|
|
247
|
+
this._address = addressStr;
|
|
248
|
+
this._initialized = true;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Sign transactions with this signer
|
|
252
|
+
*
|
|
253
|
+
* This method signs the message bytes of each transaction and returns
|
|
254
|
+
* signature dictionaries mapping address to signature.
|
|
255
|
+
*
|
|
256
|
+
* @param transactions - Array of transactions to sign
|
|
257
|
+
* @returns Array of signature dictionaries
|
|
258
|
+
*/
|
|
259
|
+
async signTransactions(transactions) {
|
|
260
|
+
if (!transactions || transactions.length === 0) {
|
|
261
|
+
return [];
|
|
262
|
+
}
|
|
263
|
+
const results = [];
|
|
264
|
+
for (const tx of transactions) {
|
|
265
|
+
if (!tx.messageBytes || tx.messageBytes.length === 0) {
|
|
266
|
+
throw new Error("Transaction messageBytes must not be empty");
|
|
267
|
+
}
|
|
268
|
+
const signature = await this._account.sign(tx.messageBytes);
|
|
269
|
+
results.push({
|
|
270
|
+
[this._address]: signature
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
return results;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Sign a single message (utility method)
|
|
277
|
+
* @param message - Message bytes to sign
|
|
278
|
+
* @returns Signature bytes
|
|
279
|
+
*/
|
|
280
|
+
async sign(message) {
|
|
281
|
+
return this._account.sign(message);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Get SOL balance in lamports
|
|
285
|
+
*/
|
|
286
|
+
async getBalance() {
|
|
287
|
+
return this._account.getBalance();
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Get SPL token balance
|
|
291
|
+
* @param mint - Token mint address
|
|
292
|
+
*/
|
|
293
|
+
async getTokenBalance(mint) {
|
|
294
|
+
return this._account.getTokenBalance(mint);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Transfer SPL tokens
|
|
298
|
+
* @param params - Transfer parameters
|
|
299
|
+
* @returns Transaction signature
|
|
300
|
+
*/
|
|
301
|
+
async transfer(params) {
|
|
302
|
+
return this._account.transfer(params);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
async function createWDKSvmSigner(account) {
|
|
306
|
+
const adapter = new WDKSvmSignerAdapter(account);
|
|
307
|
+
await adapter.initialize();
|
|
308
|
+
return adapter;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/adapters/tron-adapter.ts
|
|
312
|
+
var WDKTronSignerAdapter = class {
|
|
313
|
+
_account;
|
|
314
|
+
_address = null;
|
|
315
|
+
_initialized = false;
|
|
316
|
+
_rpcUrl;
|
|
317
|
+
constructor(account, rpcUrl = "https://api.trongrid.io") {
|
|
318
|
+
if (!account) {
|
|
319
|
+
throw new Error("WDK TRON account is required");
|
|
320
|
+
}
|
|
321
|
+
this._account = account;
|
|
322
|
+
this._rpcUrl = rpcUrl;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Get the wallet address (T-prefix base58check)
|
|
326
|
+
* @throws Error if not initialized
|
|
327
|
+
*/
|
|
328
|
+
get address() {
|
|
329
|
+
if (!this._address) {
|
|
330
|
+
throw new Error(
|
|
331
|
+
"TRON signer not initialized. Call initialize() first or use createWDKTronSigner()."
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
return this._address;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Check if the adapter is initialized
|
|
338
|
+
*/
|
|
339
|
+
get isInitialized() {
|
|
340
|
+
return this._initialized;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Initialize the adapter by fetching the address
|
|
344
|
+
* Must be called before using the signer
|
|
345
|
+
*/
|
|
346
|
+
async initialize() {
|
|
347
|
+
if (this._initialized) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
this._address = await this._account.getAddress();
|
|
351
|
+
this._initialized = true;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Sign a TRC20 transfer transaction
|
|
355
|
+
*
|
|
356
|
+
* This method:
|
|
357
|
+
* 1. Builds a TRC20 transfer transaction
|
|
358
|
+
* 2. Signs it using the WDK account
|
|
359
|
+
* 3. Returns the hex-encoded signed transaction
|
|
360
|
+
*
|
|
361
|
+
* @param params - Transaction parameters
|
|
362
|
+
* @returns Hex-encoded signed transaction
|
|
363
|
+
*/
|
|
364
|
+
async signTransaction(params) {
|
|
365
|
+
if (!params.contractAddress) {
|
|
366
|
+
throw new Error("contractAddress is required");
|
|
367
|
+
}
|
|
368
|
+
if (!params.to) {
|
|
369
|
+
throw new Error("recipient address (to) is required");
|
|
370
|
+
}
|
|
371
|
+
if (!params.amount || BigInt(params.amount) <= 0n) {
|
|
372
|
+
throw new Error("amount must be a positive value");
|
|
373
|
+
}
|
|
374
|
+
const blockInfo = await this.getBlockInfo();
|
|
375
|
+
const feeLimit = params.feeLimit ?? 1e8;
|
|
376
|
+
const transaction = await this.buildTrc20Transaction({
|
|
377
|
+
contractAddress: params.contractAddress,
|
|
378
|
+
to: params.to,
|
|
379
|
+
amount: params.amount,
|
|
380
|
+
feeLimit,
|
|
381
|
+
refBlockBytes: blockInfo.refBlockBytes,
|
|
382
|
+
refBlockHash: blockInfo.refBlockHash,
|
|
383
|
+
expiration: params.expiration ?? blockInfo.expiration
|
|
384
|
+
});
|
|
385
|
+
const signedTx = await this._account.signTransaction(transaction);
|
|
386
|
+
return this.serializeTransaction(signedTx);
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get the current reference block info for transaction building
|
|
390
|
+
* This is required for TRON's replay protection mechanism
|
|
391
|
+
*/
|
|
392
|
+
async getBlockInfo() {
|
|
393
|
+
try {
|
|
394
|
+
const response = await fetch(`${this._rpcUrl}/wallet/getnowblock`, {
|
|
395
|
+
method: "POST",
|
|
396
|
+
headers: { "Content-Type": "application/json" },
|
|
397
|
+
body: JSON.stringify({})
|
|
398
|
+
});
|
|
399
|
+
if (!response.ok) {
|
|
400
|
+
throw new Error(`Failed to get block info: ${response.status}`);
|
|
401
|
+
}
|
|
402
|
+
const block = await response.json();
|
|
403
|
+
const blockNum = block.block_header.raw_data.number;
|
|
404
|
+
const refBlockBytes = blockNum.toString(16).padStart(8, "0").slice(-4);
|
|
405
|
+
const refBlockHash = block.blockID.slice(16, 32);
|
|
406
|
+
const expiration = block.block_header.raw_data.timestamp + 6e4;
|
|
407
|
+
return {
|
|
408
|
+
refBlockBytes,
|
|
409
|
+
refBlockHash,
|
|
410
|
+
expiration
|
|
411
|
+
};
|
|
412
|
+
} catch (error) {
|
|
413
|
+
throw new Error(
|
|
414
|
+
`Failed to get TRON block info: ${error instanceof Error ? error.message : String(error)}`
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Build a TRC20 transfer transaction
|
|
420
|
+
*/
|
|
421
|
+
async buildTrc20Transaction(params) {
|
|
422
|
+
const functionSelector = "transfer(address,uint256)";
|
|
423
|
+
const toAddressHex = this.addressToHex(params.to).slice(2).padStart(64, "0");
|
|
424
|
+
const amountHex = BigInt(params.amount).toString(16).padStart(64, "0");
|
|
425
|
+
const parameter = toAddressHex + amountHex;
|
|
426
|
+
try {
|
|
427
|
+
const response = await fetch(`${this._rpcUrl}/wallet/triggersmartcontract`, {
|
|
428
|
+
method: "POST",
|
|
429
|
+
headers: { "Content-Type": "application/json" },
|
|
430
|
+
body: JSON.stringify({
|
|
431
|
+
owner_address: this.addressToHex(this._address),
|
|
432
|
+
contract_address: this.addressToHex(params.contractAddress),
|
|
433
|
+
function_selector: functionSelector,
|
|
434
|
+
parameter,
|
|
435
|
+
fee_limit: params.feeLimit
|
|
436
|
+
})
|
|
437
|
+
});
|
|
438
|
+
if (!response.ok) {
|
|
439
|
+
throw new Error(`Failed to build transaction: ${response.status}`);
|
|
440
|
+
}
|
|
441
|
+
const result = await response.json();
|
|
442
|
+
if (result.result?.code) {
|
|
443
|
+
throw new Error(`Transaction build failed: ${result.result.message}`);
|
|
444
|
+
}
|
|
445
|
+
return result.transaction;
|
|
446
|
+
} catch (error) {
|
|
447
|
+
throw new Error(
|
|
448
|
+
`Failed to build TRC20 transaction: ${error instanceof Error ? error.message : String(error)}`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Serialize a signed transaction to hex format
|
|
454
|
+
*/
|
|
455
|
+
serializeTransaction(signedTx) {
|
|
456
|
+
if (signedTx.signature && signedTx.signature.length > 0) {
|
|
457
|
+
return JSON.stringify(signedTx);
|
|
458
|
+
}
|
|
459
|
+
return signedTx.raw_data_hex;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Convert TRON base58 address to hex format
|
|
463
|
+
*/
|
|
464
|
+
addressToHex(address) {
|
|
465
|
+
if (address.startsWith("41") || address.startsWith("0x")) {
|
|
466
|
+
return address.startsWith("0x") ? "41" + address.slice(2) : address;
|
|
467
|
+
}
|
|
468
|
+
const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
469
|
+
let num = BigInt(0);
|
|
470
|
+
for (const char of address) {
|
|
471
|
+
num = num * BigInt(58) + BigInt(ALPHABET.indexOf(char));
|
|
472
|
+
}
|
|
473
|
+
let hex = num.toString(16);
|
|
474
|
+
let leadingZeros = 0;
|
|
475
|
+
for (const char of address) {
|
|
476
|
+
if (char === "1") leadingZeros++;
|
|
477
|
+
else break;
|
|
478
|
+
}
|
|
479
|
+
hex = "00".repeat(leadingZeros) + hex;
|
|
480
|
+
return hex.slice(0, 42);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Get TRX balance in SUN
|
|
484
|
+
*/
|
|
485
|
+
async getBalance() {
|
|
486
|
+
return this._account.getBalance();
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Get TRC20 token balance
|
|
490
|
+
* @param contractAddress - TRC20 contract address
|
|
491
|
+
*/
|
|
492
|
+
async getTrc20Balance(contractAddress) {
|
|
493
|
+
return this._account.getTrc20Balance(contractAddress);
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
async function createWDKTronSigner(account, rpcUrl) {
|
|
497
|
+
const adapter = new WDKTronSignerAdapter(account, rpcUrl);
|
|
498
|
+
await adapter.initialize();
|
|
499
|
+
return adapter;
|
|
500
|
+
}
|
|
501
|
+
|
|
87
502
|
// src/cache.ts
|
|
88
503
|
var DEFAULT_CACHE_CONFIG = {
|
|
89
504
|
defaultTTL: 3e4,
|
|
@@ -573,6 +988,11 @@ var DEFAULT_CHAINS = {
|
|
|
573
988
|
network: "eip155:130",
|
|
574
989
|
name: "unichain"
|
|
575
990
|
},
|
|
991
|
+
optimism: {
|
|
992
|
+
chainId: 10,
|
|
993
|
+
network: "eip155:10",
|
|
994
|
+
name: "optimism"
|
|
995
|
+
},
|
|
576
996
|
polygon: {
|
|
577
997
|
chainId: 137,
|
|
578
998
|
network: "eip155:137",
|
|
@@ -584,6 +1004,7 @@ var DEFAULT_RPC_ENDPOINTS = {
|
|
|
584
1004
|
arbitrum: "https://arb1.arbitrum.io/rpc",
|
|
585
1005
|
base: "https://mainnet.base.org",
|
|
586
1006
|
ink: "https://rpc-gel.inkonchain.com",
|
|
1007
|
+
optimism: "https://mainnet.optimism.io",
|
|
587
1008
|
polygon: "https://polygon-rpc.com"
|
|
588
1009
|
};
|
|
589
1010
|
var USDT0_ADDRESSES = {
|
|
@@ -591,7 +1012,7 @@ var USDT0_ADDRESSES = {
|
|
|
591
1012
|
arbitrum: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
|
|
592
1013
|
ink: "0x0200C29006150606B650577BBE7B6248F58470c1",
|
|
593
1014
|
berachain: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
|
|
594
|
-
unichain: "
|
|
1015
|
+
unichain: "0x9151434b16b9763660705744891fA906F660EcC5"
|
|
595
1016
|
};
|
|
596
1017
|
var USDC_ADDRESSES = {
|
|
597
1018
|
ethereum: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
@@ -770,6 +1191,9 @@ var WDKErrorCode = /* @__PURE__ */ ((WDKErrorCode2) => {
|
|
|
770
1191
|
WDKErrorCode2[WDKErrorCode2["RPC_TIMEOUT"] = 8002] = "RPC_TIMEOUT";
|
|
771
1192
|
WDKErrorCode2[WDKErrorCode2["RPC_RATE_LIMITED"] = 8003] = "RPC_RATE_LIMITED";
|
|
772
1193
|
WDKErrorCode2[WDKErrorCode2["RPC_CONNECTION_FAILED"] = 8004] = "RPC_CONNECTION_FAILED";
|
|
1194
|
+
WDKErrorCode2[WDKErrorCode2["PROTOCOL_NOT_REGISTERED"] = 8101] = "PROTOCOL_NOT_REGISTERED";
|
|
1195
|
+
WDKErrorCode2[WDKErrorCode2["PROTOCOL_EXECUTION_FAILED"] = 8102] = "PROTOCOL_EXECUTION_FAILED";
|
|
1196
|
+
WDKErrorCode2[WDKErrorCode2["INVALID_PARAMETER"] = 8103] = "INVALID_PARAMETER";
|
|
773
1197
|
WDKErrorCode2[WDKErrorCode2["UNKNOWN_ERROR"] = 9999] = "UNKNOWN_ERROR";
|
|
774
1198
|
return WDKErrorCode2;
|
|
775
1199
|
})(WDKErrorCode || {});
|
|
@@ -1351,6 +1775,13 @@ var WDKSigner = class {
|
|
|
1351
1775
|
}
|
|
1352
1776
|
try {
|
|
1353
1777
|
const account = await this.getAccount();
|
|
1778
|
+
if (!account.estimateGas) {
|
|
1779
|
+
throw new TransactionError(
|
|
1780
|
+
6002 /* GAS_ESTIMATION_FAILED */,
|
|
1781
|
+
`Gas estimation is not supported by this WDK account on ${this._chain}`,
|
|
1782
|
+
{ chain: this._chain, context: { to: params.to } }
|
|
1783
|
+
);
|
|
1784
|
+
}
|
|
1354
1785
|
return await withRetry(async () => {
|
|
1355
1786
|
const estimatePromise = account.estimateGas({
|
|
1356
1787
|
to: params.to,
|
|
@@ -1455,24 +1886,45 @@ var T402WDK = class _T402WDK {
|
|
|
1455
1886
|
static _WDK = null;
|
|
1456
1887
|
static _WalletManagerEvm = null;
|
|
1457
1888
|
static _BridgeUsdt0Evm = null;
|
|
1889
|
+
// Multi-chain wallet module storage
|
|
1890
|
+
static _WalletModules = {};
|
|
1891
|
+
static _ProtocolModules = {};
|
|
1892
|
+
// Multi-chain signer caches
|
|
1893
|
+
_tonSignerCache = /* @__PURE__ */ new Map();
|
|
1894
|
+
_svmSignerCache = /* @__PURE__ */ new Map();
|
|
1895
|
+
_tronSignerCache = /* @__PURE__ */ new Map();
|
|
1458
1896
|
/**
|
|
1459
1897
|
* Register the Tether WDK modules
|
|
1460
1898
|
*
|
|
1461
1899
|
* This must be called before creating T402WDK instances if you want
|
|
1462
1900
|
* to use the actual WDK. Otherwise, a mock implementation is used.
|
|
1463
1901
|
*
|
|
1464
|
-
*
|
|
1902
|
+
* Supports two registration patterns:
|
|
1465
1903
|
*
|
|
1466
|
-
*
|
|
1467
|
-
*
|
|
1468
|
-
*
|
|
1469
|
-
*
|
|
1470
|
-
* import BridgeUsdt0Evm from '@tetherto/wdk-protocol-bridge-usdt0-evm';
|
|
1904
|
+
* 1. Legacy (EVM-only):
|
|
1905
|
+
* ```typescript
|
|
1906
|
+
* T402WDK.registerWDK(WDK, WalletManagerEvm, BridgeUsdt0Evm);
|
|
1907
|
+
* ```
|
|
1471
1908
|
*
|
|
1472
|
-
*
|
|
1473
|
-
*
|
|
1909
|
+
* 2. Unified (multi-chain):
|
|
1910
|
+
* ```typescript
|
|
1911
|
+
* T402WDK.registerWDK(WDK, {
|
|
1912
|
+
* wallets: {
|
|
1913
|
+
* evm: WalletManagerEvm,
|
|
1914
|
+
* ton: WalletManagerTon,
|
|
1915
|
+
* solana: WalletManagerSolana,
|
|
1916
|
+
* tron: WalletManagerTron,
|
|
1917
|
+
* },
|
|
1918
|
+
* protocols: {
|
|
1919
|
+
* bridgeUsdt0Evm: BridgeUsdt0Evm,
|
|
1920
|
+
* bridgeUsdt0Ton: BridgeUsdt0Ton,
|
|
1921
|
+
* }
|
|
1922
|
+
* });
|
|
1923
|
+
* ```
|
|
1924
|
+
*
|
|
1925
|
+
* @throws {WDKInitializationError} If registration fails
|
|
1474
1926
|
*/
|
|
1475
|
-
static registerWDK(WDK,
|
|
1927
|
+
static registerWDK(WDK, modulesOrWalletManager, BridgeUsdt0Evm) {
|
|
1476
1928
|
if (!WDK) {
|
|
1477
1929
|
throw new WDKInitializationError("WDK constructor is required");
|
|
1478
1930
|
}
|
|
@@ -1480,8 +1932,18 @@ var T402WDK = class _T402WDK {
|
|
|
1480
1932
|
throw new WDKInitializationError("WDK must be a constructor function");
|
|
1481
1933
|
}
|
|
1482
1934
|
_T402WDK._WDK = WDK;
|
|
1483
|
-
|
|
1484
|
-
|
|
1935
|
+
if (modulesOrWalletManager && typeof modulesOrWalletManager === "object" && ("wallets" in modulesOrWalletManager || "protocols" in modulesOrWalletManager)) {
|
|
1936
|
+
const modules = modulesOrWalletManager;
|
|
1937
|
+
_T402WDK._WalletModules = modules.wallets ?? {};
|
|
1938
|
+
_T402WDK._ProtocolModules = modules.protocols ?? {};
|
|
1939
|
+
_T402WDK._WalletManagerEvm = modules.wallets?.evm ?? null;
|
|
1940
|
+
_T402WDK._BridgeUsdt0Evm = modules.protocols?.bridgeUsdt0Evm ?? null;
|
|
1941
|
+
} else {
|
|
1942
|
+
_T402WDK._WalletManagerEvm = modulesOrWalletManager ?? null;
|
|
1943
|
+
_T402WDK._BridgeUsdt0Evm = BridgeUsdt0Evm ?? null;
|
|
1944
|
+
_T402WDK._WalletModules = { evm: modulesOrWalletManager };
|
|
1945
|
+
_T402WDK._ProtocolModules = { bridgeUsdt0Evm: BridgeUsdt0Evm };
|
|
1946
|
+
}
|
|
1485
1947
|
}
|
|
1486
1948
|
/**
|
|
1487
1949
|
* Check if WDK is registered
|
|
@@ -1501,6 +1963,40 @@ var T402WDK = class _T402WDK {
|
|
|
1501
1963
|
static isBridgeRegistered() {
|
|
1502
1964
|
return _T402WDK._BridgeUsdt0Evm !== null;
|
|
1503
1965
|
}
|
|
1966
|
+
/**
|
|
1967
|
+
* Check if TON wallet manager is registered
|
|
1968
|
+
*/
|
|
1969
|
+
static isTonRegistered() {
|
|
1970
|
+
return _T402WDK._WalletModules.ton !== void 0;
|
|
1971
|
+
}
|
|
1972
|
+
/**
|
|
1973
|
+
* Check if Solana wallet manager is registered
|
|
1974
|
+
*/
|
|
1975
|
+
static isSolanaRegistered() {
|
|
1976
|
+
return _T402WDK._WalletModules.solana !== void 0;
|
|
1977
|
+
}
|
|
1978
|
+
/**
|
|
1979
|
+
* Check if TRON wallet manager is registered
|
|
1980
|
+
*/
|
|
1981
|
+
static isTronRegistered() {
|
|
1982
|
+
return _T402WDK._WalletModules.tron !== void 0;
|
|
1983
|
+
}
|
|
1984
|
+
/**
|
|
1985
|
+
* Get all registered wallet modules
|
|
1986
|
+
*/
|
|
1987
|
+
static getRegisteredWalletModules() {
|
|
1988
|
+
return Object.keys(_T402WDK._WalletModules).filter(
|
|
1989
|
+
(key) => _T402WDK._WalletModules[key] !== void 0
|
|
1990
|
+
);
|
|
1991
|
+
}
|
|
1992
|
+
/**
|
|
1993
|
+
* Get all registered protocol modules
|
|
1994
|
+
*/
|
|
1995
|
+
static getRegisteredProtocolModules() {
|
|
1996
|
+
return Object.keys(_T402WDK._ProtocolModules).filter(
|
|
1997
|
+
(key) => _T402WDK._ProtocolModules[key] !== void 0
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
1504
2000
|
/**
|
|
1505
2001
|
* Generate a new random seed phrase
|
|
1506
2002
|
*
|
|
@@ -1522,6 +2018,124 @@ var T402WDK = class _T402WDK {
|
|
|
1522
2018
|
);
|
|
1523
2019
|
}
|
|
1524
2020
|
}
|
|
2021
|
+
/**
|
|
2022
|
+
* Quick setup: seed phrase + chains + modules → ready-to-use T402WDK.
|
|
2023
|
+
*
|
|
2024
|
+
* Registers all provided wallet/protocol modules and creates a fully
|
|
2025
|
+
* configured instance in a single call.
|
|
2026
|
+
*
|
|
2027
|
+
* @example
|
|
2028
|
+
* ```typescript
|
|
2029
|
+
* import WDK from '@tetherto/wdk';
|
|
2030
|
+
* import WalletManagerEvm from '@tetherto/wdk-wallet-evm';
|
|
2031
|
+
* import BridgeUsdt0Evm from '@tetherto/wdk-protocol-bridge-usdt0-evm';
|
|
2032
|
+
*
|
|
2033
|
+
* const wallet = T402WDK.create({
|
|
2034
|
+
* seedPhrase: 'your twelve word seed phrase ...',
|
|
2035
|
+
* chains: {
|
|
2036
|
+
* arbitrum: 'https://arb1.arbitrum.io/rpc',
|
|
2037
|
+
* base: 'https://mainnet.base.org',
|
|
2038
|
+
* },
|
|
2039
|
+
* modules: {
|
|
2040
|
+
* wallets: { evm: WalletManagerEvm },
|
|
2041
|
+
* protocols: { bridgeUsdt0Evm: BridgeUsdt0Evm },
|
|
2042
|
+
* },
|
|
2043
|
+
* });
|
|
2044
|
+
* ```
|
|
2045
|
+
*/
|
|
2046
|
+
static create(WDK, config) {
|
|
2047
|
+
_T402WDK.registerWDK(WDK, config.modules);
|
|
2048
|
+
return new _T402WDK(config.seedPhrase, config.chains, config.options);
|
|
2049
|
+
}
|
|
2050
|
+
/**
|
|
2051
|
+
* Create a T402WDK from a pre-configured @tetherto/wdk instance.
|
|
2052
|
+
*
|
|
2053
|
+
* Wraps an existing WDK instance (already has wallets/protocols registered)
|
|
2054
|
+
* into a T402WDK without re-registering modules.
|
|
2055
|
+
*
|
|
2056
|
+
* @param wdkInstance - A pre-configured WDK instance
|
|
2057
|
+
* @param config - EVM chain configuration (RPC endpoints)
|
|
2058
|
+
* @param options - Additional options
|
|
2059
|
+
*/
|
|
2060
|
+
static fromWDK(wdkInstance, config = {}, options) {
|
|
2061
|
+
if (!wdkInstance) {
|
|
2062
|
+
throw new WDKInitializationError("WDK instance is required");
|
|
2063
|
+
}
|
|
2064
|
+
const instance = new _T402WDK("__from_wdk__", config, options);
|
|
2065
|
+
instance._wdk = wdkInstance;
|
|
2066
|
+
instance._initializationError = null;
|
|
2067
|
+
return instance;
|
|
2068
|
+
}
|
|
2069
|
+
/**
|
|
2070
|
+
* Get all signers as an array ready for T402 HTTP clients.
|
|
2071
|
+
*
|
|
2072
|
+
* Returns signer entries for all configured EVM chains, plus any
|
|
2073
|
+
* registered non-EVM chains (TON, Solana, TRON).
|
|
2074
|
+
*
|
|
2075
|
+
* @example
|
|
2076
|
+
* ```typescript
|
|
2077
|
+
* const signers = await wallet.getAllSigners();
|
|
2078
|
+
* const client = createT402HTTPClient({ signers });
|
|
2079
|
+
* ```
|
|
2080
|
+
*/
|
|
2081
|
+
async getAllSigners(options) {
|
|
2082
|
+
const accountIndex = options?.accountIndex ?? 0;
|
|
2083
|
+
const schemes = options?.schemes ?? ["exact"];
|
|
2084
|
+
const includeNonEvm = options?.includeNonEvm ?? true;
|
|
2085
|
+
const entries = [];
|
|
2086
|
+
for (const chain of this.getConfiguredChains()) {
|
|
2087
|
+
const config = this._normalizedChains.get(chain);
|
|
2088
|
+
if (!config) continue;
|
|
2089
|
+
try {
|
|
2090
|
+
const signer = await this.getSigner(chain, accountIndex);
|
|
2091
|
+
for (const scheme of schemes) {
|
|
2092
|
+
entries.push({
|
|
2093
|
+
scheme,
|
|
2094
|
+
network: config.network,
|
|
2095
|
+
signer,
|
|
2096
|
+
family: "evm"
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
} catch {
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
if (!includeNonEvm) {
|
|
2103
|
+
return entries;
|
|
2104
|
+
}
|
|
2105
|
+
if (_T402WDK.isTonRegistered()) {
|
|
2106
|
+
try {
|
|
2107
|
+
const signer = await this.getTonSigner(accountIndex);
|
|
2108
|
+
for (const scheme of schemes) {
|
|
2109
|
+
entries.push({ scheme, network: "ton:mainnet", signer, family: "ton" });
|
|
2110
|
+
}
|
|
2111
|
+
} catch {
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
if (_T402WDK.isSolanaRegistered()) {
|
|
2115
|
+
try {
|
|
2116
|
+
const signer = await this.getSvmSigner(accountIndex);
|
|
2117
|
+
for (const scheme of schemes) {
|
|
2118
|
+
entries.push({
|
|
2119
|
+
scheme,
|
|
2120
|
+
network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
2121
|
+
signer,
|
|
2122
|
+
family: "svm"
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
} catch {
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
if (_T402WDK.isTronRegistered()) {
|
|
2129
|
+
try {
|
|
2130
|
+
const signer = await this.getTronSigner(accountIndex);
|
|
2131
|
+
for (const scheme of schemes) {
|
|
2132
|
+
entries.push({ scheme, network: "tron:mainnet", signer, family: "tron" });
|
|
2133
|
+
}
|
|
2134
|
+
} catch {
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
return entries;
|
|
2138
|
+
}
|
|
1525
2139
|
/**
|
|
1526
2140
|
* Create a new T402WDK instance
|
|
1527
2141
|
*
|
|
@@ -1531,16 +2145,19 @@ var T402WDK = class _T402WDK {
|
|
|
1531
2145
|
* @throws {WDKInitializationError} If seed phrase is invalid
|
|
1532
2146
|
*/
|
|
1533
2147
|
constructor(seedPhrase, config = {}, options = {}) {
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
2148
|
+
const isFromWDK = seedPhrase === "__from_wdk__";
|
|
2149
|
+
if (!isFromWDK) {
|
|
2150
|
+
if (!seedPhrase || typeof seedPhrase !== "string") {
|
|
2151
|
+
throw new WDKInitializationError("Seed phrase is required and must be a string");
|
|
2152
|
+
}
|
|
2153
|
+
const words = seedPhrase.trim().split(/\s+/);
|
|
2154
|
+
const validWordCounts = [12, 15, 18, 21, 24];
|
|
2155
|
+
if (!validWordCounts.includes(words.length)) {
|
|
2156
|
+
throw new WDKInitializationError(
|
|
2157
|
+
`Invalid seed phrase: expected 12, 15, 18, 21, or 24 words, got ${words.length}`,
|
|
2158
|
+
{ context: { wordCount: words.length } }
|
|
2159
|
+
);
|
|
2160
|
+
}
|
|
1544
2161
|
}
|
|
1545
2162
|
this._seedPhrase = seedPhrase;
|
|
1546
2163
|
this._balanceCache = new BalanceCache(options.cache);
|
|
@@ -1558,7 +2175,7 @@ var T402WDK = class _T402WDK {
|
|
|
1558
2175
|
}
|
|
1559
2176
|
}
|
|
1560
2177
|
this._addDefaultChainsIfNeeded();
|
|
1561
|
-
if (_T402WDK._WDK) {
|
|
2178
|
+
if (!isFromWDK && _T402WDK._WDK) {
|
|
1562
2179
|
this._initializeWDK();
|
|
1563
2180
|
}
|
|
1564
2181
|
}
|
|
@@ -1720,6 +2337,195 @@ var T402WDK = class _T402WDK {
|
|
|
1720
2337
|
*/
|
|
1721
2338
|
clearSignerCache() {
|
|
1722
2339
|
this._signerCache.clear();
|
|
2340
|
+
this._tonSignerCache.clear();
|
|
2341
|
+
this._svmSignerCache.clear();
|
|
2342
|
+
this._tronSignerCache.clear();
|
|
2343
|
+
}
|
|
2344
|
+
// ========== Multi-Chain Signers ==========
|
|
2345
|
+
/**
|
|
2346
|
+
* Get a TON signer for T402 payments
|
|
2347
|
+
*
|
|
2348
|
+
* @param accountIndex - HD wallet account index (default: 0)
|
|
2349
|
+
* @throws {ChainError} If TON wallet manager is not registered
|
|
2350
|
+
* @returns An initialized ClientTonSigner
|
|
2351
|
+
*
|
|
2352
|
+
* @example
|
|
2353
|
+
* ```typescript
|
|
2354
|
+
* const tonSigner = await wallet.getTonSigner();
|
|
2355
|
+
*
|
|
2356
|
+
* const client = createT402HTTPClient({
|
|
2357
|
+
* signers: [{ scheme: 'exact', network: 'ton:mainnet', signer: tonSigner }]
|
|
2358
|
+
* });
|
|
2359
|
+
* ```
|
|
2360
|
+
*/
|
|
2361
|
+
async getTonSigner(accountIndex = 0) {
|
|
2362
|
+
const cached = this._tonSignerCache.get(accountIndex);
|
|
2363
|
+
if (cached) {
|
|
2364
|
+
return cached;
|
|
2365
|
+
}
|
|
2366
|
+
if (!_T402WDK._WalletModules.ton) {
|
|
2367
|
+
throw new ChainError(
|
|
2368
|
+
2002 /* CHAIN_NOT_SUPPORTED */,
|
|
2369
|
+
"TON wallet manager not registered. Call T402WDK.registerWDK(WDK, { wallets: { ton: WalletManagerTon } }).",
|
|
2370
|
+
{ chain: "ton" }
|
|
2371
|
+
);
|
|
2372
|
+
}
|
|
2373
|
+
try {
|
|
2374
|
+
const account = await this.wdk.getAccount("ton", accountIndex);
|
|
2375
|
+
const signer = await createWDKTonSigner(account);
|
|
2376
|
+
this._tonSignerCache.set(accountIndex, signer);
|
|
2377
|
+
return signer;
|
|
2378
|
+
} catch (error) {
|
|
2379
|
+
if (isWDKError(error)) {
|
|
2380
|
+
throw error;
|
|
2381
|
+
}
|
|
2382
|
+
throw wrapError(error, 3001 /* SIGNER_NOT_INITIALIZED */, "Failed to create TON signer", {
|
|
2383
|
+
chain: "ton",
|
|
2384
|
+
accountIndex
|
|
2385
|
+
});
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
/**
|
|
2389
|
+
* Get a Solana (SVM) signer for T402 payments
|
|
2390
|
+
*
|
|
2391
|
+
* @param accountIndex - HD wallet account index (default: 0)
|
|
2392
|
+
* @throws {ChainError} If Solana wallet manager is not registered
|
|
2393
|
+
* @returns An initialized TransactionSigner (ClientSvmSigner)
|
|
2394
|
+
*
|
|
2395
|
+
* @example
|
|
2396
|
+
* ```typescript
|
|
2397
|
+
* const svmSigner = await wallet.getSvmSigner();
|
|
2398
|
+
*
|
|
2399
|
+
* const client = createT402HTTPClient({
|
|
2400
|
+
* signers: [{ scheme: 'exact', network: 'solana:mainnet', signer: svmSigner }]
|
|
2401
|
+
* });
|
|
2402
|
+
* ```
|
|
2403
|
+
*/
|
|
2404
|
+
async getSvmSigner(accountIndex = 0) {
|
|
2405
|
+
const cached = this._svmSignerCache.get(accountIndex);
|
|
2406
|
+
if (cached) {
|
|
2407
|
+
return cached;
|
|
2408
|
+
}
|
|
2409
|
+
if (!_T402WDK._WalletModules.solana) {
|
|
2410
|
+
throw new ChainError(
|
|
2411
|
+
2002 /* CHAIN_NOT_SUPPORTED */,
|
|
2412
|
+
"Solana wallet manager not registered. Call T402WDK.registerWDK(WDK, { wallets: { solana: WalletManagerSolana } }).",
|
|
2413
|
+
{ chain: "solana" }
|
|
2414
|
+
);
|
|
2415
|
+
}
|
|
2416
|
+
try {
|
|
2417
|
+
const account = await this.wdk.getAccount(
|
|
2418
|
+
"solana",
|
|
2419
|
+
accountIndex
|
|
2420
|
+
);
|
|
2421
|
+
const signer = await createWDKSvmSigner(account);
|
|
2422
|
+
this._svmSignerCache.set(accountIndex, signer);
|
|
2423
|
+
return signer;
|
|
2424
|
+
} catch (error) {
|
|
2425
|
+
if (isWDKError(error)) {
|
|
2426
|
+
throw error;
|
|
2427
|
+
}
|
|
2428
|
+
throw wrapError(
|
|
2429
|
+
error,
|
|
2430
|
+
3001 /* SIGNER_NOT_INITIALIZED */,
|
|
2431
|
+
"Failed to create Solana signer",
|
|
2432
|
+
{ chain: "solana", accountIndex }
|
|
2433
|
+
);
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
/**
|
|
2437
|
+
* Get a TRON signer for T402 payments
|
|
2438
|
+
*
|
|
2439
|
+
* @param accountIndex - HD wallet account index (default: 0)
|
|
2440
|
+
* @param rpcUrl - Optional custom RPC URL (default: https://api.trongrid.io)
|
|
2441
|
+
* @throws {ChainError} If TRON wallet manager is not registered
|
|
2442
|
+
* @returns An initialized ClientTronSigner
|
|
2443
|
+
*
|
|
2444
|
+
* @example
|
|
2445
|
+
* ```typescript
|
|
2446
|
+
* const tronSigner = await wallet.getTronSigner();
|
|
2447
|
+
*
|
|
2448
|
+
* const client = createT402HTTPClient({
|
|
2449
|
+
* signers: [{ scheme: 'exact', network: 'tron:mainnet', signer: tronSigner }]
|
|
2450
|
+
* });
|
|
2451
|
+
* ```
|
|
2452
|
+
*/
|
|
2453
|
+
async getTronSigner(accountIndex = 0, rpcUrl) {
|
|
2454
|
+
if (!rpcUrl) {
|
|
2455
|
+
const cached = this._tronSignerCache.get(accountIndex);
|
|
2456
|
+
if (cached) {
|
|
2457
|
+
return cached;
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
if (!_T402WDK._WalletModules.tron) {
|
|
2461
|
+
throw new ChainError(
|
|
2462
|
+
2002 /* CHAIN_NOT_SUPPORTED */,
|
|
2463
|
+
"TRON wallet manager not registered. Call T402WDK.registerWDK(WDK, { wallets: { tron: WalletManagerTron } }).",
|
|
2464
|
+
{ chain: "tron" }
|
|
2465
|
+
);
|
|
2466
|
+
}
|
|
2467
|
+
try {
|
|
2468
|
+
const account = await this.wdk.getAccount("tron", accountIndex);
|
|
2469
|
+
const signer = await createWDKTronSigner(account, rpcUrl);
|
|
2470
|
+
if (!rpcUrl) {
|
|
2471
|
+
this._tronSignerCache.set(accountIndex, signer);
|
|
2472
|
+
}
|
|
2473
|
+
return signer;
|
|
2474
|
+
} catch (error) {
|
|
2475
|
+
if (isWDKError(error)) {
|
|
2476
|
+
throw error;
|
|
2477
|
+
}
|
|
2478
|
+
throw wrapError(error, 3001 /* SIGNER_NOT_INITIALIZED */, "Failed to create TRON signer", {
|
|
2479
|
+
chain: "tron",
|
|
2480
|
+
accountIndex
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
/**
|
|
2485
|
+
* Get a signer for a specific chain family
|
|
2486
|
+
*
|
|
2487
|
+
* @param family - Chain family (evm, svm, ton, tron)
|
|
2488
|
+
* @param chainOrIndex - Chain name for EVM, or account index for others
|
|
2489
|
+
* @param accountIndex - Account index (only used for EVM)
|
|
2490
|
+
* @throws {ChainError} If chain family is not supported or not configured
|
|
2491
|
+
* @returns An appropriate signer for the chain family
|
|
2492
|
+
*
|
|
2493
|
+
* @example
|
|
2494
|
+
* ```typescript
|
|
2495
|
+
* // Get EVM signer for Arbitrum
|
|
2496
|
+
* const evmSigner = await wallet.getSignerByFamily('evm', 'arbitrum');
|
|
2497
|
+
*
|
|
2498
|
+
* // Get TON signer
|
|
2499
|
+
* const tonSigner = await wallet.getSignerByFamily('ton');
|
|
2500
|
+
*
|
|
2501
|
+
* // Get Solana signer with account index 1
|
|
2502
|
+
* const svmSigner = await wallet.getSignerByFamily('svm', 1);
|
|
2503
|
+
* ```
|
|
2504
|
+
*/
|
|
2505
|
+
async getSignerByFamily(family, chainOrIndex, accountIndex = 0) {
|
|
2506
|
+
switch (family) {
|
|
2507
|
+
case "evm":
|
|
2508
|
+
if (typeof chainOrIndex !== "string") {
|
|
2509
|
+
throw new ChainError(
|
|
2510
|
+
2003 /* INVALID_CHAIN_CONFIG */,
|
|
2511
|
+
'EVM signers require a chain name (e.g., "arbitrum", "ethereum")',
|
|
2512
|
+
{ chain: family }
|
|
2513
|
+
);
|
|
2514
|
+
}
|
|
2515
|
+
return this.getSigner(chainOrIndex, accountIndex);
|
|
2516
|
+
case "ton":
|
|
2517
|
+
return this.getTonSigner(typeof chainOrIndex === "number" ? chainOrIndex : accountIndex);
|
|
2518
|
+
case "svm":
|
|
2519
|
+
return this.getSvmSigner(typeof chainOrIndex === "number" ? chainOrIndex : accountIndex);
|
|
2520
|
+
case "tron":
|
|
2521
|
+
return this.getTronSigner(typeof chainOrIndex === "number" ? chainOrIndex : accountIndex);
|
|
2522
|
+
default:
|
|
2523
|
+
throw new ChainError(
|
|
2524
|
+
2002 /* CHAIN_NOT_SUPPORTED */,
|
|
2525
|
+
`Chain family "${family}" is not supported. Available: evm, ton, svm, tron`,
|
|
2526
|
+
{ chain: family }
|
|
2527
|
+
);
|
|
2528
|
+
}
|
|
1723
2529
|
}
|
|
1724
2530
|
/**
|
|
1725
2531
|
* Get wallet address for a chain
|
|
@@ -2067,6 +2873,118 @@ var T402WDK = class _T402WDK {
|
|
|
2067
2873
|
}
|
|
2068
2874
|
return (0, import_evm.getBridgeableChains)().filter((chain) => chain !== fromChain);
|
|
2069
2875
|
}
|
|
2876
|
+
// ========== Swap Protocol ==========
|
|
2877
|
+
/**
|
|
2878
|
+
* Check if the Velora swap protocol is registered and available
|
|
2879
|
+
*/
|
|
2880
|
+
canSwap() {
|
|
2881
|
+
return _T402WDK._ProtocolModules.swapVeloraEvm !== void 0;
|
|
2882
|
+
}
|
|
2883
|
+
/**
|
|
2884
|
+
* Get a swap quote for converting a token to USDT0
|
|
2885
|
+
*
|
|
2886
|
+
* @param chain - Chain name (e.g., "ethereum", "arbitrum")
|
|
2887
|
+
* @param fromToken - Input token address
|
|
2888
|
+
* @param amount - Amount to swap in smallest units
|
|
2889
|
+
* @throws {WDKError} If swap protocol is not registered or quote fails
|
|
2890
|
+
*/
|
|
2891
|
+
async getSwapQuote(chain, fromToken, amount) {
|
|
2892
|
+
if (!this.canSwap()) {
|
|
2893
|
+
throw new WDKError(
|
|
2894
|
+
8101 /* PROTOCOL_NOT_REGISTERED */,
|
|
2895
|
+
"Velora swap protocol not registered. Call T402WDK.registerWDK(WDK, { protocols: { swapVeloraEvm: SwapVeloraEvm } })."
|
|
2896
|
+
);
|
|
2897
|
+
}
|
|
2898
|
+
const usdt0Address = USDT0_ADDRESSES[chain];
|
|
2899
|
+
if (!usdt0Address) {
|
|
2900
|
+
throw new ChainError(
|
|
2901
|
+
2002 /* CHAIN_NOT_SUPPORTED */,
|
|
2902
|
+
`Chain "${chain}" does not have a known USDT0 address`,
|
|
2903
|
+
{ chain }
|
|
2904
|
+
);
|
|
2905
|
+
}
|
|
2906
|
+
try {
|
|
2907
|
+
const result = await this.wdk.executeProtocol("swap-velora", {
|
|
2908
|
+
action: "quote",
|
|
2909
|
+
chain,
|
|
2910
|
+
fromToken,
|
|
2911
|
+
toToken: usdt0Address,
|
|
2912
|
+
amount: amount.toString()
|
|
2913
|
+
});
|
|
2914
|
+
return result;
|
|
2915
|
+
} catch (error) {
|
|
2916
|
+
throw wrapError(
|
|
2917
|
+
error,
|
|
2918
|
+
8102 /* PROTOCOL_EXECUTION_FAILED */,
|
|
2919
|
+
`Failed to get swap quote on ${chain}`,
|
|
2920
|
+
{ chain, fromToken, amount: amount.toString() }
|
|
2921
|
+
);
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
/**
|
|
2925
|
+
* Swap any token to USDT0 for payment
|
|
2926
|
+
*
|
|
2927
|
+
* Uses the Velora protocol to execute a token swap on the specified chain.
|
|
2928
|
+
*
|
|
2929
|
+
* @param params - Swap parameters
|
|
2930
|
+
* @throws {WDKError} If swap protocol is not registered or swap fails
|
|
2931
|
+
*
|
|
2932
|
+
* @example
|
|
2933
|
+
* ```typescript
|
|
2934
|
+
* // Swap 0.1 WETH to USDT0 on Arbitrum
|
|
2935
|
+
* const result = await wallet.swapAndPay({
|
|
2936
|
+
* chain: 'arbitrum',
|
|
2937
|
+
* fromToken: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1', // WETH
|
|
2938
|
+
* amount: 100000000000000000n, // 0.1 WETH
|
|
2939
|
+
* maxSlippage: 0.005,
|
|
2940
|
+
* });
|
|
2941
|
+
* ```
|
|
2942
|
+
*/
|
|
2943
|
+
async swapAndPay(params) {
|
|
2944
|
+
if (!this.canSwap()) {
|
|
2945
|
+
throw new WDKError(
|
|
2946
|
+
8101 /* PROTOCOL_NOT_REGISTERED */,
|
|
2947
|
+
"Velora swap protocol not registered. Call T402WDK.registerWDK(WDK, { protocols: { swapVeloraEvm: SwapVeloraEvm } })."
|
|
2948
|
+
);
|
|
2949
|
+
}
|
|
2950
|
+
const usdt0Address = USDT0_ADDRESSES[params.chain];
|
|
2951
|
+
if (!usdt0Address) {
|
|
2952
|
+
throw new ChainError(
|
|
2953
|
+
2002 /* CHAIN_NOT_SUPPORTED */,
|
|
2954
|
+
`Chain "${params.chain}" does not have a known USDT0 address`,
|
|
2955
|
+
{ chain: params.chain }
|
|
2956
|
+
);
|
|
2957
|
+
}
|
|
2958
|
+
if (params.maxSlippage !== void 0 && (params.maxSlippage < 0 || params.maxSlippage > 0.5)) {
|
|
2959
|
+
throw new WDKError(
|
|
2960
|
+
8103 /* INVALID_PARAMETER */,
|
|
2961
|
+
"maxSlippage must be between 0 and 0.5 (0% to 50%)"
|
|
2962
|
+
);
|
|
2963
|
+
}
|
|
2964
|
+
try {
|
|
2965
|
+
const result = await this.wdk.executeProtocol("swap-velora", {
|
|
2966
|
+
action: "swap",
|
|
2967
|
+
chain: params.chain,
|
|
2968
|
+
fromToken: params.fromToken,
|
|
2969
|
+
toToken: usdt0Address,
|
|
2970
|
+
amount: params.amount.toString(),
|
|
2971
|
+
maxSlippage: params.maxSlippage ?? 5e-3
|
|
2972
|
+
});
|
|
2973
|
+
this._balanceCache.invalidateChain(params.chain);
|
|
2974
|
+
return result;
|
|
2975
|
+
} catch (error) {
|
|
2976
|
+
throw wrapError(
|
|
2977
|
+
error,
|
|
2978
|
+
8102 /* PROTOCOL_EXECUTION_FAILED */,
|
|
2979
|
+
`Failed to execute swap on ${params.chain}`,
|
|
2980
|
+
{
|
|
2981
|
+
chain: params.chain,
|
|
2982
|
+
fromToken: params.fromToken,
|
|
2983
|
+
amount: params.amount.toString()
|
|
2984
|
+
}
|
|
2985
|
+
);
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2070
2988
|
// ========== Cache Management ==========
|
|
2071
2989
|
/**
|
|
2072
2990
|
* Check if balance caching is enabled
|
|
@@ -2120,6 +3038,9 @@ var T402WDK = class _T402WDK {
|
|
|
2120
3038
|
dispose() {
|
|
2121
3039
|
this._balanceCache.dispose();
|
|
2122
3040
|
this._signerCache.clear();
|
|
3041
|
+
this._tonSignerCache.clear();
|
|
3042
|
+
this._svmSignerCache.clear();
|
|
3043
|
+
this._tronSignerCache.clear();
|
|
2123
3044
|
}
|
|
2124
3045
|
};
|
|
2125
3046
|
function formatTokenAmount(amount, decimals) {
|
|
@@ -2203,6 +3124,94 @@ function createDirectBridge(signer, chain) {
|
|
|
2203
3124
|
// src/index.ts
|
|
2204
3125
|
var import_evm3 = require("@t402/evm");
|
|
2205
3126
|
|
|
3127
|
+
// src/compatibility.ts
|
|
3128
|
+
var WDK_COMPATIBILITY = {
|
|
3129
|
+
/** Minimum supported @tetherto/wdk version */
|
|
3130
|
+
minVersion: "1.0.0-beta.0",
|
|
3131
|
+
/** Versions that have been tested */
|
|
3132
|
+
testedVersions: ["1.0.0-beta.3", "1.0.0-beta.4", "1.0.0-beta.5"],
|
|
3133
|
+
/** Tested wallet-evm module versions */
|
|
3134
|
+
walletEvmVersions: ["1.0.0-beta.5", "2.0.0-rc.1"],
|
|
3135
|
+
/** Feature availability by @tetherto/wdk core version */
|
|
3136
|
+
features: {
|
|
3137
|
+
signTypedData: "1.0.0-beta.0",
|
|
3138
|
+
estimateGas: "1.0.0-beta.3",
|
|
3139
|
+
multiChainWallets: "1.0.0-beta.0",
|
|
3140
|
+
bridgeProtocol: "1.0.0-beta.3",
|
|
3141
|
+
swapProtocol: "1.0.0-beta.4"
|
|
3142
|
+
},
|
|
3143
|
+
/** Known wallet module minimum versions */
|
|
3144
|
+
walletModuleVersions: {
|
|
3145
|
+
evm: "1.0.0-beta.5",
|
|
3146
|
+
ton: "1.0.0-beta.7",
|
|
3147
|
+
btc: "1.0.0-beta.5",
|
|
3148
|
+
tron: "1.0.0-beta.4",
|
|
3149
|
+
solana: "1.0.0-beta.5",
|
|
3150
|
+
spark: "1.0.0-beta.6"
|
|
3151
|
+
}
|
|
3152
|
+
};
|
|
3153
|
+
function parseVersion(version) {
|
|
3154
|
+
const match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
|
|
3155
|
+
if (!match) {
|
|
3156
|
+
return { major: 0, minor: 0, patch: 0, prerelease: "" };
|
|
3157
|
+
}
|
|
3158
|
+
return {
|
|
3159
|
+
major: parseInt(match[1], 10),
|
|
3160
|
+
minor: parseInt(match[2], 10),
|
|
3161
|
+
patch: parseInt(match[3], 10),
|
|
3162
|
+
prerelease: match[4] ?? ""
|
|
3163
|
+
};
|
|
3164
|
+
}
|
|
3165
|
+
function compareVersions(a, b) {
|
|
3166
|
+
const va = parseVersion(a);
|
|
3167
|
+
const vb = parseVersion(b);
|
|
3168
|
+
if (va.major !== vb.major) return va.major < vb.major ? -1 : 1;
|
|
3169
|
+
if (va.minor !== vb.minor) return va.minor < vb.minor ? -1 : 1;
|
|
3170
|
+
if (va.patch !== vb.patch) return va.patch < vb.patch ? -1 : 1;
|
|
3171
|
+
if (va.prerelease && !vb.prerelease) return -1;
|
|
3172
|
+
if (!va.prerelease && vb.prerelease) return 1;
|
|
3173
|
+
if (va.prerelease && vb.prerelease) {
|
|
3174
|
+
return va.prerelease < vb.prerelease ? -1 : va.prerelease > vb.prerelease ? 1 : 0;
|
|
3175
|
+
}
|
|
3176
|
+
return 0;
|
|
3177
|
+
}
|
|
3178
|
+
function checkWdkCompatibility(version) {
|
|
3179
|
+
const warnings = [];
|
|
3180
|
+
if (compareVersions(version, WDK_COMPATIBILITY.minVersion) < 0) {
|
|
3181
|
+
return {
|
|
3182
|
+
compatible: false,
|
|
3183
|
+
warnings: [
|
|
3184
|
+
`@tetherto/wdk ${version} is below minimum supported version ${WDK_COMPATIBILITY.minVersion}`
|
|
3185
|
+
]
|
|
3186
|
+
};
|
|
3187
|
+
}
|
|
3188
|
+
const isTested = WDK_COMPATIBILITY.testedVersions.includes(version);
|
|
3189
|
+
if (!isTested) {
|
|
3190
|
+
warnings.push(
|
|
3191
|
+
`@tetherto/wdk ${version} has not been explicitly tested. Tested versions: ${WDK_COMPATIBILITY.testedVersions.join(", ")}`
|
|
3192
|
+
);
|
|
3193
|
+
}
|
|
3194
|
+
for (const [feature, minFeatureVersion] of Object.entries(WDK_COMPATIBILITY.features)) {
|
|
3195
|
+
if (compareVersions(version, minFeatureVersion) < 0) {
|
|
3196
|
+
warnings.push(`Feature '${feature}' requires @tetherto/wdk >= ${minFeatureVersion}`);
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
return { compatible: true, warnings };
|
|
3200
|
+
}
|
|
3201
|
+
function checkWalletEvmCompatibility(version) {
|
|
3202
|
+
const warnings = [];
|
|
3203
|
+
const isTested = WDK_COMPATIBILITY.walletEvmVersions.includes(version);
|
|
3204
|
+
if (!isTested) {
|
|
3205
|
+
warnings.push(
|
|
3206
|
+
`@tetherto/wdk-wallet-evm ${version} has not been explicitly tested. Tested versions: ${WDK_COMPATIBILITY.walletEvmVersions.join(", ")}`
|
|
3207
|
+
);
|
|
3208
|
+
}
|
|
3209
|
+
return { compatible: true, warnings };
|
|
3210
|
+
}
|
|
3211
|
+
function getWalletModuleMinVersion(module2) {
|
|
3212
|
+
return WDK_COMPATIBILITY.walletModuleVersions[module2];
|
|
3213
|
+
}
|
|
3214
|
+
|
|
2206
3215
|
// src/hardware/types.ts
|
|
2207
3216
|
var HardwareWalletErrorCode = /* @__PURE__ */ ((HardwareWalletErrorCode2) => {
|
|
2208
3217
|
HardwareWalletErrorCode2["DEVICE_NOT_FOUND"] = "DEVICE_NOT_FOUND";
|
|
@@ -2858,11 +3867,20 @@ function isHardwareWalletSupported() {
|
|
|
2858
3867
|
WDKErrorCode,
|
|
2859
3868
|
WDKInitializationError,
|
|
2860
3869
|
WDKSigner,
|
|
3870
|
+
WDKSvmSignerAdapter,
|
|
3871
|
+
WDKTonSignerAdapter,
|
|
3872
|
+
WDKTronSignerAdapter,
|
|
3873
|
+
WDK_COMPATIBILITY,
|
|
2861
3874
|
WdkBridge,
|
|
3875
|
+
checkWalletEvmCompatibility,
|
|
3876
|
+
checkWdkCompatibility,
|
|
2862
3877
|
createDirectBridge,
|
|
2863
3878
|
createLedgerSigner,
|
|
2864
3879
|
createTrezorSigner,
|
|
2865
3880
|
createWDKSigner,
|
|
3881
|
+
createWDKSvmSigner,
|
|
3882
|
+
createWDKTonSigner,
|
|
3883
|
+
createWDKTronSigner,
|
|
2866
3884
|
detectHardwareWalletSupport,
|
|
2867
3885
|
getBridgeableChains,
|
|
2868
3886
|
getChainFromNetwork,
|
|
@@ -2870,6 +3888,7 @@ function isHardwareWalletSupported() {
|
|
|
2870
3888
|
getNetworkFromChain,
|
|
2871
3889
|
getPreferredToken,
|
|
2872
3890
|
getUsdt0Chains,
|
|
3891
|
+
getWalletModuleMinVersion,
|
|
2873
3892
|
hasErrorCode,
|
|
2874
3893
|
isHardwareWalletSupported,
|
|
2875
3894
|
isWDKError,
|