@t402/evm 2.2.0 → 2.3.1
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 +606 -352
- package/dist/cjs/index.js +1436 -268
- 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 +606 -352
- package/dist/esm/index.mjs +626 -138
- 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
|
@@ -0,0 +1,1030 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
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;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
21
|
+
|
|
22
|
+
// src/upto/index.ts
|
|
23
|
+
var upto_exports = {};
|
|
24
|
+
__export(upto_exports, {
|
|
25
|
+
UptoEvmFacilitatorScheme: () => UptoEvmFacilitatorScheme,
|
|
26
|
+
UptoEvmScheme: () => UptoEvmScheme,
|
|
27
|
+
UptoEvmServerScheme: () => UptoEvmServerScheme,
|
|
28
|
+
createUptoEvmFacilitatorScheme: () => createUptoEvmFacilitatorScheme,
|
|
29
|
+
createUptoEvmScheme: () => createUptoEvmScheme,
|
|
30
|
+
createUptoEvmServerScheme: () => createUptoEvmServerScheme,
|
|
31
|
+
isUptoEIP2612Payload: () => isUptoEIP2612Payload,
|
|
32
|
+
permitTypes: () => permitTypes
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(upto_exports);
|
|
35
|
+
|
|
36
|
+
// src/upto/client/scheme.ts
|
|
37
|
+
var import_viem2 = require("viem");
|
|
38
|
+
|
|
39
|
+
// src/types.ts
|
|
40
|
+
var permitTypes = {
|
|
41
|
+
Permit: [
|
|
42
|
+
{ name: "owner", type: "address" },
|
|
43
|
+
{ name: "spender", type: "address" },
|
|
44
|
+
{ name: "value", type: "uint256" },
|
|
45
|
+
{ name: "nonce", type: "uint256" },
|
|
46
|
+
{ name: "deadline", type: "uint256" }
|
|
47
|
+
]
|
|
48
|
+
};
|
|
49
|
+
function isUptoEIP2612Payload(payload) {
|
|
50
|
+
if (typeof payload !== "object" || payload === null) return false;
|
|
51
|
+
const p = payload;
|
|
52
|
+
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;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/utils.ts
|
|
56
|
+
var import_viem = require("viem");
|
|
57
|
+
function createNonce() {
|
|
58
|
+
const cryptoObj = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : globalThis.crypto;
|
|
59
|
+
if (!cryptoObj) {
|
|
60
|
+
throw new Error("Crypto API not available");
|
|
61
|
+
}
|
|
62
|
+
return (0, import_viem.toHex)(cryptoObj.getRandomValues(new Uint8Array(32)));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/upto/client/scheme.ts
|
|
66
|
+
var UptoEvmScheme = class {
|
|
67
|
+
/**
|
|
68
|
+
* Creates a new UptoEvmScheme instance.
|
|
69
|
+
*
|
|
70
|
+
* @param signer - The EVM signer for client operations
|
|
71
|
+
*/
|
|
72
|
+
constructor(signer) {
|
|
73
|
+
this.signer = signer;
|
|
74
|
+
__publicField(this, "scheme", "upto");
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Creates a payment payload for the Up-To scheme.
|
|
78
|
+
*
|
|
79
|
+
* The payload contains an EIP-2612 permit signature authorizing
|
|
80
|
+
* the router contract (or facilitator) to transfer up to the
|
|
81
|
+
* specified maximum amount.
|
|
82
|
+
*
|
|
83
|
+
* @param t402Version - The t402 protocol version
|
|
84
|
+
* @param paymentRequirements - The payment requirements (must include maxAmount)
|
|
85
|
+
* @returns Promise resolving to a payment payload
|
|
86
|
+
*/
|
|
87
|
+
async createPaymentPayload(t402Version, paymentRequirements) {
|
|
88
|
+
if (paymentRequirements.scheme !== "upto") {
|
|
89
|
+
throw new Error(`Expected upto scheme, got ${paymentRequirements.scheme}`);
|
|
90
|
+
}
|
|
91
|
+
const extra = paymentRequirements.extra;
|
|
92
|
+
if (!extra?.name || !extra?.version) {
|
|
93
|
+
throw new Error("EIP-712 domain parameters (name, version) are required for upto scheme");
|
|
94
|
+
}
|
|
95
|
+
const maxAmount = paymentRequirements.maxAmount;
|
|
96
|
+
if (!maxAmount) {
|
|
97
|
+
throw new Error("maxAmount is required for upto scheme");
|
|
98
|
+
}
|
|
99
|
+
const spender = extra.routerAddress ? (0, import_viem2.getAddress)(extra.routerAddress) : (0, import_viem2.getAddress)(paymentRequirements.payTo);
|
|
100
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
101
|
+
const deadline = now + paymentRequirements.maxTimeoutSeconds;
|
|
102
|
+
const permitNonce = extra.permitNonce ?? 0;
|
|
103
|
+
const authorization = {
|
|
104
|
+
owner: this.signer.address,
|
|
105
|
+
spender,
|
|
106
|
+
value: maxAmount,
|
|
107
|
+
deadline: deadline.toString(),
|
|
108
|
+
nonce: permitNonce
|
|
109
|
+
};
|
|
110
|
+
const signature = await this.signPermit(authorization, paymentRequirements);
|
|
111
|
+
const paymentNonce = createNonce();
|
|
112
|
+
const payload = {
|
|
113
|
+
signature,
|
|
114
|
+
authorization,
|
|
115
|
+
paymentNonce
|
|
116
|
+
};
|
|
117
|
+
return {
|
|
118
|
+
t402Version,
|
|
119
|
+
payload
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Sign the EIP-2612 permit using EIP-712
|
|
124
|
+
*
|
|
125
|
+
* @param authorization - The permit authorization to sign
|
|
126
|
+
* @param requirements - The payment requirements
|
|
127
|
+
* @returns Promise resolving to the signature components
|
|
128
|
+
*/
|
|
129
|
+
async signPermit(authorization, requirements) {
|
|
130
|
+
const chainId = parseInt(requirements.network.split(":")[1]);
|
|
131
|
+
const extra = requirements.extra;
|
|
132
|
+
const domain = {
|
|
133
|
+
name: extra.name,
|
|
134
|
+
version: extra.version,
|
|
135
|
+
chainId,
|
|
136
|
+
verifyingContract: (0, import_viem2.getAddress)(requirements.asset)
|
|
137
|
+
};
|
|
138
|
+
const message = {
|
|
139
|
+
owner: (0, import_viem2.getAddress)(authorization.owner),
|
|
140
|
+
spender: (0, import_viem2.getAddress)(authorization.spender),
|
|
141
|
+
value: BigInt(authorization.value),
|
|
142
|
+
nonce: BigInt(authorization.nonce),
|
|
143
|
+
deadline: BigInt(authorization.deadline)
|
|
144
|
+
};
|
|
145
|
+
const signature = await this.signer.signTypedData({
|
|
146
|
+
domain,
|
|
147
|
+
types: permitTypes,
|
|
148
|
+
primaryType: "Permit",
|
|
149
|
+
message
|
|
150
|
+
});
|
|
151
|
+
const r = `0x${signature.slice(2, 66)}`;
|
|
152
|
+
const s = `0x${signature.slice(66, 130)}`;
|
|
153
|
+
const v = parseInt(signature.slice(130, 132), 16);
|
|
154
|
+
return { v, r, s };
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
function createUptoEvmScheme(signer) {
|
|
158
|
+
return new UptoEvmScheme(signer);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/upto/server/scheme.ts
|
|
162
|
+
var import_types2 = require("@t402/core/types");
|
|
163
|
+
|
|
164
|
+
// src/tokens.ts
|
|
165
|
+
var USDT0_ADDRESSES = {
|
|
166
|
+
// === Existing Networks ===
|
|
167
|
+
// Ethereum Mainnet - OFT Adapter (bridge endpoint)
|
|
168
|
+
"eip155:1": "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee",
|
|
169
|
+
// Arbitrum One - Native USDT0
|
|
170
|
+
"eip155:42161": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
|
|
171
|
+
// Ink Mainnet
|
|
172
|
+
"eip155:57073": "0x0200C29006150606B650577BBE7B6248F58470c1",
|
|
173
|
+
// Berachain Mainnet
|
|
174
|
+
"eip155:80094": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
|
|
175
|
+
// Unichain Mainnet (updated address)
|
|
176
|
+
"eip155:130": "0x9151434b16b9763660705744891fA906F660EcC5",
|
|
177
|
+
// === Phase 1: High Priority Networks ===
|
|
178
|
+
// Polygon PoS
|
|
179
|
+
"eip155:137": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
|
|
180
|
+
// Mantle
|
|
181
|
+
"eip155:5000": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
|
|
182
|
+
// Optimism
|
|
183
|
+
"eip155:10": "0x01bFF41798a0BcF287b996046Ca68b395DbC1071",
|
|
184
|
+
// Plasma
|
|
185
|
+
"eip155:9745": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
|
|
186
|
+
// Sei
|
|
187
|
+
"eip155:1329": "0x9151434b16b9763660705744891fA906F660EcC5",
|
|
188
|
+
// Conflux eSpace
|
|
189
|
+
"eip155:1030": "0xaf37E8B6C9ED7f6318979f56Fc287d76c30847ff",
|
|
190
|
+
// Monad
|
|
191
|
+
"eip155:143": "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
|
|
192
|
+
// === Phase 2: Medium Priority Networks ===
|
|
193
|
+
// Rootstock (Bitcoin sidechain)
|
|
194
|
+
"eip155:30": "0x779dED0C9e1022225F8e0630b35A9B54Be713736",
|
|
195
|
+
// XLayer (OKX L2)
|
|
196
|
+
"eip155:196": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
|
|
197
|
+
// Flare
|
|
198
|
+
"eip155:14": "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
|
|
199
|
+
// Corn
|
|
200
|
+
"eip155:21000000": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
|
|
201
|
+
// HyperEVM
|
|
202
|
+
"eip155:999": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
|
|
203
|
+
// MegaETH
|
|
204
|
+
"eip155:4326": "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb",
|
|
205
|
+
// Stable
|
|
206
|
+
"eip155:988": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736"
|
|
207
|
+
};
|
|
208
|
+
var USDC_ADDRESSES = {
|
|
209
|
+
// Ethereum Mainnet
|
|
210
|
+
"eip155:1": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
211
|
+
// Base Mainnet
|
|
212
|
+
"eip155:8453": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
213
|
+
// Base Sepolia (testnet)
|
|
214
|
+
"eip155:84532": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
215
|
+
// Sepolia (testnet)
|
|
216
|
+
"eip155:11155111": "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
217
|
+
// Arbitrum One
|
|
218
|
+
"eip155:42161": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
219
|
+
// Polygon Mainnet
|
|
220
|
+
"eip155:137": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"
|
|
221
|
+
};
|
|
222
|
+
var USDT_LEGACY_ADDRESSES = {
|
|
223
|
+
// Ethereum Mainnet
|
|
224
|
+
"eip155:1": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
|
225
|
+
// Polygon Mainnet (native USDT, not USDT0)
|
|
226
|
+
"eip155:137": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
|
|
227
|
+
// BNB Chain (BSC) - BEP-20 USDT
|
|
228
|
+
"eip155:56": "0x55d398326f99059fF775485246999027B3197955",
|
|
229
|
+
// Avalanche C-Chain
|
|
230
|
+
"eip155:43114": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
|
|
231
|
+
// Fantom
|
|
232
|
+
"eip155:250": "0x049d68029688eabf473097a2fc38ef61633a3c7a",
|
|
233
|
+
// Celo
|
|
234
|
+
"eip155:42220": "0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e",
|
|
235
|
+
// Kaia (formerly Klaytn)
|
|
236
|
+
"eip155:8217": "0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167"
|
|
237
|
+
};
|
|
238
|
+
var TOKEN_REGISTRY = {
|
|
239
|
+
// Ethereum Mainnet
|
|
240
|
+
"eip155:1": {
|
|
241
|
+
USDT0: {
|
|
242
|
+
address: USDT0_ADDRESSES["eip155:1"],
|
|
243
|
+
symbol: "USDT0",
|
|
244
|
+
name: "TetherToken",
|
|
245
|
+
version: "1",
|
|
246
|
+
decimals: 6,
|
|
247
|
+
tokenType: "eip3009",
|
|
248
|
+
priority: 1
|
|
249
|
+
},
|
|
250
|
+
USDC: {
|
|
251
|
+
address: USDC_ADDRESSES["eip155:1"],
|
|
252
|
+
symbol: "USDC",
|
|
253
|
+
name: "USD Coin",
|
|
254
|
+
version: "2",
|
|
255
|
+
decimals: 6,
|
|
256
|
+
tokenType: "eip3009",
|
|
257
|
+
priority: 2
|
|
258
|
+
},
|
|
259
|
+
USDT: {
|
|
260
|
+
address: USDT_LEGACY_ADDRESSES["eip155:1"],
|
|
261
|
+
symbol: "USDT",
|
|
262
|
+
name: "TetherUSD",
|
|
263
|
+
version: "1",
|
|
264
|
+
decimals: 6,
|
|
265
|
+
tokenType: "legacy",
|
|
266
|
+
priority: 10
|
|
267
|
+
// Lower priority due to legacy flow
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
// Arbitrum One
|
|
271
|
+
"eip155:42161": {
|
|
272
|
+
USDT0: {
|
|
273
|
+
address: USDT0_ADDRESSES["eip155:42161"],
|
|
274
|
+
symbol: "USDT0",
|
|
275
|
+
name: "TetherToken",
|
|
276
|
+
version: "1",
|
|
277
|
+
decimals: 6,
|
|
278
|
+
tokenType: "eip3009",
|
|
279
|
+
priority: 1
|
|
280
|
+
},
|
|
281
|
+
USDC: {
|
|
282
|
+
address: USDC_ADDRESSES["eip155:42161"],
|
|
283
|
+
symbol: "USDC",
|
|
284
|
+
name: "USD Coin",
|
|
285
|
+
version: "2",
|
|
286
|
+
decimals: 6,
|
|
287
|
+
tokenType: "eip3009",
|
|
288
|
+
priority: 2
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
// Ink Mainnet
|
|
292
|
+
"eip155:57073": {
|
|
293
|
+
USDT0: {
|
|
294
|
+
address: USDT0_ADDRESSES["eip155:57073"],
|
|
295
|
+
symbol: "USDT0",
|
|
296
|
+
name: "TetherToken",
|
|
297
|
+
version: "1",
|
|
298
|
+
decimals: 6,
|
|
299
|
+
tokenType: "eip3009",
|
|
300
|
+
priority: 1
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
// Berachain Mainnet
|
|
304
|
+
"eip155:80094": {
|
|
305
|
+
USDT0: {
|
|
306
|
+
address: USDT0_ADDRESSES["eip155:80094"],
|
|
307
|
+
symbol: "USDT0",
|
|
308
|
+
name: "TetherToken",
|
|
309
|
+
version: "1",
|
|
310
|
+
decimals: 6,
|
|
311
|
+
tokenType: "eip3009",
|
|
312
|
+
priority: 1
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
// Unichain Mainnet
|
|
316
|
+
"eip155:130": {
|
|
317
|
+
USDT0: {
|
|
318
|
+
address: USDT0_ADDRESSES["eip155:130"],
|
|
319
|
+
symbol: "USDT0",
|
|
320
|
+
name: "TetherToken",
|
|
321
|
+
version: "1",
|
|
322
|
+
decimals: 6,
|
|
323
|
+
tokenType: "eip3009",
|
|
324
|
+
priority: 1
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
// Base Mainnet
|
|
328
|
+
"eip155:8453": {
|
|
329
|
+
USDC: {
|
|
330
|
+
address: USDC_ADDRESSES["eip155:8453"],
|
|
331
|
+
symbol: "USDC",
|
|
332
|
+
name: "USD Coin",
|
|
333
|
+
version: "2",
|
|
334
|
+
decimals: 6,
|
|
335
|
+
tokenType: "eip3009",
|
|
336
|
+
priority: 2
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
// Base Sepolia (testnet)
|
|
340
|
+
"eip155:84532": {
|
|
341
|
+
USDC: {
|
|
342
|
+
address: USDC_ADDRESSES["eip155:84532"],
|
|
343
|
+
symbol: "USDC",
|
|
344
|
+
name: "USDC",
|
|
345
|
+
version: "2",
|
|
346
|
+
decimals: 6,
|
|
347
|
+
tokenType: "eip3009",
|
|
348
|
+
priority: 2
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
// Sepolia (testnet)
|
|
352
|
+
"eip155:11155111": {
|
|
353
|
+
USDC: {
|
|
354
|
+
address: USDC_ADDRESSES["eip155:11155111"],
|
|
355
|
+
symbol: "USDC",
|
|
356
|
+
name: "USDC",
|
|
357
|
+
version: "2",
|
|
358
|
+
decimals: 6,
|
|
359
|
+
tokenType: "eip3009",
|
|
360
|
+
priority: 2
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
// Polygon Mainnet
|
|
364
|
+
"eip155:137": {
|
|
365
|
+
USDT0: {
|
|
366
|
+
address: USDT0_ADDRESSES["eip155:137"],
|
|
367
|
+
symbol: "USDT0",
|
|
368
|
+
name: "TetherToken",
|
|
369
|
+
version: "1",
|
|
370
|
+
decimals: 6,
|
|
371
|
+
tokenType: "eip3009",
|
|
372
|
+
priority: 1
|
|
373
|
+
},
|
|
374
|
+
USDC: {
|
|
375
|
+
address: USDC_ADDRESSES["eip155:137"],
|
|
376
|
+
symbol: "USDC",
|
|
377
|
+
name: "USD Coin",
|
|
378
|
+
version: "2",
|
|
379
|
+
decimals: 6,
|
|
380
|
+
tokenType: "eip3009",
|
|
381
|
+
priority: 2
|
|
382
|
+
},
|
|
383
|
+
USDT: {
|
|
384
|
+
address: USDT_LEGACY_ADDRESSES["eip155:137"],
|
|
385
|
+
symbol: "USDT",
|
|
386
|
+
name: "TetherUSD",
|
|
387
|
+
version: "1",
|
|
388
|
+
decimals: 6,
|
|
389
|
+
tokenType: "legacy",
|
|
390
|
+
priority: 10
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
// === Phase 1: High Priority USDT0 Networks ===
|
|
394
|
+
// Optimism Mainnet
|
|
395
|
+
"eip155:10": {
|
|
396
|
+
USDT0: {
|
|
397
|
+
address: USDT0_ADDRESSES["eip155:10"],
|
|
398
|
+
symbol: "USDT0",
|
|
399
|
+
name: "TetherToken",
|
|
400
|
+
version: "1",
|
|
401
|
+
decimals: 6,
|
|
402
|
+
tokenType: "eip3009",
|
|
403
|
+
priority: 1
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
// Mantle Mainnet
|
|
407
|
+
"eip155:5000": {
|
|
408
|
+
USDT0: {
|
|
409
|
+
address: USDT0_ADDRESSES["eip155:5000"],
|
|
410
|
+
symbol: "USDT0",
|
|
411
|
+
name: "TetherToken",
|
|
412
|
+
version: "1",
|
|
413
|
+
decimals: 6,
|
|
414
|
+
tokenType: "eip3009",
|
|
415
|
+
priority: 1
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
// Plasma Mainnet
|
|
419
|
+
"eip155:9745": {
|
|
420
|
+
USDT0: {
|
|
421
|
+
address: USDT0_ADDRESSES["eip155:9745"],
|
|
422
|
+
symbol: "USDT0",
|
|
423
|
+
name: "TetherToken",
|
|
424
|
+
version: "1",
|
|
425
|
+
decimals: 6,
|
|
426
|
+
tokenType: "eip3009",
|
|
427
|
+
priority: 1
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
// Sei Mainnet
|
|
431
|
+
"eip155:1329": {
|
|
432
|
+
USDT0: {
|
|
433
|
+
address: USDT0_ADDRESSES["eip155:1329"],
|
|
434
|
+
symbol: "USDT0",
|
|
435
|
+
name: "TetherToken",
|
|
436
|
+
version: "1",
|
|
437
|
+
decimals: 6,
|
|
438
|
+
tokenType: "eip3009",
|
|
439
|
+
priority: 1
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
// Conflux eSpace Mainnet
|
|
443
|
+
"eip155:1030": {
|
|
444
|
+
USDT0: {
|
|
445
|
+
address: USDT0_ADDRESSES["eip155:1030"],
|
|
446
|
+
symbol: "USDT0",
|
|
447
|
+
name: "TetherToken",
|
|
448
|
+
version: "1",
|
|
449
|
+
decimals: 6,
|
|
450
|
+
tokenType: "eip3009",
|
|
451
|
+
priority: 1
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
// Monad Mainnet
|
|
455
|
+
"eip155:143": {
|
|
456
|
+
USDT0: {
|
|
457
|
+
address: USDT0_ADDRESSES["eip155:143"],
|
|
458
|
+
symbol: "USDT0",
|
|
459
|
+
name: "TetherToken",
|
|
460
|
+
version: "1",
|
|
461
|
+
decimals: 6,
|
|
462
|
+
tokenType: "eip3009",
|
|
463
|
+
priority: 1
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
// === Phase 2: Medium Priority USDT0 Networks ===
|
|
467
|
+
// Flare Mainnet
|
|
468
|
+
"eip155:14": {
|
|
469
|
+
USDT0: {
|
|
470
|
+
address: USDT0_ADDRESSES["eip155:14"],
|
|
471
|
+
symbol: "USDT0",
|
|
472
|
+
name: "TetherToken",
|
|
473
|
+
version: "1",
|
|
474
|
+
decimals: 6,
|
|
475
|
+
tokenType: "eip3009",
|
|
476
|
+
priority: 1
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
// Rootstock Mainnet (Bitcoin sidechain)
|
|
480
|
+
"eip155:30": {
|
|
481
|
+
USDT0: {
|
|
482
|
+
address: USDT0_ADDRESSES["eip155:30"],
|
|
483
|
+
symbol: "USDT0",
|
|
484
|
+
name: "TetherToken",
|
|
485
|
+
version: "1",
|
|
486
|
+
decimals: 6,
|
|
487
|
+
tokenType: "eip3009",
|
|
488
|
+
priority: 1
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
// XLayer Mainnet (OKX L2)
|
|
492
|
+
"eip155:196": {
|
|
493
|
+
USDT0: {
|
|
494
|
+
address: USDT0_ADDRESSES["eip155:196"],
|
|
495
|
+
symbol: "USDT0",
|
|
496
|
+
name: "TetherToken",
|
|
497
|
+
version: "1",
|
|
498
|
+
decimals: 6,
|
|
499
|
+
tokenType: "eip3009",
|
|
500
|
+
priority: 1
|
|
501
|
+
}
|
|
502
|
+
},
|
|
503
|
+
// Stable Mainnet
|
|
504
|
+
"eip155:988": {
|
|
505
|
+
USDT0: {
|
|
506
|
+
address: USDT0_ADDRESSES["eip155:988"],
|
|
507
|
+
symbol: "USDT0",
|
|
508
|
+
name: "TetherToken",
|
|
509
|
+
version: "1",
|
|
510
|
+
decimals: 6,
|
|
511
|
+
tokenType: "eip3009",
|
|
512
|
+
priority: 1
|
|
513
|
+
}
|
|
514
|
+
},
|
|
515
|
+
// HyperEVM Mainnet
|
|
516
|
+
"eip155:999": {
|
|
517
|
+
USDT0: {
|
|
518
|
+
address: USDT0_ADDRESSES["eip155:999"],
|
|
519
|
+
symbol: "USDT0",
|
|
520
|
+
name: "TetherToken",
|
|
521
|
+
version: "1",
|
|
522
|
+
decimals: 6,
|
|
523
|
+
tokenType: "eip3009",
|
|
524
|
+
priority: 1
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
// MegaETH Mainnet
|
|
528
|
+
"eip155:4326": {
|
|
529
|
+
USDT0: {
|
|
530
|
+
address: USDT0_ADDRESSES["eip155:4326"],
|
|
531
|
+
symbol: "USDT0",
|
|
532
|
+
name: "TetherToken",
|
|
533
|
+
version: "1",
|
|
534
|
+
decimals: 6,
|
|
535
|
+
tokenType: "eip3009",
|
|
536
|
+
priority: 1
|
|
537
|
+
}
|
|
538
|
+
},
|
|
539
|
+
// Corn Mainnet
|
|
540
|
+
"eip155:21000000": {
|
|
541
|
+
USDT0: {
|
|
542
|
+
address: USDT0_ADDRESSES["eip155:21000000"],
|
|
543
|
+
symbol: "USDT0",
|
|
544
|
+
name: "TetherToken",
|
|
545
|
+
version: "1",
|
|
546
|
+
decimals: 6,
|
|
547
|
+
tokenType: "eip3009",
|
|
548
|
+
priority: 1
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
// === Legacy USDT Networks (no EIP-3009 support) ===
|
|
552
|
+
// BNB Chain (BSC) - BEP-20 USDT
|
|
553
|
+
"eip155:56": {
|
|
554
|
+
USDT: {
|
|
555
|
+
address: USDT_LEGACY_ADDRESSES["eip155:56"],
|
|
556
|
+
symbol: "USDT",
|
|
557
|
+
name: "Tether USD",
|
|
558
|
+
version: "1",
|
|
559
|
+
decimals: 18,
|
|
560
|
+
// BSC USDT uses 18 decimals
|
|
561
|
+
tokenType: "legacy",
|
|
562
|
+
priority: 10
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
// Avalanche C-Chain
|
|
566
|
+
"eip155:43114": {
|
|
567
|
+
USDT: {
|
|
568
|
+
address: USDT_LEGACY_ADDRESSES["eip155:43114"],
|
|
569
|
+
symbol: "USDT",
|
|
570
|
+
name: "TetherToken",
|
|
571
|
+
version: "1",
|
|
572
|
+
decimals: 6,
|
|
573
|
+
tokenType: "legacy",
|
|
574
|
+
priority: 10
|
|
575
|
+
}
|
|
576
|
+
},
|
|
577
|
+
// Fantom
|
|
578
|
+
"eip155:250": {
|
|
579
|
+
USDT: {
|
|
580
|
+
address: USDT_LEGACY_ADDRESSES["eip155:250"],
|
|
581
|
+
symbol: "USDT",
|
|
582
|
+
name: "Frapped USDT",
|
|
583
|
+
version: "1",
|
|
584
|
+
decimals: 6,
|
|
585
|
+
tokenType: "legacy",
|
|
586
|
+
priority: 10
|
|
587
|
+
}
|
|
588
|
+
},
|
|
589
|
+
// Celo
|
|
590
|
+
"eip155:42220": {
|
|
591
|
+
USDT: {
|
|
592
|
+
address: USDT_LEGACY_ADDRESSES["eip155:42220"],
|
|
593
|
+
symbol: "USDT",
|
|
594
|
+
name: "Tether USD",
|
|
595
|
+
version: "1",
|
|
596
|
+
decimals: 18,
|
|
597
|
+
tokenType: "legacy",
|
|
598
|
+
priority: 10
|
|
599
|
+
}
|
|
600
|
+
},
|
|
601
|
+
// Kaia (formerly Klaytn)
|
|
602
|
+
"eip155:8217": {
|
|
603
|
+
USDT: {
|
|
604
|
+
address: USDT_LEGACY_ADDRESSES["eip155:8217"],
|
|
605
|
+
symbol: "USDT",
|
|
606
|
+
name: "Tether USD",
|
|
607
|
+
version: "1",
|
|
608
|
+
decimals: 6,
|
|
609
|
+
tokenType: "legacy",
|
|
610
|
+
priority: 10
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
function getTokenConfig(network, symbol) {
|
|
615
|
+
return TOKEN_REGISTRY[network]?.[symbol.toUpperCase()];
|
|
616
|
+
}
|
|
617
|
+
function getNetworkTokens(network) {
|
|
618
|
+
const tokens = TOKEN_REGISTRY[network];
|
|
619
|
+
if (!tokens) return [];
|
|
620
|
+
return Object.values(tokens).sort((a, b) => a.priority - b.priority);
|
|
621
|
+
}
|
|
622
|
+
function getDefaultToken(network) {
|
|
623
|
+
const tokens = getNetworkTokens(network);
|
|
624
|
+
return tokens[0];
|
|
625
|
+
}
|
|
626
|
+
function getTokenByAddress(network, address) {
|
|
627
|
+
const tokens = TOKEN_REGISTRY[network];
|
|
628
|
+
if (!tokens) return void 0;
|
|
629
|
+
const lowerAddress = address.toLowerCase();
|
|
630
|
+
return Object.values(tokens).find((t) => t.address.toLowerCase() === lowerAddress);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// src/upto/server/scheme.ts
|
|
634
|
+
var UptoEvmServerScheme = class {
|
|
635
|
+
/**
|
|
636
|
+
* Creates a new UptoEvmServerScheme instance.
|
|
637
|
+
*
|
|
638
|
+
* @param config - Optional configuration options for the scheme
|
|
639
|
+
*/
|
|
640
|
+
constructor(config = {}) {
|
|
641
|
+
__publicField(this, "scheme", "upto");
|
|
642
|
+
__publicField(this, "moneyParsers", []);
|
|
643
|
+
__publicField(this, "config");
|
|
644
|
+
this.config = config;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Get all supported networks
|
|
648
|
+
*
|
|
649
|
+
* @returns Array of network identifiers in CAIP-2 format
|
|
650
|
+
*/
|
|
651
|
+
static getSupportedNetworks() {
|
|
652
|
+
return Object.keys(TOKEN_REGISTRY);
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Check if a network is supported
|
|
656
|
+
*
|
|
657
|
+
* @param network - The network identifier to check
|
|
658
|
+
* @returns True if the network is supported
|
|
659
|
+
*/
|
|
660
|
+
static isNetworkSupported(network) {
|
|
661
|
+
return network in TOKEN_REGISTRY;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Register a custom money parser in the parser chain.
|
|
665
|
+
*
|
|
666
|
+
* @param parser - Custom function to convert amount to AssetAmount
|
|
667
|
+
* @returns The server instance for chaining
|
|
668
|
+
*/
|
|
669
|
+
registerMoneyParser(parser) {
|
|
670
|
+
this.moneyParsers.push(parser);
|
|
671
|
+
return this;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Parses a price into an asset amount for maxAmount.
|
|
675
|
+
*
|
|
676
|
+
* @param price - The price to parse (represents maxAmount)
|
|
677
|
+
* @param network - The network to use
|
|
678
|
+
* @returns Promise resolving to the parsed asset amount
|
|
679
|
+
*/
|
|
680
|
+
async parsePrice(price, network) {
|
|
681
|
+
if (typeof price === "object" && price !== null && "amount" in price) {
|
|
682
|
+
if (!price.asset) {
|
|
683
|
+
const token2 = this.getPreferredToken(network);
|
|
684
|
+
return { amount: price.amount, asset: token2.address };
|
|
685
|
+
}
|
|
686
|
+
return price;
|
|
687
|
+
}
|
|
688
|
+
const decimalAmount = this.parseToDecimal(price);
|
|
689
|
+
for (const parser of this.moneyParsers) {
|
|
690
|
+
const result = await parser(decimalAmount, network);
|
|
691
|
+
if (result !== null) {
|
|
692
|
+
return result;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
const token = this.getPreferredToken(network);
|
|
696
|
+
const amount = Math.floor(decimalAmount * 10 ** token.decimals).toString();
|
|
697
|
+
return {
|
|
698
|
+
amount,
|
|
699
|
+
asset: token.address
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Enhance payment requirements for the upto scheme.
|
|
704
|
+
*
|
|
705
|
+
* @param paymentRequirements - Base payment requirements
|
|
706
|
+
* @param supportedKind - The supported kind from facilitator
|
|
707
|
+
* @param supportedKind.t402Version - T402 protocol version
|
|
708
|
+
* @param supportedKind.scheme - Payment scheme
|
|
709
|
+
* @param supportedKind.network - Network identifier
|
|
710
|
+
* @param supportedKind.extra - Extra configuration
|
|
711
|
+
* @param facilitatorExtensions - Extensions supported by the facilitator
|
|
712
|
+
* @returns Enhanced payment requirements for upto scheme
|
|
713
|
+
*/
|
|
714
|
+
async enhancePaymentRequirements(paymentRequirements, supportedKind, facilitatorExtensions) {
|
|
715
|
+
void facilitatorExtensions;
|
|
716
|
+
const network = supportedKind.network;
|
|
717
|
+
const token = getTokenByAddress(network, paymentRequirements.asset);
|
|
718
|
+
if (!token) {
|
|
719
|
+
throw new Error(`Unknown token ${paymentRequirements.asset} on ${network}`);
|
|
720
|
+
}
|
|
721
|
+
const extra = {
|
|
722
|
+
// EIP-712 domain (required for permit signing)
|
|
723
|
+
name: token.name,
|
|
724
|
+
version: token.version,
|
|
725
|
+
// Router address (optional - if set, permits go to router)
|
|
726
|
+
...this.config.routerAddress && { routerAddress: this.config.routerAddress },
|
|
727
|
+
// Billing unit info (optional)
|
|
728
|
+
...this.config.defaultUnit && { unit: this.config.defaultUnit },
|
|
729
|
+
...this.config.defaultUnitPrice && { unitPrice: this.config.defaultUnitPrice },
|
|
730
|
+
// Upto-specific fields
|
|
731
|
+
maxAmount: paymentRequirements.amount,
|
|
732
|
+
minAmount: import_types2.UPTO_DEFAULTS.MIN_AMOUNT,
|
|
733
|
+
// Merge any facilitator extra
|
|
734
|
+
...supportedKind.extra
|
|
735
|
+
};
|
|
736
|
+
return {
|
|
737
|
+
...paymentRequirements,
|
|
738
|
+
scheme: "upto",
|
|
739
|
+
extra
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Get the preferred token for a network.
|
|
744
|
+
*
|
|
745
|
+
* @param network - The network identifier
|
|
746
|
+
* @returns Token configuration
|
|
747
|
+
* @throws Error if no token is found for the network
|
|
748
|
+
*/
|
|
749
|
+
getPreferredToken(network) {
|
|
750
|
+
if (this.config.preferredToken) {
|
|
751
|
+
const token = getTokenConfig(network, this.config.preferredToken);
|
|
752
|
+
if (token) return token;
|
|
753
|
+
}
|
|
754
|
+
const defaultToken = getDefaultToken(network);
|
|
755
|
+
if (!defaultToken) {
|
|
756
|
+
throw new Error(`No token configured for network ${network}`);
|
|
757
|
+
}
|
|
758
|
+
return defaultToken;
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Parse price to decimal value.
|
|
762
|
+
*
|
|
763
|
+
* @param price - Price string or number
|
|
764
|
+
* @returns Decimal amount
|
|
765
|
+
*/
|
|
766
|
+
parseToDecimal(price) {
|
|
767
|
+
if (typeof price === "number") {
|
|
768
|
+
return price;
|
|
769
|
+
}
|
|
770
|
+
const cleaned = price.replace(/[$,]/g, "").trim();
|
|
771
|
+
const parsed = parseFloat(cleaned);
|
|
772
|
+
if (isNaN(parsed)) {
|
|
773
|
+
throw new Error(`Invalid price format: ${price}`);
|
|
774
|
+
}
|
|
775
|
+
return parsed;
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
function createUptoEvmServerScheme(config) {
|
|
779
|
+
return new UptoEvmServerScheme(config);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// src/upto/facilitator/scheme.ts
|
|
783
|
+
var import_viem3 = require("viem");
|
|
784
|
+
var T402_UPTO_ROUTER_ABI = (0, import_viem3.parseAbi)([
|
|
785
|
+
"function executeUptoTransfer(address token, address from, address to, uint256 maxAmount, uint256 settleAmount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external",
|
|
786
|
+
"function isFacilitator(address facilitator) external view returns (bool)",
|
|
787
|
+
"function checkPermitValidity(address token, address from, uint256 maxAmount) external view returns (bool valid, uint256 balance)"
|
|
788
|
+
]);
|
|
789
|
+
var UptoEvmFacilitatorScheme = class {
|
|
790
|
+
/**
|
|
791
|
+
* Creates a new UptoEvmFacilitatorScheme instance.
|
|
792
|
+
*
|
|
793
|
+
* @param signer - The EVM signer for facilitator operations
|
|
794
|
+
* @param config - Optional configuration
|
|
795
|
+
*/
|
|
796
|
+
constructor(signer, config) {
|
|
797
|
+
this.signer = signer;
|
|
798
|
+
__publicField(this, "scheme", "upto");
|
|
799
|
+
__publicField(this, "caipFamily", "eip155:*");
|
|
800
|
+
__publicField(this, "config");
|
|
801
|
+
this.config = config ?? {};
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Get mechanism-specific extra data for the supported kinds endpoint.
|
|
805
|
+
*
|
|
806
|
+
* @param network - The network identifier
|
|
807
|
+
* @returns Extra data including router address if configured
|
|
808
|
+
*/
|
|
809
|
+
getExtra(network) {
|
|
810
|
+
const routerAddress = this.config.routerAddresses?.[network];
|
|
811
|
+
if (routerAddress) {
|
|
812
|
+
return { routerAddress };
|
|
813
|
+
}
|
|
814
|
+
return void 0;
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Get signer addresses used by this facilitator.
|
|
818
|
+
*
|
|
819
|
+
* @param _ - The network identifier (unused for EVM)
|
|
820
|
+
* @returns Array of facilitator wallet addresses
|
|
821
|
+
*/
|
|
822
|
+
getSigners(_) {
|
|
823
|
+
return [...this.signer.getAddresses()];
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Verifies an upto payment payload.
|
|
827
|
+
*
|
|
828
|
+
* @param payload - The payment payload to verify
|
|
829
|
+
* @param requirements - The payment requirements
|
|
830
|
+
* @returns Promise resolving to verification response
|
|
831
|
+
*/
|
|
832
|
+
async verify(payload, requirements) {
|
|
833
|
+
const uptoPayload = payload.payload;
|
|
834
|
+
if (!uptoPayload || !isUptoEIP2612Payload(uptoPayload)) {
|
|
835
|
+
return {
|
|
836
|
+
isValid: false,
|
|
837
|
+
invalidReason: "invalid_payload_structure",
|
|
838
|
+
payer: void 0
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
if (payload.accepted.scheme !== "upto" || requirements.scheme !== "upto") {
|
|
842
|
+
return {
|
|
843
|
+
isValid: false,
|
|
844
|
+
invalidReason: "unsupported_scheme",
|
|
845
|
+
payer: uptoPayload.authorization.owner
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
if (!requirements.extra?.name || !requirements.extra?.version) {
|
|
849
|
+
return {
|
|
850
|
+
isValid: false,
|
|
851
|
+
invalidReason: "missing_eip712_domain",
|
|
852
|
+
payer: uptoPayload.authorization.owner
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
const maxAmount = requirements.extra?.maxAmount;
|
|
856
|
+
if (!maxAmount) {
|
|
857
|
+
return {
|
|
858
|
+
isValid: false,
|
|
859
|
+
invalidReason: "missing_maxAmount",
|
|
860
|
+
payer: uptoPayload.authorization.owner
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
if (payload.accepted.network !== requirements.network) {
|
|
864
|
+
return {
|
|
865
|
+
isValid: false,
|
|
866
|
+
invalidReason: "network_mismatch",
|
|
867
|
+
payer: uptoPayload.authorization.owner
|
|
868
|
+
};
|
|
869
|
+
}
|
|
870
|
+
const deadline = parseInt(uptoPayload.authorization.deadline);
|
|
871
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
872
|
+
if (deadline <= now) {
|
|
873
|
+
return {
|
|
874
|
+
isValid: false,
|
|
875
|
+
invalidReason: "permit_expired",
|
|
876
|
+
payer: uptoPayload.authorization.owner
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
if (uptoPayload.authorization.value !== maxAmount) {
|
|
880
|
+
return {
|
|
881
|
+
isValid: false,
|
|
882
|
+
invalidReason: "amount_mismatch",
|
|
883
|
+
payer: uptoPayload.authorization.owner
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
const chainId = parseInt(requirements.network.split(":")[1]);
|
|
887
|
+
const permitTypedData = {
|
|
888
|
+
types: permitTypes,
|
|
889
|
+
primaryType: "Permit",
|
|
890
|
+
domain: {
|
|
891
|
+
name: requirements.extra.name,
|
|
892
|
+
version: requirements.extra.version,
|
|
893
|
+
chainId,
|
|
894
|
+
verifyingContract: (0, import_viem3.getAddress)(requirements.asset)
|
|
895
|
+
},
|
|
896
|
+
message: {
|
|
897
|
+
owner: (0, import_viem3.getAddress)(uptoPayload.authorization.owner),
|
|
898
|
+
spender: (0, import_viem3.getAddress)(uptoPayload.authorization.spender),
|
|
899
|
+
value: BigInt(uptoPayload.authorization.value),
|
|
900
|
+
nonce: BigInt(uptoPayload.authorization.nonce),
|
|
901
|
+
deadline: BigInt(uptoPayload.authorization.deadline)
|
|
902
|
+
}
|
|
903
|
+
};
|
|
904
|
+
const signature = `0x${uptoPayload.signature.r.slice(2)}${uptoPayload.signature.s.slice(2)}${uptoPayload.signature.v.toString(16).padStart(2, "0")}`;
|
|
905
|
+
try {
|
|
906
|
+
const isValid = await this.signer.verifyTypedData({
|
|
907
|
+
address: uptoPayload.authorization.owner,
|
|
908
|
+
...permitTypedData,
|
|
909
|
+
signature
|
|
910
|
+
});
|
|
911
|
+
if (!isValid) {
|
|
912
|
+
return {
|
|
913
|
+
isValid: false,
|
|
914
|
+
invalidReason: "invalid_signature",
|
|
915
|
+
payer: uptoPayload.authorization.owner
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
} catch (error) {
|
|
919
|
+
return {
|
|
920
|
+
isValid: false,
|
|
921
|
+
invalidReason: `signature_verification_failed: ${error instanceof Error ? error.message : "unknown"}`,
|
|
922
|
+
payer: uptoPayload.authorization.owner
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
return {
|
|
926
|
+
isValid: true,
|
|
927
|
+
payer: uptoPayload.authorization.owner
|
|
928
|
+
};
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Settles an upto payment by calling the T402UptoRouter contract.
|
|
932
|
+
*
|
|
933
|
+
* @param payload - The verified payment payload
|
|
934
|
+
* @param requirements - The payment requirements
|
|
935
|
+
* @returns Promise resolving to settlement response
|
|
936
|
+
*/
|
|
937
|
+
async settle(payload, requirements) {
|
|
938
|
+
const uptoPayload = payload.payload;
|
|
939
|
+
const maxAmount = requirements.extra?.maxAmount;
|
|
940
|
+
const minAmount = requirements.extra?.minAmount;
|
|
941
|
+
const routerAddress = requirements.extra?.routerAddress;
|
|
942
|
+
if (!maxAmount) {
|
|
943
|
+
return {
|
|
944
|
+
success: false,
|
|
945
|
+
errorReason: "maxAmount not found in payment requirements",
|
|
946
|
+
transaction: "",
|
|
947
|
+
network: requirements.network,
|
|
948
|
+
payer: uptoPayload.authorization.owner
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
const settleAmount = maxAmount;
|
|
952
|
+
if (minAmount && BigInt(settleAmount) < BigInt(minAmount)) {
|
|
953
|
+
return {
|
|
954
|
+
success: false,
|
|
955
|
+
errorReason: `Settle amount ${settleAmount} below minimum ${minAmount}`,
|
|
956
|
+
transaction: "",
|
|
957
|
+
network: requirements.network,
|
|
958
|
+
payer: uptoPayload.authorization.owner
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
if (!routerAddress) {
|
|
962
|
+
return {
|
|
963
|
+
success: false,
|
|
964
|
+
errorReason: "Router address not configured",
|
|
965
|
+
transaction: "",
|
|
966
|
+
network: requirements.network,
|
|
967
|
+
payer: uptoPayload.authorization.owner
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
try {
|
|
971
|
+
const txHash = await this.signer.sendTransaction({
|
|
972
|
+
to: (0, import_viem3.getAddress)(routerAddress),
|
|
973
|
+
data: (0, import_viem3.encodeFunctionData)({
|
|
974
|
+
abi: T402_UPTO_ROUTER_ABI,
|
|
975
|
+
functionName: "executeUptoTransfer",
|
|
976
|
+
args: [
|
|
977
|
+
(0, import_viem3.getAddress)(requirements.asset),
|
|
978
|
+
(0, import_viem3.getAddress)(uptoPayload.authorization.owner),
|
|
979
|
+
(0, import_viem3.getAddress)(requirements.payTo),
|
|
980
|
+
BigInt(maxAmount),
|
|
981
|
+
BigInt(settleAmount),
|
|
982
|
+
BigInt(uptoPayload.authorization.deadline),
|
|
983
|
+
uptoPayload.signature.v,
|
|
984
|
+
uptoPayload.signature.r,
|
|
985
|
+
uptoPayload.signature.s
|
|
986
|
+
]
|
|
987
|
+
})
|
|
988
|
+
});
|
|
989
|
+
const receipt = await this.signer.waitForTransactionReceipt({ hash: txHash });
|
|
990
|
+
if (receipt.status !== "success") {
|
|
991
|
+
return {
|
|
992
|
+
success: false,
|
|
993
|
+
errorReason: "transaction_reverted",
|
|
994
|
+
transaction: txHash,
|
|
995
|
+
network: requirements.network,
|
|
996
|
+
payer: uptoPayload.authorization.owner
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
return {
|
|
1000
|
+
success: true,
|
|
1001
|
+
transaction: txHash,
|
|
1002
|
+
network: requirements.network,
|
|
1003
|
+
payer: uptoPayload.authorization.owner
|
|
1004
|
+
};
|
|
1005
|
+
} catch (error) {
|
|
1006
|
+
return {
|
|
1007
|
+
success: false,
|
|
1008
|
+
errorReason: `Settlement failed: ${error instanceof Error ? error.message : "unknown"}`,
|
|
1009
|
+
transaction: "",
|
|
1010
|
+
network: requirements.network,
|
|
1011
|
+
payer: uptoPayload.authorization.owner
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1016
|
+
function createUptoEvmFacilitatorScheme(signer, config) {
|
|
1017
|
+
return new UptoEvmFacilitatorScheme(signer, config);
|
|
1018
|
+
}
|
|
1019
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1020
|
+
0 && (module.exports = {
|
|
1021
|
+
UptoEvmFacilitatorScheme,
|
|
1022
|
+
UptoEvmScheme,
|
|
1023
|
+
UptoEvmServerScheme,
|
|
1024
|
+
createUptoEvmFacilitatorScheme,
|
|
1025
|
+
createUptoEvmScheme,
|
|
1026
|
+
createUptoEvmServerScheme,
|
|
1027
|
+
isUptoEIP2612Payload,
|
|
1028
|
+
permitTypes
|
|
1029
|
+
});
|
|
1030
|
+
//# sourceMappingURL=index.js.map
|