moltspay 0.5.3 → 0.7.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/cdp/index.d.mts +111 -0
- package/dist/cdp/index.d.ts +111 -0
- package/dist/cdp/index.js +30655 -0
- package/dist/cdp/index.js.map +1 -0
- package/dist/cdp/index.mjs +30631 -0
- package/dist/cdp/index.mjs.map +1 -0
- package/dist/chains/index.d.mts +1 -1
- package/dist/chains/index.d.ts +1 -1
- package/dist/cli/index.js +940 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/index.mjs +917 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/client/index.d.mts +134 -0
- package/dist/client/index.d.ts +134 -0
- package/dist/client/index.js +331 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/index.mjs +296 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/createWallet-D53qu7ie.d.mts +77 -0
- package/dist/createWallet-D53qu7ie.d.ts +77 -0
- package/dist/index-Dg8n6wdW.d.mts +32 -0
- package/dist/index-Dg8n6wdW.d.ts +32 -0
- package/dist/index.d.mts +6 -937
- package/dist/index.d.ts +6 -937
- package/dist/index.js +31023 -3250
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +30998 -3178
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +120 -0
- package/dist/server/index.d.ts +120 -0
- package/dist/server/index.js +418 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +393 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/wallet/index.d.mts +3 -451
- package/dist/wallet/index.d.ts +3 -451
- package/dist/wallet/index.js +5 -1021
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +16 -1015
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +19 -19
- package/dist/cli.js +0 -1984
- package/dist/cli.js.map +0 -1
- package/dist/cli.mjs +0 -1969
- package/dist/cli.mjs.map +0 -1
- package/dist/guide/index.d.mts +0 -39
- package/dist/guide/index.d.ts +0 -39
- package/dist/guide/index.js +0 -181
- package/dist/guide/index.js.map +0 -1
- package/dist/guide/index.mjs +0 -152
- package/dist/guide/index.mjs.map +0 -1
- package/dist/index-CyFg9s2m.d.mts +0 -161
- package/dist/index-CyFg9s2m.d.ts +0 -161
- package/dist/orders/index.d.mts +0 -97
- package/dist/orders/index.d.ts +0 -97
- package/dist/orders/index.js +0 -162
- package/dist/orders/index.js.map +0 -1
- package/dist/orders/index.mjs +0 -136
- package/dist/orders/index.mjs.map +0 -1
- package/dist/permit/index.d.mts +0 -49
- package/dist/permit/index.d.ts +0 -49
- package/dist/permit/index.js +0 -273
- package/dist/permit/index.js.map +0 -1
- package/dist/permit/index.mjs +0 -246
- package/dist/permit/index.mjs.map +0 -1
- /package/dist/{cli.d.mts → cli/index.d.mts} +0 -0
- /package/dist/{cli.d.ts → cli/index.d.ts} +0 -0
package/dist/permit/index.js
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
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 __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/permit/index.ts
|
|
21
|
-
var permit_exports = {};
|
|
22
|
-
__export(permit_exports, {
|
|
23
|
-
PermitPayment: () => PermitPayment
|
|
24
|
-
});
|
|
25
|
-
module.exports = __toCommonJS(permit_exports);
|
|
26
|
-
|
|
27
|
-
// src/permit/Permit.ts
|
|
28
|
-
var import_ethers = require("ethers");
|
|
29
|
-
|
|
30
|
-
// src/chains/index.ts
|
|
31
|
-
var CHAINS = {
|
|
32
|
-
// ============ Mainnet ============
|
|
33
|
-
base: {
|
|
34
|
-
name: "Base",
|
|
35
|
-
chainId: 8453,
|
|
36
|
-
rpc: "https://mainnet.base.org",
|
|
37
|
-
usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
38
|
-
explorer: "https://basescan.org/address/",
|
|
39
|
-
explorerTx: "https://basescan.org/tx/",
|
|
40
|
-
avgBlockTime: 2
|
|
41
|
-
},
|
|
42
|
-
polygon: {
|
|
43
|
-
name: "Polygon",
|
|
44
|
-
chainId: 137,
|
|
45
|
-
rpc: "https://polygon-rpc.com",
|
|
46
|
-
usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
47
|
-
explorer: "https://polygonscan.com/address/",
|
|
48
|
-
explorerTx: "https://polygonscan.com/tx/",
|
|
49
|
-
avgBlockTime: 2
|
|
50
|
-
},
|
|
51
|
-
ethereum: {
|
|
52
|
-
name: "Ethereum",
|
|
53
|
-
chainId: 1,
|
|
54
|
-
rpc: "https://eth.llamarpc.com",
|
|
55
|
-
usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
56
|
-
explorer: "https://etherscan.io/address/",
|
|
57
|
-
explorerTx: "https://etherscan.io/tx/",
|
|
58
|
-
avgBlockTime: 12
|
|
59
|
-
},
|
|
60
|
-
// ============ Testnet ============
|
|
61
|
-
base_sepolia: {
|
|
62
|
-
name: "Base Sepolia",
|
|
63
|
-
chainId: 84532,
|
|
64
|
-
rpc: "https://sepolia.base.org",
|
|
65
|
-
usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
66
|
-
explorer: "https://sepolia.basescan.org/address/",
|
|
67
|
-
explorerTx: "https://sepolia.basescan.org/tx/",
|
|
68
|
-
avgBlockTime: 2
|
|
69
|
-
},
|
|
70
|
-
sepolia: {
|
|
71
|
-
name: "Sepolia",
|
|
72
|
-
chainId: 11155111,
|
|
73
|
-
rpc: "https://rpc.sepolia.org",
|
|
74
|
-
usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
75
|
-
explorer: "https://sepolia.etherscan.io/address/",
|
|
76
|
-
explorerTx: "https://sepolia.etherscan.io/tx/",
|
|
77
|
-
avgBlockTime: 12
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
function getChain(name) {
|
|
81
|
-
const config = CHAINS[name];
|
|
82
|
-
if (!config) {
|
|
83
|
-
throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(", ")}`);
|
|
84
|
-
}
|
|
85
|
-
return config;
|
|
86
|
-
}
|
|
87
|
-
var ERC20_ABI = [
|
|
88
|
-
"function balanceOf(address owner) view returns (uint256)",
|
|
89
|
-
"function transfer(address to, uint256 amount) returns (bool)",
|
|
90
|
-
"function approve(address spender, uint256 amount) returns (bool)",
|
|
91
|
-
"function allowance(address owner, address spender) view returns (uint256)",
|
|
92
|
-
"function decimals() view returns (uint8)",
|
|
93
|
-
"function symbol() view returns (string)",
|
|
94
|
-
"function name() view returns (string)",
|
|
95
|
-
"function nonces(address owner) view returns (uint256)",
|
|
96
|
-
"function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)",
|
|
97
|
-
"event Transfer(address indexed from, address indexed to, uint256 value)",
|
|
98
|
-
"event Approval(address indexed owner, address indexed spender, uint256 value)"
|
|
99
|
-
];
|
|
100
|
-
|
|
101
|
-
// src/permit/Permit.ts
|
|
102
|
-
var PermitPayment = class {
|
|
103
|
-
chain;
|
|
104
|
-
chainConfig;
|
|
105
|
-
spenderAddress;
|
|
106
|
-
provider;
|
|
107
|
-
wallet;
|
|
108
|
-
usdcContract;
|
|
109
|
-
constructor(config = {}) {
|
|
110
|
-
this.chain = config.chain || "base_sepolia";
|
|
111
|
-
this.chainConfig = getChain(this.chain);
|
|
112
|
-
this.spenderAddress = config.spenderAddress || process.env.PAYMENT_AGENT_WALLET || "";
|
|
113
|
-
const rpcUrl = config.rpcUrl || this.chainConfig.rpc;
|
|
114
|
-
this.provider = new import_ethers.ethers.JsonRpcProvider(rpcUrl);
|
|
115
|
-
const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;
|
|
116
|
-
if (privateKey) {
|
|
117
|
-
this.wallet = new import_ethers.ethers.Wallet(privateKey, this.provider);
|
|
118
|
-
this.spenderAddress = this.wallet.address;
|
|
119
|
-
}
|
|
120
|
-
this.usdcContract = new import_ethers.ethers.Contract(
|
|
121
|
-
this.chainConfig.usdc,
|
|
122
|
-
ERC20_ABI,
|
|
123
|
-
this.wallet || this.provider
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Get user current nonce
|
|
128
|
-
*/
|
|
129
|
-
async getNonce(owner) {
|
|
130
|
-
return Number(await this.usdcContract.nonces(owner));
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Generate EIP-712 signing request (for frontend/user wallet)
|
|
134
|
-
*/
|
|
135
|
-
async createPermitRequest(owner, amount, orderId, deadlineMinutes = 30) {
|
|
136
|
-
const nonce = await this.getNonce(owner);
|
|
137
|
-
const deadline = Math.floor(Date.now() / 1e3) + deadlineMinutes * 60;
|
|
138
|
-
const value = BigInt(Math.floor(amount * 1e6)).toString();
|
|
139
|
-
const domain = {
|
|
140
|
-
name: "USD Coin",
|
|
141
|
-
version: "2",
|
|
142
|
-
chainId: this.chainConfig.chainId,
|
|
143
|
-
verifyingContract: this.chainConfig.usdc
|
|
144
|
-
};
|
|
145
|
-
const types = {
|
|
146
|
-
EIP712Domain: [
|
|
147
|
-
{ name: "name", type: "string" },
|
|
148
|
-
{ name: "version", type: "string" },
|
|
149
|
-
{ name: "chainId", type: "uint256" },
|
|
150
|
-
{ name: "verifyingContract", type: "address" }
|
|
151
|
-
],
|
|
152
|
-
Permit: [
|
|
153
|
-
{ name: "owner", type: "address" },
|
|
154
|
-
{ name: "spender", type: "address" },
|
|
155
|
-
{ name: "value", type: "uint256" },
|
|
156
|
-
{ name: "nonce", type: "uint256" },
|
|
157
|
-
{ name: "deadline", type: "uint256" }
|
|
158
|
-
]
|
|
159
|
-
};
|
|
160
|
-
const message = {
|
|
161
|
-
owner,
|
|
162
|
-
spender: this.spenderAddress,
|
|
163
|
-
value,
|
|
164
|
-
nonce,
|
|
165
|
-
deadline
|
|
166
|
-
};
|
|
167
|
-
const typedData = {
|
|
168
|
-
types,
|
|
169
|
-
primaryType: "Permit",
|
|
170
|
-
domain,
|
|
171
|
-
message
|
|
172
|
-
};
|
|
173
|
-
return {
|
|
174
|
-
type: "permit_request",
|
|
175
|
-
version: "1.0",
|
|
176
|
-
order_id: orderId,
|
|
177
|
-
typed_data: typedData
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Execute permit + transferFrom
|
|
182
|
-
*
|
|
183
|
-
* @param owner User address
|
|
184
|
-
* @param amount Amount
|
|
185
|
-
* @param signature User signature {v, r, s, deadline}
|
|
186
|
-
*/
|
|
187
|
-
async executePermitAndTransfer(owner, amount, signature) {
|
|
188
|
-
if (!this.wallet) {
|
|
189
|
-
return { success: false, error: "Wallet not configured. Private key required." };
|
|
190
|
-
}
|
|
191
|
-
try {
|
|
192
|
-
const value = BigInt(Math.floor(amount * 1e6));
|
|
193
|
-
const permitTx = await this.usdcContract.permit(
|
|
194
|
-
owner,
|
|
195
|
-
this.spenderAddress,
|
|
196
|
-
value,
|
|
197
|
-
signature.deadline,
|
|
198
|
-
signature.v,
|
|
199
|
-
signature.r,
|
|
200
|
-
signature.s
|
|
201
|
-
);
|
|
202
|
-
await permitTx.wait();
|
|
203
|
-
const transferTx = await this.usdcContract.transferFrom(owner, this.spenderAddress, value);
|
|
204
|
-
const receipt = await transferTx.wait();
|
|
205
|
-
return {
|
|
206
|
-
success: receipt.status === 1,
|
|
207
|
-
tx_hash: transferTx.hash
|
|
208
|
-
};
|
|
209
|
-
} catch (error) {
|
|
210
|
-
return {
|
|
211
|
-
success: false,
|
|
212
|
-
error: error.message
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Execute permit only (no transfer)
|
|
218
|
-
*/
|
|
219
|
-
async executePermit(owner, amount, signature) {
|
|
220
|
-
if (!this.wallet) {
|
|
221
|
-
return { success: false, error: "Wallet not configured. Private key required." };
|
|
222
|
-
}
|
|
223
|
-
try {
|
|
224
|
-
const value = BigInt(Math.floor(amount * 1e6));
|
|
225
|
-
const tx = await this.usdcContract.permit(
|
|
226
|
-
owner,
|
|
227
|
-
this.spenderAddress,
|
|
228
|
-
value,
|
|
229
|
-
signature.deadline,
|
|
230
|
-
signature.v,
|
|
231
|
-
signature.r,
|
|
232
|
-
signature.s
|
|
233
|
-
);
|
|
234
|
-
const receipt = await tx.wait();
|
|
235
|
-
return {
|
|
236
|
-
success: receipt.status === 1,
|
|
237
|
-
tx_hash: tx.hash
|
|
238
|
-
};
|
|
239
|
-
} catch (error) {
|
|
240
|
-
return {
|
|
241
|
-
success: false,
|
|
242
|
-
error: error.message
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* Format Permit request as user message
|
|
248
|
-
*/
|
|
249
|
-
formatPermitMessage(request) {
|
|
250
|
-
const { typed_data } = request;
|
|
251
|
-
const { message } = typed_data;
|
|
252
|
-
return `\u{1F510} **Signature Authorization Request**
|
|
253
|
-
|
|
254
|
-
Authorize \`${(Number(message.value) / 1e6).toFixed(2)} USDC\` to service provider
|
|
255
|
-
|
|
256
|
-
**Signature Details:**
|
|
257
|
-
- Owner: \`${message.owner}\`
|
|
258
|
-
- Spender: \`${message.spender}\`
|
|
259
|
-
- Amount: ${(Number(message.value) / 1e6).toFixed(2)} USDC
|
|
260
|
-
- Deadline: ${new Date(message.deadline * 1e3).toISOString()}
|
|
261
|
-
|
|
262
|
-
Please sign this request in your wallet (no gas required).
|
|
263
|
-
|
|
264
|
-
\`\`\`json
|
|
265
|
-
${JSON.stringify(typed_data, null, 2)}
|
|
266
|
-
\`\`\``;
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
270
|
-
0 && (module.exports = {
|
|
271
|
-
PermitPayment
|
|
272
|
-
});
|
|
273
|
-
//# sourceMappingURL=index.js.map
|
package/dist/permit/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/permit/index.ts","../../src/permit/Permit.ts","../../src/chains/index.ts"],"sourcesContent":["export { PermitPayment, type PermitConfig } from './Permit.js';\n","/**\n * PermitPayment - EIP-2612 Gasless Pre-authorization\n * \n * User signs authorization, service provider pays gas to execute transferFrom\n */\n\nimport { ethers } from 'ethers';\nimport { getChain, ERC20_ABI } from '../chains/index.js';\nimport type {\n ChainName,\n ChainConfig,\n PermitRequest,\n PermitSignature,\n PermitExecuteResult,\n EIP712TypedData,\n} from '../types/index.js';\n\nexport interface PermitConfig {\n chain?: ChainName;\n privateKey?: string;\n spenderAddress?: string;\n rpcUrl?: string;\n}\n\nexport class PermitPayment {\n readonly chain: ChainName;\n readonly chainConfig: ChainConfig;\n readonly spenderAddress: string;\n \n private provider: ethers.JsonRpcProvider;\n private wallet?: ethers.Wallet;\n private usdcContract: ethers.Contract;\n\n constructor(config: PermitConfig = {}) {\n this.chain = config.chain || 'base_sepolia';\n this.chainConfig = getChain(this.chain);\n this.spenderAddress = config.spenderAddress || process.env.PAYMENT_AGENT_WALLET || '';\n\n const rpcUrl = config.rpcUrl || this.chainConfig.rpc;\n this.provider = new ethers.JsonRpcProvider(rpcUrl);\n\n const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;\n if (privateKey) {\n this.wallet = new ethers.Wallet(privateKey, this.provider);\n this.spenderAddress = this.wallet.address;\n }\n\n this.usdcContract = new ethers.Contract(\n this.chainConfig.usdc,\n ERC20_ABI,\n this.wallet || this.provider\n );\n }\n\n /**\n * Get user current nonce\n */\n async getNonce(owner: string): Promise<number> {\n return Number(await this.usdcContract.nonces(owner));\n }\n\n /**\n * Generate EIP-712 signing request (for frontend/user wallet)\n */\n async createPermitRequest(\n owner: string,\n amount: number,\n orderId: string,\n deadlineMinutes: number = 30\n ): Promise<PermitRequest> {\n const nonce = await this.getNonce(owner);\n const deadline = Math.floor(Date.now() / 1000) + deadlineMinutes * 60;\n const value = BigInt(Math.floor(amount * 1e6)).toString();\n\n // USDC EIP-712 domain (may differ by chain)\n const domain = {\n name: 'USD Coin',\n version: '2',\n chainId: this.chainConfig.chainId,\n verifyingContract: this.chainConfig.usdc,\n };\n\n const types = {\n EIP712Domain: [\n { name: 'name', type: 'string' },\n { name: 'version', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n { name: 'verifyingContract', type: 'address' },\n ],\n Permit: [\n { name: 'owner', type: 'address' },\n { name: 'spender', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n };\n\n const message = {\n owner,\n spender: this.spenderAddress,\n value,\n nonce,\n deadline,\n };\n\n const typedData: EIP712TypedData = {\n types,\n primaryType: 'Permit',\n domain,\n message,\n };\n\n return {\n type: 'permit_request',\n version: '1.0',\n order_id: orderId,\n typed_data: typedData,\n };\n }\n\n /**\n * Execute permit + transferFrom\n * \n * @param owner User address\n * @param amount Amount\n * @param signature User signature {v, r, s, deadline}\n */\n async executePermitAndTransfer(\n owner: string,\n amount: number,\n signature: PermitSignature\n ): Promise<PermitExecuteResult> {\n if (!this.wallet) {\n return { success: false, error: 'Wallet not configured. Private key required.' };\n }\n\n try {\n const value = BigInt(Math.floor(amount * 1e6));\n\n // 1. Call permit\n const permitTx = await this.usdcContract.permit(\n owner,\n this.spenderAddress,\n value,\n signature.deadline,\n signature.v,\n signature.r,\n signature.s\n );\n await permitTx.wait();\n\n // 2. Call transferFrom\n const transferTx = await this.usdcContract.transferFrom(owner, this.spenderAddress, value);\n const receipt = await transferTx.wait();\n\n return {\n success: receipt.status === 1,\n tx_hash: transferTx.hash,\n };\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n }\n\n /**\n * Execute permit only (no transfer)\n */\n async executePermit(\n owner: string,\n amount: number,\n signature: PermitSignature\n ): Promise<PermitExecuteResult> {\n if (!this.wallet) {\n return { success: false, error: 'Wallet not configured. Private key required.' };\n }\n\n try {\n const value = BigInt(Math.floor(amount * 1e6));\n\n const tx = await this.usdcContract.permit(\n owner,\n this.spenderAddress,\n value,\n signature.deadline,\n signature.v,\n signature.r,\n signature.s\n );\n const receipt = await tx.wait();\n\n return {\n success: receipt.status === 1,\n tx_hash: tx.hash,\n };\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n }\n\n /**\n * Format Permit request as user message\n */\n formatPermitMessage(request: PermitRequest): string {\n const { typed_data } = request;\n const { message } = typed_data;\n\n return `🔐 **Signature Authorization Request**\n\nAuthorize \\`${(Number(message.value) / 1e6).toFixed(2)} USDC\\` to service provider\n\n**Signature Details:**\n- Owner: \\`${message.owner}\\`\n- Spender: \\`${message.spender}\\`\n- Amount: ${(Number(message.value) / 1e6).toFixed(2)} USDC\n- Deadline: ${new Date(message.deadline * 1000).toISOString()}\n\nPlease sign this request in your wallet (no gas required).\n\n\\`\\`\\`json\n${JSON.stringify(typed_data, null, 2)}\n\\`\\`\\``;\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName } from '../types/index.js';\n\nexport const CHAINS: Record<ChainName, ChainConfig> = {\n // ============ Mainnet ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n explorer: 'https://basescan.org/address/',\n explorerTx: 'https://basescan.org/tx/',\n avgBlockTime: 2,\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n rpc: 'https://polygon-rpc.com',\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n rpc: 'https://eth.llamarpc.com',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n explorer: 'https://etherscan.io/address/',\n explorerTx: 'https://etherscan.io/tx/',\n avgBlockTime: 12,\n },\n\n // ============ Testnet ============\n base_sepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n rpc: 'https://sepolia.base.org',\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n sepolia: {\n name: 'Sepolia',\n chainId: 11155111,\n rpc: 'https://rpc.sepolia.org',\n usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n explorer: 'https://sepolia.etherscan.io/address/',\n explorerTx: 'https://sepolia.etherscan.io/tx/',\n avgBlockTime: 12,\n },\n};\n\n/**\n * Get chain configuration\n */\nexport function getChain(name: ChainName): ChainConfig {\n const config = CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * List all supported chains\n */\nexport function listChains(): ChainName[] {\n return Object.keys(CHAINS) as ChainName[];\n}\n\n/**\n * Get chain config by chainId\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(CHAINS).find(c => c.chainId === chainId);\n}\n\n/**\n * ERC20 ABI (minimal, only required methods)\n */\nexport const ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function nonces(address owner) view returns (uint256)',\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event Approval(address indexed owner, address indexed spender, uint256 value)',\n];\n\nexport type { ChainConfig, ChainName };\n"],"mappings":"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","names":[]}
|
package/dist/permit/index.mjs
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
// src/permit/Permit.ts
|
|
2
|
-
import { ethers } from "ethers";
|
|
3
|
-
|
|
4
|
-
// src/chains/index.ts
|
|
5
|
-
var CHAINS = {
|
|
6
|
-
// ============ Mainnet ============
|
|
7
|
-
base: {
|
|
8
|
-
name: "Base",
|
|
9
|
-
chainId: 8453,
|
|
10
|
-
rpc: "https://mainnet.base.org",
|
|
11
|
-
usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
12
|
-
explorer: "https://basescan.org/address/",
|
|
13
|
-
explorerTx: "https://basescan.org/tx/",
|
|
14
|
-
avgBlockTime: 2
|
|
15
|
-
},
|
|
16
|
-
polygon: {
|
|
17
|
-
name: "Polygon",
|
|
18
|
-
chainId: 137,
|
|
19
|
-
rpc: "https://polygon-rpc.com",
|
|
20
|
-
usdc: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
21
|
-
explorer: "https://polygonscan.com/address/",
|
|
22
|
-
explorerTx: "https://polygonscan.com/tx/",
|
|
23
|
-
avgBlockTime: 2
|
|
24
|
-
},
|
|
25
|
-
ethereum: {
|
|
26
|
-
name: "Ethereum",
|
|
27
|
-
chainId: 1,
|
|
28
|
-
rpc: "https://eth.llamarpc.com",
|
|
29
|
-
usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
30
|
-
explorer: "https://etherscan.io/address/",
|
|
31
|
-
explorerTx: "https://etherscan.io/tx/",
|
|
32
|
-
avgBlockTime: 12
|
|
33
|
-
},
|
|
34
|
-
// ============ Testnet ============
|
|
35
|
-
base_sepolia: {
|
|
36
|
-
name: "Base Sepolia",
|
|
37
|
-
chainId: 84532,
|
|
38
|
-
rpc: "https://sepolia.base.org",
|
|
39
|
-
usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
40
|
-
explorer: "https://sepolia.basescan.org/address/",
|
|
41
|
-
explorerTx: "https://sepolia.basescan.org/tx/",
|
|
42
|
-
avgBlockTime: 2
|
|
43
|
-
},
|
|
44
|
-
sepolia: {
|
|
45
|
-
name: "Sepolia",
|
|
46
|
-
chainId: 11155111,
|
|
47
|
-
rpc: "https://rpc.sepolia.org",
|
|
48
|
-
usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
|
|
49
|
-
explorer: "https://sepolia.etherscan.io/address/",
|
|
50
|
-
explorerTx: "https://sepolia.etherscan.io/tx/",
|
|
51
|
-
avgBlockTime: 12
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
function getChain(name) {
|
|
55
|
-
const config = CHAINS[name];
|
|
56
|
-
if (!config) {
|
|
57
|
-
throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(", ")}`);
|
|
58
|
-
}
|
|
59
|
-
return config;
|
|
60
|
-
}
|
|
61
|
-
var ERC20_ABI = [
|
|
62
|
-
"function balanceOf(address owner) view returns (uint256)",
|
|
63
|
-
"function transfer(address to, uint256 amount) returns (bool)",
|
|
64
|
-
"function approve(address spender, uint256 amount) returns (bool)",
|
|
65
|
-
"function allowance(address owner, address spender) view returns (uint256)",
|
|
66
|
-
"function decimals() view returns (uint8)",
|
|
67
|
-
"function symbol() view returns (string)",
|
|
68
|
-
"function name() view returns (string)",
|
|
69
|
-
"function nonces(address owner) view returns (uint256)",
|
|
70
|
-
"function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)",
|
|
71
|
-
"event Transfer(address indexed from, address indexed to, uint256 value)",
|
|
72
|
-
"event Approval(address indexed owner, address indexed spender, uint256 value)"
|
|
73
|
-
];
|
|
74
|
-
|
|
75
|
-
// src/permit/Permit.ts
|
|
76
|
-
var PermitPayment = class {
|
|
77
|
-
chain;
|
|
78
|
-
chainConfig;
|
|
79
|
-
spenderAddress;
|
|
80
|
-
provider;
|
|
81
|
-
wallet;
|
|
82
|
-
usdcContract;
|
|
83
|
-
constructor(config = {}) {
|
|
84
|
-
this.chain = config.chain || "base_sepolia";
|
|
85
|
-
this.chainConfig = getChain(this.chain);
|
|
86
|
-
this.spenderAddress = config.spenderAddress || process.env.PAYMENT_AGENT_WALLET || "";
|
|
87
|
-
const rpcUrl = config.rpcUrl || this.chainConfig.rpc;
|
|
88
|
-
this.provider = new ethers.JsonRpcProvider(rpcUrl);
|
|
89
|
-
const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;
|
|
90
|
-
if (privateKey) {
|
|
91
|
-
this.wallet = new ethers.Wallet(privateKey, this.provider);
|
|
92
|
-
this.spenderAddress = this.wallet.address;
|
|
93
|
-
}
|
|
94
|
-
this.usdcContract = new ethers.Contract(
|
|
95
|
-
this.chainConfig.usdc,
|
|
96
|
-
ERC20_ABI,
|
|
97
|
-
this.wallet || this.provider
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Get user current nonce
|
|
102
|
-
*/
|
|
103
|
-
async getNonce(owner) {
|
|
104
|
-
return Number(await this.usdcContract.nonces(owner));
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Generate EIP-712 signing request (for frontend/user wallet)
|
|
108
|
-
*/
|
|
109
|
-
async createPermitRequest(owner, amount, orderId, deadlineMinutes = 30) {
|
|
110
|
-
const nonce = await this.getNonce(owner);
|
|
111
|
-
const deadline = Math.floor(Date.now() / 1e3) + deadlineMinutes * 60;
|
|
112
|
-
const value = BigInt(Math.floor(amount * 1e6)).toString();
|
|
113
|
-
const domain = {
|
|
114
|
-
name: "USD Coin",
|
|
115
|
-
version: "2",
|
|
116
|
-
chainId: this.chainConfig.chainId,
|
|
117
|
-
verifyingContract: this.chainConfig.usdc
|
|
118
|
-
};
|
|
119
|
-
const types = {
|
|
120
|
-
EIP712Domain: [
|
|
121
|
-
{ name: "name", type: "string" },
|
|
122
|
-
{ name: "version", type: "string" },
|
|
123
|
-
{ name: "chainId", type: "uint256" },
|
|
124
|
-
{ name: "verifyingContract", type: "address" }
|
|
125
|
-
],
|
|
126
|
-
Permit: [
|
|
127
|
-
{ name: "owner", type: "address" },
|
|
128
|
-
{ name: "spender", type: "address" },
|
|
129
|
-
{ name: "value", type: "uint256" },
|
|
130
|
-
{ name: "nonce", type: "uint256" },
|
|
131
|
-
{ name: "deadline", type: "uint256" }
|
|
132
|
-
]
|
|
133
|
-
};
|
|
134
|
-
const message = {
|
|
135
|
-
owner,
|
|
136
|
-
spender: this.spenderAddress,
|
|
137
|
-
value,
|
|
138
|
-
nonce,
|
|
139
|
-
deadline
|
|
140
|
-
};
|
|
141
|
-
const typedData = {
|
|
142
|
-
types,
|
|
143
|
-
primaryType: "Permit",
|
|
144
|
-
domain,
|
|
145
|
-
message
|
|
146
|
-
};
|
|
147
|
-
return {
|
|
148
|
-
type: "permit_request",
|
|
149
|
-
version: "1.0",
|
|
150
|
-
order_id: orderId,
|
|
151
|
-
typed_data: typedData
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Execute permit + transferFrom
|
|
156
|
-
*
|
|
157
|
-
* @param owner User address
|
|
158
|
-
* @param amount Amount
|
|
159
|
-
* @param signature User signature {v, r, s, deadline}
|
|
160
|
-
*/
|
|
161
|
-
async executePermitAndTransfer(owner, amount, signature) {
|
|
162
|
-
if (!this.wallet) {
|
|
163
|
-
return { success: false, error: "Wallet not configured. Private key required." };
|
|
164
|
-
}
|
|
165
|
-
try {
|
|
166
|
-
const value = BigInt(Math.floor(amount * 1e6));
|
|
167
|
-
const permitTx = await this.usdcContract.permit(
|
|
168
|
-
owner,
|
|
169
|
-
this.spenderAddress,
|
|
170
|
-
value,
|
|
171
|
-
signature.deadline,
|
|
172
|
-
signature.v,
|
|
173
|
-
signature.r,
|
|
174
|
-
signature.s
|
|
175
|
-
);
|
|
176
|
-
await permitTx.wait();
|
|
177
|
-
const transferTx = await this.usdcContract.transferFrom(owner, this.spenderAddress, value);
|
|
178
|
-
const receipt = await transferTx.wait();
|
|
179
|
-
return {
|
|
180
|
-
success: receipt.status === 1,
|
|
181
|
-
tx_hash: transferTx.hash
|
|
182
|
-
};
|
|
183
|
-
} catch (error) {
|
|
184
|
-
return {
|
|
185
|
-
success: false,
|
|
186
|
-
error: error.message
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Execute permit only (no transfer)
|
|
192
|
-
*/
|
|
193
|
-
async executePermit(owner, amount, signature) {
|
|
194
|
-
if (!this.wallet) {
|
|
195
|
-
return { success: false, error: "Wallet not configured. Private key required." };
|
|
196
|
-
}
|
|
197
|
-
try {
|
|
198
|
-
const value = BigInt(Math.floor(amount * 1e6));
|
|
199
|
-
const tx = await this.usdcContract.permit(
|
|
200
|
-
owner,
|
|
201
|
-
this.spenderAddress,
|
|
202
|
-
value,
|
|
203
|
-
signature.deadline,
|
|
204
|
-
signature.v,
|
|
205
|
-
signature.r,
|
|
206
|
-
signature.s
|
|
207
|
-
);
|
|
208
|
-
const receipt = await tx.wait();
|
|
209
|
-
return {
|
|
210
|
-
success: receipt.status === 1,
|
|
211
|
-
tx_hash: tx.hash
|
|
212
|
-
};
|
|
213
|
-
} catch (error) {
|
|
214
|
-
return {
|
|
215
|
-
success: false,
|
|
216
|
-
error: error.message
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Format Permit request as user message
|
|
222
|
-
*/
|
|
223
|
-
formatPermitMessage(request) {
|
|
224
|
-
const { typed_data } = request;
|
|
225
|
-
const { message } = typed_data;
|
|
226
|
-
return `\u{1F510} **Signature Authorization Request**
|
|
227
|
-
|
|
228
|
-
Authorize \`${(Number(message.value) / 1e6).toFixed(2)} USDC\` to service provider
|
|
229
|
-
|
|
230
|
-
**Signature Details:**
|
|
231
|
-
- Owner: \`${message.owner}\`
|
|
232
|
-
- Spender: \`${message.spender}\`
|
|
233
|
-
- Amount: ${(Number(message.value) / 1e6).toFixed(2)} USDC
|
|
234
|
-
- Deadline: ${new Date(message.deadline * 1e3).toISOString()}
|
|
235
|
-
|
|
236
|
-
Please sign this request in your wallet (no gas required).
|
|
237
|
-
|
|
238
|
-
\`\`\`json
|
|
239
|
-
${JSON.stringify(typed_data, null, 2)}
|
|
240
|
-
\`\`\``;
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
export {
|
|
244
|
-
PermitPayment
|
|
245
|
-
};
|
|
246
|
-
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/permit/Permit.ts","../../src/chains/index.ts"],"sourcesContent":["/**\n * PermitPayment - EIP-2612 Gasless Pre-authorization\n * \n * User signs authorization, service provider pays gas to execute transferFrom\n */\n\nimport { ethers } from 'ethers';\nimport { getChain, ERC20_ABI } from '../chains/index.js';\nimport type {\n ChainName,\n ChainConfig,\n PermitRequest,\n PermitSignature,\n PermitExecuteResult,\n EIP712TypedData,\n} from '../types/index.js';\n\nexport interface PermitConfig {\n chain?: ChainName;\n privateKey?: string;\n spenderAddress?: string;\n rpcUrl?: string;\n}\n\nexport class PermitPayment {\n readonly chain: ChainName;\n readonly chainConfig: ChainConfig;\n readonly spenderAddress: string;\n \n private provider: ethers.JsonRpcProvider;\n private wallet?: ethers.Wallet;\n private usdcContract: ethers.Contract;\n\n constructor(config: PermitConfig = {}) {\n this.chain = config.chain || 'base_sepolia';\n this.chainConfig = getChain(this.chain);\n this.spenderAddress = config.spenderAddress || process.env.PAYMENT_AGENT_WALLET || '';\n\n const rpcUrl = config.rpcUrl || this.chainConfig.rpc;\n this.provider = new ethers.JsonRpcProvider(rpcUrl);\n\n const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;\n if (privateKey) {\n this.wallet = new ethers.Wallet(privateKey, this.provider);\n this.spenderAddress = this.wallet.address;\n }\n\n this.usdcContract = new ethers.Contract(\n this.chainConfig.usdc,\n ERC20_ABI,\n this.wallet || this.provider\n );\n }\n\n /**\n * Get user current nonce\n */\n async getNonce(owner: string): Promise<number> {\n return Number(await this.usdcContract.nonces(owner));\n }\n\n /**\n * Generate EIP-712 signing request (for frontend/user wallet)\n */\n async createPermitRequest(\n owner: string,\n amount: number,\n orderId: string,\n deadlineMinutes: number = 30\n ): Promise<PermitRequest> {\n const nonce = await this.getNonce(owner);\n const deadline = Math.floor(Date.now() / 1000) + deadlineMinutes * 60;\n const value = BigInt(Math.floor(amount * 1e6)).toString();\n\n // USDC EIP-712 domain (may differ by chain)\n const domain = {\n name: 'USD Coin',\n version: '2',\n chainId: this.chainConfig.chainId,\n verifyingContract: this.chainConfig.usdc,\n };\n\n const types = {\n EIP712Domain: [\n { name: 'name', type: 'string' },\n { name: 'version', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n { name: 'verifyingContract', type: 'address' },\n ],\n Permit: [\n { name: 'owner', type: 'address' },\n { name: 'spender', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'nonce', type: 'uint256' },\n { name: 'deadline', type: 'uint256' },\n ],\n };\n\n const message = {\n owner,\n spender: this.spenderAddress,\n value,\n nonce,\n deadline,\n };\n\n const typedData: EIP712TypedData = {\n types,\n primaryType: 'Permit',\n domain,\n message,\n };\n\n return {\n type: 'permit_request',\n version: '1.0',\n order_id: orderId,\n typed_data: typedData,\n };\n }\n\n /**\n * Execute permit + transferFrom\n * \n * @param owner User address\n * @param amount Amount\n * @param signature User signature {v, r, s, deadline}\n */\n async executePermitAndTransfer(\n owner: string,\n amount: number,\n signature: PermitSignature\n ): Promise<PermitExecuteResult> {\n if (!this.wallet) {\n return { success: false, error: 'Wallet not configured. Private key required.' };\n }\n\n try {\n const value = BigInt(Math.floor(amount * 1e6));\n\n // 1. Call permit\n const permitTx = await this.usdcContract.permit(\n owner,\n this.spenderAddress,\n value,\n signature.deadline,\n signature.v,\n signature.r,\n signature.s\n );\n await permitTx.wait();\n\n // 2. Call transferFrom\n const transferTx = await this.usdcContract.transferFrom(owner, this.spenderAddress, value);\n const receipt = await transferTx.wait();\n\n return {\n success: receipt.status === 1,\n tx_hash: transferTx.hash,\n };\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n }\n\n /**\n * Execute permit only (no transfer)\n */\n async executePermit(\n owner: string,\n amount: number,\n signature: PermitSignature\n ): Promise<PermitExecuteResult> {\n if (!this.wallet) {\n return { success: false, error: 'Wallet not configured. Private key required.' };\n }\n\n try {\n const value = BigInt(Math.floor(amount * 1e6));\n\n const tx = await this.usdcContract.permit(\n owner,\n this.spenderAddress,\n value,\n signature.deadline,\n signature.v,\n signature.r,\n signature.s\n );\n const receipt = await tx.wait();\n\n return {\n success: receipt.status === 1,\n tx_hash: tx.hash,\n };\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n }\n\n /**\n * Format Permit request as user message\n */\n formatPermitMessage(request: PermitRequest): string {\n const { typed_data } = request;\n const { message } = typed_data;\n\n return `🔐 **Signature Authorization Request**\n\nAuthorize \\`${(Number(message.value) / 1e6).toFixed(2)} USDC\\` to service provider\n\n**Signature Details:**\n- Owner: \\`${message.owner}\\`\n- Spender: \\`${message.spender}\\`\n- Amount: ${(Number(message.value) / 1e6).toFixed(2)} USDC\n- Deadline: ${new Date(message.deadline * 1000).toISOString()}\n\nPlease sign this request in your wallet (no gas required).\n\n\\`\\`\\`json\n${JSON.stringify(typed_data, null, 2)}\n\\`\\`\\``;\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName } from '../types/index.js';\n\nexport const CHAINS: Record<ChainName, ChainConfig> = {\n // ============ Mainnet ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n explorer: 'https://basescan.org/address/',\n explorerTx: 'https://basescan.org/tx/',\n avgBlockTime: 2,\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n rpc: 'https://polygon-rpc.com',\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n rpc: 'https://eth.llamarpc.com',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n explorer: 'https://etherscan.io/address/',\n explorerTx: 'https://etherscan.io/tx/',\n avgBlockTime: 12,\n },\n\n // ============ Testnet ============\n base_sepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n rpc: 'https://sepolia.base.org',\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n sepolia: {\n name: 'Sepolia',\n chainId: 11155111,\n rpc: 'https://rpc.sepolia.org',\n usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n explorer: 'https://sepolia.etherscan.io/address/',\n explorerTx: 'https://sepolia.etherscan.io/tx/',\n avgBlockTime: 12,\n },\n};\n\n/**\n * Get chain configuration\n */\nexport function getChain(name: ChainName): ChainConfig {\n const config = CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * List all supported chains\n */\nexport function listChains(): ChainName[] {\n return Object.keys(CHAINS) as ChainName[];\n}\n\n/**\n * Get chain config by chainId\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(CHAINS).find(c => c.chainId === chainId);\n}\n\n/**\n * ERC20 ABI (minimal, only required methods)\n */\nexport const ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function nonces(address owner) view returns (uint256)',\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event Approval(address indexed owner, address indexed spender, uint256 value)',\n];\n\nexport type { ChainConfig, ChainName };\n"],"mappings":";AAMA,SAAS,cAAc;;;ACAhB,IAAM,SAAyC;AAAA;AAAA,EAEpD,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA;AAAA,EAGA,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,cAAc;AAAA,EAChB;AACF;AAKO,SAAS,SAAS,MAA8B;AACrD,QAAM,SAAS,OAAO,IAAI;AAC1B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,sBAAsB,IAAI,gBAAgB,OAAO,KAAK,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EAC5F;AACA,SAAO;AACT;AAmBO,IAAM,YAAY;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ADzEO,IAAM,gBAAN,MAAoB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EAED;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,SAAuB,CAAC,GAAG;AACrC,SAAK,QAAQ,OAAO,SAAS;AAC7B,SAAK,cAAc,SAAS,KAAK,KAAK;AACtC,SAAK,iBAAiB,OAAO,kBAAkB,QAAQ,IAAI,wBAAwB;AAEnF,UAAM,SAAS,OAAO,UAAU,KAAK,YAAY;AACjD,SAAK,WAAW,IAAI,OAAO,gBAAgB,MAAM;AAEjD,UAAM,aAAa,OAAO,cAAc,QAAQ,IAAI;AACpD,QAAI,YAAY;AACd,WAAK,SAAS,IAAI,OAAO,OAAO,YAAY,KAAK,QAAQ;AACzD,WAAK,iBAAiB,KAAK,OAAO;AAAA,IACpC;AAEA,SAAK,eAAe,IAAI,OAAO;AAAA,MAC7B,KAAK,YAAY;AAAA,MACjB;AAAA,MACA,KAAK,UAAU,KAAK;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,OAAgC;AAC7C,WAAO,OAAO,MAAM,KAAK,aAAa,OAAO,KAAK,CAAC;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,oBACJ,OACA,QACA,SACA,kBAA0B,IACF;AACxB,UAAM,QAAQ,MAAM,KAAK,SAAS,KAAK;AACvC,UAAM,WAAW,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI,kBAAkB;AACnE,UAAM,QAAQ,OAAO,KAAK,MAAM,SAAS,GAAG,CAAC,EAAE,SAAS;AAGxD,UAAM,SAAS;AAAA,MACb,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,KAAK,YAAY;AAAA,MAC1B,mBAAmB,KAAK,YAAY;AAAA,IACtC;AAEA,UAAM,QAAQ;AAAA,MACZ,cAAc;AAAA,QACZ,EAAE,MAAM,QAAQ,MAAM,SAAS;AAAA,QAC/B,EAAE,MAAM,WAAW,MAAM,SAAS;AAAA,QAClC,EAAE,MAAM,WAAW,MAAM,UAAU;AAAA,QACnC,EAAE,MAAM,qBAAqB,MAAM,UAAU;AAAA,MAC/C;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,QACjC,EAAE,MAAM,WAAW,MAAM,UAAU;AAAA,QACnC,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,QACjC,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,QACjC,EAAE,MAAM,YAAY,MAAM,UAAU;AAAA,MACtC;AAAA,IACF;AAEA,UAAM,UAAU;AAAA,MACd;AAAA,MACA,SAAS,KAAK;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,YAA6B;AAAA,MACjC;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU;AAAA,MACV,YAAY;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,yBACJ,OACA,QACA,WAC8B;AAC9B,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAO,EAAE,SAAS,OAAO,OAAO,+CAA+C;AAAA,IACjF;AAEA,QAAI;AACF,YAAM,QAAQ,OAAO,KAAK,MAAM,SAAS,GAAG,CAAC;AAG7C,YAAM,WAAW,MAAM,KAAK,aAAa;AAAA,QACvC;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AACA,YAAM,SAAS,KAAK;AAGpB,YAAM,aAAa,MAAM,KAAK,aAAa,aAAa,OAAO,KAAK,gBAAgB,KAAK;AACzF,YAAM,UAAU,MAAM,WAAW,KAAK;AAEtC,aAAO;AAAA,QACL,SAAS,QAAQ,WAAW;AAAA,QAC5B,SAAS,WAAW;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAQ,MAAgB;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cACJ,OACA,QACA,WAC8B;AAC9B,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAO,EAAE,SAAS,OAAO,OAAO,+CAA+C;AAAA,IACjF;AAEA,QAAI;AACF,YAAM,QAAQ,OAAO,KAAK,MAAM,SAAS,GAAG,CAAC;AAE7C,YAAM,KAAK,MAAM,KAAK,aAAa;AAAA,QACjC;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AACA,YAAM,UAAU,MAAM,GAAG,KAAK;AAE9B,aAAO;AAAA,QACL,SAAS,QAAQ,WAAW;AAAA,QAC5B,SAAS,GAAG;AAAA,MACd;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAQ,MAAgB;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,SAAgC;AAClD,UAAM,EAAE,WAAW,IAAI;AACvB,UAAM,EAAE,QAAQ,IAAI;AAEpB,WAAO;AAAA;AAAA,eAEI,OAAO,QAAQ,KAAK,IAAI,KAAK,QAAQ,CAAC,CAAC;AAAA;AAAA;AAAA,aAGzC,QAAQ,KAAK;AAAA,eACX,QAAQ,OAAO;AAAA,aACjB,OAAO,QAAQ,KAAK,IAAI,KAAK,QAAQ,CAAC,CAAC;AAAA,cACtC,IAAI,KAAK,QAAQ,WAAW,GAAI,EAAE,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAK3D,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;AAAA;AAAA,EAEnC;AACF;","names":[]}
|
|
File without changes
|
|
File without changes
|