@t402/evm 2.1.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/dist/cjs/exact/client/index.d.ts +2 -2
- package/dist/cjs/exact/client/index.js +4 -2
- package/dist/cjs/exact/client/index.js.map +1 -1
- package/dist/cjs/exact/facilitator/index.d.ts +1 -1
- package/dist/cjs/exact/facilitator/index.js +40 -4
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/server/index.d.ts +1 -1
- package/dist/cjs/exact/server/index.js +301 -33
- package/dist/cjs/exact/server/index.js.map +1 -1
- package/dist/cjs/exact/v1/client/index.d.ts +1 -1
- package/dist/cjs/exact/v1/client/index.js +3 -1
- package/dist/cjs/exact/v1/client/index.js.map +1 -1
- package/dist/cjs/exact/v1/facilitator/index.d.ts +1 -1
- package/dist/cjs/exact/v1/facilitator/index.js +21 -2
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
- package/dist/cjs/index.d.ts +636 -355
- package/dist/cjs/index.js +1451 -261
- package/dist/cjs/index.js.map +1 -1
- package/dist/{esm/scheme-yqGaK9rK.d.mts → cjs/scheme-B4rXSKCN.d.ts} +18 -16
- package/dist/cjs/scheme-CIar5W2B.d.ts +200 -0
- package/dist/cjs/{scheme-OojTBKAz.d.ts → scheme-CjijeY7y.d.ts} +1 -1
- package/dist/{esm/signer-BkcAzwYi.d.mts → cjs/signer-DcavxxZt.d.ts} +1 -18
- package/dist/cjs/upto/client/index.d.ts +61 -0
- package/dist/cjs/upto/client/index.js +154 -0
- package/dist/cjs/upto/client/index.js.map +1 -0
- package/dist/cjs/upto/index.d.ts +111 -0
- package/dist/cjs/upto/index.js +1030 -0
- package/dist/cjs/upto/index.js.map +1 -0
- package/dist/cjs/v1/index.d.ts +1 -1
- package/dist/cjs/v1/index.js +3 -1
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/{chunk-ACDQ5QNT.mjs → chunk-4FBTQTNM.mjs} +27 -5
- package/dist/esm/chunk-4FBTQTNM.mjs.map +1 -0
- package/dist/esm/chunk-IWSDEZKI.mjs +477 -0
- package/dist/esm/chunk-IWSDEZKI.mjs.map +1 -0
- package/dist/esm/{chunk-LGSG73NJ.mjs → chunk-LM5RZBVP.mjs} +9 -4
- package/dist/esm/{chunk-LGSG73NJ.mjs.map → chunk-LM5RZBVP.mjs.map} +1 -1
- package/dist/esm/chunk-NSSMTXJJ.mjs +8 -0
- package/dist/esm/chunk-NSSMTXJJ.mjs.map +1 -0
- package/dist/esm/chunk-SJ52GTJJ.mjs +411 -0
- package/dist/esm/chunk-SJ52GTJJ.mjs.map +1 -0
- package/dist/esm/chunk-SURTCHSX.mjs +129 -0
- package/dist/esm/chunk-SURTCHSX.mjs.map +1 -0
- package/dist/esm/chunk-SYVPLXYV.mjs +26 -0
- package/dist/esm/chunk-SYVPLXYV.mjs.map +1 -0
- package/dist/esm/{chunk-XYKAO6KJ.mjs → chunk-Y4U7Q543.mjs} +2 -25
- package/dist/esm/chunk-Y4U7Q543.mjs.map +1 -0
- package/dist/esm/{chunk-JBWWBRYY.mjs → chunk-ZWEYARER.mjs} +9 -4
- package/dist/esm/{chunk-JBWWBRYY.mjs.map → chunk-ZWEYARER.mjs.map} +1 -1
- package/dist/esm/exact/client/index.d.mts +2 -2
- package/dist/esm/exact/client/index.mjs +6 -4
- package/dist/esm/exact/client/index.mjs.map +1 -1
- package/dist/esm/exact/facilitator/index.d.mts +1 -1
- package/dist/esm/exact/facilitator/index.mjs +26 -5
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/server/index.d.mts +1 -1
- package/dist/esm/exact/server/index.mjs +29 -30
- package/dist/esm/exact/server/index.mjs.map +1 -1
- package/dist/esm/exact/v1/client/index.d.mts +1 -1
- package/dist/esm/exact/v1/client/index.mjs +4 -2
- package/dist/esm/exact/v1/facilitator/index.d.mts +1 -1
- package/dist/esm/exact/v1/facilitator/index.mjs +4 -2
- package/dist/esm/index.d.mts +636 -355
- package/dist/esm/index.mjs +645 -135
- package/dist/esm/index.mjs.map +1 -1
- package/dist/{cjs/scheme-yqGaK9rK.d.ts → esm/scheme-B4rXSKCN.d.mts} +18 -16
- package/dist/esm/scheme-DATfd6oM.d.mts +200 -0
- package/dist/esm/{scheme-D4mOqq9l.d.mts → scheme-Ddb0dG_F.d.mts} +1 -1
- package/dist/{cjs/signer-BkcAzwYi.d.ts → esm/signer-DcavxxZt.d.mts} +1 -18
- package/dist/esm/upto/client/index.d.mts +61 -0
- package/dist/esm/upto/client/index.mjs +11 -0
- package/dist/esm/upto/client/index.mjs.map +1 -0
- package/dist/esm/upto/index.d.mts +111 -0
- package/dist/esm/upto/index.mjs +26 -0
- package/dist/esm/upto/index.mjs.map +1 -0
- package/dist/esm/v1/index.d.mts +1 -1
- package/dist/esm/v1/index.mjs +5 -3
- package/package.json +30 -6
- package/dist/cjs/scheme-C6uD7PdY.d.ts +0 -130
- package/dist/esm/chunk-ACDQ5QNT.mjs.map +0 -1
- package/dist/esm/chunk-OEXW2OK2.mjs +0 -251
- package/dist/esm/chunk-OEXW2OK2.mjs.map +0 -1
- package/dist/esm/chunk-XYKAO6KJ.mjs.map +0 -1
package/dist/cjs/index.js
CHANGED
|
@@ -3,6 +3,7 @@ var __defProp = Object.defineProperty;
|
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
7
|
var __export = (target, all) => {
|
|
7
8
|
for (var name in all)
|
|
8
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -15,7 +16,9 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
16
|
}
|
|
16
17
|
return to;
|
|
17
18
|
};
|
|
19
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
18
20
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
19
22
|
|
|
20
23
|
// src/index.ts
|
|
21
24
|
var src_exports = {};
|
|
@@ -24,6 +27,7 @@ __export(src_exports, {
|
|
|
24
27
|
BUNDLER_METHODS: () => BUNDLER_METHODS,
|
|
25
28
|
BundlerClient: () => BundlerClient,
|
|
26
29
|
BundlerError: () => BundlerError,
|
|
30
|
+
CrossChainPaymentRouter: () => CrossChainPaymentRouter,
|
|
27
31
|
DEFAULT_GAS_LIMITS: () => DEFAULT_GAS_LIMITS,
|
|
28
32
|
ENTRYPOINT_V06_ADDRESS: () => ENTRYPOINT_V06_ADDRESS,
|
|
29
33
|
ENTRYPOINT_V07_ABI: () => ENTRYPOINT_V07_ABI,
|
|
@@ -35,49 +39,41 @@ __export(src_exports, {
|
|
|
35
39
|
GaslessT402Client: () => GaslessT402Client,
|
|
36
40
|
LAYERZERO_ENDPOINT_IDS: () => LAYERZERO_ENDPOINT_IDS,
|
|
37
41
|
LAYERZERO_ENDPOINT_V2: () => LAYERZERO_ENDPOINT_V2,
|
|
42
|
+
LAYERZERO_SCAN_BASE_URL: () => LAYERZERO_SCAN_BASE_URL,
|
|
43
|
+
LayerZeroScanClient: () => LayerZeroScanClient,
|
|
38
44
|
PaymasterClient: () => PaymasterClient,
|
|
39
45
|
PaymasterType: () => PaymasterType,
|
|
40
|
-
TOKEN_PRIORITY: () => TOKEN_PRIORITY,
|
|
41
|
-
TOKEN_REGISTRY: () => TOKEN_REGISTRY,
|
|
42
|
-
USDC_ADDRESSES: () => USDC_ADDRESSES,
|
|
43
|
-
USDT0_ADDRESSES: () => USDT0_ADDRESSES,
|
|
44
46
|
USDT0_OFT_ADDRESSES: () => USDT0_OFT_ADDRESSES,
|
|
45
|
-
|
|
47
|
+
UptoEvmFacilitatorScheme: () => UptoEvmFacilitatorScheme,
|
|
48
|
+
UptoEvmScheme: () => UptoEvmScheme,
|
|
49
|
+
UptoEvmServerScheme: () => UptoEvmServerScheme,
|
|
46
50
|
Usdt0Bridge: () => Usdt0Bridge,
|
|
47
51
|
UserOpBuilder: () => UserOpBuilder,
|
|
48
52
|
addressToBytes32: () => addressToBytes32,
|
|
49
|
-
authorizationTypes: () => authorizationTypes,
|
|
50
53
|
bytes32ToAddress: () => bytes32ToAddress,
|
|
51
54
|
createBundlerClient: () => createBundlerClient,
|
|
55
|
+
createCrossChainPaymentRouter: () => createCrossChainPaymentRouter,
|
|
52
56
|
createGaslessT402Client: () => createGaslessT402Client,
|
|
57
|
+
createLayerZeroScanClient: () => createLayerZeroScanClient,
|
|
53
58
|
createPaymasterClient: () => createPaymasterClient,
|
|
59
|
+
createUptoEvmFacilitatorScheme: () => createUptoEvmFacilitatorScheme,
|
|
60
|
+
createUptoEvmScheme: () => createUptoEvmScheme,
|
|
61
|
+
createUptoEvmServerScheme: () => createUptoEvmServerScheme,
|
|
54
62
|
createUsdt0Bridge: () => createUsdt0Bridge,
|
|
55
63
|
createUserOpBuilder: () => createUserOpBuilder,
|
|
56
64
|
decodePaymasterAndData: () => decodePaymasterAndData,
|
|
57
|
-
eip3009ABI: () => eip3009ABI,
|
|
58
65
|
encodePaymasterAndData: () => encodePaymasterAndData,
|
|
59
|
-
erc20LegacyABI: () => erc20LegacyABI,
|
|
60
66
|
getBridgeableChains: () => getBridgeableChains,
|
|
61
|
-
getDefaultToken: () => getDefaultToken,
|
|
62
|
-
getEIP712Domain: () => getEIP712Domain,
|
|
63
67
|
getEndpointId: () => getEndpointId,
|
|
64
|
-
getNetworkTokens: () => getNetworkTokens,
|
|
65
|
-
getNetworksForToken: () => getNetworksForToken,
|
|
66
|
-
getTokenByAddress: () => getTokenByAddress,
|
|
67
|
-
getTokenConfig: () => getTokenConfig,
|
|
68
|
-
getUsdt0Networks: () => getUsdt0Networks,
|
|
69
68
|
getUsdt0OftAddress: () => getUsdt0OftAddress,
|
|
70
|
-
legacyAuthorizationTypes: () => legacyAuthorizationTypes,
|
|
71
69
|
packAccountGasLimits: () => packAccountGasLimits,
|
|
72
70
|
packGasFees: () => packGasFees,
|
|
73
71
|
supportsBridging: () => supportsBridging,
|
|
74
|
-
supportsEIP3009: () => supportsEIP3009,
|
|
75
|
-
toClientEvmSigner: () => toClientEvmSigner,
|
|
76
|
-
toFacilitatorEvmSigner: () => toFacilitatorEvmSigner,
|
|
77
72
|
unpackAccountGasLimits: () => unpackAccountGasLimits,
|
|
78
73
|
unpackGasFees: () => unpackGasFees
|
|
79
74
|
});
|
|
80
75
|
module.exports = __toCommonJS(src_exports);
|
|
76
|
+
__reExport(src_exports, require("@t402/evm-core"), module.exports);
|
|
81
77
|
|
|
82
78
|
// src/exact/client/scheme.ts
|
|
83
79
|
var import_viem2 = require("viem");
|
|
@@ -104,54 +100,6 @@ var legacyAuthorizationTypes = {
|
|
|
104
100
|
{ name: "spender", type: "address" }
|
|
105
101
|
]
|
|
106
102
|
};
|
|
107
|
-
var eip3009ABI = [
|
|
108
|
-
{
|
|
109
|
-
inputs: [
|
|
110
|
-
{ name: "from", type: "address" },
|
|
111
|
-
{ name: "to", type: "address" },
|
|
112
|
-
{ name: "value", type: "uint256" },
|
|
113
|
-
{ name: "validAfter", type: "uint256" },
|
|
114
|
-
{ name: "validBefore", type: "uint256" },
|
|
115
|
-
{ name: "nonce", type: "bytes32" },
|
|
116
|
-
{ name: "v", type: "uint8" },
|
|
117
|
-
{ name: "r", type: "bytes32" },
|
|
118
|
-
{ name: "s", type: "bytes32" }
|
|
119
|
-
],
|
|
120
|
-
name: "transferWithAuthorization",
|
|
121
|
-
outputs: [],
|
|
122
|
-
stateMutability: "nonpayable",
|
|
123
|
-
type: "function"
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
inputs: [
|
|
127
|
-
{ name: "from", type: "address" },
|
|
128
|
-
{ name: "to", type: "address" },
|
|
129
|
-
{ name: "value", type: "uint256" },
|
|
130
|
-
{ name: "validAfter", type: "uint256" },
|
|
131
|
-
{ name: "validBefore", type: "uint256" },
|
|
132
|
-
{ name: "nonce", type: "bytes32" },
|
|
133
|
-
{ name: "signature", type: "bytes" }
|
|
134
|
-
],
|
|
135
|
-
name: "transferWithAuthorization",
|
|
136
|
-
outputs: [],
|
|
137
|
-
stateMutability: "nonpayable",
|
|
138
|
-
type: "function"
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
inputs: [{ name: "account", type: "address" }],
|
|
142
|
-
name: "balanceOf",
|
|
143
|
-
outputs: [{ name: "", type: "uint256" }],
|
|
144
|
-
stateMutability: "view",
|
|
145
|
-
type: "function"
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
inputs: [],
|
|
149
|
-
name: "version",
|
|
150
|
-
outputs: [{ name: "", type: "string" }],
|
|
151
|
-
stateMutability: "view",
|
|
152
|
-
type: "function"
|
|
153
|
-
}
|
|
154
|
-
];
|
|
155
103
|
var erc20LegacyABI = [
|
|
156
104
|
{
|
|
157
105
|
inputs: [{ name: "account", type: "address" }],
|
|
@@ -212,7 +160,7 @@ var ExactEvmScheme = class {
|
|
|
212
160
|
*/
|
|
213
161
|
constructor(signer) {
|
|
214
162
|
this.signer = signer;
|
|
215
|
-
this
|
|
163
|
+
__publicField(this, "scheme", "exact");
|
|
216
164
|
}
|
|
217
165
|
/**
|
|
218
166
|
* Creates a payment payload for the Exact scheme.
|
|
@@ -291,7 +239,7 @@ var ExactLegacyEvmScheme = class {
|
|
|
291
239
|
*/
|
|
292
240
|
constructor(signer) {
|
|
293
241
|
this.signer = signer;
|
|
294
|
-
this
|
|
242
|
+
__publicField(this, "scheme", "exact-legacy");
|
|
295
243
|
}
|
|
296
244
|
/**
|
|
297
245
|
* Creates a payment payload for the exact-legacy scheme.
|
|
@@ -366,6 +314,7 @@ var ExactLegacyEvmScheme = class {
|
|
|
366
314
|
|
|
367
315
|
// src/tokens.ts
|
|
368
316
|
var USDT0_ADDRESSES = {
|
|
317
|
+
// === Existing Networks ===
|
|
369
318
|
// Ethereum Mainnet - OFT Adapter (bridge endpoint)
|
|
370
319
|
"eip155:1": "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee",
|
|
371
320
|
// Arbitrum One - Native USDT0
|
|
@@ -374,8 +323,38 @@ var USDT0_ADDRESSES = {
|
|
|
374
323
|
"eip155:57073": "0x0200C29006150606B650577BBE7B6248F58470c1",
|
|
375
324
|
// Berachain Mainnet
|
|
376
325
|
"eip155:80094": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
|
|
377
|
-
// Unichain Mainnet
|
|
378
|
-
"eip155:130": "
|
|
326
|
+
// Unichain Mainnet (updated address)
|
|
327
|
+
"eip155:130": "0x9151434b16b9763660705744891fA906F660EcC5",
|
|
328
|
+
// === Phase 1: High Priority Networks ===
|
|
329
|
+
// Polygon PoS
|
|
330
|
+
"eip155:137": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
|
|
331
|
+
// Mantle
|
|
332
|
+
"eip155:5000": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
|
|
333
|
+
// Optimism
|
|
334
|
+
"eip155:10": "0x01bFF41798a0BcF287b996046Ca68b395DbC1071",
|
|
335
|
+
// Plasma
|
|
336
|
+
"eip155:9745": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
|
|
337
|
+
// Sei
|
|
338
|
+
"eip155:1329": "0x9151434b16b9763660705744891fA906F660EcC5",
|
|
339
|
+
// Conflux eSpace
|
|
340
|
+
"eip155:1030": "0xaf37E8B6C9ED7f6318979f56Fc287d76c30847ff",
|
|
341
|
+
// Monad
|
|
342
|
+
"eip155:143": "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
|
|
343
|
+
// === Phase 2: Medium Priority Networks ===
|
|
344
|
+
// Rootstock (Bitcoin sidechain)
|
|
345
|
+
"eip155:30": "0x779dED0C9e1022225F8e0630b35A9B54Be713736",
|
|
346
|
+
// XLayer (OKX L2)
|
|
347
|
+
"eip155:196": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
|
|
348
|
+
// Flare
|
|
349
|
+
"eip155:14": "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
|
|
350
|
+
// Corn
|
|
351
|
+
"eip155:21000000": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
|
|
352
|
+
// HyperEVM
|
|
353
|
+
"eip155:999": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
|
|
354
|
+
// MegaETH
|
|
355
|
+
"eip155:4326": "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb",
|
|
356
|
+
// Stable
|
|
357
|
+
"eip155:988": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736"
|
|
379
358
|
};
|
|
380
359
|
var USDC_ADDRESSES = {
|
|
381
360
|
// Ethereum Mainnet
|
|
@@ -394,8 +373,18 @@ var USDC_ADDRESSES = {
|
|
|
394
373
|
var USDT_LEGACY_ADDRESSES = {
|
|
395
374
|
// Ethereum Mainnet
|
|
396
375
|
"eip155:1": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
397
|
-
// Polygon Mainnet
|
|
398
|
-
"eip155:137": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F"
|
|
376
|
+
// Polygon Mainnet (native USDT, not USDT0)
|
|
377
|
+
"eip155:137": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
|
|
378
|
+
// BNB Chain (BSC) - BEP-20 USDT
|
|
379
|
+
"eip155:56": "0x55d398326f99059fF775485246999027B3197955",
|
|
380
|
+
// Avalanche C-Chain
|
|
381
|
+
"eip155:43114": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
|
|
382
|
+
// Fantom
|
|
383
|
+
"eip155:250": "0x049d68029688eabf473097a2fc38ef61633a3c7a",
|
|
384
|
+
// Celo
|
|
385
|
+
"eip155:42220": "0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e",
|
|
386
|
+
// Kaia (formerly Klaytn)
|
|
387
|
+
"eip155:8217": "0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167"
|
|
399
388
|
};
|
|
400
389
|
var TOKEN_REGISTRY = {
|
|
401
390
|
// Ethereum Mainnet
|
|
@@ -524,6 +513,15 @@ var TOKEN_REGISTRY = {
|
|
|
524
513
|
},
|
|
525
514
|
// Polygon Mainnet
|
|
526
515
|
"eip155:137": {
|
|
516
|
+
USDT0: {
|
|
517
|
+
address: USDT0_ADDRESSES["eip155:137"],
|
|
518
|
+
symbol: "USDT0",
|
|
519
|
+
name: "TetherToken",
|
|
520
|
+
version: "1",
|
|
521
|
+
decimals: 6,
|
|
522
|
+
tokenType: "eip3009",
|
|
523
|
+
priority: 1
|
|
524
|
+
},
|
|
527
525
|
USDC: {
|
|
528
526
|
address: USDC_ADDRESSES["eip155:137"],
|
|
529
527
|
symbol: "USDC",
|
|
@@ -542,18 +540,228 @@ var TOKEN_REGISTRY = {
|
|
|
542
540
|
tokenType: "legacy",
|
|
543
541
|
priority: 10
|
|
544
542
|
}
|
|
543
|
+
},
|
|
544
|
+
// === Phase 1: High Priority USDT0 Networks ===
|
|
545
|
+
// Optimism Mainnet
|
|
546
|
+
"eip155:10": {
|
|
547
|
+
USDT0: {
|
|
548
|
+
address: USDT0_ADDRESSES["eip155:10"],
|
|
549
|
+
symbol: "USDT0",
|
|
550
|
+
name: "TetherToken",
|
|
551
|
+
version: "1",
|
|
552
|
+
decimals: 6,
|
|
553
|
+
tokenType: "eip3009",
|
|
554
|
+
priority: 1
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
// Mantle Mainnet
|
|
558
|
+
"eip155:5000": {
|
|
559
|
+
USDT0: {
|
|
560
|
+
address: USDT0_ADDRESSES["eip155:5000"],
|
|
561
|
+
symbol: "USDT0",
|
|
562
|
+
name: "TetherToken",
|
|
563
|
+
version: "1",
|
|
564
|
+
decimals: 6,
|
|
565
|
+
tokenType: "eip3009",
|
|
566
|
+
priority: 1
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
// Plasma Mainnet
|
|
570
|
+
"eip155:9745": {
|
|
571
|
+
USDT0: {
|
|
572
|
+
address: USDT0_ADDRESSES["eip155:9745"],
|
|
573
|
+
symbol: "USDT0",
|
|
574
|
+
name: "TetherToken",
|
|
575
|
+
version: "1",
|
|
576
|
+
decimals: 6,
|
|
577
|
+
tokenType: "eip3009",
|
|
578
|
+
priority: 1
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
// Sei Mainnet
|
|
582
|
+
"eip155:1329": {
|
|
583
|
+
USDT0: {
|
|
584
|
+
address: USDT0_ADDRESSES["eip155:1329"],
|
|
585
|
+
symbol: "USDT0",
|
|
586
|
+
name: "TetherToken",
|
|
587
|
+
version: "1",
|
|
588
|
+
decimals: 6,
|
|
589
|
+
tokenType: "eip3009",
|
|
590
|
+
priority: 1
|
|
591
|
+
}
|
|
592
|
+
},
|
|
593
|
+
// Conflux eSpace Mainnet
|
|
594
|
+
"eip155:1030": {
|
|
595
|
+
USDT0: {
|
|
596
|
+
address: USDT0_ADDRESSES["eip155:1030"],
|
|
597
|
+
symbol: "USDT0",
|
|
598
|
+
name: "TetherToken",
|
|
599
|
+
version: "1",
|
|
600
|
+
decimals: 6,
|
|
601
|
+
tokenType: "eip3009",
|
|
602
|
+
priority: 1
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
// Monad Mainnet
|
|
606
|
+
"eip155:143": {
|
|
607
|
+
USDT0: {
|
|
608
|
+
address: USDT0_ADDRESSES["eip155:143"],
|
|
609
|
+
symbol: "USDT0",
|
|
610
|
+
name: "TetherToken",
|
|
611
|
+
version: "1",
|
|
612
|
+
decimals: 6,
|
|
613
|
+
tokenType: "eip3009",
|
|
614
|
+
priority: 1
|
|
615
|
+
}
|
|
616
|
+
},
|
|
617
|
+
// === Phase 2: Medium Priority USDT0 Networks ===
|
|
618
|
+
// Flare Mainnet
|
|
619
|
+
"eip155:14": {
|
|
620
|
+
USDT0: {
|
|
621
|
+
address: USDT0_ADDRESSES["eip155:14"],
|
|
622
|
+
symbol: "USDT0",
|
|
623
|
+
name: "TetherToken",
|
|
624
|
+
version: "1",
|
|
625
|
+
decimals: 6,
|
|
626
|
+
tokenType: "eip3009",
|
|
627
|
+
priority: 1
|
|
628
|
+
}
|
|
629
|
+
},
|
|
630
|
+
// Rootstock Mainnet (Bitcoin sidechain)
|
|
631
|
+
"eip155:30": {
|
|
632
|
+
USDT0: {
|
|
633
|
+
address: USDT0_ADDRESSES["eip155:30"],
|
|
634
|
+
symbol: "USDT0",
|
|
635
|
+
name: "TetherToken",
|
|
636
|
+
version: "1",
|
|
637
|
+
decimals: 6,
|
|
638
|
+
tokenType: "eip3009",
|
|
639
|
+
priority: 1
|
|
640
|
+
}
|
|
641
|
+
},
|
|
642
|
+
// XLayer Mainnet (OKX L2)
|
|
643
|
+
"eip155:196": {
|
|
644
|
+
USDT0: {
|
|
645
|
+
address: USDT0_ADDRESSES["eip155:196"],
|
|
646
|
+
symbol: "USDT0",
|
|
647
|
+
name: "TetherToken",
|
|
648
|
+
version: "1",
|
|
649
|
+
decimals: 6,
|
|
650
|
+
tokenType: "eip3009",
|
|
651
|
+
priority: 1
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
// Stable Mainnet
|
|
655
|
+
"eip155:988": {
|
|
656
|
+
USDT0: {
|
|
657
|
+
address: USDT0_ADDRESSES["eip155:988"],
|
|
658
|
+
symbol: "USDT0",
|
|
659
|
+
name: "TetherToken",
|
|
660
|
+
version: "1",
|
|
661
|
+
decimals: 6,
|
|
662
|
+
tokenType: "eip3009",
|
|
663
|
+
priority: 1
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
// HyperEVM Mainnet
|
|
667
|
+
"eip155:999": {
|
|
668
|
+
USDT0: {
|
|
669
|
+
address: USDT0_ADDRESSES["eip155:999"],
|
|
670
|
+
symbol: "USDT0",
|
|
671
|
+
name: "TetherToken",
|
|
672
|
+
version: "1",
|
|
673
|
+
decimals: 6,
|
|
674
|
+
tokenType: "eip3009",
|
|
675
|
+
priority: 1
|
|
676
|
+
}
|
|
677
|
+
},
|
|
678
|
+
// MegaETH Mainnet
|
|
679
|
+
"eip155:4326": {
|
|
680
|
+
USDT0: {
|
|
681
|
+
address: USDT0_ADDRESSES["eip155:4326"],
|
|
682
|
+
symbol: "USDT0",
|
|
683
|
+
name: "TetherToken",
|
|
684
|
+
version: "1",
|
|
685
|
+
decimals: 6,
|
|
686
|
+
tokenType: "eip3009",
|
|
687
|
+
priority: 1
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
// Corn Mainnet
|
|
691
|
+
"eip155:21000000": {
|
|
692
|
+
USDT0: {
|
|
693
|
+
address: USDT0_ADDRESSES["eip155:21000000"],
|
|
694
|
+
symbol: "USDT0",
|
|
695
|
+
name: "TetherToken",
|
|
696
|
+
version: "1",
|
|
697
|
+
decimals: 6,
|
|
698
|
+
tokenType: "eip3009",
|
|
699
|
+
priority: 1
|
|
700
|
+
}
|
|
701
|
+
},
|
|
702
|
+
// === Legacy USDT Networks (no EIP-3009 support) ===
|
|
703
|
+
// BNB Chain (BSC) - BEP-20 USDT
|
|
704
|
+
"eip155:56": {
|
|
705
|
+
USDT: {
|
|
706
|
+
address: USDT_LEGACY_ADDRESSES["eip155:56"],
|
|
707
|
+
symbol: "USDT",
|
|
708
|
+
name: "Tether USD",
|
|
709
|
+
version: "1",
|
|
710
|
+
decimals: 18,
|
|
711
|
+
// BSC USDT uses 18 decimals
|
|
712
|
+
tokenType: "legacy",
|
|
713
|
+
priority: 10
|
|
714
|
+
}
|
|
715
|
+
},
|
|
716
|
+
// Avalanche C-Chain
|
|
717
|
+
"eip155:43114": {
|
|
718
|
+
USDT: {
|
|
719
|
+
address: USDT_LEGACY_ADDRESSES["eip155:43114"],
|
|
720
|
+
symbol: "USDT",
|
|
721
|
+
name: "TetherToken",
|
|
722
|
+
version: "1",
|
|
723
|
+
decimals: 6,
|
|
724
|
+
tokenType: "legacy",
|
|
725
|
+
priority: 10
|
|
726
|
+
}
|
|
727
|
+
},
|
|
728
|
+
// Fantom
|
|
729
|
+
"eip155:250": {
|
|
730
|
+
USDT: {
|
|
731
|
+
address: USDT_LEGACY_ADDRESSES["eip155:250"],
|
|
732
|
+
symbol: "USDT",
|
|
733
|
+
name: "Frapped USDT",
|
|
734
|
+
version: "1",
|
|
735
|
+
decimals: 6,
|
|
736
|
+
tokenType: "legacy",
|
|
737
|
+
priority: 10
|
|
738
|
+
}
|
|
739
|
+
},
|
|
740
|
+
// Celo
|
|
741
|
+
"eip155:42220": {
|
|
742
|
+
USDT: {
|
|
743
|
+
address: USDT_LEGACY_ADDRESSES["eip155:42220"],
|
|
744
|
+
symbol: "USDT",
|
|
745
|
+
name: "Tether USD",
|
|
746
|
+
version: "1",
|
|
747
|
+
decimals: 18,
|
|
748
|
+
tokenType: "legacy",
|
|
749
|
+
priority: 10
|
|
750
|
+
}
|
|
751
|
+
},
|
|
752
|
+
// Kaia (formerly Klaytn)
|
|
753
|
+
"eip155:8217": {
|
|
754
|
+
USDT: {
|
|
755
|
+
address: USDT_LEGACY_ADDRESSES["eip155:8217"],
|
|
756
|
+
symbol: "USDT",
|
|
757
|
+
name: "Tether USD",
|
|
758
|
+
version: "1",
|
|
759
|
+
decimals: 6,
|
|
760
|
+
tokenType: "legacy",
|
|
761
|
+
priority: 10
|
|
762
|
+
}
|
|
545
763
|
}
|
|
546
764
|
};
|
|
547
|
-
var TOKEN_PRIORITY = {
|
|
548
|
-
USDT0: 1,
|
|
549
|
-
// Highest priority - gasless, cross-chain
|
|
550
|
-
USDC: 2,
|
|
551
|
-
// Second - wide support, EIP-3009
|
|
552
|
-
USDT: 10,
|
|
553
|
-
// Lower - requires approval transaction
|
|
554
|
-
DAI: 5
|
|
555
|
-
// Medium - good support
|
|
556
|
-
};
|
|
557
765
|
function getTokenConfig(network, symbol) {
|
|
558
766
|
return TOKEN_REGISTRY[network]?.[symbol.toUpperCase()];
|
|
559
767
|
}
|
|
@@ -572,42 +780,42 @@ function getTokenByAddress(network, address) {
|
|
|
572
780
|
const lowerAddress = address.toLowerCase();
|
|
573
781
|
return Object.values(tokens).find((t) => t.address.toLowerCase() === lowerAddress);
|
|
574
782
|
}
|
|
575
|
-
function supportsEIP3009(network, symbol) {
|
|
576
|
-
const config = getTokenConfig(network, symbol);
|
|
577
|
-
return config?.tokenType === "eip3009";
|
|
578
|
-
}
|
|
579
|
-
function getNetworksForToken(symbol) {
|
|
580
|
-
const networks = [];
|
|
581
|
-
for (const [network, tokens] of Object.entries(TOKEN_REGISTRY)) {
|
|
582
|
-
if (tokens[symbol.toUpperCase()]) {
|
|
583
|
-
networks.push(network);
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
return networks;
|
|
587
|
-
}
|
|
588
|
-
function getUsdt0Networks() {
|
|
589
|
-
return getNetworksForToken("USDT0");
|
|
590
|
-
}
|
|
591
|
-
function getEIP712Domain(network, tokenAddress, chainId) {
|
|
592
|
-
const token = getTokenByAddress(network, tokenAddress);
|
|
593
|
-
if (!token) return void 0;
|
|
594
|
-
return {
|
|
595
|
-
name: token.name,
|
|
596
|
-
version: token.version,
|
|
597
|
-
chainId,
|
|
598
|
-
verifyingContract: token.address
|
|
599
|
-
};
|
|
600
|
-
}
|
|
601
783
|
|
|
602
784
|
// src/exact-legacy/server/scheme.ts
|
|
603
785
|
var ExactLegacyEvmScheme2 = class {
|
|
786
|
+
/**
|
|
787
|
+
* Creates a new ExactLegacyEvmScheme instance.
|
|
788
|
+
*
|
|
789
|
+
* @param config - Optional configuration options for the scheme
|
|
790
|
+
*/
|
|
604
791
|
constructor(config = {}) {
|
|
605
|
-
this
|
|
606
|
-
this
|
|
792
|
+
__publicField(this, "scheme", "exact-legacy");
|
|
793
|
+
__publicField(this, "moneyParsers", []);
|
|
794
|
+
__publicField(this, "config");
|
|
607
795
|
this.config = config;
|
|
608
796
|
}
|
|
797
|
+
/**
|
|
798
|
+
* Get all supported networks that have legacy tokens
|
|
799
|
+
*
|
|
800
|
+
* @returns Array of network identifiers with legacy token support
|
|
801
|
+
*/
|
|
802
|
+
static getSupportedNetworks() {
|
|
803
|
+
return Object.keys(USDT_LEGACY_ADDRESSES);
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Check if a network has legacy token support
|
|
807
|
+
*
|
|
808
|
+
* @param network - The network identifier to check
|
|
809
|
+
* @returns True if the network has legacy token support
|
|
810
|
+
*/
|
|
811
|
+
static isNetworkSupported(network) {
|
|
812
|
+
return network in USDT_LEGACY_ADDRESSES;
|
|
813
|
+
}
|
|
609
814
|
/**
|
|
610
815
|
* Register a custom money parser in the parser chain.
|
|
816
|
+
*
|
|
817
|
+
* @param parser - Custom function to convert amount to AssetAmount
|
|
818
|
+
* @returns The scheme instance for method chaining
|
|
611
819
|
*/
|
|
612
820
|
registerMoneyParser(parser) {
|
|
613
821
|
this.moneyParsers.push(parser);
|
|
@@ -615,6 +823,10 @@ var ExactLegacyEvmScheme2 = class {
|
|
|
615
823
|
}
|
|
616
824
|
/**
|
|
617
825
|
* Parses a price into an asset amount for legacy tokens.
|
|
826
|
+
*
|
|
827
|
+
* @param price - The price to parse (Money or AssetAmount)
|
|
828
|
+
* @param network - The network identifier in CAIP-2 format
|
|
829
|
+
* @returns Promise resolving to the parsed asset amount
|
|
618
830
|
*/
|
|
619
831
|
async parsePrice(price, network) {
|
|
620
832
|
if (typeof price === "object" && price !== null && "amount" in price) {
|
|
@@ -642,6 +854,15 @@ var ExactLegacyEvmScheme2 = class {
|
|
|
642
854
|
/**
|
|
643
855
|
* Build payment requirements for this scheme/network combination.
|
|
644
856
|
* Adds the spender (facilitator) address to the extra field.
|
|
857
|
+
*
|
|
858
|
+
* @param paymentRequirements - The base payment requirements to enhance
|
|
859
|
+
* @param supportedKind - The supported kind from facilitator
|
|
860
|
+
* @param supportedKind.t402Version - The t402 protocol version
|
|
861
|
+
* @param supportedKind.scheme - The logical payment scheme identifier
|
|
862
|
+
* @param supportedKind.network - The network identifier in CAIP-2 format
|
|
863
|
+
* @param supportedKind.extra - Optional extra metadata with spender address
|
|
864
|
+
* @param extensionKeys - Extension keys supported by the facilitator (unused)
|
|
865
|
+
* @returns Promise resolving to enhanced payment requirements
|
|
645
866
|
*/
|
|
646
867
|
enhancePaymentRequirements(paymentRequirements, supportedKind, extensionKeys) {
|
|
647
868
|
void extensionKeys;
|
|
@@ -657,6 +878,9 @@ var ExactLegacyEvmScheme2 = class {
|
|
|
657
878
|
}
|
|
658
879
|
/**
|
|
659
880
|
* Parse Money (string | number) to a decimal number.
|
|
881
|
+
*
|
|
882
|
+
* @param money - The money value to parse (e.g., "$1.50" or 1.50)
|
|
883
|
+
* @returns The decimal number representation
|
|
660
884
|
*/
|
|
661
885
|
parseMoneyToDecimal(money) {
|
|
662
886
|
if (typeof money === "number") {
|
|
@@ -671,6 +895,10 @@ var ExactLegacyEvmScheme2 = class {
|
|
|
671
895
|
}
|
|
672
896
|
/**
|
|
673
897
|
* Default money conversion implementation for legacy tokens.
|
|
898
|
+
*
|
|
899
|
+
* @param amount - The decimal amount to convert (e.g., 1.50)
|
|
900
|
+
* @param network - The network identifier in CAIP-2 format
|
|
901
|
+
* @returns The asset amount in token units
|
|
674
902
|
*/
|
|
675
903
|
defaultMoneyConversion(amount, network) {
|
|
676
904
|
const token = this.getDefaultAsset(network);
|
|
@@ -688,6 +916,10 @@ var ExactLegacyEvmScheme2 = class {
|
|
|
688
916
|
}
|
|
689
917
|
/**
|
|
690
918
|
* Convert decimal amount to token units
|
|
919
|
+
*
|
|
920
|
+
* @param decimalAmount - The decimal amount as a string (e.g., "1.50")
|
|
921
|
+
* @param decimals - The number of decimal places for the token
|
|
922
|
+
* @returns The token amount as a string in smallest units
|
|
691
923
|
*/
|
|
692
924
|
convertToTokenAmount(decimalAmount, decimals) {
|
|
693
925
|
const amount = parseFloat(decimalAmount);
|
|
@@ -699,6 +931,9 @@ var ExactLegacyEvmScheme2 = class {
|
|
|
699
931
|
}
|
|
700
932
|
/**
|
|
701
933
|
* Get the default legacy token for a network.
|
|
934
|
+
*
|
|
935
|
+
* @param network - The network identifier in CAIP-2 format
|
|
936
|
+
* @returns The token configuration for the default legacy token
|
|
702
937
|
*/
|
|
703
938
|
getDefaultAsset(network) {
|
|
704
939
|
if (this.config.preferredToken) {
|
|
@@ -718,18 +953,6 @@ var ExactLegacyEvmScheme2 = class {
|
|
|
718
953
|
}
|
|
719
954
|
throw new Error(`No legacy tokens configured for network ${network}`);
|
|
720
955
|
}
|
|
721
|
-
/**
|
|
722
|
-
* Get all supported networks that have legacy tokens
|
|
723
|
-
*/
|
|
724
|
-
static getSupportedNetworks() {
|
|
725
|
-
return Object.keys(USDT_LEGACY_ADDRESSES);
|
|
726
|
-
}
|
|
727
|
-
/**
|
|
728
|
-
* Check if a network has legacy token support
|
|
729
|
-
*/
|
|
730
|
-
static isNetworkSupported(network) {
|
|
731
|
-
return network in USDT_LEGACY_ADDRESSES;
|
|
732
|
-
}
|
|
733
956
|
};
|
|
734
957
|
|
|
735
958
|
// src/exact-legacy/facilitator/scheme.ts
|
|
@@ -743,8 +966,9 @@ var ExactLegacyEvmScheme3 = class {
|
|
|
743
966
|
*/
|
|
744
967
|
constructor(signer, config) {
|
|
745
968
|
this.signer = signer;
|
|
746
|
-
this
|
|
747
|
-
this
|
|
969
|
+
__publicField(this, "scheme", "exact-legacy");
|
|
970
|
+
__publicField(this, "caipFamily", "eip155:*");
|
|
971
|
+
__publicField(this, "config");
|
|
748
972
|
this.config = {
|
|
749
973
|
minAllowanceRatio: config?.minAllowanceRatio ?? 1
|
|
750
974
|
};
|
|
@@ -769,6 +993,9 @@ var ExactLegacyEvmScheme3 = class {
|
|
|
769
993
|
}
|
|
770
994
|
/**
|
|
771
995
|
* Get signer addresses used by this facilitator.
|
|
996
|
+
*
|
|
997
|
+
* @param network - The network identifier (unused, returns same addresses for all networks)
|
|
998
|
+
* @returns Array of signer addresses
|
|
772
999
|
*/
|
|
773
1000
|
getSigners(network) {
|
|
774
1001
|
void network;
|
|
@@ -776,6 +1003,10 @@ var ExactLegacyEvmScheme3 = class {
|
|
|
776
1003
|
}
|
|
777
1004
|
/**
|
|
778
1005
|
* Verifies a payment payload.
|
|
1006
|
+
*
|
|
1007
|
+
* @param payload - The payment payload to verify
|
|
1008
|
+
* @param requirements - The payment requirements to verify against
|
|
1009
|
+
* @returns Promise resolving to verification response with validity status
|
|
779
1010
|
*/
|
|
780
1011
|
async verify(payload, requirements) {
|
|
781
1012
|
const legacyPayload = payload.payload;
|
|
@@ -922,70 +1153,569 @@ var ExactLegacyEvmScheme3 = class {
|
|
|
922
1153
|
}
|
|
923
1154
|
/**
|
|
924
1155
|
* Settles a payment by executing transferFrom.
|
|
1156
|
+
*
|
|
1157
|
+
* @param payload - The payment payload containing transfer authorization
|
|
1158
|
+
* @param requirements - The payment requirements specifying amount and recipient
|
|
1159
|
+
* @returns Promise resolving to settlement response with transaction hash
|
|
1160
|
+
*/
|
|
1161
|
+
async settle(payload, requirements) {
|
|
1162
|
+
const legacyPayload = payload.payload;
|
|
1163
|
+
const valid = await this.verify(payload, requirements);
|
|
1164
|
+
if (!valid.isValid) {
|
|
1165
|
+
return {
|
|
1166
|
+
success: false,
|
|
1167
|
+
network: payload.accepted.network,
|
|
1168
|
+
transaction: "",
|
|
1169
|
+
errorReason: valid.invalidReason ?? "invalid_payment",
|
|
1170
|
+
payer: legacyPayload.authorization.from
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1173
|
+
try {
|
|
1174
|
+
const tx = await this.signer.writeContract({
|
|
1175
|
+
address: (0, import_viem4.getAddress)(requirements.asset),
|
|
1176
|
+
abi: erc20LegacyABI,
|
|
1177
|
+
functionName: "transferFrom",
|
|
1178
|
+
args: [
|
|
1179
|
+
(0, import_viem4.getAddress)(legacyPayload.authorization.from),
|
|
1180
|
+
(0, import_viem4.getAddress)(legacyPayload.authorization.to),
|
|
1181
|
+
BigInt(legacyPayload.authorization.value)
|
|
1182
|
+
]
|
|
1183
|
+
});
|
|
1184
|
+
const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });
|
|
1185
|
+
if (receipt.status !== "success") {
|
|
1186
|
+
return {
|
|
1187
|
+
success: false,
|
|
1188
|
+
errorReason: "transaction_failed",
|
|
1189
|
+
transaction: tx,
|
|
1190
|
+
network: payload.accepted.network,
|
|
1191
|
+
payer: legacyPayload.authorization.from
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
return {
|
|
1195
|
+
success: true,
|
|
1196
|
+
transaction: tx,
|
|
1197
|
+
network: payload.accepted.network,
|
|
1198
|
+
payer: legacyPayload.authorization.from
|
|
1199
|
+
};
|
|
1200
|
+
} catch (error) {
|
|
1201
|
+
console.error("Failed to settle legacy transaction:", error);
|
|
1202
|
+
return {
|
|
1203
|
+
success: false,
|
|
1204
|
+
errorReason: "settlement_failed",
|
|
1205
|
+
transaction: "",
|
|
1206
|
+
network: payload.accepted.network,
|
|
1207
|
+
payer: legacyPayload.authorization.from
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
};
|
|
1212
|
+
|
|
1213
|
+
// src/upto/client/scheme.ts
|
|
1214
|
+
var import_viem5 = require("viem");
|
|
1215
|
+
|
|
1216
|
+
// src/types.ts
|
|
1217
|
+
var permitTypes = {
|
|
1218
|
+
Permit: [
|
|
1219
|
+
{ name: "owner", type: "address" },
|
|
1220
|
+
{ name: "spender", type: "address" },
|
|
1221
|
+
{ name: "value", type: "uint256" },
|
|
1222
|
+
{ name: "nonce", type: "uint256" },
|
|
1223
|
+
{ name: "deadline", type: "uint256" }
|
|
1224
|
+
]
|
|
1225
|
+
};
|
|
1226
|
+
function isUptoEIP2612Payload(payload) {
|
|
1227
|
+
if (typeof payload !== "object" || payload === null) return false;
|
|
1228
|
+
const p = payload;
|
|
1229
|
+
return "signature" in p && "authorization" in p && "paymentNonce" in p && typeof p.authorization === "object" && p.authorization !== null && "owner" in p.authorization && "spender" in p.authorization && "value" in p.authorization && "deadline" in p.authorization && "nonce" in p.authorization;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
// src/upto/client/scheme.ts
|
|
1233
|
+
var UptoEvmScheme = class {
|
|
1234
|
+
/**
|
|
1235
|
+
* Creates a new UptoEvmScheme instance.
|
|
1236
|
+
*
|
|
1237
|
+
* @param signer - The EVM signer for client operations
|
|
1238
|
+
*/
|
|
1239
|
+
constructor(signer) {
|
|
1240
|
+
this.signer = signer;
|
|
1241
|
+
__publicField(this, "scheme", "upto");
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Creates a payment payload for the Up-To scheme.
|
|
1245
|
+
*
|
|
1246
|
+
* The payload contains an EIP-2612 permit signature authorizing
|
|
1247
|
+
* the router contract (or facilitator) to transfer up to the
|
|
1248
|
+
* specified maximum amount.
|
|
1249
|
+
*
|
|
1250
|
+
* @param t402Version - The t402 protocol version
|
|
1251
|
+
* @param paymentRequirements - The payment requirements (must include maxAmount)
|
|
1252
|
+
* @returns Promise resolving to a payment payload
|
|
1253
|
+
*/
|
|
1254
|
+
async createPaymentPayload(t402Version, paymentRequirements) {
|
|
1255
|
+
if (paymentRequirements.scheme !== "upto") {
|
|
1256
|
+
throw new Error(`Expected upto scheme, got ${paymentRequirements.scheme}`);
|
|
1257
|
+
}
|
|
1258
|
+
const extra = paymentRequirements.extra;
|
|
1259
|
+
if (!extra?.name || !extra?.version) {
|
|
1260
|
+
throw new Error("EIP-712 domain parameters (name, version) are required for upto scheme");
|
|
1261
|
+
}
|
|
1262
|
+
const maxAmount = paymentRequirements.maxAmount;
|
|
1263
|
+
if (!maxAmount) {
|
|
1264
|
+
throw new Error("maxAmount is required for upto scheme");
|
|
1265
|
+
}
|
|
1266
|
+
const spender = extra.routerAddress ? (0, import_viem5.getAddress)(extra.routerAddress) : (0, import_viem5.getAddress)(paymentRequirements.payTo);
|
|
1267
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
1268
|
+
const deadline = now + paymentRequirements.maxTimeoutSeconds;
|
|
1269
|
+
const permitNonce = extra.permitNonce ?? 0;
|
|
1270
|
+
const authorization = {
|
|
1271
|
+
owner: this.signer.address,
|
|
1272
|
+
spender,
|
|
1273
|
+
value: maxAmount,
|
|
1274
|
+
deadline: deadline.toString(),
|
|
1275
|
+
nonce: permitNonce
|
|
1276
|
+
};
|
|
1277
|
+
const signature = await this.signPermit(authorization, paymentRequirements);
|
|
1278
|
+
const paymentNonce = createNonce();
|
|
1279
|
+
const payload = {
|
|
1280
|
+
signature,
|
|
1281
|
+
authorization,
|
|
1282
|
+
paymentNonce
|
|
1283
|
+
};
|
|
1284
|
+
return {
|
|
1285
|
+
t402Version,
|
|
1286
|
+
payload
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Sign the EIP-2612 permit using EIP-712
|
|
1291
|
+
*
|
|
1292
|
+
* @param authorization - The permit authorization to sign
|
|
1293
|
+
* @param requirements - The payment requirements
|
|
1294
|
+
* @returns Promise resolving to the signature components
|
|
1295
|
+
*/
|
|
1296
|
+
async signPermit(authorization, requirements) {
|
|
1297
|
+
const chainId = parseInt(requirements.network.split(":")[1]);
|
|
1298
|
+
const extra = requirements.extra;
|
|
1299
|
+
const domain = {
|
|
1300
|
+
name: extra.name,
|
|
1301
|
+
version: extra.version,
|
|
1302
|
+
chainId,
|
|
1303
|
+
verifyingContract: (0, import_viem5.getAddress)(requirements.asset)
|
|
1304
|
+
};
|
|
1305
|
+
const message = {
|
|
1306
|
+
owner: (0, import_viem5.getAddress)(authorization.owner),
|
|
1307
|
+
spender: (0, import_viem5.getAddress)(authorization.spender),
|
|
1308
|
+
value: BigInt(authorization.value),
|
|
1309
|
+
nonce: BigInt(authorization.nonce),
|
|
1310
|
+
deadline: BigInt(authorization.deadline)
|
|
1311
|
+
};
|
|
1312
|
+
const signature = await this.signer.signTypedData({
|
|
1313
|
+
domain,
|
|
1314
|
+
types: permitTypes,
|
|
1315
|
+
primaryType: "Permit",
|
|
1316
|
+
message
|
|
1317
|
+
});
|
|
1318
|
+
const r = `0x${signature.slice(2, 66)}`;
|
|
1319
|
+
const s = `0x${signature.slice(66, 130)}`;
|
|
1320
|
+
const v = parseInt(signature.slice(130, 132), 16);
|
|
1321
|
+
return { v, r, s };
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
function createUptoEvmScheme(signer) {
|
|
1325
|
+
return new UptoEvmScheme(signer);
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
// src/upto/server/scheme.ts
|
|
1329
|
+
var import_types2 = require("@t402/core/types");
|
|
1330
|
+
var UptoEvmServerScheme = class {
|
|
1331
|
+
/**
|
|
1332
|
+
* Creates a new UptoEvmServerScheme instance.
|
|
1333
|
+
*
|
|
1334
|
+
* @param config - Optional configuration options for the scheme
|
|
1335
|
+
*/
|
|
1336
|
+
constructor(config = {}) {
|
|
1337
|
+
__publicField(this, "scheme", "upto");
|
|
1338
|
+
__publicField(this, "moneyParsers", []);
|
|
1339
|
+
__publicField(this, "config");
|
|
1340
|
+
this.config = config;
|
|
1341
|
+
}
|
|
1342
|
+
/**
|
|
1343
|
+
* Get all supported networks
|
|
1344
|
+
*
|
|
1345
|
+
* @returns Array of network identifiers in CAIP-2 format
|
|
1346
|
+
*/
|
|
1347
|
+
static getSupportedNetworks() {
|
|
1348
|
+
return Object.keys(TOKEN_REGISTRY);
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Check if a network is supported
|
|
1352
|
+
*
|
|
1353
|
+
* @param network - The network identifier to check
|
|
1354
|
+
* @returns True if the network is supported
|
|
1355
|
+
*/
|
|
1356
|
+
static isNetworkSupported(network) {
|
|
1357
|
+
return network in TOKEN_REGISTRY;
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Register a custom money parser in the parser chain.
|
|
1361
|
+
*
|
|
1362
|
+
* @param parser - Custom function to convert amount to AssetAmount
|
|
1363
|
+
* @returns The server instance for chaining
|
|
1364
|
+
*/
|
|
1365
|
+
registerMoneyParser(parser) {
|
|
1366
|
+
this.moneyParsers.push(parser);
|
|
1367
|
+
return this;
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Parses a price into an asset amount for maxAmount.
|
|
1371
|
+
*
|
|
1372
|
+
* @param price - The price to parse (represents maxAmount)
|
|
1373
|
+
* @param network - The network to use
|
|
1374
|
+
* @returns Promise resolving to the parsed asset amount
|
|
1375
|
+
*/
|
|
1376
|
+
async parsePrice(price, network) {
|
|
1377
|
+
if (typeof price === "object" && price !== null && "amount" in price) {
|
|
1378
|
+
if (!price.asset) {
|
|
1379
|
+
const token2 = this.getPreferredToken(network);
|
|
1380
|
+
return { amount: price.amount, asset: token2.address };
|
|
1381
|
+
}
|
|
1382
|
+
return price;
|
|
1383
|
+
}
|
|
1384
|
+
const decimalAmount = this.parseToDecimal(price);
|
|
1385
|
+
for (const parser of this.moneyParsers) {
|
|
1386
|
+
const result = await parser(decimalAmount, network);
|
|
1387
|
+
if (result !== null) {
|
|
1388
|
+
return result;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
const token = this.getPreferredToken(network);
|
|
1392
|
+
const amount = Math.floor(decimalAmount * 10 ** token.decimals).toString();
|
|
1393
|
+
return {
|
|
1394
|
+
amount,
|
|
1395
|
+
asset: token.address
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Enhance payment requirements for the upto scheme.
|
|
1400
|
+
*
|
|
1401
|
+
* @param paymentRequirements - Base payment requirements
|
|
1402
|
+
* @param supportedKind - The supported kind from facilitator
|
|
1403
|
+
* @param supportedKind.t402Version - T402 protocol version
|
|
1404
|
+
* @param supportedKind.scheme - Payment scheme
|
|
1405
|
+
* @param supportedKind.network - Network identifier
|
|
1406
|
+
* @param supportedKind.extra - Extra configuration
|
|
1407
|
+
* @param facilitatorExtensions - Extensions supported by the facilitator
|
|
1408
|
+
* @returns Enhanced payment requirements for upto scheme
|
|
1409
|
+
*/
|
|
1410
|
+
async enhancePaymentRequirements(paymentRequirements, supportedKind, facilitatorExtensions) {
|
|
1411
|
+
void facilitatorExtensions;
|
|
1412
|
+
const network = supportedKind.network;
|
|
1413
|
+
const token = getTokenByAddress(network, paymentRequirements.asset);
|
|
1414
|
+
if (!token) {
|
|
1415
|
+
throw new Error(`Unknown token ${paymentRequirements.asset} on ${network}`);
|
|
1416
|
+
}
|
|
1417
|
+
const extra = {
|
|
1418
|
+
// EIP-712 domain (required for permit signing)
|
|
1419
|
+
name: token.name,
|
|
1420
|
+
version: token.version,
|
|
1421
|
+
// Router address (optional - if set, permits go to router)
|
|
1422
|
+
...this.config.routerAddress && { routerAddress: this.config.routerAddress },
|
|
1423
|
+
// Billing unit info (optional)
|
|
1424
|
+
...this.config.defaultUnit && { unit: this.config.defaultUnit },
|
|
1425
|
+
...this.config.defaultUnitPrice && { unitPrice: this.config.defaultUnitPrice },
|
|
1426
|
+
// Upto-specific fields
|
|
1427
|
+
maxAmount: paymentRequirements.amount,
|
|
1428
|
+
minAmount: import_types2.UPTO_DEFAULTS.MIN_AMOUNT,
|
|
1429
|
+
// Merge any facilitator extra
|
|
1430
|
+
...supportedKind.extra
|
|
1431
|
+
};
|
|
1432
|
+
return {
|
|
1433
|
+
...paymentRequirements,
|
|
1434
|
+
scheme: "upto",
|
|
1435
|
+
extra
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Get the preferred token for a network.
|
|
1440
|
+
*
|
|
1441
|
+
* @param network - The network identifier
|
|
1442
|
+
* @returns Token configuration
|
|
1443
|
+
* @throws Error if no token is found for the network
|
|
1444
|
+
*/
|
|
1445
|
+
getPreferredToken(network) {
|
|
1446
|
+
if (this.config.preferredToken) {
|
|
1447
|
+
const token = getTokenConfig(network, this.config.preferredToken);
|
|
1448
|
+
if (token) return token;
|
|
1449
|
+
}
|
|
1450
|
+
const defaultToken = getDefaultToken(network);
|
|
1451
|
+
if (!defaultToken) {
|
|
1452
|
+
throw new Error(`No token configured for network ${network}`);
|
|
1453
|
+
}
|
|
1454
|
+
return defaultToken;
|
|
1455
|
+
}
|
|
1456
|
+
/**
|
|
1457
|
+
* Parse price to decimal value.
|
|
1458
|
+
*
|
|
1459
|
+
* @param price - Price string or number
|
|
1460
|
+
* @returns Decimal amount
|
|
1461
|
+
*/
|
|
1462
|
+
parseToDecimal(price) {
|
|
1463
|
+
if (typeof price === "number") {
|
|
1464
|
+
return price;
|
|
1465
|
+
}
|
|
1466
|
+
const cleaned = price.replace(/[$,]/g, "").trim();
|
|
1467
|
+
const parsed = parseFloat(cleaned);
|
|
1468
|
+
if (isNaN(parsed)) {
|
|
1469
|
+
throw new Error(`Invalid price format: ${price}`);
|
|
1470
|
+
}
|
|
1471
|
+
return parsed;
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
function createUptoEvmServerScheme(config) {
|
|
1475
|
+
return new UptoEvmServerScheme(config);
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
// src/upto/facilitator/scheme.ts
|
|
1479
|
+
var import_viem6 = require("viem");
|
|
1480
|
+
var T402_UPTO_ROUTER_ABI = (0, import_viem6.parseAbi)([
|
|
1481
|
+
"function executeUptoTransfer(address token, address from, address to, uint256 maxAmount, uint256 settleAmount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external",
|
|
1482
|
+
"function isFacilitator(address facilitator) external view returns (bool)",
|
|
1483
|
+
"function checkPermitValidity(address token, address from, uint256 maxAmount) external view returns (bool valid, uint256 balance)"
|
|
1484
|
+
]);
|
|
1485
|
+
var UptoEvmFacilitatorScheme = class {
|
|
1486
|
+
/**
|
|
1487
|
+
* Creates a new UptoEvmFacilitatorScheme instance.
|
|
1488
|
+
*
|
|
1489
|
+
* @param signer - The EVM signer for facilitator operations
|
|
1490
|
+
* @param config - Optional configuration
|
|
1491
|
+
*/
|
|
1492
|
+
constructor(signer, config) {
|
|
1493
|
+
this.signer = signer;
|
|
1494
|
+
__publicField(this, "scheme", "upto");
|
|
1495
|
+
__publicField(this, "caipFamily", "eip155:*");
|
|
1496
|
+
__publicField(this, "config");
|
|
1497
|
+
this.config = config ?? {};
|
|
1498
|
+
}
|
|
1499
|
+
/**
|
|
1500
|
+
* Get mechanism-specific extra data for the supported kinds endpoint.
|
|
1501
|
+
*
|
|
1502
|
+
* @param network - The network identifier
|
|
1503
|
+
* @returns Extra data including router address if configured
|
|
1504
|
+
*/
|
|
1505
|
+
getExtra(network) {
|
|
1506
|
+
const routerAddress = this.config.routerAddresses?.[network];
|
|
1507
|
+
if (routerAddress) {
|
|
1508
|
+
return { routerAddress };
|
|
1509
|
+
}
|
|
1510
|
+
return void 0;
|
|
1511
|
+
}
|
|
1512
|
+
/**
|
|
1513
|
+
* Get signer addresses used by this facilitator.
|
|
1514
|
+
*
|
|
1515
|
+
* @param _ - The network identifier (unused for EVM)
|
|
1516
|
+
* @returns Array of facilitator wallet addresses
|
|
1517
|
+
*/
|
|
1518
|
+
getSigners(_) {
|
|
1519
|
+
return [...this.signer.getAddresses()];
|
|
1520
|
+
}
|
|
1521
|
+
/**
|
|
1522
|
+
* Verifies an upto payment payload.
|
|
1523
|
+
*
|
|
1524
|
+
* @param payload - The payment payload to verify
|
|
1525
|
+
* @param requirements - The payment requirements
|
|
1526
|
+
* @returns Promise resolving to verification response
|
|
1527
|
+
*/
|
|
1528
|
+
async verify(payload, requirements) {
|
|
1529
|
+
const uptoPayload = payload.payload;
|
|
1530
|
+
if (!uptoPayload || !isUptoEIP2612Payload(uptoPayload)) {
|
|
1531
|
+
return {
|
|
1532
|
+
isValid: false,
|
|
1533
|
+
invalidReason: "invalid_payload_structure",
|
|
1534
|
+
payer: void 0
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1537
|
+
if (payload.accepted.scheme !== "upto" || requirements.scheme !== "upto") {
|
|
1538
|
+
return {
|
|
1539
|
+
isValid: false,
|
|
1540
|
+
invalidReason: "unsupported_scheme",
|
|
1541
|
+
payer: uptoPayload.authorization.owner
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
1545
|
+
return {
|
|
1546
|
+
isValid: false,
|
|
1547
|
+
invalidReason: "missing_eip712_domain",
|
|
1548
|
+
payer: uptoPayload.authorization.owner
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
const maxAmount = requirements.extra?.maxAmount;
|
|
1552
|
+
if (!maxAmount) {
|
|
1553
|
+
return {
|
|
1554
|
+
isValid: false,
|
|
1555
|
+
invalidReason: "missing_maxAmount",
|
|
1556
|
+
payer: uptoPayload.authorization.owner
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
if (payload.accepted.network !== requirements.network) {
|
|
1560
|
+
return {
|
|
1561
|
+
isValid: false,
|
|
1562
|
+
invalidReason: "network_mismatch",
|
|
1563
|
+
payer: uptoPayload.authorization.owner
|
|
1564
|
+
};
|
|
1565
|
+
}
|
|
1566
|
+
const deadline = parseInt(uptoPayload.authorization.deadline);
|
|
1567
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
1568
|
+
if (deadline <= now) {
|
|
1569
|
+
return {
|
|
1570
|
+
isValid: false,
|
|
1571
|
+
invalidReason: "permit_expired",
|
|
1572
|
+
payer: uptoPayload.authorization.owner
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1575
|
+
if (uptoPayload.authorization.value !== maxAmount) {
|
|
1576
|
+
return {
|
|
1577
|
+
isValid: false,
|
|
1578
|
+
invalidReason: "amount_mismatch",
|
|
1579
|
+
payer: uptoPayload.authorization.owner
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1582
|
+
const chainId = parseInt(requirements.network.split(":")[1]);
|
|
1583
|
+
const permitTypedData = {
|
|
1584
|
+
types: permitTypes,
|
|
1585
|
+
primaryType: "Permit",
|
|
1586
|
+
domain: {
|
|
1587
|
+
name: requirements.extra.name,
|
|
1588
|
+
version: requirements.extra.version,
|
|
1589
|
+
chainId,
|
|
1590
|
+
verifyingContract: (0, import_viem6.getAddress)(requirements.asset)
|
|
1591
|
+
},
|
|
1592
|
+
message: {
|
|
1593
|
+
owner: (0, import_viem6.getAddress)(uptoPayload.authorization.owner),
|
|
1594
|
+
spender: (0, import_viem6.getAddress)(uptoPayload.authorization.spender),
|
|
1595
|
+
value: BigInt(uptoPayload.authorization.value),
|
|
1596
|
+
nonce: BigInt(uptoPayload.authorization.nonce),
|
|
1597
|
+
deadline: BigInt(uptoPayload.authorization.deadline)
|
|
1598
|
+
}
|
|
1599
|
+
};
|
|
1600
|
+
const signature = `0x${uptoPayload.signature.r.slice(2)}${uptoPayload.signature.s.slice(2)}${uptoPayload.signature.v.toString(16).padStart(2, "0")}`;
|
|
1601
|
+
try {
|
|
1602
|
+
const isValid = await this.signer.verifyTypedData({
|
|
1603
|
+
address: uptoPayload.authorization.owner,
|
|
1604
|
+
...permitTypedData,
|
|
1605
|
+
signature
|
|
1606
|
+
});
|
|
1607
|
+
if (!isValid) {
|
|
1608
|
+
return {
|
|
1609
|
+
isValid: false,
|
|
1610
|
+
invalidReason: "invalid_signature",
|
|
1611
|
+
payer: uptoPayload.authorization.owner
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
} catch (error) {
|
|
1615
|
+
return {
|
|
1616
|
+
isValid: false,
|
|
1617
|
+
invalidReason: `signature_verification_failed: ${error instanceof Error ? error.message : "unknown"}`,
|
|
1618
|
+
payer: uptoPayload.authorization.owner
|
|
1619
|
+
};
|
|
1620
|
+
}
|
|
1621
|
+
return {
|
|
1622
|
+
isValid: true,
|
|
1623
|
+
payer: uptoPayload.authorization.owner
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1626
|
+
/**
|
|
1627
|
+
* Settles an upto payment by calling the T402UptoRouter contract.
|
|
1628
|
+
*
|
|
1629
|
+
* @param payload - The verified payment payload
|
|
1630
|
+
* @param requirements - The payment requirements
|
|
1631
|
+
* @returns Promise resolving to settlement response
|
|
925
1632
|
*/
|
|
926
1633
|
async settle(payload, requirements) {
|
|
927
|
-
const
|
|
928
|
-
const
|
|
929
|
-
|
|
1634
|
+
const uptoPayload = payload.payload;
|
|
1635
|
+
const maxAmount = requirements.extra?.maxAmount;
|
|
1636
|
+
const minAmount = requirements.extra?.minAmount;
|
|
1637
|
+
const routerAddress = requirements.extra?.routerAddress;
|
|
1638
|
+
if (!maxAmount) {
|
|
930
1639
|
return {
|
|
931
1640
|
success: false,
|
|
932
|
-
|
|
1641
|
+
errorReason: "maxAmount not found in payment requirements",
|
|
933
1642
|
transaction: "",
|
|
934
|
-
|
|
935
|
-
payer:
|
|
1643
|
+
network: requirements.network,
|
|
1644
|
+
payer: uptoPayload.authorization.owner
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
const settleAmount = maxAmount;
|
|
1648
|
+
if (minAmount && BigInt(settleAmount) < BigInt(minAmount)) {
|
|
1649
|
+
return {
|
|
1650
|
+
success: false,
|
|
1651
|
+
errorReason: `Settle amount ${settleAmount} below minimum ${minAmount}`,
|
|
1652
|
+
transaction: "",
|
|
1653
|
+
network: requirements.network,
|
|
1654
|
+
payer: uptoPayload.authorization.owner
|
|
1655
|
+
};
|
|
1656
|
+
}
|
|
1657
|
+
if (!routerAddress) {
|
|
1658
|
+
return {
|
|
1659
|
+
success: false,
|
|
1660
|
+
errorReason: "Router address not configured",
|
|
1661
|
+
transaction: "",
|
|
1662
|
+
network: requirements.network,
|
|
1663
|
+
payer: uptoPayload.authorization.owner
|
|
936
1664
|
};
|
|
937
1665
|
}
|
|
938
1666
|
try {
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
1667
|
+
const txHash = await this.signer.sendTransaction({
|
|
1668
|
+
to: (0, import_viem6.getAddress)(routerAddress),
|
|
1669
|
+
data: (0, import_viem6.encodeFunctionData)({
|
|
1670
|
+
abi: T402_UPTO_ROUTER_ABI,
|
|
1671
|
+
functionName: "executeUptoTransfer",
|
|
1672
|
+
args: [
|
|
1673
|
+
(0, import_viem6.getAddress)(requirements.asset),
|
|
1674
|
+
(0, import_viem6.getAddress)(uptoPayload.authorization.owner),
|
|
1675
|
+
(0, import_viem6.getAddress)(requirements.payTo),
|
|
1676
|
+
BigInt(maxAmount),
|
|
1677
|
+
BigInt(settleAmount),
|
|
1678
|
+
BigInt(uptoPayload.authorization.deadline),
|
|
1679
|
+
uptoPayload.signature.v,
|
|
1680
|
+
uptoPayload.signature.r,
|
|
1681
|
+
uptoPayload.signature.s
|
|
1682
|
+
]
|
|
1683
|
+
})
|
|
948
1684
|
});
|
|
949
|
-
const receipt = await this.signer.waitForTransactionReceipt({ hash:
|
|
1685
|
+
const receipt = await this.signer.waitForTransactionReceipt({ hash: txHash });
|
|
950
1686
|
if (receipt.status !== "success") {
|
|
951
1687
|
return {
|
|
952
1688
|
success: false,
|
|
953
|
-
errorReason: "
|
|
954
|
-
transaction:
|
|
955
|
-
network:
|
|
956
|
-
payer:
|
|
1689
|
+
errorReason: "transaction_reverted",
|
|
1690
|
+
transaction: txHash,
|
|
1691
|
+
network: requirements.network,
|
|
1692
|
+
payer: uptoPayload.authorization.owner
|
|
957
1693
|
};
|
|
958
1694
|
}
|
|
959
1695
|
return {
|
|
960
1696
|
success: true,
|
|
961
|
-
transaction:
|
|
962
|
-
network:
|
|
963
|
-
payer:
|
|
1697
|
+
transaction: txHash,
|
|
1698
|
+
network: requirements.network,
|
|
1699
|
+
payer: uptoPayload.authorization.owner
|
|
964
1700
|
};
|
|
965
1701
|
} catch (error) {
|
|
966
|
-
console.error("Failed to settle legacy transaction:", error);
|
|
967
1702
|
return {
|
|
968
1703
|
success: false,
|
|
969
|
-
errorReason: "
|
|
1704
|
+
errorReason: `Settlement failed: ${error instanceof Error ? error.message : "unknown"}`,
|
|
970
1705
|
transaction: "",
|
|
971
|
-
network:
|
|
972
|
-
payer:
|
|
1706
|
+
network: requirements.network,
|
|
1707
|
+
payer: uptoPayload.authorization.owner
|
|
973
1708
|
};
|
|
974
1709
|
}
|
|
975
1710
|
}
|
|
976
1711
|
};
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
function toClientEvmSigner(signer) {
|
|
980
|
-
return signer;
|
|
981
|
-
}
|
|
982
|
-
function toFacilitatorEvmSigner(client) {
|
|
983
|
-
return {
|
|
984
|
-
...client,
|
|
985
|
-
getAddresses: () => [client.address]
|
|
986
|
-
};
|
|
1712
|
+
function createUptoEvmFacilitatorScheme(signer, config) {
|
|
1713
|
+
return new UptoEvmFacilitatorScheme(signer, config);
|
|
987
1714
|
}
|
|
988
1715
|
|
|
1716
|
+
// src/bridge/client.ts
|
|
1717
|
+
var import_viem7 = require("viem");
|
|
1718
|
+
|
|
989
1719
|
// src/bridge/constants.ts
|
|
990
1720
|
var LAYERZERO_ENDPOINT_IDS = {
|
|
991
1721
|
// Mainnets
|
|
@@ -1158,9 +1888,7 @@ function supportsBridging(chain) {
|
|
|
1158
1888
|
return chain in USDT0_OFT_ADDRESSES && chain in LAYERZERO_ENDPOINT_IDS;
|
|
1159
1889
|
}
|
|
1160
1890
|
function getBridgeableChains() {
|
|
1161
|
-
return Object.keys(USDT0_OFT_ADDRESSES).filter(
|
|
1162
|
-
(chain) => chain in LAYERZERO_ENDPOINT_IDS
|
|
1163
|
-
);
|
|
1891
|
+
return Object.keys(USDT0_OFT_ADDRESSES).filter((chain) => chain in LAYERZERO_ENDPOINT_IDS);
|
|
1164
1892
|
}
|
|
1165
1893
|
function addressToBytes32(address) {
|
|
1166
1894
|
const cleanAddress = address.slice(2).toLowerCase();
|
|
@@ -1171,6 +1899,7 @@ function bytes32ToAddress(bytes32) {
|
|
|
1171
1899
|
}
|
|
1172
1900
|
|
|
1173
1901
|
// src/bridge/client.ts
|
|
1902
|
+
var OFT_SENT_EVENT_TOPIC = (0, import_viem7.keccak256)((0, import_viem7.toBytes)("OFTSent(bytes32,uint32,address,uint256,uint256)"));
|
|
1174
1903
|
var DEFAULT_SLIPPAGE = 0.5;
|
|
1175
1904
|
var ESTIMATED_BRIDGE_TIME = 300;
|
|
1176
1905
|
var Usdt0Bridge = class {
|
|
@@ -1181,6 +1910,8 @@ var Usdt0Bridge = class {
|
|
|
1181
1910
|
* @param chain - Source chain name (e.g., "arbitrum", "ethereum")
|
|
1182
1911
|
*/
|
|
1183
1912
|
constructor(signer, chain) {
|
|
1913
|
+
__publicField(this, "signer");
|
|
1914
|
+
__publicField(this, "chain");
|
|
1184
1915
|
if (!supportsBridging(chain)) {
|
|
1185
1916
|
throw new Error(
|
|
1186
1917
|
`Chain "${chain}" does not support USDT0 bridging. Supported chains: ${getBridgeableChains().join(", ")}`
|
|
@@ -1243,10 +1974,10 @@ var Usdt0Bridge = class {
|
|
|
1243
1974
|
if (receipt.status !== "success") {
|
|
1244
1975
|
throw new Error(`Bridge transaction failed: ${txHash}`);
|
|
1245
1976
|
}
|
|
1977
|
+
const messageGuid = this.extractMessageGuid(receipt);
|
|
1246
1978
|
return {
|
|
1247
1979
|
txHash,
|
|
1248
|
-
messageGuid
|
|
1249
|
-
// Would be extracted from event logs
|
|
1980
|
+
messageGuid,
|
|
1250
1981
|
amountSent: params.amount,
|
|
1251
1982
|
amountToReceive: sendParam.minAmountLD,
|
|
1252
1983
|
fromChain: params.fromChain,
|
|
@@ -1254,8 +1985,44 @@ var Usdt0Bridge = class {
|
|
|
1254
1985
|
estimatedTime: ESTIMATED_BRIDGE_TIME
|
|
1255
1986
|
};
|
|
1256
1987
|
}
|
|
1988
|
+
/**
|
|
1989
|
+
* Get all supported destination chains from current chain
|
|
1990
|
+
*
|
|
1991
|
+
* @returns Array of supported destination chain names
|
|
1992
|
+
*/
|
|
1993
|
+
getSupportedDestinations() {
|
|
1994
|
+
return getBridgeableChains().filter((chain) => chain !== this.chain);
|
|
1995
|
+
}
|
|
1996
|
+
/**
|
|
1997
|
+
* Check if a destination chain is supported
|
|
1998
|
+
*
|
|
1999
|
+
* @param toChain - The destination chain to check
|
|
2000
|
+
* @returns True if the destination chain is supported
|
|
2001
|
+
*/
|
|
2002
|
+
supportsDestination(toChain) {
|
|
2003
|
+
return toChain !== this.chain && supportsBridging(toChain);
|
|
2004
|
+
}
|
|
2005
|
+
/**
|
|
2006
|
+
* Extract LayerZero message GUID from OFTSent event logs
|
|
2007
|
+
*
|
|
2008
|
+
* @param receipt - Transaction receipt with logs
|
|
2009
|
+
* @returns Message GUID as hex string
|
|
2010
|
+
*/
|
|
2011
|
+
extractMessageGuid(receipt) {
|
|
2012
|
+
for (const log of receipt.logs) {
|
|
2013
|
+
if (log.topics[0] === OFT_SENT_EVENT_TOPIC && log.topics[1]) {
|
|
2014
|
+
return log.topics[1];
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
throw new Error(
|
|
2018
|
+
"Failed to extract message GUID from transaction logs. The OFTSent event was not found in the transaction receipt."
|
|
2019
|
+
);
|
|
2020
|
+
}
|
|
1257
2021
|
/**
|
|
1258
2022
|
* Ensure sufficient token allowance for the OFT contract
|
|
2023
|
+
*
|
|
2024
|
+
* @param oftAddress - The OFT contract address
|
|
2025
|
+
* @param amount - The amount to approve
|
|
1259
2026
|
*/
|
|
1260
2027
|
async ensureAllowance(oftAddress, amount) {
|
|
1261
2028
|
const allowance = await this.signer.readContract({
|
|
@@ -1276,6 +2043,9 @@ var Usdt0Bridge = class {
|
|
|
1276
2043
|
}
|
|
1277
2044
|
/**
|
|
1278
2045
|
* Build SendParam struct for LayerZero
|
|
2046
|
+
*
|
|
2047
|
+
* @param params - Bridge parameters
|
|
2048
|
+
* @returns SendParam struct for the OFT contract
|
|
1279
2049
|
*/
|
|
1280
2050
|
buildSendParam(params) {
|
|
1281
2051
|
const dstEid = getEndpointId(params.toChain);
|
|
@@ -1296,6 +2066,8 @@ var Usdt0Bridge = class {
|
|
|
1296
2066
|
}
|
|
1297
2067
|
/**
|
|
1298
2068
|
* Validate bridge parameters
|
|
2069
|
+
*
|
|
2070
|
+
* @param params - Bridge parameters to validate
|
|
1299
2071
|
*/
|
|
1300
2072
|
validateBridgeParams(params) {
|
|
1301
2073
|
if (params.fromChain !== this.chain) {
|
|
@@ -1316,21 +2088,301 @@ var Usdt0Bridge = class {
|
|
|
1316
2088
|
throw new Error("Amount must be greater than 0");
|
|
1317
2089
|
}
|
|
1318
2090
|
}
|
|
2091
|
+
};
|
|
2092
|
+
function createUsdt0Bridge(signer, chain) {
|
|
2093
|
+
return new Usdt0Bridge(signer, chain);
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
// src/bridge/scan.ts
|
|
2097
|
+
var LAYERZERO_SCAN_BASE_URL = "https://scan.layerzero-api.com/v1";
|
|
2098
|
+
var DEFAULT_TIMEOUT = 6e5;
|
|
2099
|
+
var DEFAULT_POLL_INTERVAL = 1e4;
|
|
2100
|
+
var LayerZeroScanClient = class {
|
|
1319
2101
|
/**
|
|
1320
|
-
*
|
|
2102
|
+
* Create a new LayerZero Scan client
|
|
2103
|
+
*
|
|
2104
|
+
* @param baseUrl - API base URL (default: production endpoint)
|
|
2105
|
+
*/
|
|
2106
|
+
constructor(baseUrl = LAYERZERO_SCAN_BASE_URL) {
|
|
2107
|
+
__publicField(this, "baseUrl");
|
|
2108
|
+
this.baseUrl = baseUrl;
|
|
2109
|
+
}
|
|
2110
|
+
/**
|
|
2111
|
+
* Get message by GUID
|
|
2112
|
+
*
|
|
2113
|
+
* @param guid - LayerZero message GUID
|
|
2114
|
+
* @returns Message details including status
|
|
2115
|
+
* @throws Error if message not found or API error
|
|
2116
|
+
*/
|
|
2117
|
+
async getMessage(guid) {
|
|
2118
|
+
const url = `${this.baseUrl}/messages/guid/${guid}`;
|
|
2119
|
+
const response = await fetch(url, {
|
|
2120
|
+
method: "GET",
|
|
2121
|
+
headers: {
|
|
2122
|
+
Accept: "application/json"
|
|
2123
|
+
}
|
|
2124
|
+
});
|
|
2125
|
+
if (!response.ok) {
|
|
2126
|
+
if (response.status === 404) {
|
|
2127
|
+
throw new Error(`Message not found: ${guid}`);
|
|
2128
|
+
}
|
|
2129
|
+
throw new Error(`LayerZero Scan API error: ${response.status} ${response.statusText}`);
|
|
2130
|
+
}
|
|
2131
|
+
const data = await response.json();
|
|
2132
|
+
return this.mapApiResponse(data);
|
|
2133
|
+
}
|
|
2134
|
+
/**
|
|
2135
|
+
* Get messages by wallet address
|
|
2136
|
+
*
|
|
2137
|
+
* @param address - Wallet address that initiated messages
|
|
2138
|
+
* @param limit - Maximum number of messages to return (default: 20)
|
|
2139
|
+
* @returns Array of messages
|
|
2140
|
+
*/
|
|
2141
|
+
async getMessagesByWallet(address, limit = 20) {
|
|
2142
|
+
const url = `${this.baseUrl}/messages/wallet/${address}?limit=${limit}`;
|
|
2143
|
+
const response = await fetch(url, {
|
|
2144
|
+
method: "GET",
|
|
2145
|
+
headers: {
|
|
2146
|
+
Accept: "application/json"
|
|
2147
|
+
}
|
|
2148
|
+
});
|
|
2149
|
+
if (!response.ok) {
|
|
2150
|
+
throw new Error(`LayerZero Scan API error: ${response.status} ${response.statusText}`);
|
|
2151
|
+
}
|
|
2152
|
+
const data = await response.json();
|
|
2153
|
+
const messages = data.messages ?? data.data ?? [];
|
|
2154
|
+
return messages.map((msg) => this.mapApiResponse(msg));
|
|
2155
|
+
}
|
|
2156
|
+
/**
|
|
2157
|
+
* Poll message status until delivered or failed
|
|
2158
|
+
*
|
|
2159
|
+
* @param guid - LayerZero message GUID
|
|
2160
|
+
* @param options - Wait configuration options
|
|
2161
|
+
* @returns Final message state (DELIVERED)
|
|
2162
|
+
* @throws Error if message fails, is blocked, or times out
|
|
2163
|
+
*/
|
|
2164
|
+
async waitForDelivery(guid, options = {}) {
|
|
2165
|
+
const {
|
|
2166
|
+
timeout = DEFAULT_TIMEOUT,
|
|
2167
|
+
pollInterval = DEFAULT_POLL_INTERVAL,
|
|
2168
|
+
onStatusChange
|
|
2169
|
+
} = options;
|
|
2170
|
+
const startTime = Date.now();
|
|
2171
|
+
let lastStatus = null;
|
|
2172
|
+
while (Date.now() - startTime < timeout) {
|
|
2173
|
+
try {
|
|
2174
|
+
const message = await this.getMessage(guid);
|
|
2175
|
+
if (lastStatus !== message.status) {
|
|
2176
|
+
lastStatus = message.status;
|
|
2177
|
+
onStatusChange?.(message.status);
|
|
2178
|
+
}
|
|
2179
|
+
if (message.status === "DELIVERED") {
|
|
2180
|
+
return message;
|
|
2181
|
+
}
|
|
2182
|
+
if (message.status === "FAILED") {
|
|
2183
|
+
throw new Error(`Bridge message failed: ${guid}`);
|
|
2184
|
+
}
|
|
2185
|
+
if (message.status === "BLOCKED") {
|
|
2186
|
+
throw new Error(`Bridge message blocked by DVN: ${guid}`);
|
|
2187
|
+
}
|
|
2188
|
+
await this.sleep(pollInterval);
|
|
2189
|
+
} catch (error) {
|
|
2190
|
+
if (error.message.includes("not found")) {
|
|
2191
|
+
await this.sleep(pollInterval);
|
|
2192
|
+
continue;
|
|
2193
|
+
}
|
|
2194
|
+
throw error;
|
|
2195
|
+
}
|
|
2196
|
+
}
|
|
2197
|
+
throw new Error(`Timeout waiting for message delivery: ${guid}`);
|
|
2198
|
+
}
|
|
2199
|
+
/**
|
|
2200
|
+
* Check if a message has been delivered
|
|
2201
|
+
*
|
|
2202
|
+
* @param guid - LayerZero message GUID
|
|
2203
|
+
* @returns True if delivered, false otherwise
|
|
2204
|
+
*/
|
|
2205
|
+
async isDelivered(guid) {
|
|
2206
|
+
try {
|
|
2207
|
+
const message = await this.getMessage(guid);
|
|
2208
|
+
return message.status === "DELIVERED";
|
|
2209
|
+
} catch {
|
|
2210
|
+
return false;
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
/**
|
|
2214
|
+
* Map API response to our interface
|
|
2215
|
+
*
|
|
2216
|
+
* @param data - The raw API response data
|
|
2217
|
+
* @returns The mapped LayerZeroMessage object
|
|
2218
|
+
*/
|
|
2219
|
+
mapApiResponse(data) {
|
|
2220
|
+
const msg = data;
|
|
2221
|
+
return {
|
|
2222
|
+
guid: msg.guid ?? msg.messageGuid ?? "",
|
|
2223
|
+
srcEid: msg.srcEid ?? msg.srcChainId ?? 0,
|
|
2224
|
+
dstEid: msg.dstEid ?? msg.dstChainId ?? 0,
|
|
2225
|
+
srcUaAddress: msg.srcUaAddress ?? msg.srcAddress ?? "",
|
|
2226
|
+
dstUaAddress: msg.dstUaAddress ?? msg.dstAddress ?? "",
|
|
2227
|
+
srcTxHash: msg.srcTxHash ?? "",
|
|
2228
|
+
dstTxHash: msg.dstTxHash ?? void 0,
|
|
2229
|
+
status: msg.status ?? "INFLIGHT",
|
|
2230
|
+
srcBlockNumber: msg.srcBlockNumber ?? 0,
|
|
2231
|
+
dstBlockNumber: msg.dstBlockNumber ?? void 0,
|
|
2232
|
+
created: msg.created ?? msg.createdAt ?? "",
|
|
2233
|
+
updated: msg.updated ?? msg.updatedAt ?? ""
|
|
2234
|
+
};
|
|
2235
|
+
}
|
|
2236
|
+
/**
|
|
2237
|
+
* Sleep helper
|
|
2238
|
+
*
|
|
2239
|
+
* @param ms - The number of milliseconds to sleep
|
|
2240
|
+
* @returns A promise that resolves after the specified delay
|
|
2241
|
+
*/
|
|
2242
|
+
sleep(ms) {
|
|
2243
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2244
|
+
}
|
|
2245
|
+
};
|
|
2246
|
+
function createLayerZeroScanClient(baseUrl) {
|
|
2247
|
+
return new LayerZeroScanClient(baseUrl);
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
// src/bridge/router.ts
|
|
2251
|
+
var CrossChainPaymentRouter = class {
|
|
2252
|
+
/**
|
|
2253
|
+
* Create a cross-chain payment router
|
|
2254
|
+
*
|
|
2255
|
+
* @param signer - Wallet signer for bridge operations
|
|
2256
|
+
* @param sourceChain - Chain where user's funds are located
|
|
2257
|
+
*/
|
|
2258
|
+
constructor(signer, sourceChain) {
|
|
2259
|
+
__publicField(this, "bridge");
|
|
2260
|
+
__publicField(this, "scanClient");
|
|
2261
|
+
__publicField(this, "sourceChain");
|
|
2262
|
+
this.bridge = new Usdt0Bridge(signer, sourceChain);
|
|
2263
|
+
this.scanClient = new LayerZeroScanClient();
|
|
2264
|
+
this.sourceChain = sourceChain;
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* Get all bridgeable chains
|
|
2268
|
+
*
|
|
2269
|
+
* @returns Array of all chain names that support USDT0 bridging
|
|
2270
|
+
*/
|
|
2271
|
+
static getBridgeableChains() {
|
|
2272
|
+
return getBridgeableChains();
|
|
2273
|
+
}
|
|
2274
|
+
/**
|
|
2275
|
+
* Route payment across chains
|
|
2276
|
+
*
|
|
2277
|
+
* This method:
|
|
2278
|
+
* 1. Bridges USDT0 from source chain to destination chain
|
|
2279
|
+
* 2. Sends funds to the payer's address on destination chain
|
|
2280
|
+
* 3. Returns tracking info for monitoring delivery
|
|
2281
|
+
*
|
|
2282
|
+
* After delivery, the payer can use the bridged funds to pay on the destination chain.
|
|
2283
|
+
*
|
|
2284
|
+
* @param params - Payment routing parameters
|
|
2285
|
+
* @returns Result with transaction hash and tracking info
|
|
2286
|
+
*/
|
|
2287
|
+
async routePayment(params) {
|
|
2288
|
+
this.validateParams(params);
|
|
2289
|
+
const result = await this.bridge.send({
|
|
2290
|
+
fromChain: params.sourceChain,
|
|
2291
|
+
toChain: params.destinationChain,
|
|
2292
|
+
amount: params.amount,
|
|
2293
|
+
recipient: params.payer,
|
|
2294
|
+
slippageTolerance: params.slippageTolerance
|
|
2295
|
+
});
|
|
2296
|
+
return {
|
|
2297
|
+
bridgeTxHash: result.txHash,
|
|
2298
|
+
messageGuid: result.messageGuid,
|
|
2299
|
+
amountBridged: result.amountSent,
|
|
2300
|
+
estimatedReceiveAmount: result.amountToReceive,
|
|
2301
|
+
sourceChain: params.sourceChain,
|
|
2302
|
+
destinationChain: params.destinationChain,
|
|
2303
|
+
estimatedDeliveryTime: result.estimatedTime
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
/**
|
|
2307
|
+
* Get estimated fees for routing a payment
|
|
2308
|
+
*
|
|
2309
|
+
* @param params - Payment parameters
|
|
2310
|
+
* @returns Quote with native fee and estimated receive amount
|
|
2311
|
+
*/
|
|
2312
|
+
async estimateFees(params) {
|
|
2313
|
+
const quote = await this.bridge.quote({
|
|
2314
|
+
fromChain: params.sourceChain,
|
|
2315
|
+
toChain: params.destinationChain,
|
|
2316
|
+
amount: params.amount,
|
|
2317
|
+
recipient: params.payer
|
|
2318
|
+
});
|
|
2319
|
+
return {
|
|
2320
|
+
nativeFee: quote.nativeFee,
|
|
2321
|
+
estimatedReceiveAmount: quote.minAmountToReceive,
|
|
2322
|
+
estimatedTime: quote.estimatedTime
|
|
2323
|
+
};
|
|
2324
|
+
}
|
|
2325
|
+
/**
|
|
2326
|
+
* Track message delivery status
|
|
2327
|
+
*
|
|
2328
|
+
* @param messageGuid - LayerZero message GUID from routePayment result
|
|
2329
|
+
* @returns Current message status
|
|
2330
|
+
*/
|
|
2331
|
+
async trackMessage(messageGuid) {
|
|
2332
|
+
return this.scanClient.getMessage(messageGuid);
|
|
2333
|
+
}
|
|
2334
|
+
/**
|
|
2335
|
+
* Wait for payment to be delivered on destination chain
|
|
2336
|
+
*
|
|
2337
|
+
* @param messageGuid - LayerZero message GUID from routePayment result
|
|
2338
|
+
* @param options - Wait options (timeout, poll interval, callbacks)
|
|
2339
|
+
* @returns Final message state when delivered
|
|
2340
|
+
*/
|
|
2341
|
+
async waitForDelivery(messageGuid, options) {
|
|
2342
|
+
return this.scanClient.waitForDelivery(messageGuid, options);
|
|
2343
|
+
}
|
|
2344
|
+
/**
|
|
2345
|
+
* Check if routing between two chains is supported
|
|
2346
|
+
*
|
|
2347
|
+
* @param sourceChain - Source chain name
|
|
2348
|
+
* @param destinationChain - Destination chain name
|
|
2349
|
+
* @returns True if routing is supported
|
|
2350
|
+
*/
|
|
2351
|
+
canRoute(sourceChain, destinationChain) {
|
|
2352
|
+
return sourceChain !== destinationChain && supportsBridging(sourceChain) && supportsBridging(destinationChain);
|
|
2353
|
+
}
|
|
2354
|
+
/**
|
|
2355
|
+
* Get all supported destination chains from source chain
|
|
2356
|
+
*
|
|
2357
|
+
* @returns Array of chain names that can receive bridged funds
|
|
1321
2358
|
*/
|
|
1322
2359
|
getSupportedDestinations() {
|
|
1323
|
-
return
|
|
2360
|
+
return this.bridge.getSupportedDestinations();
|
|
1324
2361
|
}
|
|
1325
2362
|
/**
|
|
1326
|
-
*
|
|
2363
|
+
* Validate routing parameters
|
|
2364
|
+
*
|
|
2365
|
+
* @param params - The cross-chain payment parameters to validate
|
|
2366
|
+
* @throws Error if parameters are invalid or routing is not supported
|
|
1327
2367
|
*/
|
|
1328
|
-
|
|
1329
|
-
|
|
2368
|
+
validateParams(params) {
|
|
2369
|
+
if (params.sourceChain !== this.sourceChain) {
|
|
2370
|
+
throw new Error(
|
|
2371
|
+
`Source chain mismatch: router initialized for "${this.sourceChain}" but got "${params.sourceChain}"`
|
|
2372
|
+
);
|
|
2373
|
+
}
|
|
2374
|
+
if (!this.canRoute(params.sourceChain, params.destinationChain)) {
|
|
2375
|
+
throw new Error(
|
|
2376
|
+
`Cannot route payment from "${params.sourceChain}" to "${params.destinationChain}". Supported chains: ${getBridgeableChains().join(", ")}`
|
|
2377
|
+
);
|
|
2378
|
+
}
|
|
2379
|
+
if (params.amount <= 0n) {
|
|
2380
|
+
throw new Error("Amount must be greater than 0");
|
|
2381
|
+
}
|
|
1330
2382
|
}
|
|
1331
2383
|
};
|
|
1332
|
-
function
|
|
1333
|
-
return new
|
|
2384
|
+
function createCrossChainPaymentRouter(signer, sourceChain) {
|
|
2385
|
+
return new CrossChainPaymentRouter(signer, sourceChain);
|
|
1334
2386
|
}
|
|
1335
2387
|
|
|
1336
2388
|
// src/erc4337/constants.ts
|
|
@@ -1508,25 +2560,35 @@ function unpackGasFees(packed) {
|
|
|
1508
2560
|
}
|
|
1509
2561
|
|
|
1510
2562
|
// src/erc4337/builder.ts
|
|
1511
|
-
var
|
|
2563
|
+
var import_viem8 = require("viem");
|
|
1512
2564
|
var UserOpBuilder = class {
|
|
2565
|
+
/**
|
|
2566
|
+
* Create a new UserOpBuilder instance
|
|
2567
|
+
*
|
|
2568
|
+
* @param options - Optional configuration for the builder
|
|
2569
|
+
*/
|
|
1513
2570
|
constructor(options = {}) {
|
|
2571
|
+
__publicField(this, "entryPoint");
|
|
2572
|
+
__publicField(this, "gasMultiplier");
|
|
1514
2573
|
this.entryPoint = options.entryPoint ?? ENTRYPOINT_V07_ADDRESS;
|
|
1515
2574
|
this.gasMultiplier = options.gasMultiplier ?? 1.2;
|
|
1516
2575
|
}
|
|
1517
2576
|
/**
|
|
1518
2577
|
* Build a UserOperation from a transaction intent
|
|
2578
|
+
*
|
|
2579
|
+
* @param signer - The smart account signer
|
|
2580
|
+
* @param intent - The transaction intent to execute
|
|
2581
|
+
* @param client - The public client for chain interaction
|
|
2582
|
+
* @param gasEstimate - Optional gas estimates (uses defaults if not provided)
|
|
2583
|
+
* @param paymaster - Optional paymaster data for sponsored transactions
|
|
2584
|
+
* @returns A UserOperation ready for signing
|
|
1519
2585
|
*/
|
|
1520
2586
|
async buildUserOp(signer, intent, client, gasEstimate, paymaster) {
|
|
1521
2587
|
const sender = await signer.getAddress();
|
|
1522
2588
|
const nonce = await this.getNonce(client, sender);
|
|
1523
2589
|
const isDeployed = await signer.isDeployed();
|
|
1524
2590
|
const initCode = isDeployed ? "0x" : await signer.getInitCode();
|
|
1525
|
-
const callData = signer.encodeExecute(
|
|
1526
|
-
intent.to,
|
|
1527
|
-
intent.value ?? 0n,
|
|
1528
|
-
intent.data ?? "0x"
|
|
1529
|
-
);
|
|
2591
|
+
const callData = signer.encodeExecute(intent.to, intent.value ?? 0n, intent.data ?? "0x");
|
|
1530
2592
|
const { maxFeePerGas, maxPriorityFeePerGas } = await this.getGasPrices(client);
|
|
1531
2593
|
const gas = gasEstimate ?? DEFAULT_GAS_LIMITS;
|
|
1532
2594
|
const verificationGasLimit = this.applyMultiplier(gas.verificationGasLimit);
|
|
@@ -1550,6 +2612,13 @@ var UserOpBuilder = class {
|
|
|
1550
2612
|
}
|
|
1551
2613
|
/**
|
|
1552
2614
|
* Build a batch UserOperation from multiple transaction intents
|
|
2615
|
+
*
|
|
2616
|
+
* @param signer - The smart account signer
|
|
2617
|
+
* @param intents - Array of transaction intents to execute
|
|
2618
|
+
* @param client - The public client for chain interaction
|
|
2619
|
+
* @param gasEstimate - Optional gas estimates (uses defaults if not provided)
|
|
2620
|
+
* @param paymaster - Optional paymaster data for sponsored transactions
|
|
2621
|
+
* @returns A UserOperation ready for signing
|
|
1553
2622
|
*/
|
|
1554
2623
|
async buildBatchUserOp(signer, intents, client, gasEstimate, paymaster) {
|
|
1555
2624
|
const sender = await signer.getAddress();
|
|
@@ -1586,6 +2655,9 @@ var UserOpBuilder = class {
|
|
|
1586
2655
|
}
|
|
1587
2656
|
/**
|
|
1588
2657
|
* Pack a UserOperation for on-chain submission (v0.7 format)
|
|
2658
|
+
*
|
|
2659
|
+
* @param userOp - The UserOperation to pack
|
|
2660
|
+
* @returns The packed UserOperation for on-chain submission
|
|
1589
2661
|
*/
|
|
1590
2662
|
packUserOp(userOp) {
|
|
1591
2663
|
return {
|
|
@@ -1593,10 +2665,7 @@ var UserOpBuilder = class {
|
|
|
1593
2665
|
nonce: userOp.nonce,
|
|
1594
2666
|
initCode: userOp.initCode,
|
|
1595
2667
|
callData: userOp.callData,
|
|
1596
|
-
accountGasLimits: packAccountGasLimits(
|
|
1597
|
-
userOp.verificationGasLimit,
|
|
1598
|
-
userOp.callGasLimit
|
|
1599
|
-
),
|
|
2668
|
+
accountGasLimits: packAccountGasLimits(userOp.verificationGasLimit, userOp.callGasLimit),
|
|
1600
2669
|
preVerificationGas: userOp.preVerificationGas,
|
|
1601
2670
|
gasFees: packGasFees(userOp.maxPriorityFeePerGas, userOp.maxFeePerGas),
|
|
1602
2671
|
paymasterAndData: userOp.paymasterAndData,
|
|
@@ -1605,8 +2674,13 @@ var UserOpBuilder = class {
|
|
|
1605
2674
|
}
|
|
1606
2675
|
/**
|
|
1607
2676
|
* Compute the UserOperation hash for signing
|
|
2677
|
+
*
|
|
2678
|
+
* @param userOp - The UserOperation to hash
|
|
2679
|
+
* @param client - The public client for chain interaction
|
|
2680
|
+
* @param _ - The chain ID (reserved for future use)
|
|
2681
|
+
* @returns The UserOperation hash
|
|
1608
2682
|
*/
|
|
1609
|
-
async getUserOpHash(userOp, client,
|
|
2683
|
+
async getUserOpHash(userOp, client, _) {
|
|
1610
2684
|
const packed = this.packUserOp(userOp);
|
|
1611
2685
|
const userOpTuple = {
|
|
1612
2686
|
sender: packed.sender,
|
|
@@ -1629,6 +2703,12 @@ var UserOpBuilder = class {
|
|
|
1629
2703
|
}
|
|
1630
2704
|
/**
|
|
1631
2705
|
* Sign a UserOperation
|
|
2706
|
+
*
|
|
2707
|
+
* @param userOp - The UserOperation to sign
|
|
2708
|
+
* @param signer - The smart account signer
|
|
2709
|
+
* @param client - The public client for chain interaction
|
|
2710
|
+
* @param chainId - The chain ID for the signature
|
|
2711
|
+
* @returns The UserOperation with signature attached
|
|
1632
2712
|
*/
|
|
1633
2713
|
async signUserOp(userOp, signer, client, chainId) {
|
|
1634
2714
|
const userOpHash = await this.getUserOpHash(userOp, client, chainId);
|
|
@@ -1640,6 +2720,10 @@ var UserOpBuilder = class {
|
|
|
1640
2720
|
}
|
|
1641
2721
|
/**
|
|
1642
2722
|
* Get the nonce for an account from EntryPoint
|
|
2723
|
+
*
|
|
2724
|
+
* @param client - The public client for chain interaction
|
|
2725
|
+
* @param sender - The smart account address
|
|
2726
|
+
* @returns The current nonce for the account
|
|
1643
2727
|
*/
|
|
1644
2728
|
async getNonce(client, sender) {
|
|
1645
2729
|
try {
|
|
@@ -1657,6 +2741,9 @@ var UserOpBuilder = class {
|
|
|
1657
2741
|
}
|
|
1658
2742
|
/**
|
|
1659
2743
|
* Get current gas prices from the chain
|
|
2744
|
+
*
|
|
2745
|
+
* @param client - The public client for chain interaction
|
|
2746
|
+
* @returns The current gas prices for EIP-1559 transactions
|
|
1660
2747
|
*/
|
|
1661
2748
|
async getGasPrices(client) {
|
|
1662
2749
|
const block = await client.getBlock({ blockTag: "latest" });
|
|
@@ -1667,25 +2754,26 @@ var UserOpBuilder = class {
|
|
|
1667
2754
|
}
|
|
1668
2755
|
/**
|
|
1669
2756
|
* Apply gas multiplier for safety margin
|
|
2757
|
+
*
|
|
2758
|
+
* @param gas - The gas amount to multiply
|
|
2759
|
+
* @returns The gas amount with safety margin applied
|
|
1670
2760
|
*/
|
|
1671
2761
|
applyMultiplier(gas) {
|
|
1672
2762
|
return BigInt(Math.ceil(Number(gas) * this.gasMultiplier));
|
|
1673
2763
|
}
|
|
1674
2764
|
/**
|
|
1675
2765
|
* Encode paymaster data for the UserOperation
|
|
2766
|
+
*
|
|
2767
|
+
* @param paymaster - The paymaster configuration
|
|
2768
|
+
* @returns The encoded paymaster data
|
|
1676
2769
|
*/
|
|
1677
2770
|
encodePaymasterData(paymaster) {
|
|
1678
2771
|
const paymasterAddress = paymaster.paymaster;
|
|
1679
|
-
const verificationGas = (0,
|
|
2772
|
+
const verificationGas = (0, import_viem8.pad)((0, import_viem8.toHex)(paymaster.paymasterVerificationGasLimit), {
|
|
1680
2773
|
size: 16
|
|
1681
2774
|
});
|
|
1682
|
-
const postOpGas = (0,
|
|
1683
|
-
return (0,
|
|
1684
|
-
paymasterAddress,
|
|
1685
|
-
verificationGas,
|
|
1686
|
-
postOpGas,
|
|
1687
|
-
paymaster.paymasterData
|
|
1688
|
-
]);
|
|
2775
|
+
const postOpGas = (0, import_viem8.pad)((0, import_viem8.toHex)(paymaster.paymasterPostOpGasLimit), { size: 16 });
|
|
2776
|
+
return (0, import_viem8.concat)([paymasterAddress, verificationGas, postOpGas, paymaster.paymasterData]);
|
|
1689
2777
|
}
|
|
1690
2778
|
};
|
|
1691
2779
|
function createUserOpBuilder(options) {
|
|
@@ -1694,6 +2782,13 @@ function createUserOpBuilder(options) {
|
|
|
1694
2782
|
|
|
1695
2783
|
// src/erc4337/bundler.ts
|
|
1696
2784
|
var BundlerError = class extends Error {
|
|
2785
|
+
/**
|
|
2786
|
+
* Create a new BundlerError
|
|
2787
|
+
*
|
|
2788
|
+
* @param message - The error message
|
|
2789
|
+
* @param code - Optional JSON-RPC error code
|
|
2790
|
+
* @param data - Optional additional error data
|
|
2791
|
+
*/
|
|
1697
2792
|
constructor(message, code, data) {
|
|
1698
2793
|
super(message);
|
|
1699
2794
|
this.code = code;
|
|
@@ -1702,21 +2797,31 @@ var BundlerError = class extends Error {
|
|
|
1702
2797
|
}
|
|
1703
2798
|
};
|
|
1704
2799
|
var BundlerClient = class {
|
|
2800
|
+
/**
|
|
2801
|
+
* Create a new BundlerClient instance
|
|
2802
|
+
*
|
|
2803
|
+
* @param config - Configuration for the bundler client
|
|
2804
|
+
*/
|
|
1705
2805
|
constructor(config) {
|
|
1706
|
-
this
|
|
2806
|
+
__publicField(this, "bundlerUrl");
|
|
2807
|
+
__publicField(this, "entryPoint");
|
|
2808
|
+
__publicField(this, "requestId", 0);
|
|
1707
2809
|
this.bundlerUrl = config.bundlerUrl;
|
|
1708
2810
|
this.entryPoint = config.entryPoint ?? ENTRYPOINT_V07_ADDRESS;
|
|
1709
|
-
|
|
2811
|
+
void config.chainId;
|
|
1710
2812
|
}
|
|
1711
2813
|
/**
|
|
1712
2814
|
* Send a UserOperation to the bundler
|
|
2815
|
+
*
|
|
2816
|
+
* @param userOp - The UserOperation to send
|
|
2817
|
+
* @returns The result containing the userOpHash and a wait function
|
|
1713
2818
|
*/
|
|
1714
2819
|
async sendUserOperation(userOp) {
|
|
1715
2820
|
const packed = this.packForRpc(userOp);
|
|
1716
|
-
const userOpHash = await this.rpcCall(
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
);
|
|
2821
|
+
const userOpHash = await this.rpcCall(BUNDLER_METHODS.sendUserOperation, [
|
|
2822
|
+
packed,
|
|
2823
|
+
this.entryPoint
|
|
2824
|
+
]);
|
|
1720
2825
|
return {
|
|
1721
2826
|
userOpHash,
|
|
1722
2827
|
wait: () => this.waitForReceipt(userOpHash)
|
|
@@ -1724,6 +2829,9 @@ var BundlerClient = class {
|
|
|
1724
2829
|
}
|
|
1725
2830
|
/**
|
|
1726
2831
|
* Estimate gas for a UserOperation
|
|
2832
|
+
*
|
|
2833
|
+
* @param userOp - Partial UserOperation with required sender and callData
|
|
2834
|
+
* @returns Gas estimates for the UserOperation
|
|
1727
2835
|
*/
|
|
1728
2836
|
async estimateUserOperationGas(userOp) {
|
|
1729
2837
|
const estimationOp = {
|
|
@@ -1752,6 +2860,9 @@ var BundlerClient = class {
|
|
|
1752
2860
|
}
|
|
1753
2861
|
/**
|
|
1754
2862
|
* Get UserOperation by hash
|
|
2863
|
+
*
|
|
2864
|
+
* @param userOpHash - The hash of the UserOperation to retrieve
|
|
2865
|
+
* @returns The UserOperation and EntryPoint, or null if not found
|
|
1755
2866
|
*/
|
|
1756
2867
|
async getUserOperationByHash(userOpHash) {
|
|
1757
2868
|
const result = await this.rpcCall(BUNDLER_METHODS.getUserOperationByHash, [userOpHash]);
|
|
@@ -1759,6 +2870,9 @@ var BundlerClient = class {
|
|
|
1759
2870
|
}
|
|
1760
2871
|
/**
|
|
1761
2872
|
* Get UserOperation receipt
|
|
2873
|
+
*
|
|
2874
|
+
* @param userOpHash - The hash of the UserOperation
|
|
2875
|
+
* @returns The receipt, or null if not yet included
|
|
1762
2876
|
*/
|
|
1763
2877
|
async getUserOperationReceipt(userOpHash) {
|
|
1764
2878
|
const result = await this.rpcCall(BUNDLER_METHODS.getUserOperationReceipt, [userOpHash]);
|
|
@@ -1781,12 +2895,16 @@ var BundlerClient = class {
|
|
|
1781
2895
|
}
|
|
1782
2896
|
/**
|
|
1783
2897
|
* Get supported EntryPoints
|
|
2898
|
+
*
|
|
2899
|
+
* @returns Array of supported EntryPoint addresses
|
|
1784
2900
|
*/
|
|
1785
2901
|
async getSupportedEntryPoints() {
|
|
1786
2902
|
return this.rpcCall(BUNDLER_METHODS.supportedEntryPoints, []);
|
|
1787
2903
|
}
|
|
1788
2904
|
/**
|
|
1789
2905
|
* Get chain ID from bundler
|
|
2906
|
+
*
|
|
2907
|
+
* @returns The chain ID
|
|
1790
2908
|
*/
|
|
1791
2909
|
async getChainId() {
|
|
1792
2910
|
const result = await this.rpcCall(BUNDLER_METHODS.chainId, []);
|
|
@@ -1794,6 +2912,12 @@ var BundlerClient = class {
|
|
|
1794
2912
|
}
|
|
1795
2913
|
/**
|
|
1796
2914
|
* Wait for UserOperation receipt with polling
|
|
2915
|
+
*
|
|
2916
|
+
* @param userOpHash - The hash of the UserOperation to wait for
|
|
2917
|
+
* @param options - Polling options
|
|
2918
|
+
* @param options.timeout - Maximum time to wait in milliseconds (default: 60000)
|
|
2919
|
+
* @param options.pollingInterval - Interval between polls in milliseconds (default: 2000)
|
|
2920
|
+
* @returns The UserOperation receipt
|
|
1797
2921
|
*/
|
|
1798
2922
|
async waitForReceipt(userOpHash, options = {}) {
|
|
1799
2923
|
const timeout = options.timeout ?? 6e4;
|
|
@@ -1806,12 +2930,13 @@ var BundlerClient = class {
|
|
|
1806
2930
|
}
|
|
1807
2931
|
await new Promise((resolve) => setTimeout(resolve, pollingInterval));
|
|
1808
2932
|
}
|
|
1809
|
-
throw new BundlerError(
|
|
1810
|
-
`Timeout waiting for UserOperation receipt: ${userOpHash}`
|
|
1811
|
-
);
|
|
2933
|
+
throw new BundlerError(`Timeout waiting for UserOperation receipt: ${userOpHash}`);
|
|
1812
2934
|
}
|
|
1813
2935
|
/**
|
|
1814
2936
|
* Pack UserOperation for RPC (convert bigints to hex strings)
|
|
2937
|
+
*
|
|
2938
|
+
* @param userOp - The UserOperation to pack
|
|
2939
|
+
* @returns The packed UserOperation for RPC transmission
|
|
1815
2940
|
*/
|
|
1816
2941
|
packForRpc(userOp) {
|
|
1817
2942
|
return {
|
|
@@ -1819,10 +2944,7 @@ var BundlerClient = class {
|
|
|
1819
2944
|
nonce: this.toHex(userOp.nonce),
|
|
1820
2945
|
initCode: userOp.initCode,
|
|
1821
2946
|
callData: userOp.callData,
|
|
1822
|
-
accountGasLimits: packAccountGasLimits(
|
|
1823
|
-
userOp.verificationGasLimit,
|
|
1824
|
-
userOp.callGasLimit
|
|
1825
|
-
),
|
|
2947
|
+
accountGasLimits: packAccountGasLimits(userOp.verificationGasLimit, userOp.callGasLimit),
|
|
1826
2948
|
preVerificationGas: this.toHex(userOp.preVerificationGas),
|
|
1827
2949
|
gasFees: packGasFees(userOp.maxPriorityFeePerGas, userOp.maxFeePerGas),
|
|
1828
2950
|
paymasterAndData: userOp.paymasterAndData,
|
|
@@ -1831,12 +2953,19 @@ var BundlerClient = class {
|
|
|
1831
2953
|
}
|
|
1832
2954
|
/**
|
|
1833
2955
|
* Convert bigint to hex string
|
|
2956
|
+
*
|
|
2957
|
+
* @param value - The bigint value to convert
|
|
2958
|
+
* @returns The hex string representation
|
|
1834
2959
|
*/
|
|
1835
2960
|
toHex(value) {
|
|
1836
2961
|
return `0x${value.toString(16)}`;
|
|
1837
2962
|
}
|
|
1838
2963
|
/**
|
|
1839
2964
|
* Make a JSON-RPC call to the bundler
|
|
2965
|
+
*
|
|
2966
|
+
* @param method - The JSON-RPC method name
|
|
2967
|
+
* @param params - The method parameters
|
|
2968
|
+
* @returns The result from the bundler
|
|
1840
2969
|
*/
|
|
1841
2970
|
async rpcCall(method, params) {
|
|
1842
2971
|
const request = {
|
|
@@ -1853,9 +2982,7 @@ var BundlerClient = class {
|
|
|
1853
2982
|
body: JSON.stringify(request)
|
|
1854
2983
|
});
|
|
1855
2984
|
if (!response.ok) {
|
|
1856
|
-
throw new BundlerError(
|
|
1857
|
-
`HTTP error: ${response.status} ${response.statusText}`
|
|
1858
|
-
);
|
|
2985
|
+
throw new BundlerError(`HTTP error: ${response.status} ${response.statusText}`);
|
|
1859
2986
|
}
|
|
1860
2987
|
const json = await response.json();
|
|
1861
2988
|
if (json.error) {
|
|
@@ -1869,25 +2996,32 @@ function createBundlerClient(config) {
|
|
|
1869
2996
|
}
|
|
1870
2997
|
|
|
1871
2998
|
// src/erc4337/paymaster.ts
|
|
1872
|
-
var
|
|
2999
|
+
var import_viem9 = require("viem");
|
|
1873
3000
|
var PaymasterClient = class {
|
|
3001
|
+
/**
|
|
3002
|
+
* Creates a new PaymasterClient instance
|
|
3003
|
+
*
|
|
3004
|
+
* @param config - Paymaster configuration including type, address, and optional URL
|
|
3005
|
+
*/
|
|
1874
3006
|
constructor(config) {
|
|
3007
|
+
__publicField(this, "config");
|
|
1875
3008
|
this.config = config;
|
|
1876
3009
|
}
|
|
1877
3010
|
/**
|
|
1878
3011
|
* Get paymaster data for a UserOperation
|
|
3012
|
+
*
|
|
3013
|
+
* @param userOp - Partial UserOperation to get paymaster data for
|
|
3014
|
+
* @param chainId - The chain ID for the operation
|
|
3015
|
+
* @param entryPoint - The EntryPoint contract address
|
|
3016
|
+
* @param context - Optional context data for the paymaster
|
|
3017
|
+
* @returns Paymaster data including address and gas limits
|
|
1879
3018
|
*/
|
|
1880
3019
|
async getPaymasterData(userOp, chainId, entryPoint, context) {
|
|
1881
3020
|
switch (this.config.type) {
|
|
1882
3021
|
case "verifying":
|
|
1883
3022
|
return this.getVerifyingPaymasterData(userOp, chainId, entryPoint);
|
|
1884
3023
|
case "sponsoring":
|
|
1885
|
-
return this.getSponsoringPaymasterData(
|
|
1886
|
-
userOp,
|
|
1887
|
-
chainId,
|
|
1888
|
-
entryPoint,
|
|
1889
|
-
context
|
|
1890
|
-
);
|
|
3024
|
+
return this.getSponsoringPaymasterData(userOp, chainId, entryPoint, context);
|
|
1891
3025
|
case "token":
|
|
1892
3026
|
return this.getTokenPaymasterData(userOp, chainId, entryPoint);
|
|
1893
3027
|
default:
|
|
@@ -1896,8 +3030,12 @@ var PaymasterClient = class {
|
|
|
1896
3030
|
}
|
|
1897
3031
|
/**
|
|
1898
3032
|
* Get gas estimates including paymaster gas
|
|
3033
|
+
*
|
|
3034
|
+
* @param _userOp - Partial UserOperation to estimate gas for (reserved for future use)
|
|
3035
|
+
* @param _chainId - The chain ID for the operation (reserved for future use)
|
|
3036
|
+
* @returns Gas estimates including paymaster verification and postOp gas
|
|
1899
3037
|
*/
|
|
1900
|
-
async estimatePaymasterGas(
|
|
3038
|
+
async estimatePaymasterGas(_userOp, _chainId) {
|
|
1901
3039
|
return {
|
|
1902
3040
|
verificationGasLimit: DEFAULT_GAS_LIMITS.verificationGasLimit,
|
|
1903
3041
|
callGasLimit: DEFAULT_GAS_LIMITS.callGasLimit,
|
|
@@ -1908,6 +3046,12 @@ var PaymasterClient = class {
|
|
|
1908
3046
|
}
|
|
1909
3047
|
/**
|
|
1910
3048
|
* Check if the paymaster will sponsor this operation
|
|
3049
|
+
*
|
|
3050
|
+
* @param userOp - Partial UserOperation to check sponsorship for
|
|
3051
|
+
* @param chainId - The chain ID for the operation
|
|
3052
|
+
* @param entryPoint - The EntryPoint contract address
|
|
3053
|
+
* @param context - Optional context data for policy validation
|
|
3054
|
+
* @returns True if the paymaster will sponsor the operation
|
|
1911
3055
|
*/
|
|
1912
3056
|
async willSponsor(userOp, chainId, entryPoint, context) {
|
|
1913
3057
|
if (!this.config.url) {
|
|
@@ -1933,6 +3077,11 @@ var PaymasterClient = class {
|
|
|
1933
3077
|
}
|
|
1934
3078
|
/**
|
|
1935
3079
|
* Get verifying paymaster data (off-chain signature)
|
|
3080
|
+
*
|
|
3081
|
+
* @param userOp - Partial UserOperation to get paymaster data for
|
|
3082
|
+
* @param chainId - The chain ID for the operation
|
|
3083
|
+
* @param entryPoint - The EntryPoint contract address
|
|
3084
|
+
* @returns Paymaster data with verification signature
|
|
1936
3085
|
*/
|
|
1937
3086
|
async getVerifyingPaymasterData(userOp, chainId, entryPoint) {
|
|
1938
3087
|
if (this.config.url) {
|
|
@@ -1947,6 +3096,12 @@ var PaymasterClient = class {
|
|
|
1947
3096
|
}
|
|
1948
3097
|
/**
|
|
1949
3098
|
* Get sponsoring paymaster data (third-party pays)
|
|
3099
|
+
*
|
|
3100
|
+
* @param userOp - Partial UserOperation to get sponsorship for
|
|
3101
|
+
* @param chainId - The chain ID for the operation
|
|
3102
|
+
* @param entryPoint - The EntryPoint contract address
|
|
3103
|
+
* @param context - Optional context data for sponsorship validation
|
|
3104
|
+
* @returns Paymaster data for sponsored operation
|
|
1950
3105
|
*/
|
|
1951
3106
|
async getSponsoringPaymasterData(userOp, chainId, entryPoint, context) {
|
|
1952
3107
|
if (!this.config.url) {
|
|
@@ -1976,6 +3131,11 @@ var PaymasterClient = class {
|
|
|
1976
3131
|
}
|
|
1977
3132
|
/**
|
|
1978
3133
|
* Get token paymaster data (pay gas with ERC20)
|
|
3134
|
+
*
|
|
3135
|
+
* @param userOp - Partial UserOperation to get token paymaster data for
|
|
3136
|
+
* @param chainId - The chain ID for the operation
|
|
3137
|
+
* @param entryPoint - The EntryPoint contract address
|
|
3138
|
+
* @returns Paymaster data for ERC20 token payment
|
|
1979
3139
|
*/
|
|
1980
3140
|
async getTokenPaymasterData(userOp, chainId, entryPoint) {
|
|
1981
3141
|
const tokenAddress = this.config.options?.tokenAddress;
|
|
@@ -1997,6 +3157,12 @@ var PaymasterClient = class {
|
|
|
1997
3157
|
}
|
|
1998
3158
|
/**
|
|
1999
3159
|
* Call paymaster service API
|
|
3160
|
+
*
|
|
3161
|
+
* @param userOp - Partial UserOperation to send to the service
|
|
3162
|
+
* @param chainId - The chain ID for the operation
|
|
3163
|
+
* @param entryPoint - The EntryPoint contract address
|
|
3164
|
+
* @param context - Optional context data for the service
|
|
3165
|
+
* @returns Paymaster data from the service response
|
|
2000
3166
|
*/
|
|
2001
3167
|
async callPaymasterService(userOp, chainId, entryPoint, context) {
|
|
2002
3168
|
if (!this.config.url) {
|
|
@@ -2026,12 +3192,14 @@ var PaymasterClient = class {
|
|
|
2026
3192
|
}
|
|
2027
3193
|
/**
|
|
2028
3194
|
* Serialize UserOperation for API calls
|
|
3195
|
+
*
|
|
3196
|
+
* @param userOp - Partial UserOperation to serialize
|
|
3197
|
+
* @returns Serialized UserOperation with hex-encoded values
|
|
2029
3198
|
*/
|
|
2030
3199
|
serializeUserOp(userOp) {
|
|
2031
3200
|
const result = {};
|
|
2032
3201
|
if (userOp.sender) result.sender = userOp.sender;
|
|
2033
|
-
if (userOp.nonce !== void 0)
|
|
2034
|
-
result.nonce = `0x${userOp.nonce.toString(16)}`;
|
|
3202
|
+
if (userOp.nonce !== void 0) result.nonce = `0x${userOp.nonce.toString(16)}`;
|
|
2035
3203
|
if (userOp.initCode) result.initCode = userOp.initCode;
|
|
2036
3204
|
if (userOp.callData) result.callData = userOp.callData;
|
|
2037
3205
|
if (userOp.verificationGasLimit !== void 0)
|
|
@@ -2053,10 +3221,10 @@ function createPaymasterClient(config) {
|
|
|
2053
3221
|
return new PaymasterClient(config);
|
|
2054
3222
|
}
|
|
2055
3223
|
function encodePaymasterAndData(data) {
|
|
2056
|
-
return (0,
|
|
3224
|
+
return (0, import_viem9.concat)([
|
|
2057
3225
|
data.paymaster,
|
|
2058
|
-
(0,
|
|
2059
|
-
(0,
|
|
3226
|
+
(0, import_viem9.pad)((0, import_viem9.toHex)(data.paymasterVerificationGasLimit), { size: 16 }),
|
|
3227
|
+
(0, import_viem9.pad)((0, import_viem9.toHex)(data.paymasterPostOpGasLimit), { size: 16 }),
|
|
2060
3228
|
data.paymasterData
|
|
2061
3229
|
]);
|
|
2062
3230
|
}
|
|
@@ -2065,9 +3233,7 @@ function decodePaymasterAndData(paymasterAndData) {
|
|
|
2065
3233
|
return null;
|
|
2066
3234
|
}
|
|
2067
3235
|
const paymaster = `0x${paymasterAndData.slice(2, 42)}`;
|
|
2068
|
-
const paymasterVerificationGasLimit = BigInt(
|
|
2069
|
-
`0x${paymasterAndData.slice(42, 74)}`
|
|
2070
|
-
);
|
|
3236
|
+
const paymasterVerificationGasLimit = BigInt(`0x${paymasterAndData.slice(42, 74)}`);
|
|
2071
3237
|
const paymasterPostOpGasLimit = BigInt(`0x${paymasterAndData.slice(74, 106)}`);
|
|
2072
3238
|
const paymasterData = `0x${paymasterAndData.slice(106)}`;
|
|
2073
3239
|
return {
|
|
@@ -2079,13 +3245,13 @@ function decodePaymasterAndData(paymasterAndData) {
|
|
|
2079
3245
|
}
|
|
2080
3246
|
|
|
2081
3247
|
// src/erc4337/paymasters/pimlico.ts
|
|
2082
|
-
var
|
|
3248
|
+
var import_viem10 = require("viem");
|
|
2083
3249
|
|
|
2084
3250
|
// src/erc4337/accounts/safe.ts
|
|
2085
|
-
var
|
|
3251
|
+
var import_viem11 = require("viem");
|
|
2086
3252
|
|
|
2087
3253
|
// src/erc4337/t402.ts
|
|
2088
|
-
var
|
|
3254
|
+
var import_viem12 = require("viem");
|
|
2089
3255
|
var ERC20_TRANSFER_ABI = [
|
|
2090
3256
|
{
|
|
2091
3257
|
inputs: [
|
|
@@ -2118,7 +3284,18 @@ var EIP3009_TRANSFER_ABI = [
|
|
|
2118
3284
|
}
|
|
2119
3285
|
];
|
|
2120
3286
|
var GaslessT402Client = class {
|
|
3287
|
+
/**
|
|
3288
|
+
* Creates a new GaslessT402Client instance
|
|
3289
|
+
*
|
|
3290
|
+
* @param config - Configuration including signer, bundler, paymaster, and chain settings
|
|
3291
|
+
*/
|
|
2121
3292
|
constructor(config) {
|
|
3293
|
+
__publicField(this, "signer");
|
|
3294
|
+
__publicField(this, "builder");
|
|
3295
|
+
__publicField(this, "bundler");
|
|
3296
|
+
__publicField(this, "paymaster");
|
|
3297
|
+
__publicField(this, "chainId");
|
|
3298
|
+
__publicField(this, "publicClient");
|
|
2122
3299
|
this.signer = config.signer;
|
|
2123
3300
|
this.builder = new UserOpBuilder();
|
|
2124
3301
|
this.bundler = new BundlerClient(config.bundler);
|
|
@@ -2132,6 +3309,9 @@ var GaslessT402Client = class {
|
|
|
2132
3309
|
* This submits the payment as a UserOperation which can be:
|
|
2133
3310
|
* - Sponsored by a paymaster (truly gasless)
|
|
2134
3311
|
* - Paid from the smart account's balance
|
|
3312
|
+
*
|
|
3313
|
+
* @param params - Payment parameters including token, recipient, and amount
|
|
3314
|
+
* @returns Result containing the user operation hash and wait function
|
|
2135
3315
|
*/
|
|
2136
3316
|
async executePayment(params) {
|
|
2137
3317
|
const callData = params.authorization ? this.buildAuthorizedTransferCallData(params) : this.buildTransferCallData(params);
|
|
@@ -2159,6 +3339,9 @@ var GaslessT402Client = class {
|
|
|
2159
3339
|
}
|
|
2160
3340
|
/**
|
|
2161
3341
|
* Execute multiple T402 payments in a single UserOperation
|
|
3342
|
+
*
|
|
3343
|
+
* @param payments - Array of payment parameters to batch together
|
|
3344
|
+
* @returns Result containing the user operation hash and wait function
|
|
2162
3345
|
*/
|
|
2163
3346
|
async executeBatchPayments(payments) {
|
|
2164
3347
|
const intents = payments.map((params) => ({
|
|
@@ -2185,6 +3368,9 @@ var GaslessT402Client = class {
|
|
|
2185
3368
|
}
|
|
2186
3369
|
/**
|
|
2187
3370
|
* Check if a payment can be sponsored (gasless)
|
|
3371
|
+
*
|
|
3372
|
+
* @param params - Payment parameters to check for sponsorship eligibility
|
|
3373
|
+
* @returns True if the payment can be sponsored by the paymaster
|
|
2188
3374
|
*/
|
|
2189
3375
|
async canSponsor(params) {
|
|
2190
3376
|
if (!this.paymaster) return false;
|
|
@@ -2202,21 +3388,28 @@ var GaslessT402Client = class {
|
|
|
2202
3388
|
}
|
|
2203
3389
|
/**
|
|
2204
3390
|
* Get the smart account address
|
|
3391
|
+
*
|
|
3392
|
+
* @returns The address of the smart account
|
|
2205
3393
|
*/
|
|
2206
3394
|
async getAccountAddress() {
|
|
2207
3395
|
return this.signer.getAddress();
|
|
2208
3396
|
}
|
|
2209
3397
|
/**
|
|
2210
3398
|
* Check if the smart account is deployed
|
|
3399
|
+
*
|
|
3400
|
+
* @returns True if the smart account contract is deployed on-chain
|
|
2211
3401
|
*/
|
|
2212
3402
|
async isAccountDeployed() {
|
|
2213
3403
|
return this.signer.isDeployed();
|
|
2214
3404
|
}
|
|
2215
3405
|
/**
|
|
2216
3406
|
* Build call data for a simple ERC20 transfer
|
|
3407
|
+
*
|
|
3408
|
+
* @param params - Payment parameters including recipient and amount
|
|
3409
|
+
* @returns Encoded call data for ERC20 transfer function
|
|
2217
3410
|
*/
|
|
2218
3411
|
buildTransferCallData(params) {
|
|
2219
|
-
return (0,
|
|
3412
|
+
return (0, import_viem12.encodeFunctionData)({
|
|
2220
3413
|
abi: ERC20_TRANSFER_ABI,
|
|
2221
3414
|
functionName: "transfer",
|
|
2222
3415
|
args: [params.to, params.amount]
|
|
@@ -2224,6 +3417,9 @@ var GaslessT402Client = class {
|
|
|
2224
3417
|
}
|
|
2225
3418
|
/**
|
|
2226
3419
|
* Build call data for an authorized transfer (EIP-3009)
|
|
3420
|
+
*
|
|
3421
|
+
* @param params - Payment parameters including authorization signature
|
|
3422
|
+
* @returns Encoded call data for transferWithAuthorization function
|
|
2227
3423
|
*/
|
|
2228
3424
|
buildAuthorizedTransferCallData(params) {
|
|
2229
3425
|
if (!params.authorization) {
|
|
@@ -2233,7 +3429,7 @@ var GaslessT402Client = class {
|
|
|
2233
3429
|
const r = `0x${sig.slice(2, 66)}`;
|
|
2234
3430
|
const s = `0x${sig.slice(66, 130)}`;
|
|
2235
3431
|
const v = parseInt(sig.slice(130, 132), 16);
|
|
2236
|
-
return (0,
|
|
3432
|
+
return (0, import_viem12.encodeFunctionData)({
|
|
2237
3433
|
abi: EIP3009_TRANSFER_ABI,
|
|
2238
3434
|
functionName: "transferWithAuthorization",
|
|
2239
3435
|
args: [
|
|
@@ -2252,14 +3448,13 @@ var GaslessT402Client = class {
|
|
|
2252
3448
|
}
|
|
2253
3449
|
/**
|
|
2254
3450
|
* Estimate gas for a single transaction
|
|
3451
|
+
*
|
|
3452
|
+
* @param intent - Transaction intent with target, value, and data
|
|
3453
|
+
* @returns Gas estimates for the UserOperation
|
|
2255
3454
|
*/
|
|
2256
3455
|
async estimateGas(intent) {
|
|
2257
3456
|
const sender = await this.signer.getAddress();
|
|
2258
|
-
const callData = this.signer.encodeExecute(
|
|
2259
|
-
intent.to,
|
|
2260
|
-
intent.value ?? 0n,
|
|
2261
|
-
intent.data ?? "0x"
|
|
2262
|
-
);
|
|
3457
|
+
const callData = this.signer.encodeExecute(intent.to, intent.value ?? 0n, intent.data ?? "0x");
|
|
2263
3458
|
try {
|
|
2264
3459
|
return await this.bundler.estimateUserOperationGas({
|
|
2265
3460
|
sender,
|
|
@@ -2275,6 +3470,9 @@ var GaslessT402Client = class {
|
|
|
2275
3470
|
}
|
|
2276
3471
|
/**
|
|
2277
3472
|
* Estimate gas for a batch transaction
|
|
3473
|
+
*
|
|
3474
|
+
* @param intents - Array of transaction intents to batch
|
|
3475
|
+
* @returns Gas estimates for the batched UserOperation
|
|
2278
3476
|
*/
|
|
2279
3477
|
async estimateBatchGas(intents) {
|
|
2280
3478
|
const sender = await this.signer.getAddress();
|
|
@@ -2298,15 +3496,14 @@ var GaslessT402Client = class {
|
|
|
2298
3496
|
}
|
|
2299
3497
|
/**
|
|
2300
3498
|
* Get paymaster data if configured
|
|
3499
|
+
*
|
|
3500
|
+
* @param _ - Gas estimates (unused but kept for potential future use)
|
|
3501
|
+
* @returns Paymaster data or undefined if no paymaster configured
|
|
2301
3502
|
*/
|
|
2302
|
-
async getPaymasterData(
|
|
3503
|
+
async getPaymasterData(_) {
|
|
2303
3504
|
if (!this.paymaster) return void 0;
|
|
2304
3505
|
const sender = await this.signer.getAddress();
|
|
2305
|
-
return this.paymaster.getPaymasterData(
|
|
2306
|
-
{ sender },
|
|
2307
|
-
this.chainId,
|
|
2308
|
-
ENTRYPOINT_V07_ADDRESS
|
|
2309
|
-
);
|
|
3506
|
+
return this.paymaster.getPaymasterData({ sender }, this.chainId, ENTRYPOINT_V07_ADDRESS);
|
|
2310
3507
|
}
|
|
2311
3508
|
};
|
|
2312
3509
|
function createGaslessT402Client(config) {
|
|
@@ -2318,6 +3515,7 @@ function createGaslessT402Client(config) {
|
|
|
2318
3515
|
BUNDLER_METHODS,
|
|
2319
3516
|
BundlerClient,
|
|
2320
3517
|
BundlerError,
|
|
3518
|
+
CrossChainPaymentRouter,
|
|
2321
3519
|
DEFAULT_GAS_LIMITS,
|
|
2322
3520
|
ENTRYPOINT_V06_ADDRESS,
|
|
2323
3521
|
ENTRYPOINT_V07_ABI,
|
|
@@ -2329,46 +3527,38 @@ function createGaslessT402Client(config) {
|
|
|
2329
3527
|
GaslessT402Client,
|
|
2330
3528
|
LAYERZERO_ENDPOINT_IDS,
|
|
2331
3529
|
LAYERZERO_ENDPOINT_V2,
|
|
3530
|
+
LAYERZERO_SCAN_BASE_URL,
|
|
3531
|
+
LayerZeroScanClient,
|
|
2332
3532
|
PaymasterClient,
|
|
2333
3533
|
PaymasterType,
|
|
2334
|
-
TOKEN_PRIORITY,
|
|
2335
|
-
TOKEN_REGISTRY,
|
|
2336
|
-
USDC_ADDRESSES,
|
|
2337
|
-
USDT0_ADDRESSES,
|
|
2338
3534
|
USDT0_OFT_ADDRESSES,
|
|
2339
|
-
|
|
3535
|
+
UptoEvmFacilitatorScheme,
|
|
3536
|
+
UptoEvmScheme,
|
|
3537
|
+
UptoEvmServerScheme,
|
|
2340
3538
|
Usdt0Bridge,
|
|
2341
3539
|
UserOpBuilder,
|
|
2342
3540
|
addressToBytes32,
|
|
2343
|
-
authorizationTypes,
|
|
2344
3541
|
bytes32ToAddress,
|
|
2345
3542
|
createBundlerClient,
|
|
3543
|
+
createCrossChainPaymentRouter,
|
|
2346
3544
|
createGaslessT402Client,
|
|
3545
|
+
createLayerZeroScanClient,
|
|
2347
3546
|
createPaymasterClient,
|
|
3547
|
+
createUptoEvmFacilitatorScheme,
|
|
3548
|
+
createUptoEvmScheme,
|
|
3549
|
+
createUptoEvmServerScheme,
|
|
2348
3550
|
createUsdt0Bridge,
|
|
2349
3551
|
createUserOpBuilder,
|
|
2350
3552
|
decodePaymasterAndData,
|
|
2351
|
-
eip3009ABI,
|
|
2352
3553
|
encodePaymasterAndData,
|
|
2353
|
-
erc20LegacyABI,
|
|
2354
3554
|
getBridgeableChains,
|
|
2355
|
-
getDefaultToken,
|
|
2356
|
-
getEIP712Domain,
|
|
2357
3555
|
getEndpointId,
|
|
2358
|
-
getNetworkTokens,
|
|
2359
|
-
getNetworksForToken,
|
|
2360
|
-
getTokenByAddress,
|
|
2361
|
-
getTokenConfig,
|
|
2362
|
-
getUsdt0Networks,
|
|
2363
3556
|
getUsdt0OftAddress,
|
|
2364
|
-
legacyAuthorizationTypes,
|
|
2365
3557
|
packAccountGasLimits,
|
|
2366
3558
|
packGasFees,
|
|
2367
3559
|
supportsBridging,
|
|
2368
|
-
supportsEIP3009,
|
|
2369
|
-
toClientEvmSigner,
|
|
2370
|
-
toFacilitatorEvmSigner,
|
|
2371
3560
|
unpackAccountGasLimits,
|
|
2372
|
-
unpackGasFees
|
|
3561
|
+
unpackGasFees,
|
|
3562
|
+
...require("@t402/evm-core")
|
|
2373
3563
|
});
|
|
2374
3564
|
//# sourceMappingURL=index.js.map
|