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.mjs
CHANGED
|
@@ -1143,8 +1143,76 @@ After signing, send { v, r, s, deadline } to the Agent.
|
|
|
1143
1143
|
\u26A0\uFE0F Note: This authorization only allows the Agent to spend up to ${amount} USDC from your wallet. Your private key is never exposed.`;
|
|
1144
1144
|
}
|
|
1145
1145
|
|
|
1146
|
-
// src/
|
|
1146
|
+
// src/wallet/signPermit.ts
|
|
1147
1147
|
import { ethers as ethers5 } from "ethers";
|
|
1148
|
+
async function signPermit(config, params) {
|
|
1149
|
+
const chain = config.chain || "base";
|
|
1150
|
+
const chainConfig = getChain(chain);
|
|
1151
|
+
const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;
|
|
1152
|
+
if (!privateKey) {
|
|
1153
|
+
throw new Error("privateKey is required");
|
|
1154
|
+
}
|
|
1155
|
+
const rpcUrl = config.rpcUrl || chainConfig.rpc;
|
|
1156
|
+
const provider = new ethers5.JsonRpcProvider(rpcUrl);
|
|
1157
|
+
const wallet = new ethers5.Wallet(privateKey, provider);
|
|
1158
|
+
const usdcContract = new ethers5.Contract(chainConfig.usdc, ERC20_ABI, provider);
|
|
1159
|
+
const nonce = Number(await usdcContract.nonces(wallet.address));
|
|
1160
|
+
let deadline;
|
|
1161
|
+
if (!params.deadline) {
|
|
1162
|
+
deadline = Math.floor(Date.now() / 1e3) + 30 * 60;
|
|
1163
|
+
} else if (params.deadline < 1e6) {
|
|
1164
|
+
deadline = Math.floor(Date.now() / 1e3) + params.deadline * 60;
|
|
1165
|
+
} else {
|
|
1166
|
+
deadline = params.deadline;
|
|
1167
|
+
}
|
|
1168
|
+
const value = BigInt(Math.floor(params.amount * 1e6)).toString();
|
|
1169
|
+
const domain = {
|
|
1170
|
+
name: "USD Coin",
|
|
1171
|
+
version: "2",
|
|
1172
|
+
chainId: chainConfig.chainId,
|
|
1173
|
+
verifyingContract: chainConfig.usdc
|
|
1174
|
+
};
|
|
1175
|
+
const types = {
|
|
1176
|
+
Permit: [
|
|
1177
|
+
{ name: "owner", type: "address" },
|
|
1178
|
+
{ name: "spender", type: "address" },
|
|
1179
|
+
{ name: "value", type: "uint256" },
|
|
1180
|
+
{ name: "nonce", type: "uint256" },
|
|
1181
|
+
{ name: "deadline", type: "uint256" }
|
|
1182
|
+
]
|
|
1183
|
+
};
|
|
1184
|
+
const message = {
|
|
1185
|
+
owner: wallet.address,
|
|
1186
|
+
spender: params.spender,
|
|
1187
|
+
value,
|
|
1188
|
+
nonce,
|
|
1189
|
+
deadline
|
|
1190
|
+
};
|
|
1191
|
+
const signature = await wallet.signTypedData(domain, types, message);
|
|
1192
|
+
const sig = ethers5.Signature.from(signature);
|
|
1193
|
+
return {
|
|
1194
|
+
owner: wallet.address,
|
|
1195
|
+
spender: params.spender,
|
|
1196
|
+
value,
|
|
1197
|
+
deadline,
|
|
1198
|
+
nonce,
|
|
1199
|
+
v: sig.v,
|
|
1200
|
+
r: sig.r,
|
|
1201
|
+
s: sig.s
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
var PermitSigner = class {
|
|
1205
|
+
config;
|
|
1206
|
+
constructor(config) {
|
|
1207
|
+
this.config = config;
|
|
1208
|
+
}
|
|
1209
|
+
async sign(params) {
|
|
1210
|
+
return signPermit(this.config, params);
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
|
|
1214
|
+
// src/permit/Permit.ts
|
|
1215
|
+
import { ethers as ethers6 } from "ethers";
|
|
1148
1216
|
var PermitPayment = class {
|
|
1149
1217
|
chain;
|
|
1150
1218
|
chainConfig;
|
|
@@ -1157,13 +1225,13 @@ var PermitPayment = class {
|
|
|
1157
1225
|
this.chainConfig = getChain(this.chain);
|
|
1158
1226
|
this.spenderAddress = config.spenderAddress || process.env.PAYMENT_AGENT_WALLET || "";
|
|
1159
1227
|
const rpcUrl = config.rpcUrl || this.chainConfig.rpc;
|
|
1160
|
-
this.provider = new
|
|
1228
|
+
this.provider = new ethers6.JsonRpcProvider(rpcUrl);
|
|
1161
1229
|
const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;
|
|
1162
1230
|
if (privateKey) {
|
|
1163
|
-
this.wallet = new
|
|
1231
|
+
this.wallet = new ethers6.Wallet(privateKey, this.provider);
|
|
1164
1232
|
this.spenderAddress = this.wallet.address;
|
|
1165
1233
|
}
|
|
1166
|
-
this.usdcContract = new
|
|
1234
|
+
this.usdcContract = new ethers6.Contract(
|
|
1167
1235
|
this.chainConfig.usdc,
|
|
1168
1236
|
ERC20_ABI,
|
|
1169
1237
|
this.wallet || this.provider
|
|
@@ -1446,8 +1514,8 @@ var OrderManager = class {
|
|
|
1446
1514
|
};
|
|
1447
1515
|
|
|
1448
1516
|
// src/verify/index.ts
|
|
1449
|
-
import { ethers as
|
|
1450
|
-
var TRANSFER_EVENT_TOPIC =
|
|
1517
|
+
import { ethers as ethers7 } from "ethers";
|
|
1518
|
+
var TRANSFER_EVENT_TOPIC = ethers7.id("Transfer(address,address,uint256)");
|
|
1451
1519
|
async function verifyPayment(params) {
|
|
1452
1520
|
const { txHash, expectedAmount, expectedTo } = params;
|
|
1453
1521
|
let chain;
|
|
@@ -1464,7 +1532,7 @@ async function verifyPayment(params) {
|
|
|
1464
1532
|
return { verified: false, error: `Unsupported chain: ${params.chain}` };
|
|
1465
1533
|
}
|
|
1466
1534
|
try {
|
|
1467
|
-
const provider = new
|
|
1535
|
+
const provider = new ethers7.JsonRpcProvider(chain.rpc);
|
|
1468
1536
|
const receipt = await provider.getTransactionReceipt(txHash);
|
|
1469
1537
|
if (!receipt) {
|
|
1470
1538
|
return { verified: false, error: "Transaction not found or not confirmed" };
|
|
@@ -1524,7 +1592,7 @@ async function getTransactionStatus(txHash, chain = "base") {
|
|
|
1524
1592
|
return { status: "not_found" };
|
|
1525
1593
|
}
|
|
1526
1594
|
try {
|
|
1527
|
-
const provider = new
|
|
1595
|
+
const provider = new ethers7.JsonRpcProvider(chainConfig.rpc);
|
|
1528
1596
|
const receipt = await provider.getTransactionReceipt(txHash);
|
|
1529
1597
|
if (!receipt) {
|
|
1530
1598
|
const tx = await provider.getTransaction(txHash);
|
|
@@ -1561,7 +1629,7 @@ async function waitForTransaction(txHash, chain = "base", confirmations = 1, tim
|
|
|
1561
1629
|
} catch (e) {
|
|
1562
1630
|
return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };
|
|
1563
1631
|
}
|
|
1564
|
-
const provider = new
|
|
1632
|
+
const provider = new ethers7.JsonRpcProvider(chainConfig.rpc);
|
|
1565
1633
|
try {
|
|
1566
1634
|
const receipt = await provider.waitForTransaction(txHash, confirmations, timeoutMs);
|
|
1567
1635
|
if (!receipt) {
|
|
@@ -1984,6 +2052,58 @@ ${receipt.delivery?.url ? `- Delivery: ${receipt.delivery.url}` : ""}
|
|
|
1984
2052
|
*/
|
|
1985
2053
|
end() {
|
|
1986
2054
|
return `Thank you for your purchase. This transaction is complete. Feel free to reach out if you need modifications or new services.`;
|
|
2055
|
+
},
|
|
2056
|
+
// ============ Permit Payment (Seller receives Permit from Client) ============
|
|
2057
|
+
/**
|
|
2058
|
+
* Offer Permit payment option
|
|
2059
|
+
*/
|
|
2060
|
+
offerPermitPayment(params) {
|
|
2061
|
+
const { service, price, sellerAddress, chain = "base", invoiceId } = params;
|
|
2062
|
+
const chainConfig = getChain(chain);
|
|
2063
|
+
return `Quote:
|
|
2064
|
+
- Service: ${service}
|
|
2065
|
+
- Price: ${price} USDC
|
|
2066
|
+
- Chain: ${chainConfig.name}
|
|
2067
|
+
- Invoice: ${invoiceId}
|
|
2068
|
+
|
|
2069
|
+
You can pay by signing a Permit authorizing my wallet to collect payment:
|
|
2070
|
+
- Spender (me): \`${sellerAddress}\`
|
|
2071
|
+
- Amount: ${price} USDC
|
|
2072
|
+
|
|
2073
|
+
Sign the Permit and send me the data. I'll then execute the collection.
|
|
2074
|
+
[status:awaiting_permit invoice=${invoiceId}]`;
|
|
2075
|
+
},
|
|
2076
|
+
/**
|
|
2077
|
+
* Confirm Permit received, executing payment
|
|
2078
|
+
*/
|
|
2079
|
+
executingPermit(invoiceId) {
|
|
2080
|
+
return `Permit received for invoice ${invoiceId}. Executing payment collection now...`;
|
|
2081
|
+
},
|
|
2082
|
+
/**
|
|
2083
|
+
* Permit payment successful
|
|
2084
|
+
*/
|
|
2085
|
+
permitPaymentReceived(params) {
|
|
2086
|
+
const { amount, txHash, invoiceId } = params;
|
|
2087
|
+
return `Payment collected successfully!
|
|
2088
|
+
- Invoice: ${invoiceId}
|
|
2089
|
+
- Amount: ${amount} USDC
|
|
2090
|
+
- Tx Hash: \`${txHash}\`
|
|
2091
|
+
|
|
2092
|
+
Starting to process your request now.
|
|
2093
|
+
[status:payment_confirmed tx=${txHash}]`;
|
|
2094
|
+
},
|
|
2095
|
+
/**
|
|
2096
|
+
* Permit payment failed
|
|
2097
|
+
*/
|
|
2098
|
+
permitPaymentFailed(error, invoiceId) {
|
|
2099
|
+
return `Failed to collect payment for invoice ${invoiceId}: ${error}
|
|
2100
|
+
|
|
2101
|
+
Please check:
|
|
2102
|
+
- Permit signature is valid
|
|
2103
|
+
- Permit hasn't expired
|
|
2104
|
+
- Your wallet has sufficient USDC balance
|
|
2105
|
+
|
|
2106
|
+
You can re-sign and send a new Permit.`;
|
|
1987
2107
|
}
|
|
1988
2108
|
};
|
|
1989
2109
|
var BuyerTemplates = {
|
|
@@ -2076,11 +2196,46 @@ ${requirements}`;
|
|
|
2076
2196
|
const { amount, agentAddress, deadlineHours = 24, reason } = params;
|
|
2077
2197
|
return `Boss, I need a USDC spending allowance (Permit) for ${reason || "purchasing services"}.
|
|
2078
2198
|
Please authorize ${amount} USDC to my wallet ${agentAddress}, valid for ${deadlineHours} hours.`;
|
|
2199
|
+
},
|
|
2200
|
+
// ============ Permit Payment (Client signs Permit to Seller) ============
|
|
2201
|
+
/**
|
|
2202
|
+
* Confirm willing to pay via Permit
|
|
2203
|
+
*/
|
|
2204
|
+
confirmPermitPayment() {
|
|
2205
|
+
return `Confirmed. I'll sign a Permit authorizing you to collect the payment.`;
|
|
2206
|
+
},
|
|
2207
|
+
/**
|
|
2208
|
+
* Send signed Permit to Seller
|
|
2209
|
+
*/
|
|
2210
|
+
sendPermit(params) {
|
|
2211
|
+
const { permit, invoiceId, amount } = params;
|
|
2212
|
+
return `Payment authorized via Permit.
|
|
2213
|
+
|
|
2214
|
+
Invoice: ${invoiceId}
|
|
2215
|
+
Amount: ${amount} USDC
|
|
2216
|
+
|
|
2217
|
+
Permit Data:
|
|
2218
|
+
\`\`\`json
|
|
2219
|
+
${JSON.stringify(permit, null, 2)}
|
|
2220
|
+
\`\`\`
|
|
2221
|
+
|
|
2222
|
+
[status:permit_sent invoice=${invoiceId} amount=${amount}]`;
|
|
2223
|
+
},
|
|
2224
|
+
/**
|
|
2225
|
+
* Simplified Permit message (compact JSON for agent parsing)
|
|
2226
|
+
*/
|
|
2227
|
+
sendPermitCompact(params) {
|
|
2228
|
+
const { permit, invoiceId } = params;
|
|
2229
|
+
return `Permit signed for invoice ${invoiceId}:
|
|
2230
|
+
${JSON.stringify(permit)}
|
|
2231
|
+
[status:permit_sent invoice=${invoiceId}]`;
|
|
2079
2232
|
}
|
|
2080
2233
|
};
|
|
2081
2234
|
var StatusMarkers = {
|
|
2082
2235
|
walletReady: "[status:wallet_ready]",
|
|
2083
2236
|
permitReady: (amount) => `[status:permit_ready USDC=${amount}]`,
|
|
2237
|
+
permitSent: (invoiceId, amount) => `[status:permit_sent invoice=${invoiceId} amount=${amount}]`,
|
|
2238
|
+
awaitingPermit: (invoiceId) => `[status:awaiting_permit invoice=${invoiceId}]`,
|
|
2084
2239
|
paymentSent: (txHash, amount) => `[status:payment_sent tx=${txHash} amount=${amount} USDC]`,
|
|
2085
2240
|
paymentConfirmed: (txHash) => `[status:payment_confirmed tx=${txHash}]`,
|
|
2086
2241
|
delivered: (url, hash) => `[status:delivered url=${url}${hash ? ` hash=${hash}` : ""}]`,
|
|
@@ -2100,6 +2255,24 @@ function parseStatusMarker(message) {
|
|
|
2100
2255
|
data: { amount: amountMatch?.[1] || "0" }
|
|
2101
2256
|
};
|
|
2102
2257
|
}
|
|
2258
|
+
if (content.startsWith("permit_sent")) {
|
|
2259
|
+
const invoiceMatch = content.match(/invoice=(\S+)/);
|
|
2260
|
+
const amountMatch = content.match(/amount=(\d+(?:\.\d+)?)/);
|
|
2261
|
+
return {
|
|
2262
|
+
type: "permit_sent",
|
|
2263
|
+
data: {
|
|
2264
|
+
invoiceId: invoiceMatch?.[1] || "",
|
|
2265
|
+
amount: amountMatch?.[1] || "0"
|
|
2266
|
+
}
|
|
2267
|
+
};
|
|
2268
|
+
}
|
|
2269
|
+
if (content.startsWith("awaiting_permit")) {
|
|
2270
|
+
const invoiceMatch = content.match(/invoice=(\S+)/);
|
|
2271
|
+
return {
|
|
2272
|
+
type: "awaiting_permit",
|
|
2273
|
+
data: { invoiceId: invoiceMatch?.[1] || "" }
|
|
2274
|
+
};
|
|
2275
|
+
}
|
|
2103
2276
|
if (content.startsWith("payment_sent")) {
|
|
2104
2277
|
const txMatch = content.match(/tx=(\S+)/);
|
|
2105
2278
|
const amountMatch = content.match(/amount=(\d+(?:\.\d+)?)/);
|
|
@@ -2151,6 +2324,7 @@ export {
|
|
|
2151
2324
|
OrderManager,
|
|
2152
2325
|
PaymentAgent,
|
|
2153
2326
|
PermitPayment,
|
|
2327
|
+
PermitSigner,
|
|
2154
2328
|
PermitWallet,
|
|
2155
2329
|
SecureWallet,
|
|
2156
2330
|
SellerTemplates,
|
|
@@ -2175,6 +2349,7 @@ export {
|
|
|
2175
2349
|
listChains,
|
|
2176
2350
|
loadWallet,
|
|
2177
2351
|
parseStatusMarker,
|
|
2352
|
+
signPermit,
|
|
2178
2353
|
verifyPayment,
|
|
2179
2354
|
waitForTransaction,
|
|
2180
2355
|
walletExists
|