moltspay 0.2.1 → 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/chains/index.d.mts +6 -6
- package/dist/chains/index.d.ts +6 -6
- package/dist/chains/index.js +2 -2
- package/dist/chains/index.js.map +1 -1
- package/dist/chains/index.mjs +2 -2
- package/dist/chains/index.mjs.map +1 -1
- package/dist/cli.js +42 -39
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +42 -39
- package/dist/cli.mjs.map +1 -1
- package/dist/{index-CZzgdtin.d.mts → index-CyFg9s2m.d.mts} +1 -1
- package/dist/{index-CZzgdtin.d.ts → index-CyFg9s2m.d.ts} +1 -1
- package/dist/index.d.mts +91 -27
- package/dist/index.d.ts +91 -27
- package/dist/index.js +255 -78
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +253 -78
- package/dist/index.mjs.map +1 -1
- package/dist/orders/index.d.mts +13 -13
- package/dist/orders/index.d.ts +13 -13
- package/dist/orders/index.js +10 -10
- package/dist/orders/index.js.map +1 -1
- package/dist/orders/index.mjs +10 -10
- package/dist/orders/index.mjs.map +1 -1
- package/dist/permit/index.d.mts +11 -11
- package/dist/permit/index.d.ts +11 -11
- package/dist/permit/index.js +14 -14
- package/dist/permit/index.js.map +1 -1
- package/dist/permit/index.mjs +14 -14
- package/dist/permit/index.mjs.map +1 -1
- package/dist/verify/index.d.mts +4 -4
- package/dist/verify/index.d.ts +4 -4
- package/dist/verify/index.js +13 -13
- package/dist/verify/index.js.map +1 -1
- package/dist/verify/index.mjs +13 -13
- package/dist/verify/index.mjs.map +1 -1
- package/dist/wallet/index.d.mts +93 -23
- package/dist/wallet/index.d.ts +93 -23
- package/dist/wallet/index.js +102 -30
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +100 -30
- 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
|
|
@@ -73,7 +75,7 @@ var import_ethers = require("ethers");
|
|
|
73
75
|
|
|
74
76
|
// src/chains/index.ts
|
|
75
77
|
var CHAINS = {
|
|
76
|
-
// ============
|
|
78
|
+
// ============ Mainnet ============
|
|
77
79
|
base: {
|
|
78
80
|
name: "Base",
|
|
79
81
|
chainId: 8453,
|
|
@@ -101,7 +103,7 @@ var CHAINS = {
|
|
|
101
103
|
explorerTx: "https://etherscan.io/tx/",
|
|
102
104
|
avgBlockTime: 12
|
|
103
105
|
},
|
|
104
|
-
// ============
|
|
106
|
+
// ============ Testnet ============
|
|
105
107
|
base_sepolia: {
|
|
106
108
|
name: "Base Sepolia",
|
|
107
109
|
chainId: 84532,
|
|
@@ -172,7 +174,7 @@ var PaymentAgent = class _PaymentAgent {
|
|
|
172
174
|
);
|
|
173
175
|
}
|
|
174
176
|
/**
|
|
175
|
-
*
|
|
177
|
+
* Generate payment request(Invoice)
|
|
176
178
|
*/
|
|
177
179
|
createInvoice(params) {
|
|
178
180
|
const expiresMinutes = params.expiresMinutes || 30;
|
|
@@ -199,14 +201,14 @@ var PaymentAgent = class _PaymentAgent {
|
|
|
199
201
|
return invoice;
|
|
200
202
|
}
|
|
201
203
|
/**
|
|
202
|
-
*
|
|
204
|
+
* Generate wallet deep link(supports MetaMask etc)
|
|
203
205
|
*/
|
|
204
206
|
generateDeepLink(amount, memo) {
|
|
205
207
|
const amountWei = Math.floor(amount * 1e6);
|
|
206
208
|
return `https://metamask.app.link/send/${this.chainConfig.usdc}@${this.chainConfig.chainId}/transfer?address=${this.walletAddress}&uint256=${amountWei}`;
|
|
207
209
|
}
|
|
208
210
|
/**
|
|
209
|
-
*
|
|
211
|
+
* Verify on-chain payment
|
|
210
212
|
*/
|
|
211
213
|
async verifyPayment(txHash, options = {}) {
|
|
212
214
|
try {
|
|
@@ -261,7 +263,7 @@ var PaymentAgent = class _PaymentAgent {
|
|
|
261
263
|
}
|
|
262
264
|
}
|
|
263
265
|
/**
|
|
264
|
-
*
|
|
266
|
+
* Scan recent transfers (match by amount)
|
|
265
267
|
*/
|
|
266
268
|
async scanRecentTransfers(expectedAmount, timeoutMinutes = 30) {
|
|
267
269
|
try {
|
|
@@ -299,7 +301,7 @@ var PaymentAgent = class _PaymentAgent {
|
|
|
299
301
|
}
|
|
300
302
|
}
|
|
301
303
|
/**
|
|
302
|
-
*
|
|
304
|
+
* Get wallet balance
|
|
303
305
|
*/
|
|
304
306
|
async getBalance(address) {
|
|
305
307
|
const addr = address || this.walletAddress;
|
|
@@ -315,7 +317,7 @@ var PaymentAgent = class _PaymentAgent {
|
|
|
315
317
|
};
|
|
316
318
|
}
|
|
317
319
|
/**
|
|
318
|
-
*
|
|
320
|
+
* Format Invoice as human-readable message
|
|
319
321
|
*/
|
|
320
322
|
formatInvoiceMessage(invoice, includeJson = true) {
|
|
321
323
|
let msg = `\u{1F3AC} **Payment Request**
|
|
@@ -377,7 +379,7 @@ var Wallet = class {
|
|
|
377
379
|
);
|
|
378
380
|
}
|
|
379
381
|
/**
|
|
380
|
-
*
|
|
382
|
+
* Get wallet balance
|
|
381
383
|
*/
|
|
382
384
|
async getBalance() {
|
|
383
385
|
const [ethBalance, usdcBalance] = await Promise.all([
|
|
@@ -392,7 +394,7 @@ var Wallet = class {
|
|
|
392
394
|
};
|
|
393
395
|
}
|
|
394
396
|
/**
|
|
395
|
-
*
|
|
397
|
+
* Send USDC transfer
|
|
396
398
|
*/
|
|
397
399
|
async transfer(to, amount) {
|
|
398
400
|
try {
|
|
@@ -433,14 +435,14 @@ var Wallet = class {
|
|
|
433
435
|
}
|
|
434
436
|
}
|
|
435
437
|
/**
|
|
436
|
-
*
|
|
438
|
+
* Get ETH balance
|
|
437
439
|
*/
|
|
438
440
|
async getEthBalance() {
|
|
439
441
|
const balance = await this.provider.getBalance(this.address);
|
|
440
442
|
return import_ethers2.ethers.formatEther(balance);
|
|
441
443
|
}
|
|
442
444
|
/**
|
|
443
|
-
*
|
|
445
|
+
* Get USDC balance
|
|
444
446
|
*/
|
|
445
447
|
async getUsdcBalance() {
|
|
446
448
|
const balance = await this.usdcContract.balanceOf(this.address);
|
|
@@ -461,7 +463,7 @@ var AuditLog = class {
|
|
|
461
463
|
this.loadLastHash();
|
|
462
464
|
}
|
|
463
465
|
/**
|
|
464
|
-
*
|
|
466
|
+
* Record audit log
|
|
465
467
|
*/
|
|
466
468
|
async log(params) {
|
|
467
469
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -478,7 +480,7 @@ var AuditLog = class {
|
|
|
478
480
|
requester: params.requester,
|
|
479
481
|
prev_hash: this.lastHash,
|
|
480
482
|
hash: "",
|
|
481
|
-
//
|
|
483
|
+
// Filled after calculation
|
|
482
484
|
metadata: params.metadata
|
|
483
485
|
};
|
|
484
486
|
entry.hash = this.calculateHash(entry);
|
|
@@ -489,7 +491,7 @@ var AuditLog = class {
|
|
|
489
491
|
return entry;
|
|
490
492
|
}
|
|
491
493
|
/**
|
|
492
|
-
*
|
|
494
|
+
* Read logs for specified date
|
|
493
495
|
*/
|
|
494
496
|
read(date) {
|
|
495
497
|
const filePath = this.getFilePath(date || /* @__PURE__ */ new Date());
|
|
@@ -501,7 +503,7 @@ var AuditLog = class {
|
|
|
501
503
|
return lines.map((line) => JSON.parse(line));
|
|
502
504
|
}
|
|
503
505
|
/**
|
|
504
|
-
*
|
|
506
|
+
* Verify log integrity
|
|
505
507
|
*/
|
|
506
508
|
verify(date) {
|
|
507
509
|
const entries = this.read(date);
|
|
@@ -519,7 +521,7 @@ var AuditLog = class {
|
|
|
519
521
|
return { valid: errors.length === 0, errors };
|
|
520
522
|
}
|
|
521
523
|
/**
|
|
522
|
-
*
|
|
524
|
+
* Search logs
|
|
523
525
|
*/
|
|
524
526
|
search(filter) {
|
|
525
527
|
const results = [];
|
|
@@ -543,14 +545,14 @@ var AuditLog = class {
|
|
|
543
545
|
return results;
|
|
544
546
|
}
|
|
545
547
|
/**
|
|
546
|
-
*
|
|
548
|
+
* Get log file path
|
|
547
549
|
*/
|
|
548
550
|
getFilePath(date) {
|
|
549
551
|
const dateStr = date.toISOString().slice(0, 10);
|
|
550
552
|
return path.join(this.basePath, `audit_${dateStr}.jsonl`);
|
|
551
553
|
}
|
|
552
554
|
/**
|
|
553
|
-
*
|
|
555
|
+
* Calculate entry hash
|
|
554
556
|
*/
|
|
555
557
|
calculateHash(entry) {
|
|
556
558
|
const data = {
|
|
@@ -567,7 +569,7 @@ var AuditLog = class {
|
|
|
567
569
|
return crypto.createHash("sha256").update(str).digest("hex").slice(0, 16);
|
|
568
570
|
}
|
|
569
571
|
/**
|
|
570
|
-
*
|
|
572
|
+
* Load last log entry hash
|
|
571
573
|
*/
|
|
572
574
|
loadLastHash() {
|
|
573
575
|
const today = /* @__PURE__ */ new Date();
|
|
@@ -582,7 +584,7 @@ var AuditLog = class {
|
|
|
582
584
|
}
|
|
583
585
|
}
|
|
584
586
|
/**
|
|
585
|
-
*
|
|
587
|
+
* Ensure directory exists
|
|
586
588
|
*/
|
|
587
589
|
ensureDir() {
|
|
588
590
|
if (!fs.existsSync(this.basePath)) {
|
|
@@ -594,9 +596,9 @@ var AuditLog = class {
|
|
|
594
596
|
// src/wallet/SecureWallet.ts
|
|
595
597
|
var DEFAULT_LIMITS = {
|
|
596
598
|
singleMax: 100,
|
|
597
|
-
//
|
|
599
|
+
// Single max $100
|
|
598
600
|
dailyMax: 1e3,
|
|
599
|
-
//
|
|
601
|
+
// Daily max $1000
|
|
600
602
|
requireWhitelist: true
|
|
601
603
|
};
|
|
602
604
|
var SecureWallet = class {
|
|
@@ -617,21 +619,21 @@ var SecureWallet = class {
|
|
|
617
619
|
this.auditLog = new AuditLog(config.auditPath);
|
|
618
620
|
}
|
|
619
621
|
/**
|
|
620
|
-
*
|
|
622
|
+
* Get wallet address
|
|
621
623
|
*/
|
|
622
624
|
get address() {
|
|
623
625
|
return this.wallet.address;
|
|
624
626
|
}
|
|
625
627
|
/**
|
|
626
|
-
*
|
|
628
|
+
* Get balance
|
|
627
629
|
*/
|
|
628
630
|
async getBalance() {
|
|
629
631
|
return this.wallet.getBalance();
|
|
630
632
|
}
|
|
631
633
|
/**
|
|
632
|
-
*
|
|
634
|
+
* Secure transfer (with limit and whitelist checks)
|
|
633
635
|
*
|
|
634
|
-
*
|
|
636
|
+
* Supports two calling methods:
|
|
635
637
|
* - transfer({ to, amount, reason?, requester? })
|
|
636
638
|
* - transfer(to, amount)
|
|
637
639
|
*/
|
|
@@ -731,7 +733,7 @@ var SecureWallet = class {
|
|
|
731
733
|
return result;
|
|
732
734
|
}
|
|
733
735
|
/**
|
|
734
|
-
*
|
|
736
|
+
* Approve pending transfer
|
|
735
737
|
*/
|
|
736
738
|
async approve(requestId, approver) {
|
|
737
739
|
const pending = this.pendingTransfers.get(requestId);
|
|
@@ -772,7 +774,7 @@ var SecureWallet = class {
|
|
|
772
774
|
return result;
|
|
773
775
|
}
|
|
774
776
|
/**
|
|
775
|
-
*
|
|
777
|
+
* Reject pending transfer
|
|
776
778
|
*/
|
|
777
779
|
async reject(requestId, rejecter, reason) {
|
|
778
780
|
const pending = this.pendingTransfers.get(requestId);
|
|
@@ -787,7 +789,7 @@ var SecureWallet = class {
|
|
|
787
789
|
});
|
|
788
790
|
}
|
|
789
791
|
/**
|
|
790
|
-
*
|
|
792
|
+
* Add to whitelist
|
|
791
793
|
*/
|
|
792
794
|
async addToWhitelist(address, addedBy) {
|
|
793
795
|
const addr = address.toLowerCase();
|
|
@@ -800,7 +802,7 @@ var SecureWallet = class {
|
|
|
800
802
|
});
|
|
801
803
|
}
|
|
802
804
|
/**
|
|
803
|
-
*
|
|
805
|
+
* Remove from whitelist
|
|
804
806
|
*/
|
|
805
807
|
async removeFromWhitelist(address, removedBy) {
|
|
806
808
|
const addr = address.toLowerCase();
|
|
@@ -813,32 +815,32 @@ var SecureWallet = class {
|
|
|
813
815
|
});
|
|
814
816
|
}
|
|
815
817
|
/**
|
|
816
|
-
*
|
|
818
|
+
* Check if address is whitelisted
|
|
817
819
|
*/
|
|
818
820
|
isWhitelisted(address) {
|
|
819
821
|
return this.whitelist.has(address.toLowerCase());
|
|
820
822
|
}
|
|
821
823
|
/**
|
|
822
|
-
*
|
|
824
|
+
* Get pending transfers list
|
|
823
825
|
*/
|
|
824
826
|
getPendingTransfers() {
|
|
825
827
|
return Array.from(this.pendingTransfers.values()).filter((p) => p.status === "pending");
|
|
826
828
|
}
|
|
827
829
|
/**
|
|
828
|
-
*
|
|
830
|
+
* Get current limit config
|
|
829
831
|
*/
|
|
830
832
|
getLimits() {
|
|
831
833
|
return { ...this.limits };
|
|
832
834
|
}
|
|
833
835
|
/**
|
|
834
|
-
*
|
|
836
|
+
* Get daily used amount
|
|
835
837
|
*/
|
|
836
838
|
getDailyUsed() {
|
|
837
839
|
this.updateDailyTotal();
|
|
838
840
|
return this.dailyTotal;
|
|
839
841
|
}
|
|
840
842
|
/**
|
|
841
|
-
*
|
|
843
|
+
* Update daily limit counter
|
|
842
844
|
*/
|
|
843
845
|
updateDailyTotal() {
|
|
844
846
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -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,26 +1297,26 @@ 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
|
|
1240
1310
|
);
|
|
1241
1311
|
}
|
|
1242
1312
|
/**
|
|
1243
|
-
*
|
|
1313
|
+
* Get user current nonce
|
|
1244
1314
|
*/
|
|
1245
1315
|
async getNonce(owner) {
|
|
1246
1316
|
return Number(await this.usdcContract.nonces(owner));
|
|
1247
1317
|
}
|
|
1248
1318
|
/**
|
|
1249
|
-
*
|
|
1319
|
+
* Generate EIP-712 signing request (for frontend/user wallet)
|
|
1250
1320
|
*/
|
|
1251
1321
|
async createPermitRequest(owner, amount, orderId, deadlineMinutes = 30) {
|
|
1252
1322
|
const nonce = await this.getNonce(owner);
|
|
@@ -1294,11 +1364,11 @@ var PermitPayment = class {
|
|
|
1294
1364
|
};
|
|
1295
1365
|
}
|
|
1296
1366
|
/**
|
|
1297
|
-
*
|
|
1367
|
+
* Execute permit + transferFrom
|
|
1298
1368
|
*
|
|
1299
|
-
* @param owner
|
|
1300
|
-
* @param amount
|
|
1301
|
-
* @param signature
|
|
1369
|
+
* @param owner User address
|
|
1370
|
+
* @param amount Amount
|
|
1371
|
+
* @param signature User signature {v, r, s, deadline}
|
|
1302
1372
|
*/
|
|
1303
1373
|
async executePermitAndTransfer(owner, amount, signature) {
|
|
1304
1374
|
if (!this.wallet) {
|
|
@@ -1330,7 +1400,7 @@ var PermitPayment = class {
|
|
|
1330
1400
|
}
|
|
1331
1401
|
}
|
|
1332
1402
|
/**
|
|
1333
|
-
*
|
|
1403
|
+
* Execute permit only (no transfer)
|
|
1334
1404
|
*/
|
|
1335
1405
|
async executePermit(owner, amount, signature) {
|
|
1336
1406
|
if (!this.wallet) {
|
|
@@ -1360,22 +1430,22 @@ var PermitPayment = class {
|
|
|
1360
1430
|
}
|
|
1361
1431
|
}
|
|
1362
1432
|
/**
|
|
1363
|
-
*
|
|
1433
|
+
* Format Permit request as user message
|
|
1364
1434
|
*/
|
|
1365
1435
|
formatPermitMessage(request) {
|
|
1366
1436
|
const { typed_data } = request;
|
|
1367
1437
|
const { message } = typed_data;
|
|
1368
|
-
return `\u{1F510}
|
|
1438
|
+
return `\u{1F510} **Signature Authorization Request**
|
|
1369
1439
|
|
|
1370
|
-
|
|
1440
|
+
Authorize \`${(Number(message.value) / 1e6).toFixed(2)} USDC\` to service provider
|
|
1371
1441
|
|
|
1372
|
-
|
|
1442
|
+
**Signature Details:**
|
|
1373
1443
|
- Owner: \`${message.owner}\`
|
|
1374
1444
|
- Spender: \`${message.spender}\`
|
|
1375
1445
|
- Amount: ${(Number(message.value) / 1e6).toFixed(2)} USDC
|
|
1376
1446
|
- Deadline: ${new Date(message.deadline * 1e3).toISOString()}
|
|
1377
1447
|
|
|
1378
|
-
|
|
1448
|
+
Please sign this request in your wallet (no gas required).
|
|
1379
1449
|
|
|
1380
1450
|
\`\`\`json
|
|
1381
1451
|
${JSON.stringify(typed_data, null, 2)}
|
|
@@ -1420,13 +1490,13 @@ var OrderManager = class {
|
|
|
1420
1490
|
this.defaultChain = options.defaultChain || "base";
|
|
1421
1491
|
}
|
|
1422
1492
|
/**
|
|
1423
|
-
*
|
|
1493
|
+
* Generate order ID
|
|
1424
1494
|
*/
|
|
1425
1495
|
generateOrderId() {
|
|
1426
1496
|
return "vo_" + (0, import_crypto2.randomBytes)(4).toString("hex");
|
|
1427
1497
|
}
|
|
1428
1498
|
/**
|
|
1429
|
-
*
|
|
1499
|
+
* Create order
|
|
1430
1500
|
*/
|
|
1431
1501
|
async createOrder(params) {
|
|
1432
1502
|
const order = {
|
|
@@ -1443,13 +1513,13 @@ var OrderManager = class {
|
|
|
1443
1513
|
return order;
|
|
1444
1514
|
}
|
|
1445
1515
|
/**
|
|
1446
|
-
*
|
|
1516
|
+
* Get order
|
|
1447
1517
|
*/
|
|
1448
1518
|
async getOrder(orderId) {
|
|
1449
1519
|
return this.store.get(orderId);
|
|
1450
1520
|
}
|
|
1451
1521
|
/**
|
|
1452
|
-
*
|
|
1522
|
+
* Update order
|
|
1453
1523
|
*/
|
|
1454
1524
|
async updateOrder(orderId, updates) {
|
|
1455
1525
|
const order = await this.store.get(orderId);
|
|
@@ -1459,7 +1529,7 @@ var OrderManager = class {
|
|
|
1459
1529
|
return updated;
|
|
1460
1530
|
}
|
|
1461
1531
|
/**
|
|
1462
|
-
*
|
|
1532
|
+
* Find user pending orders
|
|
1463
1533
|
*/
|
|
1464
1534
|
async findPendingOrder(userId) {
|
|
1465
1535
|
const orders = await this.store.findByUser(userId, "pending");
|
|
@@ -1473,7 +1543,7 @@ var OrderManager = class {
|
|
|
1473
1543
|
return null;
|
|
1474
1544
|
}
|
|
1475
1545
|
/**
|
|
1476
|
-
*
|
|
1546
|
+
* Mark order as paid
|
|
1477
1547
|
*/
|
|
1478
1548
|
async markAsPaid(orderId, txHash, payerAddress) {
|
|
1479
1549
|
return this.updateOrder(orderId, {
|
|
@@ -1484,13 +1554,13 @@ var OrderManager = class {
|
|
|
1484
1554
|
});
|
|
1485
1555
|
}
|
|
1486
1556
|
/**
|
|
1487
|
-
*
|
|
1557
|
+
* Mark order as generating
|
|
1488
1558
|
*/
|
|
1489
1559
|
async markAsGenerating(orderId) {
|
|
1490
1560
|
return this.updateOrder(orderId, { status: "generating" });
|
|
1491
1561
|
}
|
|
1492
1562
|
/**
|
|
1493
|
-
*
|
|
1563
|
+
* Mark order as completed
|
|
1494
1564
|
*/
|
|
1495
1565
|
async markAsCompleted(orderId, videoPath) {
|
|
1496
1566
|
return this.updateOrder(orderId, {
|
|
@@ -1499,7 +1569,7 @@ var OrderManager = class {
|
|
|
1499
1569
|
});
|
|
1500
1570
|
}
|
|
1501
1571
|
/**
|
|
1502
|
-
*
|
|
1572
|
+
* Mark order as failed
|
|
1503
1573
|
*/
|
|
1504
1574
|
async markAsFailed(orderId, error) {
|
|
1505
1575
|
return this.updateOrder(orderId, {
|
|
@@ -1508,7 +1578,7 @@ var OrderManager = class {
|
|
|
1508
1578
|
});
|
|
1509
1579
|
}
|
|
1510
1580
|
/**
|
|
1511
|
-
*
|
|
1581
|
+
* Cancel order
|
|
1512
1582
|
*/
|
|
1513
1583
|
async cancelOrder(orderId) {
|
|
1514
1584
|
return this.updateOrder(orderId, { status: "cancelled" });
|
|
@@ -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;
|
|
@@ -1528,23 +1598,23 @@ async function verifyPayment(params) {
|
|
|
1528
1598
|
chain = getChain(params.chain || "base");
|
|
1529
1599
|
}
|
|
1530
1600
|
if (!chain) {
|
|
1531
|
-
return { verified: false, error:
|
|
1601
|
+
return { verified: false, error: `Unsupported chain: ${params.chain}` };
|
|
1532
1602
|
}
|
|
1533
1603
|
} catch (e) {
|
|
1534
|
-
return { verified: false, error:
|
|
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
|
-
return { verified: false, error: "
|
|
1610
|
+
return { verified: false, error: "Transaction not found or not confirmed" };
|
|
1541
1611
|
}
|
|
1542
1612
|
if (receipt.status !== 1) {
|
|
1543
|
-
return { verified: false, error: "
|
|
1613
|
+
return { verified: false, error: "Transaction failed" };
|
|
1544
1614
|
}
|
|
1545
1615
|
const usdcAddress = chain.usdc?.toLowerCase();
|
|
1546
1616
|
if (!usdcAddress) {
|
|
1547
|
-
return { verified: false, error:
|
|
1617
|
+
return { verified: false, error: `Chain ${chain.name} USDC address not configured` };
|
|
1548
1618
|
}
|
|
1549
1619
|
for (const log of receipt.logs) {
|
|
1550
1620
|
if (log.address.toLowerCase() !== usdcAddress) {
|
|
@@ -1563,7 +1633,7 @@ async function verifyPayment(params) {
|
|
|
1563
1633
|
if (amount < expectedAmount) {
|
|
1564
1634
|
return {
|
|
1565
1635
|
verified: false,
|
|
1566
|
-
error:
|
|
1636
|
+
error: `Insufficient amount: received ${amount} USDC, expected ${expectedAmount} USDC`,
|
|
1567
1637
|
amount,
|
|
1568
1638
|
from,
|
|
1569
1639
|
to,
|
|
@@ -1580,7 +1650,7 @@ async function verifyPayment(params) {
|
|
|
1580
1650
|
blockNumber: receipt.blockNumber
|
|
1581
1651
|
};
|
|
1582
1652
|
}
|
|
1583
|
-
return { verified: false, error: "
|
|
1653
|
+
return { verified: false, error: "No USDC transfer found" };
|
|
1584
1654
|
} catch (e) {
|
|
1585
1655
|
return { verified: false, error: e.message || String(e) };
|
|
1586
1656
|
}
|
|
@@ -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);
|
|
@@ -1626,19 +1696,19 @@ async function waitForTransaction(txHash, chain = "base", confirmations = 1, tim
|
|
|
1626
1696
|
try {
|
|
1627
1697
|
chainConfig = typeof chain === "number" ? getChainById(chain) : getChain(chain);
|
|
1628
1698
|
if (!chainConfig) {
|
|
1629
|
-
return { verified: false, confirmed: false, error:
|
|
1699
|
+
return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };
|
|
1630
1700
|
}
|
|
1631
1701
|
} catch (e) {
|
|
1632
|
-
return { verified: false, confirmed: false, error:
|
|
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) {
|
|
1638
|
-
return { verified: false, confirmed: false, error: "
|
|
1708
|
+
return { verified: false, confirmed: false, error: "Timeout waiting" };
|
|
1639
1709
|
}
|
|
1640
1710
|
if (receipt.status !== 1) {
|
|
1641
|
-
return { verified: false, confirmed: true, error: "
|
|
1711
|
+
return { verified: false, confirmed: true, error: "Transaction failed" };
|
|
1642
1712
|
}
|
|
1643
1713
|
return {
|
|
1644
1714
|
verified: true,
|
|
@@ -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
|