moltspay 0.2.2 → 0.2.3
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/cli.js +6 -3
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +6 -3
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +65 -1
- package/dist/index.d.ts +65 -1
- package/dist/index.js +186 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +184 -9
- package/dist/index.mjs.map +1 -1
- package/dist/wallet/index.d.mts +71 -1
- package/dist/wallet/index.d.ts +71 -1
- package/dist/wallet/index.js +72 -0
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +70 -0
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -38,6 +38,7 @@ __export(src_exports, {
|
|
|
38
38
|
OrderManager: () => OrderManager,
|
|
39
39
|
PaymentAgent: () => PaymentAgent,
|
|
40
40
|
PermitPayment: () => PermitPayment,
|
|
41
|
+
PermitSigner: () => PermitSigner,
|
|
41
42
|
PermitWallet: () => PermitWallet,
|
|
42
43
|
SecureWallet: () => SecureWallet,
|
|
43
44
|
SellerTemplates: () => SellerTemplates,
|
|
@@ -62,6 +63,7 @@ __export(src_exports, {
|
|
|
62
63
|
listChains: () => listChains,
|
|
63
64
|
loadWallet: () => loadWallet,
|
|
64
65
|
parseStatusMarker: () => parseStatusMarker,
|
|
66
|
+
signPermit: () => signPermit,
|
|
65
67
|
verifyPayment: () => verifyPayment,
|
|
66
68
|
waitForTransaction: () => waitForTransaction,
|
|
67
69
|
walletExists: () => walletExists
|
|
@@ -1213,8 +1215,76 @@ After signing, send { v, r, s, deadline } to the Agent.
|
|
|
1213
1215
|
\u26A0\uFE0F Note: This authorization only allows the Agent to spend up to ${amount} USDC from your wallet. Your private key is never exposed.`;
|
|
1214
1216
|
}
|
|
1215
1217
|
|
|
1216
|
-
// src/
|
|
1218
|
+
// src/wallet/signPermit.ts
|
|
1217
1219
|
var import_ethers5 = require("ethers");
|
|
1220
|
+
async function signPermit(config, params) {
|
|
1221
|
+
const chain = config.chain || "base";
|
|
1222
|
+
const chainConfig = getChain(chain);
|
|
1223
|
+
const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;
|
|
1224
|
+
if (!privateKey) {
|
|
1225
|
+
throw new Error("privateKey is required");
|
|
1226
|
+
}
|
|
1227
|
+
const rpcUrl = config.rpcUrl || chainConfig.rpc;
|
|
1228
|
+
const provider = new import_ethers5.ethers.JsonRpcProvider(rpcUrl);
|
|
1229
|
+
const wallet = new import_ethers5.ethers.Wallet(privateKey, provider);
|
|
1230
|
+
const usdcContract = new import_ethers5.ethers.Contract(chainConfig.usdc, ERC20_ABI, provider);
|
|
1231
|
+
const nonce = Number(await usdcContract.nonces(wallet.address));
|
|
1232
|
+
let deadline;
|
|
1233
|
+
if (!params.deadline) {
|
|
1234
|
+
deadline = Math.floor(Date.now() / 1e3) + 30 * 60;
|
|
1235
|
+
} else if (params.deadline < 1e6) {
|
|
1236
|
+
deadline = Math.floor(Date.now() / 1e3) + params.deadline * 60;
|
|
1237
|
+
} else {
|
|
1238
|
+
deadline = params.deadline;
|
|
1239
|
+
}
|
|
1240
|
+
const value = BigInt(Math.floor(params.amount * 1e6)).toString();
|
|
1241
|
+
const domain = {
|
|
1242
|
+
name: "USD Coin",
|
|
1243
|
+
version: "2",
|
|
1244
|
+
chainId: chainConfig.chainId,
|
|
1245
|
+
verifyingContract: chainConfig.usdc
|
|
1246
|
+
};
|
|
1247
|
+
const types = {
|
|
1248
|
+
Permit: [
|
|
1249
|
+
{ name: "owner", type: "address" },
|
|
1250
|
+
{ name: "spender", type: "address" },
|
|
1251
|
+
{ name: "value", type: "uint256" },
|
|
1252
|
+
{ name: "nonce", type: "uint256" },
|
|
1253
|
+
{ name: "deadline", type: "uint256" }
|
|
1254
|
+
]
|
|
1255
|
+
};
|
|
1256
|
+
const message = {
|
|
1257
|
+
owner: wallet.address,
|
|
1258
|
+
spender: params.spender,
|
|
1259
|
+
value,
|
|
1260
|
+
nonce,
|
|
1261
|
+
deadline
|
|
1262
|
+
};
|
|
1263
|
+
const signature = await wallet.signTypedData(domain, types, message);
|
|
1264
|
+
const sig = import_ethers5.ethers.Signature.from(signature);
|
|
1265
|
+
return {
|
|
1266
|
+
owner: wallet.address,
|
|
1267
|
+
spender: params.spender,
|
|
1268
|
+
value,
|
|
1269
|
+
deadline,
|
|
1270
|
+
nonce,
|
|
1271
|
+
v: sig.v,
|
|
1272
|
+
r: sig.r,
|
|
1273
|
+
s: sig.s
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
var PermitSigner = class {
|
|
1277
|
+
config;
|
|
1278
|
+
constructor(config) {
|
|
1279
|
+
this.config = config;
|
|
1280
|
+
}
|
|
1281
|
+
async sign(params) {
|
|
1282
|
+
return signPermit(this.config, params);
|
|
1283
|
+
}
|
|
1284
|
+
};
|
|
1285
|
+
|
|
1286
|
+
// src/permit/Permit.ts
|
|
1287
|
+
var import_ethers6 = require("ethers");
|
|
1218
1288
|
var PermitPayment = class {
|
|
1219
1289
|
chain;
|
|
1220
1290
|
chainConfig;
|
|
@@ -1227,13 +1297,13 @@ var PermitPayment = class {
|
|
|
1227
1297
|
this.chainConfig = getChain(this.chain);
|
|
1228
1298
|
this.spenderAddress = config.spenderAddress || process.env.PAYMENT_AGENT_WALLET || "";
|
|
1229
1299
|
const rpcUrl = config.rpcUrl || this.chainConfig.rpc;
|
|
1230
|
-
this.provider = new
|
|
1300
|
+
this.provider = new import_ethers6.ethers.JsonRpcProvider(rpcUrl);
|
|
1231
1301
|
const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;
|
|
1232
1302
|
if (privateKey) {
|
|
1233
|
-
this.wallet = new
|
|
1303
|
+
this.wallet = new import_ethers6.ethers.Wallet(privateKey, this.provider);
|
|
1234
1304
|
this.spenderAddress = this.wallet.address;
|
|
1235
1305
|
}
|
|
1236
|
-
this.usdcContract = new
|
|
1306
|
+
this.usdcContract = new import_ethers6.ethers.Contract(
|
|
1237
1307
|
this.chainConfig.usdc,
|
|
1238
1308
|
ERC20_ABI,
|
|
1239
1309
|
this.wallet || this.provider
|
|
@@ -1516,8 +1586,8 @@ var OrderManager = class {
|
|
|
1516
1586
|
};
|
|
1517
1587
|
|
|
1518
1588
|
// src/verify/index.ts
|
|
1519
|
-
var
|
|
1520
|
-
var TRANSFER_EVENT_TOPIC =
|
|
1589
|
+
var import_ethers7 = require("ethers");
|
|
1590
|
+
var TRANSFER_EVENT_TOPIC = import_ethers7.ethers.id("Transfer(address,address,uint256)");
|
|
1521
1591
|
async function verifyPayment(params) {
|
|
1522
1592
|
const { txHash, expectedAmount, expectedTo } = params;
|
|
1523
1593
|
let chain;
|
|
@@ -1534,7 +1604,7 @@ async function verifyPayment(params) {
|
|
|
1534
1604
|
return { verified: false, error: `Unsupported chain: ${params.chain}` };
|
|
1535
1605
|
}
|
|
1536
1606
|
try {
|
|
1537
|
-
const provider = new
|
|
1607
|
+
const provider = new import_ethers7.ethers.JsonRpcProvider(chain.rpc);
|
|
1538
1608
|
const receipt = await provider.getTransactionReceipt(txHash);
|
|
1539
1609
|
if (!receipt) {
|
|
1540
1610
|
return { verified: false, error: "Transaction not found or not confirmed" };
|
|
@@ -1594,7 +1664,7 @@ async function getTransactionStatus(txHash, chain = "base") {
|
|
|
1594
1664
|
return { status: "not_found" };
|
|
1595
1665
|
}
|
|
1596
1666
|
try {
|
|
1597
|
-
const provider = new
|
|
1667
|
+
const provider = new import_ethers7.ethers.JsonRpcProvider(chainConfig.rpc);
|
|
1598
1668
|
const receipt = await provider.getTransactionReceipt(txHash);
|
|
1599
1669
|
if (!receipt) {
|
|
1600
1670
|
const tx = await provider.getTransaction(txHash);
|
|
@@ -1631,7 +1701,7 @@ async function waitForTransaction(txHash, chain = "base", confirmations = 1, tim
|
|
|
1631
1701
|
} catch (e) {
|
|
1632
1702
|
return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };
|
|
1633
1703
|
}
|
|
1634
|
-
const provider = new
|
|
1704
|
+
const provider = new import_ethers7.ethers.JsonRpcProvider(chainConfig.rpc);
|
|
1635
1705
|
try {
|
|
1636
1706
|
const receipt = await provider.waitForTransaction(txHash, confirmations, timeoutMs);
|
|
1637
1707
|
if (!receipt) {
|
|
@@ -2054,6 +2124,58 @@ ${receipt.delivery?.url ? `- Delivery: ${receipt.delivery.url}` : ""}
|
|
|
2054
2124
|
*/
|
|
2055
2125
|
end() {
|
|
2056
2126
|
return `Thank you for your purchase. This transaction is complete. Feel free to reach out if you need modifications or new services.`;
|
|
2127
|
+
},
|
|
2128
|
+
// ============ Permit Payment (Seller receives Permit from Client) ============
|
|
2129
|
+
/**
|
|
2130
|
+
* Offer Permit payment option
|
|
2131
|
+
*/
|
|
2132
|
+
offerPermitPayment(params) {
|
|
2133
|
+
const { service, price, sellerAddress, chain = "base", invoiceId } = params;
|
|
2134
|
+
const chainConfig = getChain(chain);
|
|
2135
|
+
return `Quote:
|
|
2136
|
+
- Service: ${service}
|
|
2137
|
+
- Price: ${price} USDC
|
|
2138
|
+
- Chain: ${chainConfig.name}
|
|
2139
|
+
- Invoice: ${invoiceId}
|
|
2140
|
+
|
|
2141
|
+
You can pay by signing a Permit authorizing my wallet to collect payment:
|
|
2142
|
+
- Spender (me): \`${sellerAddress}\`
|
|
2143
|
+
- Amount: ${price} USDC
|
|
2144
|
+
|
|
2145
|
+
Sign the Permit and send me the data. I'll then execute the collection.
|
|
2146
|
+
[status:awaiting_permit invoice=${invoiceId}]`;
|
|
2147
|
+
},
|
|
2148
|
+
/**
|
|
2149
|
+
* Confirm Permit received, executing payment
|
|
2150
|
+
*/
|
|
2151
|
+
executingPermit(invoiceId) {
|
|
2152
|
+
return `Permit received for invoice ${invoiceId}. Executing payment collection now...`;
|
|
2153
|
+
},
|
|
2154
|
+
/**
|
|
2155
|
+
* Permit payment successful
|
|
2156
|
+
*/
|
|
2157
|
+
permitPaymentReceived(params) {
|
|
2158
|
+
const { amount, txHash, invoiceId } = params;
|
|
2159
|
+
return `Payment collected successfully!
|
|
2160
|
+
- Invoice: ${invoiceId}
|
|
2161
|
+
- Amount: ${amount} USDC
|
|
2162
|
+
- Tx Hash: \`${txHash}\`
|
|
2163
|
+
|
|
2164
|
+
Starting to process your request now.
|
|
2165
|
+
[status:payment_confirmed tx=${txHash}]`;
|
|
2166
|
+
},
|
|
2167
|
+
/**
|
|
2168
|
+
* Permit payment failed
|
|
2169
|
+
*/
|
|
2170
|
+
permitPaymentFailed(error, invoiceId) {
|
|
2171
|
+
return `Failed to collect payment for invoice ${invoiceId}: ${error}
|
|
2172
|
+
|
|
2173
|
+
Please check:
|
|
2174
|
+
- Permit signature is valid
|
|
2175
|
+
- Permit hasn't expired
|
|
2176
|
+
- Your wallet has sufficient USDC balance
|
|
2177
|
+
|
|
2178
|
+
You can re-sign and send a new Permit.`;
|
|
2057
2179
|
}
|
|
2058
2180
|
};
|
|
2059
2181
|
var BuyerTemplates = {
|
|
@@ -2146,11 +2268,46 @@ ${requirements}`;
|
|
|
2146
2268
|
const { amount, agentAddress, deadlineHours = 24, reason } = params;
|
|
2147
2269
|
return `Boss, I need a USDC spending allowance (Permit) for ${reason || "purchasing services"}.
|
|
2148
2270
|
Please authorize ${amount} USDC to my wallet ${agentAddress}, valid for ${deadlineHours} hours.`;
|
|
2271
|
+
},
|
|
2272
|
+
// ============ Permit Payment (Client signs Permit to Seller) ============
|
|
2273
|
+
/**
|
|
2274
|
+
* Confirm willing to pay via Permit
|
|
2275
|
+
*/
|
|
2276
|
+
confirmPermitPayment() {
|
|
2277
|
+
return `Confirmed. I'll sign a Permit authorizing you to collect the payment.`;
|
|
2278
|
+
},
|
|
2279
|
+
/**
|
|
2280
|
+
* Send signed Permit to Seller
|
|
2281
|
+
*/
|
|
2282
|
+
sendPermit(params) {
|
|
2283
|
+
const { permit, invoiceId, amount } = params;
|
|
2284
|
+
return `Payment authorized via Permit.
|
|
2285
|
+
|
|
2286
|
+
Invoice: ${invoiceId}
|
|
2287
|
+
Amount: ${amount} USDC
|
|
2288
|
+
|
|
2289
|
+
Permit Data:
|
|
2290
|
+
\`\`\`json
|
|
2291
|
+
${JSON.stringify(permit, null, 2)}
|
|
2292
|
+
\`\`\`
|
|
2293
|
+
|
|
2294
|
+
[status:permit_sent invoice=${invoiceId} amount=${amount}]`;
|
|
2295
|
+
},
|
|
2296
|
+
/**
|
|
2297
|
+
* Simplified Permit message (compact JSON for agent parsing)
|
|
2298
|
+
*/
|
|
2299
|
+
sendPermitCompact(params) {
|
|
2300
|
+
const { permit, invoiceId } = params;
|
|
2301
|
+
return `Permit signed for invoice ${invoiceId}:
|
|
2302
|
+
${JSON.stringify(permit)}
|
|
2303
|
+
[status:permit_sent invoice=${invoiceId}]`;
|
|
2149
2304
|
}
|
|
2150
2305
|
};
|
|
2151
2306
|
var StatusMarkers = {
|
|
2152
2307
|
walletReady: "[status:wallet_ready]",
|
|
2153
2308
|
permitReady: (amount) => `[status:permit_ready USDC=${amount}]`,
|
|
2309
|
+
permitSent: (invoiceId, amount) => `[status:permit_sent invoice=${invoiceId} amount=${amount}]`,
|
|
2310
|
+
awaitingPermit: (invoiceId) => `[status:awaiting_permit invoice=${invoiceId}]`,
|
|
2154
2311
|
paymentSent: (txHash, amount) => `[status:payment_sent tx=${txHash} amount=${amount} USDC]`,
|
|
2155
2312
|
paymentConfirmed: (txHash) => `[status:payment_confirmed tx=${txHash}]`,
|
|
2156
2313
|
delivered: (url, hash) => `[status:delivered url=${url}${hash ? ` hash=${hash}` : ""}]`,
|
|
@@ -2170,6 +2327,24 @@ function parseStatusMarker(message) {
|
|
|
2170
2327
|
data: { amount: amountMatch?.[1] || "0" }
|
|
2171
2328
|
};
|
|
2172
2329
|
}
|
|
2330
|
+
if (content.startsWith("permit_sent")) {
|
|
2331
|
+
const invoiceMatch = content.match(/invoice=(\S+)/);
|
|
2332
|
+
const amountMatch = content.match(/amount=(\d+(?:\.\d+)?)/);
|
|
2333
|
+
return {
|
|
2334
|
+
type: "permit_sent",
|
|
2335
|
+
data: {
|
|
2336
|
+
invoiceId: invoiceMatch?.[1] || "",
|
|
2337
|
+
amount: amountMatch?.[1] || "0"
|
|
2338
|
+
}
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
2341
|
+
if (content.startsWith("awaiting_permit")) {
|
|
2342
|
+
const invoiceMatch = content.match(/invoice=(\S+)/);
|
|
2343
|
+
return {
|
|
2344
|
+
type: "awaiting_permit",
|
|
2345
|
+
data: { invoiceId: invoiceMatch?.[1] || "" }
|
|
2346
|
+
};
|
|
2347
|
+
}
|
|
2173
2348
|
if (content.startsWith("payment_sent")) {
|
|
2174
2349
|
const txMatch = content.match(/tx=(\S+)/);
|
|
2175
2350
|
const amountMatch = content.match(/amount=(\d+(?:\.\d+)?)/);
|
|
@@ -2222,6 +2397,7 @@ function parseStatusMarker(message) {
|
|
|
2222
2397
|
OrderManager,
|
|
2223
2398
|
PaymentAgent,
|
|
2224
2399
|
PermitPayment,
|
|
2400
|
+
PermitSigner,
|
|
2225
2401
|
PermitWallet,
|
|
2226
2402
|
SecureWallet,
|
|
2227
2403
|
SellerTemplates,
|
|
@@ -2246,6 +2422,7 @@ function parseStatusMarker(message) {
|
|
|
2246
2422
|
listChains,
|
|
2247
2423
|
loadWallet,
|
|
2248
2424
|
parseStatusMarker,
|
|
2425
|
+
signPermit,
|
|
2249
2426
|
verifyPayment,
|
|
2250
2427
|
waitForTransaction,
|
|
2251
2428
|
walletExists
|