moltspay 0.2.4 → 0.2.5
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 +573 -93
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +577 -95
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +111 -1
- package/dist/index.d.ts +111 -1
- package/dist/index.js +373 -60
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +383 -72
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
|
+
AgentWallet: () => AgentWallet,
|
|
33
34
|
AllowanceWallet: () => AllowanceWallet,
|
|
34
35
|
AuditLog: () => AuditLog,
|
|
35
36
|
BuyerTemplates: () => BuyerTemplates,
|
|
@@ -57,6 +58,7 @@ __export(src_exports, {
|
|
|
57
58
|
generateReceipt: () => generateReceipt,
|
|
58
59
|
generateReceiptFromInvoice: () => generateReceiptFromInvoice,
|
|
59
60
|
generateWalletGuide: () => generateWalletGuide,
|
|
61
|
+
getAgentAddress: () => getAgentAddress,
|
|
60
62
|
getChain: () => getChain,
|
|
61
63
|
getChainById: () => getChainById,
|
|
62
64
|
getTransactionStatus: () => getTransactionStatus,
|
|
@@ -354,8 +356,317 @@ After payment, reply with your tx hash:
|
|
|
354
356
|
}
|
|
355
357
|
};
|
|
356
358
|
|
|
357
|
-
// src/
|
|
359
|
+
// src/agent/AgentWallet.ts
|
|
358
360
|
var import_ethers2 = require("ethers");
|
|
361
|
+
var fs = __toESM(require("fs"));
|
|
362
|
+
var path = __toESM(require("path"));
|
|
363
|
+
var PERMIT_ABI = [
|
|
364
|
+
...ERC20_ABI,
|
|
365
|
+
"function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)",
|
|
366
|
+
"function transferFrom(address from, address to, uint256 amount) returns (bool)",
|
|
367
|
+
"function allowance(address owner, address spender) view returns (uint256)",
|
|
368
|
+
"function nonces(address owner) view returns (uint256)"
|
|
369
|
+
];
|
|
370
|
+
var AgentWallet = class {
|
|
371
|
+
chain;
|
|
372
|
+
chainConfig;
|
|
373
|
+
storageDir;
|
|
374
|
+
_address = null;
|
|
375
|
+
_privateKey = null;
|
|
376
|
+
_wallet = null;
|
|
377
|
+
_provider = null;
|
|
378
|
+
_permits = /* @__PURE__ */ new Map();
|
|
379
|
+
constructor(config = {}) {
|
|
380
|
+
this.chain = config.chain || "base";
|
|
381
|
+
this.chainConfig = getChain(this.chain);
|
|
382
|
+
this.storageDir = config.storageDir || this.getDefaultStorageDir();
|
|
383
|
+
this.ensureInitialized();
|
|
384
|
+
}
|
|
385
|
+
getDefaultStorageDir() {
|
|
386
|
+
const home = process.env.HOME || process.env.USERPROFILE || ".";
|
|
387
|
+
return path.join(home, ".moltspay");
|
|
388
|
+
}
|
|
389
|
+
getWalletPath() {
|
|
390
|
+
return path.join(this.storageDir, "wallet.json");
|
|
391
|
+
}
|
|
392
|
+
getPermitsPath() {
|
|
393
|
+
return path.join(this.storageDir, "permits.json");
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Auto-initialize: create wallet if not exists
|
|
397
|
+
* This is called automatically in constructor
|
|
398
|
+
*/
|
|
399
|
+
ensureInitialized() {
|
|
400
|
+
if (!fs.existsSync(this.storageDir)) {
|
|
401
|
+
fs.mkdirSync(this.storageDir, { recursive: true });
|
|
402
|
+
}
|
|
403
|
+
const walletPath = this.getWalletPath();
|
|
404
|
+
if (fs.existsSync(walletPath)) {
|
|
405
|
+
const data = JSON.parse(fs.readFileSync(walletPath, "utf-8"));
|
|
406
|
+
this._address = data.address;
|
|
407
|
+
this._privateKey = data.privateKey;
|
|
408
|
+
} else {
|
|
409
|
+
const wallet = import_ethers2.ethers.Wallet.createRandom();
|
|
410
|
+
this._address = wallet.address;
|
|
411
|
+
this._privateKey = wallet.privateKey;
|
|
412
|
+
fs.writeFileSync(walletPath, JSON.stringify({
|
|
413
|
+
address: this._address,
|
|
414
|
+
privateKey: this._privateKey,
|
|
415
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
416
|
+
chain: this.chain
|
|
417
|
+
}, null, 2), { mode: 384 });
|
|
418
|
+
}
|
|
419
|
+
const permitsPath = this.getPermitsPath();
|
|
420
|
+
if (fs.existsSync(permitsPath)) {
|
|
421
|
+
const permits = JSON.parse(fs.readFileSync(permitsPath, "utf-8"));
|
|
422
|
+
for (const [owner, permit] of Object.entries(permits)) {
|
|
423
|
+
this._permits.set(owner.toLowerCase(), permit);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
/** Agent's address (auto-generated on first use) */
|
|
428
|
+
get address() {
|
|
429
|
+
return this._address;
|
|
430
|
+
}
|
|
431
|
+
get wallet() {
|
|
432
|
+
if (!this._wallet) {
|
|
433
|
+
this._wallet = new import_ethers2.ethers.Wallet(this._privateKey, this.provider);
|
|
434
|
+
}
|
|
435
|
+
return this._wallet;
|
|
436
|
+
}
|
|
437
|
+
get provider() {
|
|
438
|
+
if (!this._provider) {
|
|
439
|
+
this._provider = new import_ethers2.ethers.JsonRpcProvider(this.chainConfig.rpc);
|
|
440
|
+
}
|
|
441
|
+
return this._provider;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Store a Permit from Owner
|
|
445
|
+
*/
|
|
446
|
+
storePermit(permit) {
|
|
447
|
+
const ownerLower = permit.owner.toLowerCase();
|
|
448
|
+
this._permits.set(ownerLower, permit);
|
|
449
|
+
const permitsPath = this.getPermitsPath();
|
|
450
|
+
const permits = {};
|
|
451
|
+
for (const [owner, p] of this._permits) {
|
|
452
|
+
permits[owner] = p;
|
|
453
|
+
}
|
|
454
|
+
fs.writeFileSync(permitsPath, JSON.stringify(permits, null, 2));
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Get stored permit for an owner
|
|
458
|
+
*/
|
|
459
|
+
getPermit(owner) {
|
|
460
|
+
return this._permits.get(owner.toLowerCase());
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Check allowance from an owner
|
|
464
|
+
*/
|
|
465
|
+
async checkAllowance(owner) {
|
|
466
|
+
const usdcContract = new import_ethers2.ethers.Contract(
|
|
467
|
+
this.chainConfig.usdc,
|
|
468
|
+
PERMIT_ABI,
|
|
469
|
+
this.provider
|
|
470
|
+
);
|
|
471
|
+
const ownerAddress = import_ethers2.ethers.getAddress(owner);
|
|
472
|
+
const [allowance, balance] = await Promise.all([
|
|
473
|
+
usdcContract.allowance(ownerAddress, this.address),
|
|
474
|
+
usdcContract.balanceOf(ownerAddress)
|
|
475
|
+
]);
|
|
476
|
+
return {
|
|
477
|
+
allowance: (Number(allowance) / 1e6).toFixed(2),
|
|
478
|
+
ownerBalance: (Number(balance) / 1e6).toFixed(2),
|
|
479
|
+
canSpend: Number(allowance) > 0
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Spend USDC from Owner's wallet
|
|
484
|
+
*
|
|
485
|
+
* @param to - Recipient (service provider)
|
|
486
|
+
* @param amount - Amount in USDC
|
|
487
|
+
* @param permit - Optional, uses stored permit if not provided
|
|
488
|
+
*/
|
|
489
|
+
async spend(to, amount, permit) {
|
|
490
|
+
const toAddress = import_ethers2.ethers.getAddress(to);
|
|
491
|
+
const amountWei = BigInt(Math.floor(amount * 1e6));
|
|
492
|
+
let usePermit = permit;
|
|
493
|
+
let ownerAddress;
|
|
494
|
+
if (usePermit) {
|
|
495
|
+
ownerAddress = import_ethers2.ethers.getAddress(usePermit.owner);
|
|
496
|
+
this.storePermit(usePermit);
|
|
497
|
+
} else {
|
|
498
|
+
const usdcContract = new import_ethers2.ethers.Contract(
|
|
499
|
+
this.chainConfig.usdc,
|
|
500
|
+
PERMIT_ABI,
|
|
501
|
+
this.provider
|
|
502
|
+
);
|
|
503
|
+
for (const [owner, p] of this._permits) {
|
|
504
|
+
const allowance = await usdcContract.allowance(owner, this.address);
|
|
505
|
+
if (BigInt(allowance) >= amountWei) {
|
|
506
|
+
ownerAddress = import_ethers2.ethers.getAddress(owner);
|
|
507
|
+
usePermit = p;
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (!usePermit) {
|
|
512
|
+
return {
|
|
513
|
+
success: false,
|
|
514
|
+
error: "No valid permit. Ask Owner to authorize spending first.",
|
|
515
|
+
from: "",
|
|
516
|
+
to: toAddress,
|
|
517
|
+
amount
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
try {
|
|
522
|
+
const usdcContract = new import_ethers2.ethers.Contract(
|
|
523
|
+
this.chainConfig.usdc,
|
|
524
|
+
PERMIT_ABI,
|
|
525
|
+
this.wallet
|
|
526
|
+
);
|
|
527
|
+
const currentAllowance = await usdcContract.allowance(ownerAddress, this.address);
|
|
528
|
+
if (BigInt(currentAllowance) < amountWei) {
|
|
529
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
530
|
+
if (usePermit.deadline < now) {
|
|
531
|
+
return {
|
|
532
|
+
success: false,
|
|
533
|
+
error: "Permit expired. Ask Owner for a new authorization.",
|
|
534
|
+
from: ownerAddress,
|
|
535
|
+
to: toAddress,
|
|
536
|
+
amount
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
const permitTx = await usdcContract.permit(
|
|
540
|
+
ownerAddress,
|
|
541
|
+
this.address,
|
|
542
|
+
usePermit.value,
|
|
543
|
+
usePermit.deadline,
|
|
544
|
+
usePermit.v,
|
|
545
|
+
usePermit.r,
|
|
546
|
+
usePermit.s
|
|
547
|
+
);
|
|
548
|
+
await permitTx.wait();
|
|
549
|
+
}
|
|
550
|
+
const tx = await usdcContract.transferFrom(ownerAddress, toAddress, amountWei);
|
|
551
|
+
await tx.wait();
|
|
552
|
+
const newAllowance = await usdcContract.allowance(ownerAddress, this.address);
|
|
553
|
+
return {
|
|
554
|
+
success: true,
|
|
555
|
+
txHash: tx.hash,
|
|
556
|
+
from: ownerAddress,
|
|
557
|
+
to: toAddress,
|
|
558
|
+
amount,
|
|
559
|
+
remainingAllowance: (Number(newAllowance) / 1e6).toFixed(2),
|
|
560
|
+
explorerUrl: `${this.chainConfig.explorerTx}${tx.hash}`
|
|
561
|
+
};
|
|
562
|
+
} catch (error) {
|
|
563
|
+
return {
|
|
564
|
+
success: false,
|
|
565
|
+
error: error.message,
|
|
566
|
+
from: ownerAddress,
|
|
567
|
+
to: toAddress,
|
|
568
|
+
amount
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Get gas balance (ETH needed for transactions)
|
|
574
|
+
*/
|
|
575
|
+
async getGasBalance() {
|
|
576
|
+
const balance = await this.provider.getBalance(this.address);
|
|
577
|
+
return import_ethers2.ethers.formatEther(balance);
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Check if agent has enough gas
|
|
581
|
+
*/
|
|
582
|
+
async hasGas(minEth = 5e-4) {
|
|
583
|
+
const balance = await this.getGasBalance();
|
|
584
|
+
return parseFloat(balance) >= minEth;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Generate authorization request for Owner
|
|
588
|
+
* Owner can sign this with CLI (ethers) or MetaMask
|
|
589
|
+
*/
|
|
590
|
+
async generateAuthRequest(params) {
|
|
591
|
+
const { ownerAddress, amount, expiresInHours = 168 } = params;
|
|
592
|
+
const deadline = Math.floor(Date.now() / 1e3) + expiresInHours * 3600;
|
|
593
|
+
const value = BigInt(Math.floor(amount * 1e6)).toString();
|
|
594
|
+
const usdcContract = new import_ethers2.ethers.Contract(
|
|
595
|
+
this.chainConfig.usdc,
|
|
596
|
+
PERMIT_ABI,
|
|
597
|
+
this.provider
|
|
598
|
+
);
|
|
599
|
+
const nonce = Number(await usdcContract.nonces(ownerAddress));
|
|
600
|
+
const domain = {
|
|
601
|
+
name: "USD Coin",
|
|
602
|
+
version: "2",
|
|
603
|
+
chainId: this.chainConfig.chainId,
|
|
604
|
+
verifyingContract: this.chainConfig.usdc
|
|
605
|
+
};
|
|
606
|
+
const types = {
|
|
607
|
+
Permit: [
|
|
608
|
+
{ name: "owner", type: "address" },
|
|
609
|
+
{ name: "spender", type: "address" },
|
|
610
|
+
{ name: "value", type: "uint256" },
|
|
611
|
+
{ name: "nonce", type: "uint256" },
|
|
612
|
+
{ name: "deadline", type: "uint256" }
|
|
613
|
+
]
|
|
614
|
+
};
|
|
615
|
+
const permitMessage = {
|
|
616
|
+
owner: ownerAddress,
|
|
617
|
+
spender: this.address,
|
|
618
|
+
value,
|
|
619
|
+
nonce,
|
|
620
|
+
deadline
|
|
621
|
+
};
|
|
622
|
+
const typedData = {
|
|
623
|
+
types: { ...types, EIP712Domain: [
|
|
624
|
+
{ name: "name", type: "string" },
|
|
625
|
+
{ name: "version", type: "string" },
|
|
626
|
+
{ name: "chainId", type: "uint256" },
|
|
627
|
+
{ name: "verifyingContract", type: "address" }
|
|
628
|
+
] },
|
|
629
|
+
primaryType: "Permit",
|
|
630
|
+
domain,
|
|
631
|
+
message: permitMessage
|
|
632
|
+
};
|
|
633
|
+
const cliCommand = `npx moltspay sign-permit \\
|
|
634
|
+
--owner ${ownerAddress} \\
|
|
635
|
+
--spender ${this.address} \\
|
|
636
|
+
--amount ${amount} \\
|
|
637
|
+
--deadline ${deadline} \\
|
|
638
|
+
--nonce ${nonce} \\
|
|
639
|
+
--chain ${this.chain}`;
|
|
640
|
+
const message = `\u{1F510} Authorization Request
|
|
641
|
+
|
|
642
|
+
I need permission to spend up to ${amount} USDC from your wallet.
|
|
643
|
+
|
|
644
|
+
**Details:**
|
|
645
|
+
- Your wallet: ${ownerAddress}
|
|
646
|
+
- My address: ${this.address}
|
|
647
|
+
- Amount: ${amount} USDC
|
|
648
|
+
- Expires: ${new Date(deadline * 1e3).toISOString()}
|
|
649
|
+
- Chain: ${this.chainConfig.name}
|
|
650
|
+
|
|
651
|
+
**Option 1: Sign with CLI** (if you have the private key)
|
|
652
|
+
\`\`\`
|
|
653
|
+
${cliCommand}
|
|
654
|
+
\`\`\`
|
|
655
|
+
|
|
656
|
+
**Option 2: Sign with MetaMask**
|
|
657
|
+
Visit: https://moltspay.vercel.app/permit?data=${encodeURIComponent(JSON.stringify(typedData))}
|
|
658
|
+
|
|
659
|
+
After signing, send me the signature (v, r, s).`;
|
|
660
|
+
return { message, typedData, cliCommand };
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
function getAgentAddress(config) {
|
|
664
|
+
const wallet = new AgentWallet(config);
|
|
665
|
+
return wallet.address;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// src/wallet/Wallet.ts
|
|
669
|
+
var import_ethers3 = require("ethers");
|
|
359
670
|
var Wallet = class {
|
|
360
671
|
chain;
|
|
361
672
|
chainConfig;
|
|
@@ -371,10 +682,10 @@ var Wallet = class {
|
|
|
371
682
|
throw new Error("privateKey is required. Set via config or PAYMENT_AGENT_PRIVATE_KEY env var.");
|
|
372
683
|
}
|
|
373
684
|
const rpcUrl = config.rpcUrl || this.chainConfig.rpc;
|
|
374
|
-
this.provider = new
|
|
375
|
-
this.wallet = new
|
|
685
|
+
this.provider = new import_ethers3.ethers.JsonRpcProvider(rpcUrl);
|
|
686
|
+
this.wallet = new import_ethers3.ethers.Wallet(privateKey, this.provider);
|
|
376
687
|
this.address = this.wallet.address;
|
|
377
|
-
this.usdcContract = new
|
|
688
|
+
this.usdcContract = new import_ethers3.ethers.Contract(
|
|
378
689
|
this.chainConfig.usdc,
|
|
379
690
|
ERC20_ABI,
|
|
380
691
|
this.wallet
|
|
@@ -390,7 +701,7 @@ var Wallet = class {
|
|
|
390
701
|
]);
|
|
391
702
|
return {
|
|
392
703
|
address: this.address,
|
|
393
|
-
eth:
|
|
704
|
+
eth: import_ethers3.ethers.formatEther(ethBalance),
|
|
394
705
|
usdc: (Number(usdcBalance) / 1e6).toFixed(2),
|
|
395
706
|
chain: this.chain
|
|
396
707
|
};
|
|
@@ -400,7 +711,7 @@ var Wallet = class {
|
|
|
400
711
|
*/
|
|
401
712
|
async transfer(to, amount) {
|
|
402
713
|
try {
|
|
403
|
-
to =
|
|
714
|
+
to = import_ethers3.ethers.getAddress(to);
|
|
404
715
|
const amountWei = BigInt(Math.floor(amount * 1e6));
|
|
405
716
|
const balance = await this.usdcContract.balanceOf(this.address);
|
|
406
717
|
if (BigInt(balance) < amountWei) {
|
|
@@ -441,7 +752,7 @@ var Wallet = class {
|
|
|
441
752
|
*/
|
|
442
753
|
async getEthBalance() {
|
|
443
754
|
const balance = await this.provider.getBalance(this.address);
|
|
444
|
-
return
|
|
755
|
+
return import_ethers3.ethers.formatEther(balance);
|
|
445
756
|
}
|
|
446
757
|
/**
|
|
447
758
|
* Get USDC balance
|
|
@@ -453,14 +764,14 @@ var Wallet = class {
|
|
|
453
764
|
};
|
|
454
765
|
|
|
455
766
|
// src/audit/AuditLog.ts
|
|
456
|
-
var
|
|
457
|
-
var
|
|
767
|
+
var fs2 = __toESM(require("fs"));
|
|
768
|
+
var path2 = __toESM(require("path"));
|
|
458
769
|
var crypto = __toESM(require("crypto"));
|
|
459
770
|
var AuditLog = class {
|
|
460
771
|
basePath;
|
|
461
772
|
lastHash = "0000000000000000";
|
|
462
773
|
constructor(basePath) {
|
|
463
|
-
this.basePath = basePath ||
|
|
774
|
+
this.basePath = basePath || path2.join(process.cwd(), "data", "audit");
|
|
464
775
|
this.ensureDir();
|
|
465
776
|
this.loadLastHash();
|
|
466
777
|
}
|
|
@@ -489,7 +800,7 @@ var AuditLog = class {
|
|
|
489
800
|
this.lastHash = entry.hash;
|
|
490
801
|
const filePath = this.getFilePath(now);
|
|
491
802
|
const line = JSON.stringify(entry) + "\n";
|
|
492
|
-
|
|
803
|
+
fs2.appendFileSync(filePath, line, "utf-8");
|
|
493
804
|
return entry;
|
|
494
805
|
}
|
|
495
806
|
/**
|
|
@@ -497,10 +808,10 @@ var AuditLog = class {
|
|
|
497
808
|
*/
|
|
498
809
|
read(date) {
|
|
499
810
|
const filePath = this.getFilePath(date || /* @__PURE__ */ new Date());
|
|
500
|
-
if (!
|
|
811
|
+
if (!fs2.existsSync(filePath)) {
|
|
501
812
|
return [];
|
|
502
813
|
}
|
|
503
|
-
const content =
|
|
814
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
504
815
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
505
816
|
return lines.map((line) => JSON.parse(line));
|
|
506
817
|
}
|
|
@@ -551,7 +862,7 @@ var AuditLog = class {
|
|
|
551
862
|
*/
|
|
552
863
|
getFilePath(date) {
|
|
553
864
|
const dateStr = date.toISOString().slice(0, 10);
|
|
554
|
-
return
|
|
865
|
+
return path2.join(this.basePath, `audit_${dateStr}.jsonl`);
|
|
555
866
|
}
|
|
556
867
|
/**
|
|
557
868
|
* Calculate entry hash
|
|
@@ -589,8 +900,8 @@ var AuditLog = class {
|
|
|
589
900
|
* Ensure directory exists
|
|
590
901
|
*/
|
|
591
902
|
ensureDir() {
|
|
592
|
-
if (!
|
|
593
|
-
|
|
903
|
+
if (!fs2.existsSync(this.basePath)) {
|
|
904
|
+
fs2.mkdirSync(this.basePath, { recursive: true });
|
|
594
905
|
}
|
|
595
906
|
}
|
|
596
907
|
};
|
|
@@ -854,7 +1165,7 @@ var SecureWallet = class {
|
|
|
854
1165
|
};
|
|
855
1166
|
|
|
856
1167
|
// src/wallet/createWallet.ts
|
|
857
|
-
var
|
|
1168
|
+
var import_ethers4 = require("ethers");
|
|
858
1169
|
var import_fs = require("fs");
|
|
859
1170
|
var import_path = require("path");
|
|
860
1171
|
var import_crypto = require("crypto");
|
|
@@ -899,7 +1210,7 @@ function createWallet(options = {}) {
|
|
|
899
1210
|
}
|
|
900
1211
|
}
|
|
901
1212
|
try {
|
|
902
|
-
const wallet =
|
|
1213
|
+
const wallet = import_ethers4.ethers.Wallet.createRandom();
|
|
903
1214
|
const walletData = {
|
|
904
1215
|
address: wallet.address,
|
|
905
1216
|
label: options.label,
|
|
@@ -954,25 +1265,25 @@ function loadWallet(options = {}) {
|
|
|
954
1265
|
}
|
|
955
1266
|
}
|
|
956
1267
|
function getWalletAddress(storagePath) {
|
|
957
|
-
const
|
|
958
|
-
if (!(0, import_fs.existsSync)(
|
|
1268
|
+
const path3 = storagePath || (0, import_path.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
|
|
1269
|
+
if (!(0, import_fs.existsSync)(path3)) {
|
|
959
1270
|
return null;
|
|
960
1271
|
}
|
|
961
1272
|
try {
|
|
962
|
-
const data = JSON.parse((0, import_fs.readFileSync)(
|
|
1273
|
+
const data = JSON.parse((0, import_fs.readFileSync)(path3, "utf8"));
|
|
963
1274
|
return data.address;
|
|
964
1275
|
} catch {
|
|
965
1276
|
return null;
|
|
966
1277
|
}
|
|
967
1278
|
}
|
|
968
1279
|
function walletExists(storagePath) {
|
|
969
|
-
const
|
|
970
|
-
return (0, import_fs.existsSync)(
|
|
1280
|
+
const path3 = storagePath || (0, import_path.join)(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);
|
|
1281
|
+
return (0, import_fs.existsSync)(path3);
|
|
971
1282
|
}
|
|
972
1283
|
|
|
973
1284
|
// src/wallet/PermitWallet.ts
|
|
974
|
-
var
|
|
975
|
-
var
|
|
1285
|
+
var import_ethers5 = require("ethers");
|
|
1286
|
+
var PERMIT_ABI2 = [
|
|
976
1287
|
...ERC20_ABI,
|
|
977
1288
|
"function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)",
|
|
978
1289
|
"function transferFrom(address from, address to, uint256 amount) returns (bool)",
|
|
@@ -1003,12 +1314,12 @@ var PermitWallet = class {
|
|
|
1003
1314
|
throw new Error("privateKey is required. Set via config, env var, or walletPath.");
|
|
1004
1315
|
}
|
|
1005
1316
|
const rpcUrl = config.rpcUrl || this.chainConfig.rpc;
|
|
1006
|
-
this.provider = new
|
|
1007
|
-
this.wallet = new
|
|
1317
|
+
this.provider = new import_ethers5.ethers.JsonRpcProvider(rpcUrl);
|
|
1318
|
+
this.wallet = new import_ethers5.ethers.Wallet(privateKey, this.provider);
|
|
1008
1319
|
this.address = this.wallet.address;
|
|
1009
|
-
this.usdcContract = new
|
|
1320
|
+
this.usdcContract = new import_ethers5.ethers.Contract(
|
|
1010
1321
|
this.chainConfig.usdc,
|
|
1011
|
-
|
|
1322
|
+
PERMIT_ABI2,
|
|
1012
1323
|
this.wallet
|
|
1013
1324
|
);
|
|
1014
1325
|
}
|
|
@@ -1051,9 +1362,9 @@ var PermitWallet = class {
|
|
|
1051
1362
|
async transferWithPermit(params) {
|
|
1052
1363
|
const { to, amount, permit } = params;
|
|
1053
1364
|
try {
|
|
1054
|
-
const toAddress =
|
|
1055
|
-
const ownerAddress =
|
|
1056
|
-
if (
|
|
1365
|
+
const toAddress = import_ethers5.ethers.getAddress(to);
|
|
1366
|
+
const ownerAddress = import_ethers5.ethers.getAddress(permit.owner);
|
|
1367
|
+
if (import_ethers5.ethers.getAddress(permit.spender).toLowerCase() !== this.address.toLowerCase()) {
|
|
1057
1368
|
return {
|
|
1058
1369
|
success: false,
|
|
1059
1370
|
error: `Permit spender (${permit.spender}) doesn't match wallet address (${this.address})`
|
|
@@ -1157,7 +1468,7 @@ var PermitWallet = class {
|
|
|
1157
1468
|
*/
|
|
1158
1469
|
async getGasBalance() {
|
|
1159
1470
|
const balance = await this.provider.getBalance(this.address);
|
|
1160
|
-
return
|
|
1471
|
+
return import_ethers5.ethers.formatEther(balance);
|
|
1161
1472
|
}
|
|
1162
1473
|
/**
|
|
1163
1474
|
* Check if there's enough gas
|
|
@@ -1218,7 +1529,7 @@ After signing, send { v, r, s, deadline } to the Agent.
|
|
|
1218
1529
|
}
|
|
1219
1530
|
|
|
1220
1531
|
// src/wallet/signPermit.ts
|
|
1221
|
-
var
|
|
1532
|
+
var import_ethers6 = require("ethers");
|
|
1222
1533
|
async function signPermit(config, params) {
|
|
1223
1534
|
const chain = config.chain || "base";
|
|
1224
1535
|
const chainConfig = getChain(chain);
|
|
@@ -1227,9 +1538,9 @@ async function signPermit(config, params) {
|
|
|
1227
1538
|
throw new Error("privateKey is required");
|
|
1228
1539
|
}
|
|
1229
1540
|
const rpcUrl = config.rpcUrl || chainConfig.rpc;
|
|
1230
|
-
const provider = new
|
|
1231
|
-
const wallet = new
|
|
1232
|
-
const usdcContract = new
|
|
1541
|
+
const provider = new import_ethers6.ethers.JsonRpcProvider(rpcUrl);
|
|
1542
|
+
const wallet = new import_ethers6.ethers.Wallet(privateKey, provider);
|
|
1543
|
+
const usdcContract = new import_ethers6.ethers.Contract(chainConfig.usdc, ERC20_ABI, provider);
|
|
1233
1544
|
const nonce = Number(await usdcContract.nonces(wallet.address));
|
|
1234
1545
|
let deadline;
|
|
1235
1546
|
if (!params.deadline) {
|
|
@@ -1263,7 +1574,7 @@ async function signPermit(config, params) {
|
|
|
1263
1574
|
deadline
|
|
1264
1575
|
};
|
|
1265
1576
|
const signature = await wallet.signTypedData(domain, types, message);
|
|
1266
|
-
const sig =
|
|
1577
|
+
const sig = import_ethers6.ethers.Signature.from(signature);
|
|
1267
1578
|
return {
|
|
1268
1579
|
owner: wallet.address,
|
|
1269
1580
|
spender: params.spender,
|
|
@@ -1286,8 +1597,8 @@ var PermitSigner = class {
|
|
|
1286
1597
|
};
|
|
1287
1598
|
|
|
1288
1599
|
// src/wallet/AllowanceWallet.ts
|
|
1289
|
-
var
|
|
1290
|
-
var
|
|
1600
|
+
var import_ethers7 = require("ethers");
|
|
1601
|
+
var PERMIT_ABI3 = [
|
|
1291
1602
|
...ERC20_ABI,
|
|
1292
1603
|
"function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)",
|
|
1293
1604
|
"function transferFrom(address from, address to, uint256 amount) returns (bool)",
|
|
@@ -1308,12 +1619,12 @@ var AllowanceWallet = class {
|
|
|
1308
1619
|
this.chain = config.chain || "base_sepolia";
|
|
1309
1620
|
this.chainConfig = getChain(this.chain);
|
|
1310
1621
|
const rpcUrl = config.rpcUrl || this.chainConfig.rpc;
|
|
1311
|
-
this.provider = new
|
|
1312
|
-
this.wallet = new
|
|
1622
|
+
this.provider = new import_ethers7.ethers.JsonRpcProvider(rpcUrl);
|
|
1623
|
+
this.wallet = new import_ethers7.ethers.Wallet(config.privateKey, this.provider);
|
|
1313
1624
|
this.address = this.wallet.address;
|
|
1314
|
-
this.usdcContract = new
|
|
1625
|
+
this.usdcContract = new import_ethers7.ethers.Contract(
|
|
1315
1626
|
this.chainConfig.usdc,
|
|
1316
|
-
|
|
1627
|
+
PERMIT_ABI3,
|
|
1317
1628
|
this.wallet
|
|
1318
1629
|
);
|
|
1319
1630
|
}
|
|
@@ -1335,20 +1646,20 @@ var AllowanceWallet = class {
|
|
|
1335
1646
|
* Check allowance status with an owner
|
|
1336
1647
|
*/
|
|
1337
1648
|
async checkAllowance(owner) {
|
|
1338
|
-
const ownerAddress =
|
|
1649
|
+
const ownerAddress = import_ethers7.ethers.getAddress(owner);
|
|
1339
1650
|
const [allowance, ownerBalance, agentGasBalance] = await Promise.all([
|
|
1340
1651
|
this.usdcContract.allowance(ownerAddress, this.address),
|
|
1341
1652
|
this.usdcContract.balanceOf(ownerAddress),
|
|
1342
1653
|
this.provider.getBalance(this.address)
|
|
1343
1654
|
]);
|
|
1344
1655
|
const allowanceNum = Number(allowance) / 1e6;
|
|
1345
|
-
const hasGas = Number(
|
|
1656
|
+
const hasGas = Number(import_ethers7.ethers.formatEther(agentGasBalance)) >= 1e-4;
|
|
1346
1657
|
return {
|
|
1347
1658
|
owner: ownerAddress,
|
|
1348
1659
|
agent: this.address,
|
|
1349
1660
|
allowance: allowanceNum.toFixed(2),
|
|
1350
1661
|
ownerBalance: (Number(ownerBalance) / 1e6).toFixed(2),
|
|
1351
|
-
agentGasBalance:
|
|
1662
|
+
agentGasBalance: import_ethers7.ethers.formatEther(agentGasBalance),
|
|
1352
1663
|
canSpend: allowanceNum > 0 && hasGas,
|
|
1353
1664
|
chain: this.chainConfig.name
|
|
1354
1665
|
};
|
|
@@ -1376,18 +1687,18 @@ var AllowanceWallet = class {
|
|
|
1376
1687
|
async spend(params) {
|
|
1377
1688
|
const { to, amount, permit } = params;
|
|
1378
1689
|
try {
|
|
1379
|
-
const toAddress =
|
|
1690
|
+
const toAddress = import_ethers7.ethers.getAddress(to);
|
|
1380
1691
|
const amountWei = BigInt(Math.floor(amount * 1e6));
|
|
1381
1692
|
let ownerPermit = permit;
|
|
1382
1693
|
let ownerAddress;
|
|
1383
1694
|
if (ownerPermit) {
|
|
1384
|
-
ownerAddress =
|
|
1695
|
+
ownerAddress = import_ethers7.ethers.getAddress(ownerPermit.owner);
|
|
1385
1696
|
this.storePermit(ownerPermit);
|
|
1386
1697
|
} else {
|
|
1387
1698
|
for (const [owner, p] of this.permits) {
|
|
1388
1699
|
const allowance = await this.usdcContract.allowance(owner, this.address);
|
|
1389
1700
|
if (BigInt(allowance) >= amountWei) {
|
|
1390
|
-
ownerAddress =
|
|
1701
|
+
ownerAddress = import_ethers7.ethers.getAddress(owner);
|
|
1391
1702
|
ownerPermit = p;
|
|
1392
1703
|
break;
|
|
1393
1704
|
}
|
|
@@ -1488,7 +1799,7 @@ var AllowanceWallet = class {
|
|
|
1488
1799
|
*/
|
|
1489
1800
|
async getGasBalance() {
|
|
1490
1801
|
const balance = await this.provider.getBalance(this.address);
|
|
1491
|
-
return
|
|
1802
|
+
return import_ethers7.ethers.formatEther(balance);
|
|
1492
1803
|
}
|
|
1493
1804
|
};
|
|
1494
1805
|
function generatePermitInstructions(params) {
|
|
@@ -1562,7 +1873,7 @@ ${JSON.stringify(typedData, null, 2)}
|
|
|
1562
1873
|
}
|
|
1563
1874
|
|
|
1564
1875
|
// src/permit/Permit.ts
|
|
1565
|
-
var
|
|
1876
|
+
var import_ethers8 = require("ethers");
|
|
1566
1877
|
var PermitPayment = class {
|
|
1567
1878
|
chain;
|
|
1568
1879
|
chainConfig;
|
|
@@ -1575,13 +1886,13 @@ var PermitPayment = class {
|
|
|
1575
1886
|
this.chainConfig = getChain(this.chain);
|
|
1576
1887
|
this.spenderAddress = config.spenderAddress || process.env.PAYMENT_AGENT_WALLET || "";
|
|
1577
1888
|
const rpcUrl = config.rpcUrl || this.chainConfig.rpc;
|
|
1578
|
-
this.provider = new
|
|
1889
|
+
this.provider = new import_ethers8.ethers.JsonRpcProvider(rpcUrl);
|
|
1579
1890
|
const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;
|
|
1580
1891
|
if (privateKey) {
|
|
1581
|
-
this.wallet = new
|
|
1892
|
+
this.wallet = new import_ethers8.ethers.Wallet(privateKey, this.provider);
|
|
1582
1893
|
this.spenderAddress = this.wallet.address;
|
|
1583
1894
|
}
|
|
1584
|
-
this.usdcContract = new
|
|
1895
|
+
this.usdcContract = new import_ethers8.ethers.Contract(
|
|
1585
1896
|
this.chainConfig.usdc,
|
|
1586
1897
|
ERC20_ABI,
|
|
1587
1898
|
this.wallet || this.provider
|
|
@@ -1864,8 +2175,8 @@ var OrderManager = class {
|
|
|
1864
2175
|
};
|
|
1865
2176
|
|
|
1866
2177
|
// src/verify/index.ts
|
|
1867
|
-
var
|
|
1868
|
-
var TRANSFER_EVENT_TOPIC =
|
|
2178
|
+
var import_ethers9 = require("ethers");
|
|
2179
|
+
var TRANSFER_EVENT_TOPIC = import_ethers9.ethers.id("Transfer(address,address,uint256)");
|
|
1869
2180
|
async function verifyPayment(params) {
|
|
1870
2181
|
const { txHash, expectedAmount, expectedTo } = params;
|
|
1871
2182
|
let chain;
|
|
@@ -1882,7 +2193,7 @@ async function verifyPayment(params) {
|
|
|
1882
2193
|
return { verified: false, error: `Unsupported chain: ${params.chain}` };
|
|
1883
2194
|
}
|
|
1884
2195
|
try {
|
|
1885
|
-
const provider = new
|
|
2196
|
+
const provider = new import_ethers9.ethers.JsonRpcProvider(chain.rpc);
|
|
1886
2197
|
const receipt = await provider.getTransactionReceipt(txHash);
|
|
1887
2198
|
if (!receipt) {
|
|
1888
2199
|
return { verified: false, error: "Transaction not found or not confirmed" };
|
|
@@ -1942,7 +2253,7 @@ async function getTransactionStatus(txHash, chain = "base") {
|
|
|
1942
2253
|
return { status: "not_found" };
|
|
1943
2254
|
}
|
|
1944
2255
|
try {
|
|
1945
|
-
const provider = new
|
|
2256
|
+
const provider = new import_ethers9.ethers.JsonRpcProvider(chainConfig.rpc);
|
|
1946
2257
|
const receipt = await provider.getTransactionReceipt(txHash);
|
|
1947
2258
|
if (!receipt) {
|
|
1948
2259
|
const tx = await provider.getTransaction(txHash);
|
|
@@ -1979,7 +2290,7 @@ async function waitForTransaction(txHash, chain = "base", confirmations = 1, tim
|
|
|
1979
2290
|
} catch (e) {
|
|
1980
2291
|
return { verified: false, confirmed: false, error: `Unsupported chain: ${chain}` };
|
|
1981
2292
|
}
|
|
1982
|
-
const provider = new
|
|
2293
|
+
const provider = new import_ethers9.ethers.JsonRpcProvider(chainConfig.rpc);
|
|
1983
2294
|
try {
|
|
1984
2295
|
const receipt = await provider.waitForTransaction(txHash, confirmations, timeoutMs);
|
|
1985
2296
|
if (!receipt) {
|
|
@@ -2667,6 +2978,7 @@ function parseStatusMarker(message) {
|
|
|
2667
2978
|
}
|
|
2668
2979
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2669
2980
|
0 && (module.exports = {
|
|
2981
|
+
AgentWallet,
|
|
2670
2982
|
AllowanceWallet,
|
|
2671
2983
|
AuditLog,
|
|
2672
2984
|
BuyerTemplates,
|
|
@@ -2694,6 +3006,7 @@ function parseStatusMarker(message) {
|
|
|
2694
3006
|
generateReceipt,
|
|
2695
3007
|
generateReceiptFromInvoice,
|
|
2696
3008
|
generateWalletGuide,
|
|
3009
|
+
getAgentAddress,
|
|
2697
3010
|
getChain,
|
|
2698
3011
|
getChainById,
|
|
2699
3012
|
getTransactionStatus,
|