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/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/permit/Permit.ts
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 ethers5.JsonRpcProvider(rpcUrl);
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 ethers5.Wallet(privateKey, this.provider);
1231
+ this.wallet = new ethers6.Wallet(privateKey, this.provider);
1164
1232
  this.spenderAddress = this.wallet.address;
1165
1233
  }
1166
- this.usdcContract = new ethers5.Contract(
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 ethers6 } from "ethers";
1450
- var TRANSFER_EVENT_TOPIC = ethers6.id("Transfer(address,address,uint256)");
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 ethers6.JsonRpcProvider(chain.rpc);
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 ethers6.JsonRpcProvider(chainConfig.rpc);
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 ethers6.JsonRpcProvider(chainConfig.rpc);
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