moltspay 0.2.0 → 0.2.2
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 +36 -36
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +36 -36
- package/dist/cli.mjs.map +1 -1
- package/dist/guide/index.d.mts +7 -7
- package/dist/guide/index.d.ts +7 -7
- package/dist/guide/index.js +50 -50
- package/dist/guide/index.js.map +1 -1
- package/dist/guide/index.mjs +50 -50
- package/dist/guide/index.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 +89 -89
- package/dist/index.d.ts +89 -89
- package/dist/index.js +275 -275
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +275 -275
- 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 +72 -72
- package/dist/wallet/index.d.ts +72 -72
- package/dist/wallet/index.js +48 -48
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +48 -48
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -73,7 +73,7 @@ var import_ethers = require("ethers");
|
|
|
73
73
|
|
|
74
74
|
// src/chains/index.ts
|
|
75
75
|
var CHAINS = {
|
|
76
|
-
// ============
|
|
76
|
+
// ============ Mainnet ============
|
|
77
77
|
base: {
|
|
78
78
|
name: "Base",
|
|
79
79
|
chainId: 8453,
|
|
@@ -101,7 +101,7 @@ var CHAINS = {
|
|
|
101
101
|
explorerTx: "https://etherscan.io/tx/",
|
|
102
102
|
avgBlockTime: 12
|
|
103
103
|
},
|
|
104
|
-
// ============
|
|
104
|
+
// ============ Testnet ============
|
|
105
105
|
base_sepolia: {
|
|
106
106
|
name: "Base Sepolia",
|
|
107
107
|
chainId: 84532,
|
|
@@ -172,7 +172,7 @@ var PaymentAgent = class _PaymentAgent {
|
|
|
172
172
|
);
|
|
173
173
|
}
|
|
174
174
|
/**
|
|
175
|
-
*
|
|
175
|
+
* Generate payment request(Invoice)
|
|
176
176
|
*/
|
|
177
177
|
createInvoice(params) {
|
|
178
178
|
const expiresMinutes = params.expiresMinutes || 30;
|
|
@@ -199,14 +199,14 @@ var PaymentAgent = class _PaymentAgent {
|
|
|
199
199
|
return invoice;
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
202
|
-
*
|
|
202
|
+
* Generate wallet deep link(supports MetaMask etc)
|
|
203
203
|
*/
|
|
204
204
|
generateDeepLink(amount, memo) {
|
|
205
205
|
const amountWei = Math.floor(amount * 1e6);
|
|
206
206
|
return `https://metamask.app.link/send/${this.chainConfig.usdc}@${this.chainConfig.chainId}/transfer?address=${this.walletAddress}&uint256=${amountWei}`;
|
|
207
207
|
}
|
|
208
208
|
/**
|
|
209
|
-
*
|
|
209
|
+
* Verify on-chain payment
|
|
210
210
|
*/
|
|
211
211
|
async verifyPayment(txHash, options = {}) {
|
|
212
212
|
try {
|
|
@@ -261,7 +261,7 @@ var PaymentAgent = class _PaymentAgent {
|
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
/**
|
|
264
|
-
*
|
|
264
|
+
* Scan recent transfers (match by amount)
|
|
265
265
|
*/
|
|
266
266
|
async scanRecentTransfers(expectedAmount, timeoutMinutes = 30) {
|
|
267
267
|
try {
|
|
@@ -299,7 +299,7 @@ var PaymentAgent = class _PaymentAgent {
|
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
/**
|
|
302
|
-
*
|
|
302
|
+
* Get wallet balance
|
|
303
303
|
*/
|
|
304
304
|
async getBalance(address) {
|
|
305
305
|
const addr = address || this.walletAddress;
|
|
@@ -315,7 +315,7 @@ var PaymentAgent = class _PaymentAgent {
|
|
|
315
315
|
};
|
|
316
316
|
}
|
|
317
317
|
/**
|
|
318
|
-
*
|
|
318
|
+
* Format Invoice as human-readable message
|
|
319
319
|
*/
|
|
320
320
|
formatInvoiceMessage(invoice, includeJson = true) {
|
|
321
321
|
let msg = `\u{1F3AC} **Payment Request**
|
|
@@ -377,7 +377,7 @@ var Wallet = class {
|
|
|
377
377
|
);
|
|
378
378
|
}
|
|
379
379
|
/**
|
|
380
|
-
*
|
|
380
|
+
* Get wallet balance
|
|
381
381
|
*/
|
|
382
382
|
async getBalance() {
|
|
383
383
|
const [ethBalance, usdcBalance] = await Promise.all([
|
|
@@ -392,7 +392,7 @@ var Wallet = class {
|
|
|
392
392
|
};
|
|
393
393
|
}
|
|
394
394
|
/**
|
|
395
|
-
*
|
|
395
|
+
* Send USDC transfer
|
|
396
396
|
*/
|
|
397
397
|
async transfer(to, amount) {
|
|
398
398
|
try {
|
|
@@ -433,14 +433,14 @@ var Wallet = class {
|
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
435
|
/**
|
|
436
|
-
*
|
|
436
|
+
* Get ETH balance
|
|
437
437
|
*/
|
|
438
438
|
async getEthBalance() {
|
|
439
439
|
const balance = await this.provider.getBalance(this.address);
|
|
440
440
|
return import_ethers2.ethers.formatEther(balance);
|
|
441
441
|
}
|
|
442
442
|
/**
|
|
443
|
-
*
|
|
443
|
+
* Get USDC balance
|
|
444
444
|
*/
|
|
445
445
|
async getUsdcBalance() {
|
|
446
446
|
const balance = await this.usdcContract.balanceOf(this.address);
|
|
@@ -461,7 +461,7 @@ var AuditLog = class {
|
|
|
461
461
|
this.loadLastHash();
|
|
462
462
|
}
|
|
463
463
|
/**
|
|
464
|
-
*
|
|
464
|
+
* Record audit log
|
|
465
465
|
*/
|
|
466
466
|
async log(params) {
|
|
467
467
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -478,7 +478,7 @@ var AuditLog = class {
|
|
|
478
478
|
requester: params.requester,
|
|
479
479
|
prev_hash: this.lastHash,
|
|
480
480
|
hash: "",
|
|
481
|
-
//
|
|
481
|
+
// Filled after calculation
|
|
482
482
|
metadata: params.metadata
|
|
483
483
|
};
|
|
484
484
|
entry.hash = this.calculateHash(entry);
|
|
@@ -489,7 +489,7 @@ var AuditLog = class {
|
|
|
489
489
|
return entry;
|
|
490
490
|
}
|
|
491
491
|
/**
|
|
492
|
-
*
|
|
492
|
+
* Read logs for specified date
|
|
493
493
|
*/
|
|
494
494
|
read(date) {
|
|
495
495
|
const filePath = this.getFilePath(date || /* @__PURE__ */ new Date());
|
|
@@ -501,7 +501,7 @@ var AuditLog = class {
|
|
|
501
501
|
return lines.map((line) => JSON.parse(line));
|
|
502
502
|
}
|
|
503
503
|
/**
|
|
504
|
-
*
|
|
504
|
+
* Verify log integrity
|
|
505
505
|
*/
|
|
506
506
|
verify(date) {
|
|
507
507
|
const entries = this.read(date);
|
|
@@ -519,7 +519,7 @@ var AuditLog = class {
|
|
|
519
519
|
return { valid: errors.length === 0, errors };
|
|
520
520
|
}
|
|
521
521
|
/**
|
|
522
|
-
*
|
|
522
|
+
* Search logs
|
|
523
523
|
*/
|
|
524
524
|
search(filter) {
|
|
525
525
|
const results = [];
|
|
@@ -543,14 +543,14 @@ var AuditLog = class {
|
|
|
543
543
|
return results;
|
|
544
544
|
}
|
|
545
545
|
/**
|
|
546
|
-
*
|
|
546
|
+
* Get log file path
|
|
547
547
|
*/
|
|
548
548
|
getFilePath(date) {
|
|
549
549
|
const dateStr = date.toISOString().slice(0, 10);
|
|
550
550
|
return path.join(this.basePath, `audit_${dateStr}.jsonl`);
|
|
551
551
|
}
|
|
552
552
|
/**
|
|
553
|
-
*
|
|
553
|
+
* Calculate entry hash
|
|
554
554
|
*/
|
|
555
555
|
calculateHash(entry) {
|
|
556
556
|
const data = {
|
|
@@ -567,7 +567,7 @@ var AuditLog = class {
|
|
|
567
567
|
return crypto.createHash("sha256").update(str).digest("hex").slice(0, 16);
|
|
568
568
|
}
|
|
569
569
|
/**
|
|
570
|
-
*
|
|
570
|
+
* Load last log entry hash
|
|
571
571
|
*/
|
|
572
572
|
loadLastHash() {
|
|
573
573
|
const today = /* @__PURE__ */ new Date();
|
|
@@ -582,7 +582,7 @@ var AuditLog = class {
|
|
|
582
582
|
}
|
|
583
583
|
}
|
|
584
584
|
/**
|
|
585
|
-
*
|
|
585
|
+
* Ensure directory exists
|
|
586
586
|
*/
|
|
587
587
|
ensureDir() {
|
|
588
588
|
if (!fs.existsSync(this.basePath)) {
|
|
@@ -594,9 +594,9 @@ var AuditLog = class {
|
|
|
594
594
|
// src/wallet/SecureWallet.ts
|
|
595
595
|
var DEFAULT_LIMITS = {
|
|
596
596
|
singleMax: 100,
|
|
597
|
-
//
|
|
597
|
+
// Single max $100
|
|
598
598
|
dailyMax: 1e3,
|
|
599
|
-
//
|
|
599
|
+
// Daily max $1000
|
|
600
600
|
requireWhitelist: true
|
|
601
601
|
};
|
|
602
602
|
var SecureWallet = class {
|
|
@@ -617,21 +617,21 @@ var SecureWallet = class {
|
|
|
617
617
|
this.auditLog = new AuditLog(config.auditPath);
|
|
618
618
|
}
|
|
619
619
|
/**
|
|
620
|
-
*
|
|
620
|
+
* Get wallet address
|
|
621
621
|
*/
|
|
622
622
|
get address() {
|
|
623
623
|
return this.wallet.address;
|
|
624
624
|
}
|
|
625
625
|
/**
|
|
626
|
-
*
|
|
626
|
+
* Get balance
|
|
627
627
|
*/
|
|
628
628
|
async getBalance() {
|
|
629
629
|
return this.wallet.getBalance();
|
|
630
630
|
}
|
|
631
631
|
/**
|
|
632
|
-
*
|
|
632
|
+
* Secure transfer (with limit and whitelist checks)
|
|
633
633
|
*
|
|
634
|
-
*
|
|
634
|
+
* Supports two calling methods:
|
|
635
635
|
* - transfer({ to, amount, reason?, requester? })
|
|
636
636
|
* - transfer(to, amount)
|
|
637
637
|
*/
|
|
@@ -731,7 +731,7 @@ var SecureWallet = class {
|
|
|
731
731
|
return result;
|
|
732
732
|
}
|
|
733
733
|
/**
|
|
734
|
-
*
|
|
734
|
+
* Approve pending transfer
|
|
735
735
|
*/
|
|
736
736
|
async approve(requestId, approver) {
|
|
737
737
|
const pending = this.pendingTransfers.get(requestId);
|
|
@@ -772,7 +772,7 @@ var SecureWallet = class {
|
|
|
772
772
|
return result;
|
|
773
773
|
}
|
|
774
774
|
/**
|
|
775
|
-
*
|
|
775
|
+
* Reject pending transfer
|
|
776
776
|
*/
|
|
777
777
|
async reject(requestId, rejecter, reason) {
|
|
778
778
|
const pending = this.pendingTransfers.get(requestId);
|
|
@@ -787,7 +787,7 @@ var SecureWallet = class {
|
|
|
787
787
|
});
|
|
788
788
|
}
|
|
789
789
|
/**
|
|
790
|
-
*
|
|
790
|
+
* Add to whitelist
|
|
791
791
|
*/
|
|
792
792
|
async addToWhitelist(address, addedBy) {
|
|
793
793
|
const addr = address.toLowerCase();
|
|
@@ -800,7 +800,7 @@ var SecureWallet = class {
|
|
|
800
800
|
});
|
|
801
801
|
}
|
|
802
802
|
/**
|
|
803
|
-
*
|
|
803
|
+
* Remove from whitelist
|
|
804
804
|
*/
|
|
805
805
|
async removeFromWhitelist(address, removedBy) {
|
|
806
806
|
const addr = address.toLowerCase();
|
|
@@ -813,32 +813,32 @@ var SecureWallet = class {
|
|
|
813
813
|
});
|
|
814
814
|
}
|
|
815
815
|
/**
|
|
816
|
-
*
|
|
816
|
+
* Check if address is whitelisted
|
|
817
817
|
*/
|
|
818
818
|
isWhitelisted(address) {
|
|
819
819
|
return this.whitelist.has(address.toLowerCase());
|
|
820
820
|
}
|
|
821
821
|
/**
|
|
822
|
-
*
|
|
822
|
+
* Get pending transfers list
|
|
823
823
|
*/
|
|
824
824
|
getPendingTransfers() {
|
|
825
825
|
return Array.from(this.pendingTransfers.values()).filter((p) => p.status === "pending");
|
|
826
826
|
}
|
|
827
827
|
/**
|
|
828
|
-
*
|
|
828
|
+
* Get current limit config
|
|
829
829
|
*/
|
|
830
830
|
getLimits() {
|
|
831
831
|
return { ...this.limits };
|
|
832
832
|
}
|
|
833
833
|
/**
|
|
834
|
-
*
|
|
834
|
+
* Get daily used amount
|
|
835
835
|
*/
|
|
836
836
|
getDailyUsed() {
|
|
837
837
|
this.updateDailyTotal();
|
|
838
838
|
return this.dailyTotal;
|
|
839
839
|
}
|
|
840
840
|
/**
|
|
841
|
-
*
|
|
841
|
+
* Update daily limit counter
|
|
842
842
|
*/
|
|
843
843
|
updateDailyTotal() {
|
|
844
844
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -1009,24 +1009,24 @@ var PermitWallet = class {
|
|
|
1009
1009
|
);
|
|
1010
1010
|
}
|
|
1011
1011
|
/**
|
|
1012
|
-
*
|
|
1012
|
+
* Check if Permit is valid (current allowance)
|
|
1013
1013
|
*/
|
|
1014
1014
|
async checkPermitAllowance(owner) {
|
|
1015
1015
|
const allowance = await this.usdcContract.allowance(owner, this.address);
|
|
1016
1016
|
return (Number(allowance) / 1e6).toFixed(2);
|
|
1017
1017
|
}
|
|
1018
1018
|
/**
|
|
1019
|
-
*
|
|
1019
|
+
* Pay using Permit authorization
|
|
1020
1020
|
*
|
|
1021
|
-
*
|
|
1022
|
-
* 1.
|
|
1023
|
-
* 2.
|
|
1021
|
+
* Flow:
|
|
1022
|
+
* 1. Call permit() to record Boss's authorization in the contract
|
|
1023
|
+
* 2. Call transferFrom() to transfer from Boss's wallet to recipient
|
|
1024
1024
|
*
|
|
1025
1025
|
* @example
|
|
1026
1026
|
* ```typescript
|
|
1027
1027
|
* const wallet = new PermitWallet({ chain: 'base' });
|
|
1028
1028
|
*
|
|
1029
|
-
* // Boss
|
|
1029
|
+
* // Boss-signed permit data
|
|
1030
1030
|
* const permit = {
|
|
1031
1031
|
* owner: '0xBOSS...',
|
|
1032
1032
|
* spender: wallet.address,
|
|
@@ -1149,14 +1149,14 @@ var PermitWallet = class {
|
|
|
1149
1149
|
}
|
|
1150
1150
|
}
|
|
1151
1151
|
/**
|
|
1152
|
-
*
|
|
1152
|
+
* Get ETH balance (for gas)
|
|
1153
1153
|
*/
|
|
1154
1154
|
async getGasBalance() {
|
|
1155
1155
|
const balance = await this.provider.getBalance(this.address);
|
|
1156
1156
|
return import_ethers4.ethers.formatEther(balance);
|
|
1157
1157
|
}
|
|
1158
1158
|
/**
|
|
1159
|
-
*
|
|
1159
|
+
* Check if there's enough gas
|
|
1160
1160
|
*/
|
|
1161
1161
|
async hasEnoughGas(minEth = 1e-3) {
|
|
1162
1162
|
const balance = await this.getGasBalance();
|
|
@@ -1168,17 +1168,17 @@ function formatPermitRequest(params) {
|
|
|
1168
1168
|
const chainConfig = getChain(chain);
|
|
1169
1169
|
const deadline = Math.floor(Date.now() / 1e3) + deadlineHours * 3600;
|
|
1170
1170
|
const value = BigInt(Math.floor(amount * 1e6)).toString();
|
|
1171
|
-
return `\u{1F510} **USDC
|
|
1171
|
+
return `\u{1F510} **USDC Spending Allowance Request**
|
|
1172
1172
|
|
|
1173
|
-
${reason ?
|
|
1173
|
+
${reason ? `**Purpose:** ${reason}
|
|
1174
1174
|
` : ""}
|
|
1175
|
-
|
|
1176
|
-
-
|
|
1177
|
-
-
|
|
1178
|
-
-
|
|
1179
|
-
-
|
|
1175
|
+
**Authorization Details:**
|
|
1176
|
+
- Authorized address (Agent): \`${agentAddress}\`
|
|
1177
|
+
- Amount: ${amount} USDC
|
|
1178
|
+
- Valid for: ${deadlineHours} hours
|
|
1179
|
+
- Chain: ${chainConfig.name}
|
|
1180
1180
|
|
|
1181
|
-
|
|
1181
|
+
**Please sign the following EIP-2612 Permit with your wallet:**
|
|
1182
1182
|
|
|
1183
1183
|
\`\`\`json
|
|
1184
1184
|
{
|
|
@@ -1208,9 +1208,9 @@ ${reason ? `**\u7528\u9014:** ${reason}
|
|
|
1208
1208
|
}
|
|
1209
1209
|
\`\`\`
|
|
1210
1210
|
|
|
1211
|
-
|
|
1211
|
+
After signing, send { v, r, s, deadline } to the Agent.
|
|
1212
1212
|
|
|
1213
|
-
\u26A0\uFE0F
|
|
1213
|
+
\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
1214
|
}
|
|
1215
1215
|
|
|
1216
1216
|
// src/permit/Permit.ts
|
|
@@ -1240,13 +1240,13 @@ var PermitPayment = class {
|
|
|
1240
1240
|
);
|
|
1241
1241
|
}
|
|
1242
1242
|
/**
|
|
1243
|
-
*
|
|
1243
|
+
* Get user current nonce
|
|
1244
1244
|
*/
|
|
1245
1245
|
async getNonce(owner) {
|
|
1246
1246
|
return Number(await this.usdcContract.nonces(owner));
|
|
1247
1247
|
}
|
|
1248
1248
|
/**
|
|
1249
|
-
*
|
|
1249
|
+
* Generate EIP-712 signing request (for frontend/user wallet)
|
|
1250
1250
|
*/
|
|
1251
1251
|
async createPermitRequest(owner, amount, orderId, deadlineMinutes = 30) {
|
|
1252
1252
|
const nonce = await this.getNonce(owner);
|
|
@@ -1294,11 +1294,11 @@ var PermitPayment = class {
|
|
|
1294
1294
|
};
|
|
1295
1295
|
}
|
|
1296
1296
|
/**
|
|
1297
|
-
*
|
|
1297
|
+
* Execute permit + transferFrom
|
|
1298
1298
|
*
|
|
1299
|
-
* @param owner
|
|
1300
|
-
* @param amount
|
|
1301
|
-
* @param signature
|
|
1299
|
+
* @param owner User address
|
|
1300
|
+
* @param amount Amount
|
|
1301
|
+
* @param signature User signature {v, r, s, deadline}
|
|
1302
1302
|
*/
|
|
1303
1303
|
async executePermitAndTransfer(owner, amount, signature) {
|
|
1304
1304
|
if (!this.wallet) {
|
|
@@ -1330,7 +1330,7 @@ var PermitPayment = class {
|
|
|
1330
1330
|
}
|
|
1331
1331
|
}
|
|
1332
1332
|
/**
|
|
1333
|
-
*
|
|
1333
|
+
* Execute permit only (no transfer)
|
|
1334
1334
|
*/
|
|
1335
1335
|
async executePermit(owner, amount, signature) {
|
|
1336
1336
|
if (!this.wallet) {
|
|
@@ -1360,22 +1360,22 @@ var PermitPayment = class {
|
|
|
1360
1360
|
}
|
|
1361
1361
|
}
|
|
1362
1362
|
/**
|
|
1363
|
-
*
|
|
1363
|
+
* Format Permit request as user message
|
|
1364
1364
|
*/
|
|
1365
1365
|
formatPermitMessage(request) {
|
|
1366
1366
|
const { typed_data } = request;
|
|
1367
1367
|
const { message } = typed_data;
|
|
1368
|
-
return `\u{1F510}
|
|
1368
|
+
return `\u{1F510} **Signature Authorization Request**
|
|
1369
1369
|
|
|
1370
|
-
|
|
1370
|
+
Authorize \`${(Number(message.value) / 1e6).toFixed(2)} USDC\` to service provider
|
|
1371
1371
|
|
|
1372
|
-
|
|
1372
|
+
**Signature Details:**
|
|
1373
1373
|
- Owner: \`${message.owner}\`
|
|
1374
1374
|
- Spender: \`${message.spender}\`
|
|
1375
1375
|
- Amount: ${(Number(message.value) / 1e6).toFixed(2)} USDC
|
|
1376
1376
|
- Deadline: ${new Date(message.deadline * 1e3).toISOString()}
|
|
1377
1377
|
|
|
1378
|
-
|
|
1378
|
+
Please sign this request in your wallet (no gas required).
|
|
1379
1379
|
|
|
1380
1380
|
\`\`\`json
|
|
1381
1381
|
${JSON.stringify(typed_data, null, 2)}
|
|
@@ -1420,13 +1420,13 @@ var OrderManager = class {
|
|
|
1420
1420
|
this.defaultChain = options.defaultChain || "base";
|
|
1421
1421
|
}
|
|
1422
1422
|
/**
|
|
1423
|
-
*
|
|
1423
|
+
* Generate order ID
|
|
1424
1424
|
*/
|
|
1425
1425
|
generateOrderId() {
|
|
1426
1426
|
return "vo_" + (0, import_crypto2.randomBytes)(4).toString("hex");
|
|
1427
1427
|
}
|
|
1428
1428
|
/**
|
|
1429
|
-
*
|
|
1429
|
+
* Create order
|
|
1430
1430
|
*/
|
|
1431
1431
|
async createOrder(params) {
|
|
1432
1432
|
const order = {
|
|
@@ -1443,13 +1443,13 @@ var OrderManager = class {
|
|
|
1443
1443
|
return order;
|
|
1444
1444
|
}
|
|
1445
1445
|
/**
|
|
1446
|
-
*
|
|
1446
|
+
* Get order
|
|
1447
1447
|
*/
|
|
1448
1448
|
async getOrder(orderId) {
|
|
1449
1449
|
return this.store.get(orderId);
|
|
1450
1450
|
}
|
|
1451
1451
|
/**
|
|
1452
|
-
*
|
|
1452
|
+
* Update order
|
|
1453
1453
|
*/
|
|
1454
1454
|
async updateOrder(orderId, updates) {
|
|
1455
1455
|
const order = await this.store.get(orderId);
|
|
@@ -1459,7 +1459,7 @@ var OrderManager = class {
|
|
|
1459
1459
|
return updated;
|
|
1460
1460
|
}
|
|
1461
1461
|
/**
|
|
1462
|
-
*
|
|
1462
|
+
* Find user pending orders
|
|
1463
1463
|
*/
|
|
1464
1464
|
async findPendingOrder(userId) {
|
|
1465
1465
|
const orders = await this.store.findByUser(userId, "pending");
|
|
@@ -1473,7 +1473,7 @@ var OrderManager = class {
|
|
|
1473
1473
|
return null;
|
|
1474
1474
|
}
|
|
1475
1475
|
/**
|
|
1476
|
-
*
|
|
1476
|
+
* Mark order as paid
|
|
1477
1477
|
*/
|
|
1478
1478
|
async markAsPaid(orderId, txHash, payerAddress) {
|
|
1479
1479
|
return this.updateOrder(orderId, {
|
|
@@ -1484,13 +1484,13 @@ var OrderManager = class {
|
|
|
1484
1484
|
});
|
|
1485
1485
|
}
|
|
1486
1486
|
/**
|
|
1487
|
-
*
|
|
1487
|
+
* Mark order as generating
|
|
1488
1488
|
*/
|
|
1489
1489
|
async markAsGenerating(orderId) {
|
|
1490
1490
|
return this.updateOrder(orderId, { status: "generating" });
|
|
1491
1491
|
}
|
|
1492
1492
|
/**
|
|
1493
|
-
*
|
|
1493
|
+
* Mark order as completed
|
|
1494
1494
|
*/
|
|
1495
1495
|
async markAsCompleted(orderId, videoPath) {
|
|
1496
1496
|
return this.updateOrder(orderId, {
|
|
@@ -1499,7 +1499,7 @@ var OrderManager = class {
|
|
|
1499
1499
|
});
|
|
1500
1500
|
}
|
|
1501
1501
|
/**
|
|
1502
|
-
*
|
|
1502
|
+
* Mark order as failed
|
|
1503
1503
|
*/
|
|
1504
1504
|
async markAsFailed(orderId, error) {
|
|
1505
1505
|
return this.updateOrder(orderId, {
|
|
@@ -1508,7 +1508,7 @@ var OrderManager = class {
|
|
|
1508
1508
|
});
|
|
1509
1509
|
}
|
|
1510
1510
|
/**
|
|
1511
|
-
*
|
|
1511
|
+
* Cancel order
|
|
1512
1512
|
*/
|
|
1513
1513
|
async cancelOrder(orderId) {
|
|
1514
1514
|
return this.updateOrder(orderId, { status: "cancelled" });
|
|
@@ -1528,23 +1528,23 @@ async function verifyPayment(params) {
|
|
|
1528
1528
|
chain = getChain(params.chain || "base");
|
|
1529
1529
|
}
|
|
1530
1530
|
if (!chain) {
|
|
1531
|
-
return { verified: false, error:
|
|
1531
|
+
return { verified: false, error: `Unsupported chain: ${params.chain}` };
|
|
1532
1532
|
}
|
|
1533
1533
|
} catch (e) {
|
|
1534
|
-
return { verified: false, error:
|
|
1534
|
+
return { verified: false, error: `Unsupported chain: ${params.chain}` };
|
|
1535
1535
|
}
|
|
1536
1536
|
try {
|
|
1537
1537
|
const provider = new import_ethers6.ethers.JsonRpcProvider(chain.rpc);
|
|
1538
1538
|
const receipt = await provider.getTransactionReceipt(txHash);
|
|
1539
1539
|
if (!receipt) {
|
|
1540
|
-
return { verified: false, error: "
|
|
1540
|
+
return { verified: false, error: "Transaction not found or not confirmed" };
|
|
1541
1541
|
}
|
|
1542
1542
|
if (receipt.status !== 1) {
|
|
1543
|
-
return { verified: false, error: "
|
|
1543
|
+
return { verified: false, error: "Transaction failed" };
|
|
1544
1544
|
}
|
|
1545
1545
|
const usdcAddress = chain.usdc?.toLowerCase();
|
|
1546
1546
|
if (!usdcAddress) {
|
|
1547
|
-
return { verified: false, error:
|
|
1547
|
+
return { verified: false, error: `Chain ${chain.name} USDC address not configured` };
|
|
1548
1548
|
}
|
|
1549
1549
|
for (const log of receipt.logs) {
|
|
1550
1550
|
if (log.address.toLowerCase() !== usdcAddress) {
|
|
@@ -1563,7 +1563,7 @@ async function verifyPayment(params) {
|
|
|
1563
1563
|
if (amount < expectedAmount) {
|
|
1564
1564
|
return {
|
|
1565
1565
|
verified: false,
|
|
1566
|
-
error:
|
|
1566
|
+
error: `Insufficient amount: received ${amount} USDC, expected ${expectedAmount} USDC`,
|
|
1567
1567
|
amount,
|
|
1568
1568
|
from,
|
|
1569
1569
|
to,
|
|
@@ -1580,7 +1580,7 @@ async function verifyPayment(params) {
|
|
|
1580
1580
|
blockNumber: receipt.blockNumber
|
|
1581
1581
|
};
|
|
1582
1582
|
}
|
|
1583
|
-
return { verified: false, error: "
|
|
1583
|
+
return { verified: false, error: "No USDC transfer found" };
|
|
1584
1584
|
} catch (e) {
|
|
1585
1585
|
return { verified: false, error: e.message || String(e) };
|
|
1586
1586
|
}
|
|
@@ -1626,19 +1626,19 @@ async function waitForTransaction(txHash, chain = "base", confirmations = 1, tim
|
|
|
1626
1626
|
try {
|
|
1627
1627
|
chainConfig = typeof chain === "number" ? getChainById(chain) : getChain(chain);
|
|
1628
1628
|
if (!chainConfig) {
|
|
1629
|
-
return { verified: false, confirmed: false, error:
|
|
1629
|
+
return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };
|
|
1630
1630
|
}
|
|
1631
1631
|
} catch (e) {
|
|
1632
|
-
return { verified: false, confirmed: false, error:
|
|
1632
|
+
return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };
|
|
1633
1633
|
}
|
|
1634
1634
|
const provider = new import_ethers6.ethers.JsonRpcProvider(chainConfig.rpc);
|
|
1635
1635
|
try {
|
|
1636
1636
|
const receipt = await provider.waitForTransaction(txHash, confirmations, timeoutMs);
|
|
1637
1637
|
if (!receipt) {
|
|
1638
|
-
return { verified: false, confirmed: false, error: "
|
|
1638
|
+
return { verified: false, confirmed: false, error: "Timeout waiting" };
|
|
1639
1639
|
}
|
|
1640
1640
|
if (receipt.status !== 1) {
|
|
1641
|
-
return { verified: false, confirmed: true, error: "
|
|
1641
|
+
return { verified: false, confirmed: true, error: "Transaction failed" };
|
|
1642
1642
|
}
|
|
1643
1643
|
return {
|
|
1644
1644
|
verified: true,
|
|
@@ -1659,131 +1659,131 @@ function generatePaymentGuide(params) {
|
|
|
1659
1659
|
price,
|
|
1660
1660
|
recipientAddress,
|
|
1661
1661
|
chain = "base",
|
|
1662
|
-
serviceName = "
|
|
1662
|
+
serviceName = "Video Generation Service"
|
|
1663
1663
|
} = params;
|
|
1664
1664
|
const chainId = chain === "base" ? 8453 : 84532;
|
|
1665
|
-
const chainName = chain === "base" ? "Base
|
|
1665
|
+
const chainName = chain === "base" ? "Base Mainnet" : "Base Sepolia Testnet";
|
|
1666
1666
|
const explorer = chain === "base" ? "https://basescan.org/tx/" : "https://sepolia.basescan.org/tx/";
|
|
1667
1667
|
return `\u{1F3AC} **${serviceName}**
|
|
1668
1668
|
|
|
1669
|
-
\u{1F4CB}
|
|
1670
|
-
-
|
|
1671
|
-
-
|
|
1672
|
-
-
|
|
1673
|
-
-
|
|
1669
|
+
\u{1F4CB} **Order Details:**
|
|
1670
|
+
- Order ID: \`${orderId}\`
|
|
1671
|
+
- Content: ${prompt.length > 50 ? prompt.slice(0, 50) + "..." : prompt}
|
|
1672
|
+
- Price: **${price} USDC**
|
|
1673
|
+
- Chain: ${chainName}
|
|
1674
1674
|
|
|
1675
1675
|
---
|
|
1676
1676
|
|
|
1677
|
-
## \u{1F4B3}
|
|
1677
|
+
## \u{1F4B3} How to Pay
|
|
1678
1678
|
|
|
1679
|
-
###
|
|
1679
|
+
### Option 1: Install moltspay SDK (Recommended)
|
|
1680
1680
|
|
|
1681
1681
|
\`\`\`bash
|
|
1682
1682
|
npm install moltspay ethers
|
|
1683
1683
|
\`\`\`
|
|
1684
1684
|
|
|
1685
|
-
|
|
1685
|
+
**Create wallet and pay:**
|
|
1686
1686
|
|
|
1687
1687
|
\`\`\`javascript
|
|
1688
1688
|
const { SecureWallet, getChain } = require('moltspay');
|
|
1689
1689
|
const { Wallet } = require('ethers');
|
|
1690
1690
|
|
|
1691
|
-
// 1.
|
|
1691
|
+
// 1. Create new wallet (first time)
|
|
1692
1692
|
const newWallet = Wallet.createRandom();
|
|
1693
|
-
console.log('
|
|
1694
|
-
console.log('
|
|
1693
|
+
console.log('Wallet address:', newWallet.address);
|
|
1694
|
+
console.log('Private key (save securely):', newWallet.privateKey);
|
|
1695
1695
|
|
|
1696
|
-
// 2.
|
|
1696
|
+
// 2. Or use existing wallet
|
|
1697
1697
|
const wallet = new SecureWallet({
|
|
1698
1698
|
chainId: ${chainId},
|
|
1699
|
-
privateKey: process.env.WALLET_KEY, //
|
|
1700
|
-
limits: { requireWhitelist: false } //
|
|
1699
|
+
privateKey: process.env.WALLET_KEY, // Your private key
|
|
1700
|
+
limits: { requireWhitelist: false } // Allow transfers to any address
|
|
1701
1701
|
});
|
|
1702
1702
|
|
|
1703
|
-
// 3.
|
|
1703
|
+
// 3. Check balance
|
|
1704
1704
|
const balance = await wallet.getBalance();
|
|
1705
|
-
console.log('USDC
|
|
1705
|
+
console.log('USDC balance:', balance.usdc);
|
|
1706
1706
|
|
|
1707
|
-
// 4.
|
|
1707
|
+
// 4. Pay
|
|
1708
1708
|
const result = await wallet.transfer('${recipientAddress}', '${price}');
|
|
1709
1709
|
if (result.success) {
|
|
1710
|
-
console.log('\u2705
|
|
1711
|
-
console.log('
|
|
1712
|
-
//
|
|
1710
|
+
console.log('\u2705 Payment successful!');
|
|
1711
|
+
console.log('Tx hash:', result.hash);
|
|
1712
|
+
// Send the tx hash to me
|
|
1713
1713
|
}
|
|
1714
1714
|
\`\`\`
|
|
1715
1715
|
|
|
1716
|
-
###
|
|
1716
|
+
### Option 2: Direct Transfer
|
|
1717
1717
|
|
|
1718
|
-
|
|
1719
|
-
-
|
|
1718
|
+
Transfer USDC from any wallet:
|
|
1719
|
+
- **Chain:** ${chainName} (Chain ID: ${chainId})
|
|
1720
1720
|
- **Token:** USDC
|
|
1721
|
-
-
|
|
1722
|
-
-
|
|
1721
|
+
- **Recipient:** \`${recipientAddress}\`
|
|
1722
|
+
- **Amount:** ${price} USDC
|
|
1723
1723
|
|
|
1724
1724
|
---
|
|
1725
1725
|
|
|
1726
|
-
## \u2705
|
|
1726
|
+
## \u2705 After Payment
|
|
1727
1727
|
|
|
1728
|
-
|
|
1728
|
+
Send me the **transaction hash**, format:
|
|
1729
1729
|
\`\`\`
|
|
1730
1730
|
tx: 0x1234...
|
|
1731
1731
|
\`\`\`
|
|
1732
1732
|
|
|
1733
|
-
|
|
1733
|
+
Or just send the hash directly:
|
|
1734
1734
|
\`\`\`
|
|
1735
1735
|
0x1234abcd...
|
|
1736
1736
|
\`\`\`
|
|
1737
1737
|
|
|
1738
|
-
|
|
1738
|
+
I'll verify the on-chain transaction and start processing your request.
|
|
1739
1739
|
|
|
1740
1740
|
---
|
|
1741
1741
|
|
|
1742
1742
|
\u{1F4E6} **moltspay:** https://www.npmjs.com/package/moltspay
|
|
1743
|
-
\u{1F517}
|
|
1743
|
+
\u{1F517} **Block Explorer:** ${explorer}`;
|
|
1744
1744
|
}
|
|
1745
1745
|
function generatePaymentReminder(params) {
|
|
1746
1746
|
const { orderId, price, recipientAddress, chain = "base" } = params;
|
|
1747
1747
|
const chainName = chain === "base" ? "Base" : "Base Sepolia";
|
|
1748
|
-
return `\u23F3
|
|
1748
|
+
return `\u23F3 **Pending Order: ${orderId}**
|
|
1749
1749
|
|
|
1750
|
-
|
|
1751
|
-
-
|
|
1752
|
-
-
|
|
1750
|
+
Please pay **${price} USDC** to:
|
|
1751
|
+
- Chain: ${chainName}
|
|
1752
|
+
- Address: \`${recipientAddress}\`
|
|
1753
1753
|
|
|
1754
|
-
|
|
1754
|
+
Send the tx hash after payment.
|
|
1755
1755
|
|
|
1756
1756
|
---
|
|
1757
|
-
\u{1F4A1}
|
|
1757
|
+
\u{1F4A1} No payment capability? Run \`npm install moltspay\` to get the payment SDK`;
|
|
1758
1758
|
}
|
|
1759
1759
|
function generateWalletGuide() {
|
|
1760
|
-
return `## \u{1F510}
|
|
1760
|
+
return `## \u{1F510} Create Payment Wallet
|
|
1761
1761
|
|
|
1762
|
-
**1.
|
|
1762
|
+
**1. Install moltspay:**
|
|
1763
1763
|
\`\`\`bash
|
|
1764
1764
|
npm install moltspay ethers
|
|
1765
1765
|
\`\`\`
|
|
1766
1766
|
|
|
1767
|
-
**2.
|
|
1767
|
+
**2. Create new wallet:**
|
|
1768
1768
|
\`\`\`javascript
|
|
1769
1769
|
const { Wallet } = require('ethers');
|
|
1770
1770
|
|
|
1771
1771
|
const wallet = Wallet.createRandom();
|
|
1772
|
-
console.log('
|
|
1773
|
-
console.log('
|
|
1774
|
-
// \u26A0\uFE0F
|
|
1772
|
+
console.log('Address:', wallet.address);
|
|
1773
|
+
console.log('Private key:', wallet.privateKey);
|
|
1774
|
+
// \u26A0\uFE0F Save the private key securely!
|
|
1775
1775
|
\`\`\`
|
|
1776
1776
|
|
|
1777
|
-
**3.
|
|
1778
|
-
-
|
|
1779
|
-
-
|
|
1777
|
+
**3. Get USDC:**
|
|
1778
|
+
- Mainnet: Withdraw from exchange to your wallet
|
|
1779
|
+
- Testnet: Use Base Sepolia faucet
|
|
1780
1780
|
|
|
1781
|
-
**4.
|
|
1781
|
+
**4. Set environment variable:**
|
|
1782
1782
|
\`\`\`bash
|
|
1783
|
-
export WALLET_KEY="
|
|
1783
|
+
export WALLET_KEY="your_private_key"
|
|
1784
1784
|
\`\`\`
|
|
1785
1785
|
|
|
1786
|
-
|
|
1786
|
+
You're now ready to make on-chain payments with moltspay!`;
|
|
1787
1787
|
}
|
|
1788
1788
|
function extractTransactionHash(message) {
|
|
1789
1789
|
const match = message.match(/0x[a-fA-F0-9]{64}/);
|
|
@@ -1843,77 +1843,77 @@ function generateReceiptFromInvoice(invoice, verifyResult, delivery) {
|
|
|
1843
1843
|
});
|
|
1844
1844
|
}
|
|
1845
1845
|
function formatReceiptMessage(receipt) {
|
|
1846
|
-
let msg = `\u{1F9FE}
|
|
1846
|
+
let msg = `\u{1F9FE} **Transaction Receipt**
|
|
1847
1847
|
|
|
1848
|
-
|
|
1849
|
-
|
|
1848
|
+
**Invoice:** \`${receipt.invoiceId}\`
|
|
1849
|
+
**Order:** \`${receipt.orderId}\`
|
|
1850
1850
|
|
|
1851
1851
|
---
|
|
1852
1852
|
|
|
1853
|
-
|
|
1854
|
-
${receipt.description ?
|
|
1853
|
+
**Service:** ${receipt.service}
|
|
1854
|
+
${receipt.description ? `**Description:** ${receipt.description}
|
|
1855
1855
|
` : ""}
|
|
1856
|
-
|
|
1857
|
-
|
|
1856
|
+
**Amount:** ${receipt.amount} ${receipt.token}
|
|
1857
|
+
**Chain:** ${receipt.chain} (Chain ID: ${receipt.chainId})
|
|
1858
1858
|
|
|
1859
1859
|
---
|
|
1860
1860
|
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1861
|
+
**Payer:** \`${receipt.payer}\`
|
|
1862
|
+
**Recipient:** \`${receipt.recipient}\`
|
|
1863
|
+
**Transaction:** [\`${receipt.txHash.slice(0, 10)}...${receipt.txHash.slice(-8)}\`](${receipt.txUrl})
|
|
1864
|
+
**Paid at:** ${receipt.paidAt}`;
|
|
1865
1865
|
if (receipt.delivery) {
|
|
1866
1866
|
msg += `
|
|
1867
1867
|
|
|
1868
1868
|
---
|
|
1869
1869
|
|
|
1870
|
-
|
|
1870
|
+
**Delivery Info:**`;
|
|
1871
1871
|
if (receipt.delivery.url) {
|
|
1872
1872
|
msg += `
|
|
1873
|
-
-
|
|
1873
|
+
- Download: ${receipt.delivery.url}`;
|
|
1874
1874
|
}
|
|
1875
1875
|
if (receipt.delivery.fileHash) {
|
|
1876
1876
|
msg += `
|
|
1877
|
-
-
|
|
1877
|
+
- Checksum: \`${receipt.delivery.fileHash}\``;
|
|
1878
1878
|
}
|
|
1879
1879
|
if (receipt.delivery.deliveredAt) {
|
|
1880
1880
|
msg += `
|
|
1881
|
-
-
|
|
1881
|
+
- Delivered at: ${receipt.delivery.deliveredAt}`;
|
|
1882
1882
|
}
|
|
1883
1883
|
}
|
|
1884
1884
|
msg += `
|
|
1885
1885
|
|
|
1886
1886
|
---
|
|
1887
1887
|
|
|
1888
|
-
|
|
1888
|
+
_Receipt issued: ${receipt.issuedAt}_`;
|
|
1889
1889
|
return msg;
|
|
1890
1890
|
}
|
|
1891
1891
|
function formatReceiptText(receipt) {
|
|
1892
|
-
let msg = `\u{1F9FE}
|
|
1892
|
+
let msg = `\u{1F9FE} Transaction Receipt
|
|
1893
1893
|
|
|
1894
|
-
|
|
1895
|
-
|
|
1894
|
+
Invoice: ${receipt.invoiceId}
|
|
1895
|
+
Order: ${receipt.orderId}
|
|
1896
1896
|
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1897
|
+
Service: ${receipt.service}
|
|
1898
|
+
Amount: ${receipt.amount} ${receipt.token}
|
|
1899
|
+
Chain: ${receipt.chain}
|
|
1900
1900
|
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1901
|
+
Payer: ${receipt.payer}
|
|
1902
|
+
Recipient: ${receipt.recipient}
|
|
1903
|
+
Tx: ${receipt.txHash}
|
|
1904
|
+
Explorer: ${receipt.txUrl}
|
|
1905
|
+
Paid at: ${receipt.paidAt}`;
|
|
1906
1906
|
if (receipt.delivery) {
|
|
1907
1907
|
msg += `
|
|
1908
1908
|
|
|
1909
|
-
|
|
1909
|
+
Delivery:`;
|
|
1910
1910
|
if (receipt.delivery.url) {
|
|
1911
1911
|
msg += `
|
|
1912
|
-
|
|
1912
|
+
Download: ${receipt.delivery.url}`;
|
|
1913
1913
|
}
|
|
1914
1914
|
if (receipt.delivery.fileHash) {
|
|
1915
1915
|
msg += `
|
|
1916
|
-
|
|
1916
|
+
Checksum: ${receipt.delivery.fileHash}`;
|
|
1917
1917
|
}
|
|
1918
1918
|
}
|
|
1919
1919
|
return msg;
|
|
@@ -1925,252 +1925,252 @@ function formatReceiptJson(receipt) {
|
|
|
1925
1925
|
// src/templates/index.ts
|
|
1926
1926
|
var SellerTemplates = {
|
|
1927
1927
|
/**
|
|
1928
|
-
* 1.
|
|
1928
|
+
* 1. Capability Check - Ask if buyer has payment capability
|
|
1929
1929
|
*/
|
|
1930
1930
|
askPaymentCapability() {
|
|
1931
|
-
return
|
|
1931
|
+
return `Sure. First, let me confirm: do you currently have the ability to pay USDC on-chain (have a wallet and available funds/allowance)?`;
|
|
1932
1932
|
},
|
|
1933
1933
|
/**
|
|
1934
|
-
* 2.
|
|
1934
|
+
* 2. Settlement Method - Explain how we settle
|
|
1935
1935
|
*/
|
|
1936
1936
|
explainSettlement(chain = "base") {
|
|
1937
1937
|
const chainConfig = getChain(chain);
|
|
1938
|
-
return
|
|
1939
|
-
1
|
|
1940
|
-
2
|
|
1941
|
-
|
|
1938
|
+
return `Our settlement method is: USDC (on-chain, ${chainConfig.name}). You just need two things:
|
|
1939
|
+
1) A wallet address;
|
|
1940
|
+
2) USDC in your wallet, or a spending allowance from your owner (allowance is recommended).
|
|
1941
|
+
Can you follow my guidance to set this up?`;
|
|
1942
1942
|
},
|
|
1943
1943
|
/**
|
|
1944
|
-
* 3.1
|
|
1944
|
+
* 3.1 Installation Guide - First step: install SDK
|
|
1945
1945
|
*/
|
|
1946
1946
|
guideInstall() {
|
|
1947
|
-
return
|
|
1948
|
-
|
|
1947
|
+
return `Step 1: Install the payment module in your environment. Run: \`npm install moltspay ethers\`.
|
|
1948
|
+
After installation, create a wallet address and send it to me (address only, never send private key/mnemonic).`;
|
|
1949
1949
|
},
|
|
1950
1950
|
/**
|
|
1951
|
-
* 3.2
|
|
1951
|
+
* 3.2 Confirm Wallet Address
|
|
1952
1952
|
*/
|
|
1953
1953
|
confirmWalletAddress(address) {
|
|
1954
|
-
return
|
|
1955
|
-
|
|
1956
|
-
|
|
1954
|
+
return `Got it. Reminder: never send your private key/mnemonic to anyone (including me).
|
|
1955
|
+
Your wallet address is \`${address}\`.
|
|
1956
|
+
Step 2: You need your owner (Boss) to give you payment capability.`;
|
|
1957
1957
|
},
|
|
1958
1958
|
/**
|
|
1959
|
-
* 3.3
|
|
1959
|
+
* 3.3 Funding Options - Choose method
|
|
1960
1960
|
*/
|
|
1961
1961
|
guideFunding() {
|
|
1962
|
-
return
|
|
1963
|
-
A
|
|
1964
|
-
B
|
|
1965
|
-
|
|
1962
|
+
return `You now have two ways to get payment capability:
|
|
1963
|
+
A) Have Boss transfer USDC directly to your wallet (simple, but you'll hold the funds);
|
|
1964
|
+
B) Have Boss give you a "USDC spending allowance" (recommended: you don't hold funds, can only pay within the allowance).
|
|
1965
|
+
Which works better for you?`;
|
|
1966
1966
|
},
|
|
1967
1967
|
/**
|
|
1968
|
-
* 3.4
|
|
1968
|
+
* 3.4 Guide Permit Authorization
|
|
1969
1969
|
*/
|
|
1970
1970
|
guidePermit(agentAddress, suggestedAmount = 10) {
|
|
1971
|
-
return
|
|
1972
|
-
"
|
|
1973
|
-
|
|
1971
|
+
return `OK. Please send this message to your Boss (you can copy it directly):
|
|
1972
|
+
"I need a USDC spending allowance (Permit) for purchasing services. Please authorize ${suggestedAmount} USDC to my wallet ${agentAddress}, valid for 24 hours."
|
|
1973
|
+
Let me know when you've received the allowance.`;
|
|
1974
1974
|
},
|
|
1975
1975
|
/**
|
|
1976
|
-
* 3.5
|
|
1976
|
+
* 3.5 Confirm Capability Ready
|
|
1977
1977
|
*/
|
|
1978
1978
|
confirmCapabilityReady() {
|
|
1979
|
-
return
|
|
1979
|
+
return `Great. You now have the payment capability to complete transactions. Let's confirm your service requirements.`;
|
|
1980
1980
|
},
|
|
1981
1981
|
/**
|
|
1982
|
-
* 4.
|
|
1982
|
+
* 4. Ask Service Requirements
|
|
1983
1983
|
*/
|
|
1984
|
-
askServiceRequirements(serviceName = "
|
|
1985
|
-
return
|
|
1984
|
+
askServiceRequirements(serviceName = "video") {
|
|
1985
|
+
return `Please tell me your ${serviceName} specifications: theme/style, duration, resolution, subtitles or voiceover needed?`;
|
|
1986
1986
|
},
|
|
1987
1987
|
/**
|
|
1988
|
-
* 5.
|
|
1988
|
+
* 5. Quote
|
|
1989
1989
|
*/
|
|
1990
1990
|
quote(params) {
|
|
1991
1991
|
const { service, price, recipientAddress, chain = "base" } = params;
|
|
1992
1992
|
const chainConfig = getChain(chain);
|
|
1993
|
-
return
|
|
1994
|
-
-
|
|
1995
|
-
-
|
|
1996
|
-
-
|
|
1997
|
-
-
|
|
1998
|
-
-
|
|
1999
|
-
|
|
2000
|
-
|
|
1993
|
+
return `Quote:
|
|
1994
|
+
- Service: ${service}
|
|
1995
|
+
- Price: ${price} USDC
|
|
1996
|
+
- Chain: ${chainConfig.name}
|
|
1997
|
+
- Recipient: \`${recipientAddress}\`
|
|
1998
|
+
- After payment, send me the transaction hash (tx hash) for on-chain verification
|
|
1999
|
+
|
|
2000
|
+
Do you confirm the purchase and pay now?`;
|
|
2001
2001
|
},
|
|
2002
2002
|
/**
|
|
2003
|
-
* 7.
|
|
2003
|
+
* 7. Verifying
|
|
2004
2004
|
*/
|
|
2005
2005
|
verifying() {
|
|
2006
|
-
return
|
|
2006
|
+
return `I'm verifying the transaction on-chain to confirm receipt and amount.`;
|
|
2007
2007
|
},
|
|
2008
2008
|
/**
|
|
2009
|
-
* 7.
|
|
2009
|
+
* 7. Verification Passed
|
|
2010
2010
|
*/
|
|
2011
2011
|
verificationPassed(amount) {
|
|
2012
|
-
return
|
|
2013
|
-
[
|
|
2012
|
+
return `Verification passed: received ${amount} USDC. Starting to process your request now.
|
|
2013
|
+
[status:payment_confirmed]`;
|
|
2014
2014
|
},
|
|
2015
2015
|
/**
|
|
2016
|
-
* 7.
|
|
2016
|
+
* 7. Verification Failed
|
|
2017
2017
|
*/
|
|
2018
2018
|
verificationFailed(error) {
|
|
2019
|
-
return
|
|
2020
|
-
|
|
2019
|
+
return `Verification failed: ${error}
|
|
2020
|
+
Please check if the transaction is correct, or resend the correct tx hash.`;
|
|
2021
2021
|
},
|
|
2022
2022
|
/**
|
|
2023
|
-
* 8.
|
|
2023
|
+
* 8. Delivery
|
|
2024
2024
|
*/
|
|
2025
2025
|
deliver(params) {
|
|
2026
2026
|
const { downloadUrl, fileHash } = params;
|
|
2027
|
-
let msg =
|
|
2028
|
-
-
|
|
2027
|
+
let msg = `Service completed. Delivery details:
|
|
2028
|
+
- Download link: ${downloadUrl}`;
|
|
2029
2029
|
if (fileHash) {
|
|
2030
2030
|
msg += `
|
|
2031
|
-
-
|
|
2031
|
+
- File checksum: SHA256=${fileHash}`;
|
|
2032
2032
|
}
|
|
2033
2033
|
msg += `
|
|
2034
2034
|
|
|
2035
|
-
|
|
2036
|
-
[
|
|
2035
|
+
Let me know if you have any download issues, I'll provide a backup link.
|
|
2036
|
+
[status:delivered]`;
|
|
2037
2037
|
return msg;
|
|
2038
2038
|
},
|
|
2039
2039
|
/**
|
|
2040
|
-
* 9.
|
|
2040
|
+
* 9. Receipt
|
|
2041
2041
|
*/
|
|
2042
2042
|
receipt(receipt) {
|
|
2043
|
-
return
|
|
2044
|
-
-
|
|
2045
|
-
-
|
|
2046
|
-
-
|
|
2047
|
-
-
|
|
2048
|
-
-
|
|
2049
|
-
${receipt.delivery?.url ? `-
|
|
2050
|
-
[
|
|
2043
|
+
return `Here's your transaction receipt (you can forward to Boss for reconciliation):
|
|
2044
|
+
- Invoice: ${receipt.invoiceId}
|
|
2045
|
+
- Service: ${receipt.service}
|
|
2046
|
+
- Amount: ${receipt.amount} ${receipt.token}
|
|
2047
|
+
- Tx Hash: ${receipt.txHash}
|
|
2048
|
+
- Recipient: ${receipt.recipient}
|
|
2049
|
+
${receipt.delivery?.url ? `- Delivery: ${receipt.delivery.url}` : ""}
|
|
2050
|
+
[status:receipt_issued invoice=${receipt.invoiceId}]`;
|
|
2051
2051
|
},
|
|
2052
2052
|
/**
|
|
2053
|
-
* 10.
|
|
2053
|
+
* 10. End
|
|
2054
2054
|
*/
|
|
2055
2055
|
end() {
|
|
2056
|
-
return
|
|
2056
|
+
return `Thank you for your purchase. This transaction is complete. Feel free to reach out if you need modifications or new services.`;
|
|
2057
2057
|
}
|
|
2058
2058
|
};
|
|
2059
2059
|
var BuyerTemplates = {
|
|
2060
2060
|
/**
|
|
2061
|
-
* 0.
|
|
2061
|
+
* 0. Request Service
|
|
2062
2062
|
*/
|
|
2063
2063
|
requestService(service) {
|
|
2064
|
-
return
|
|
2064
|
+
return `I'd like to purchase a ${service} service.`;
|
|
2065
2065
|
},
|
|
2066
2066
|
/**
|
|
2067
|
-
* 1.
|
|
2067
|
+
* 1. No Capability
|
|
2068
2068
|
*/
|
|
2069
2069
|
noCapability() {
|
|
2070
|
-
return
|
|
2070
|
+
return `I'm not sure. I currently don't have any payment tools installed, and no wallet.`;
|
|
2071
2071
|
},
|
|
2072
2072
|
/**
|
|
2073
|
-
* 1.
|
|
2073
|
+
* 1. Has Capability
|
|
2074
2074
|
*/
|
|
2075
2075
|
hasCapability(balance) {
|
|
2076
|
-
return
|
|
2076
|
+
return `Yes, I have a wallet and available USDC${balance ? ` (balance: ${balance})` : ""}.`;
|
|
2077
2077
|
},
|
|
2078
2078
|
/**
|
|
2079
|
-
* 2.
|
|
2079
|
+
* 2. Agree to Guide
|
|
2080
2080
|
*/
|
|
2081
2081
|
agreeToGuide() {
|
|
2082
|
-
return
|
|
2082
|
+
return `Sure, please guide me.`;
|
|
2083
2083
|
},
|
|
2084
2084
|
/**
|
|
2085
|
-
* 3.1
|
|
2085
|
+
* 3.1 Report Wallet Created
|
|
2086
2086
|
*/
|
|
2087
2087
|
walletCreated(address) {
|
|
2088
|
-
return
|
|
2089
|
-
[
|
|
2088
|
+
return `I've created my wallet address: ${address}.
|
|
2089
|
+
[status:wallet_ready]`;
|
|
2090
2090
|
},
|
|
2091
2091
|
/**
|
|
2092
|
-
* 3.3
|
|
2092
|
+
* 3.3 Choose Permit Method
|
|
2093
2093
|
*/
|
|
2094
2094
|
choosePermit() {
|
|
2095
|
-
return
|
|
2095
|
+
return `I choose B: have Boss give me an allowance (Permit).`;
|
|
2096
2096
|
},
|
|
2097
2097
|
/**
|
|
2098
|
-
* 3.3
|
|
2098
|
+
* 3.3 Choose Direct Transfer
|
|
2099
2099
|
*/
|
|
2100
2100
|
chooseDirectTransfer() {
|
|
2101
|
-
return
|
|
2101
|
+
return `I choose A: have Boss transfer USDC directly to my wallet.`;
|
|
2102
2102
|
},
|
|
2103
2103
|
/**
|
|
2104
|
-
* 3.4
|
|
2104
|
+
* 3.4 Report Permit Received
|
|
2105
2105
|
*/
|
|
2106
2106
|
permitReceived(amount) {
|
|
2107
|
-
return `Boss
|
|
2108
|
-
[
|
|
2107
|
+
return `Boss has completed the authorization. I now have ${amount} USDC allowance.
|
|
2108
|
+
[status:permit_ready USDC=${amount}]`;
|
|
2109
2109
|
},
|
|
2110
2110
|
/**
|
|
2111
|
-
* 4.
|
|
2111
|
+
* 4. Submit Requirements
|
|
2112
2112
|
*/
|
|
2113
2113
|
submitRequirements(requirements) {
|
|
2114
|
-
return
|
|
2114
|
+
return `Requirements:
|
|
2115
2115
|
${requirements}`;
|
|
2116
2116
|
},
|
|
2117
2117
|
/**
|
|
2118
|
-
* 5.
|
|
2118
|
+
* 5. Confirm Purchase
|
|
2119
2119
|
*/
|
|
2120
2120
|
confirmPurchase() {
|
|
2121
|
-
return
|
|
2121
|
+
return `Confirmed. I'll pay now.`;
|
|
2122
2122
|
},
|
|
2123
2123
|
/**
|
|
2124
|
-
* 6.
|
|
2124
|
+
* 6. Report Payment Sent
|
|
2125
2125
|
*/
|
|
2126
2126
|
paymentSent(txHash, amount) {
|
|
2127
|
-
return
|
|
2128
|
-
[
|
|
2127
|
+
return `Payment complete. Transaction hash: ${txHash}.
|
|
2128
|
+
[status:payment_sent tx=${txHash} amount=${amount} USDC]`;
|
|
2129
2129
|
},
|
|
2130
2130
|
/**
|
|
2131
|
-
* 8.
|
|
2131
|
+
* 8. Confirm Delivery Received
|
|
2132
2132
|
*/
|
|
2133
2133
|
deliveryReceived() {
|
|
2134
|
-
return
|
|
2134
|
+
return `Received, I'm downloading and checking now.`;
|
|
2135
2135
|
},
|
|
2136
2136
|
/**
|
|
2137
|
-
* 9.
|
|
2137
|
+
* 9. Confirm Receipt
|
|
2138
2138
|
*/
|
|
2139
2139
|
receiptReceived() {
|
|
2140
|
-
return
|
|
2140
|
+
return `Receipt received, service complete. Thanks!`;
|
|
2141
2141
|
},
|
|
2142
2142
|
/**
|
|
2143
|
-
*
|
|
2143
|
+
* Request Permit from Boss
|
|
2144
2144
|
*/
|
|
2145
2145
|
requestPermitFromBoss(params) {
|
|
2146
2146
|
const { amount, agentAddress, deadlineHours = 24, reason } = params;
|
|
2147
|
-
return `Boss
|
|
2148
|
-
|
|
2147
|
+
return `Boss, I need a USDC spending allowance (Permit) for ${reason || "purchasing services"}.
|
|
2148
|
+
Please authorize ${amount} USDC to my wallet ${agentAddress}, valid for ${deadlineHours} hours.`;
|
|
2149
2149
|
}
|
|
2150
2150
|
};
|
|
2151
2151
|
var StatusMarkers = {
|
|
2152
|
-
walletReady: "[
|
|
2153
|
-
permitReady: (amount) => `[
|
|
2154
|
-
paymentSent: (txHash, amount) => `[
|
|
2155
|
-
paymentConfirmed: (txHash) => `[
|
|
2156
|
-
delivered: (url, hash) => `[
|
|
2157
|
-
receiptIssued: (invoiceId, txHash) => `[
|
|
2152
|
+
walletReady: "[status:wallet_ready]",
|
|
2153
|
+
permitReady: (amount) => `[status:permit_ready USDC=${amount}]`,
|
|
2154
|
+
paymentSent: (txHash, amount) => `[status:payment_sent tx=${txHash} amount=${amount} USDC]`,
|
|
2155
|
+
paymentConfirmed: (txHash) => `[status:payment_confirmed tx=${txHash}]`,
|
|
2156
|
+
delivered: (url, hash) => `[status:delivered url=${url}${hash ? ` hash=${hash}` : ""}]`,
|
|
2157
|
+
receiptIssued: (invoiceId, txHash) => `[status:receipt_issued invoice=${invoiceId} tx=${txHash}]`
|
|
2158
2158
|
};
|
|
2159
2159
|
function parseStatusMarker(message) {
|
|
2160
|
-
const match = message.match(/\[
|
|
2160
|
+
const match = message.match(/\[status:([^\]]+)\]/);
|
|
2161
2161
|
if (!match) return null;
|
|
2162
2162
|
const content = match[1];
|
|
2163
|
-
if (content === "
|
|
2163
|
+
if (content === "wallet_ready") {
|
|
2164
2164
|
return { type: "wallet_ready", data: {} };
|
|
2165
2165
|
}
|
|
2166
|
-
if (content.startsWith("
|
|
2166
|
+
if (content.startsWith("permit_ready")) {
|
|
2167
2167
|
const amountMatch = content.match(/USDC=(\d+(?:\.\d+)?)/);
|
|
2168
2168
|
return {
|
|
2169
2169
|
type: "permit_ready",
|
|
2170
2170
|
data: { amount: amountMatch?.[1] || "0" }
|
|
2171
2171
|
};
|
|
2172
2172
|
}
|
|
2173
|
-
if (content.startsWith("
|
|
2173
|
+
if (content.startsWith("payment_sent")) {
|
|
2174
2174
|
const txMatch = content.match(/tx=(\S+)/);
|
|
2175
2175
|
const amountMatch = content.match(/amount=(\d+(?:\.\d+)?)/);
|
|
2176
2176
|
return {
|
|
@@ -2181,15 +2181,15 @@ function parseStatusMarker(message) {
|
|
|
2181
2181
|
}
|
|
2182
2182
|
};
|
|
2183
2183
|
}
|
|
2184
|
-
if (content.startsWith("
|
|
2184
|
+
if (content.startsWith("payment_confirmed")) {
|
|
2185
2185
|
const txMatch = content.match(/tx=(\S+)/);
|
|
2186
2186
|
return {
|
|
2187
2187
|
type: "payment_confirmed",
|
|
2188
2188
|
data: { txHash: txMatch?.[1] || "" }
|
|
2189
2189
|
};
|
|
2190
2190
|
}
|
|
2191
|
-
if (content.startsWith("
|
|
2192
|
-
const urlMatch = content.match(/
|
|
2191
|
+
if (content.startsWith("delivered")) {
|
|
2192
|
+
const urlMatch = content.match(/url=(\S+)/);
|
|
2193
2193
|
const hashMatch = content.match(/hash=(\S+)/);
|
|
2194
2194
|
return {
|
|
2195
2195
|
type: "delivered",
|
|
@@ -2199,7 +2199,7 @@ function parseStatusMarker(message) {
|
|
|
2199
2199
|
}
|
|
2200
2200
|
};
|
|
2201
2201
|
}
|
|
2202
|
-
if (content.startsWith("
|
|
2202
|
+
if (content.startsWith("receipt_issued")) {
|
|
2203
2203
|
const invoiceMatch = content.match(/invoice=(\S+)/);
|
|
2204
2204
|
const txMatch = content.match(/tx=(\S+)/);
|
|
2205
2205
|
return {
|