moltspay 0.2.1 → 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/{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 +26 -26
- package/dist/index.d.ts +26 -26
- package/dist/index.js +69 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +69 -69
- 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 +22 -22
- package/dist/wallet/index.d.ts +22 -22
- package/dist/wallet/index.js +30 -30
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +30 -30
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/wallet/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { C as ChainName, a as ChainConfig, W as WalletBalance, j as TransferResult, S as SecureWalletConfig, T as TransferParams, e as PendingTransfer, i as SecurityLimits } from '../index-
|
|
1
|
+
import { C as ChainName, a as ChainConfig, W as WalletBalance, j as TransferResult, S as SecureWalletConfig, T as TransferParams, e as PendingTransfer, i as SecurityLimits } from '../index-CyFg9s2m.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Wallet -
|
|
4
|
+
* Wallet - Basic Custody Wallet
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
6
|
+
* Features:
|
|
7
|
+
* - Query balance
|
|
8
|
+
* - Send USDC transfer
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
interface WalletConfig {
|
|
@@ -22,19 +22,19 @@ declare class Wallet {
|
|
|
22
22
|
private usdcContract;
|
|
23
23
|
constructor(config?: WalletConfig);
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* Get wallet balance
|
|
26
26
|
*/
|
|
27
27
|
getBalance(): Promise<WalletBalance>;
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Send USDC transfer
|
|
30
30
|
*/
|
|
31
31
|
transfer(to: string, amount: number): Promise<TransferResult>;
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
33
|
+
* Get ETH balance
|
|
34
34
|
*/
|
|
35
35
|
getEthBalance(): Promise<string>;
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* Get USDC balance
|
|
38
38
|
*/
|
|
39
39
|
getUsdcBalance(): Promise<string>;
|
|
40
40
|
}
|
|
@@ -49,55 +49,55 @@ declare class SecureWallet {
|
|
|
49
49
|
private pendingTransfers;
|
|
50
50
|
constructor(config?: SecureWalletConfig);
|
|
51
51
|
/**
|
|
52
|
-
*
|
|
52
|
+
* Get wallet address
|
|
53
53
|
*/
|
|
54
54
|
get address(): string;
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
56
|
+
* Get balance
|
|
57
57
|
*/
|
|
58
58
|
getBalance(): Promise<WalletBalance>;
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
60
|
+
* Secure transfer (with limit and whitelist checks)
|
|
61
61
|
*
|
|
62
|
-
*
|
|
62
|
+
* Supports two calling methods:
|
|
63
63
|
* - transfer({ to, amount, reason?, requester? })
|
|
64
64
|
* - transfer(to, amount)
|
|
65
65
|
*/
|
|
66
66
|
transfer(paramsOrTo: TransferParams | string, amountArg?: number | string): Promise<TransferResult>;
|
|
67
67
|
/**
|
|
68
|
-
*
|
|
68
|
+
* Approve pending transfer
|
|
69
69
|
*/
|
|
70
70
|
approve(requestId: string, approver: string): Promise<TransferResult>;
|
|
71
71
|
/**
|
|
72
|
-
*
|
|
72
|
+
* Reject pending transfer
|
|
73
73
|
*/
|
|
74
74
|
reject(requestId: string, rejecter: string, reason?: string): Promise<void>;
|
|
75
75
|
/**
|
|
76
|
-
*
|
|
76
|
+
* Add to whitelist
|
|
77
77
|
*/
|
|
78
78
|
addToWhitelist(address: string, addedBy: string): Promise<void>;
|
|
79
79
|
/**
|
|
80
|
-
*
|
|
80
|
+
* Remove from whitelist
|
|
81
81
|
*/
|
|
82
82
|
removeFromWhitelist(address: string, removedBy: string): Promise<void>;
|
|
83
83
|
/**
|
|
84
|
-
*
|
|
84
|
+
* Check if address is whitelisted
|
|
85
85
|
*/
|
|
86
86
|
isWhitelisted(address: string): boolean;
|
|
87
87
|
/**
|
|
88
|
-
*
|
|
88
|
+
* Get pending transfers list
|
|
89
89
|
*/
|
|
90
90
|
getPendingTransfers(): PendingTransfer[];
|
|
91
91
|
/**
|
|
92
|
-
*
|
|
92
|
+
* Get current limit config
|
|
93
93
|
*/
|
|
94
94
|
getLimits(): SecurityLimits;
|
|
95
95
|
/**
|
|
96
|
-
*
|
|
96
|
+
* Get daily used amount
|
|
97
97
|
*/
|
|
98
98
|
getDailyUsed(): number;
|
|
99
99
|
/**
|
|
100
|
-
*
|
|
100
|
+
* Update daily limit counter
|
|
101
101
|
*/
|
|
102
102
|
private updateDailyTotal;
|
|
103
103
|
}
|
package/dist/wallet/index.js
CHANGED
|
@@ -46,7 +46,7 @@ var import_ethers = require("ethers");
|
|
|
46
46
|
|
|
47
47
|
// src/chains/index.ts
|
|
48
48
|
var CHAINS = {
|
|
49
|
-
// ============
|
|
49
|
+
// ============ Mainnet ============
|
|
50
50
|
base: {
|
|
51
51
|
name: "Base",
|
|
52
52
|
chainId: 8453,
|
|
@@ -74,7 +74,7 @@ var CHAINS = {
|
|
|
74
74
|
explorerTx: "https://etherscan.io/tx/",
|
|
75
75
|
avgBlockTime: 12
|
|
76
76
|
},
|
|
77
|
-
// ============
|
|
77
|
+
// ============ Testnet ============
|
|
78
78
|
base_sepolia: {
|
|
79
79
|
name: "Base Sepolia",
|
|
80
80
|
chainId: 84532,
|
|
@@ -141,7 +141,7 @@ var Wallet = class {
|
|
|
141
141
|
);
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
|
-
*
|
|
144
|
+
* Get wallet balance
|
|
145
145
|
*/
|
|
146
146
|
async getBalance() {
|
|
147
147
|
const [ethBalance, usdcBalance] = await Promise.all([
|
|
@@ -156,7 +156,7 @@ var Wallet = class {
|
|
|
156
156
|
};
|
|
157
157
|
}
|
|
158
158
|
/**
|
|
159
|
-
*
|
|
159
|
+
* Send USDC transfer
|
|
160
160
|
*/
|
|
161
161
|
async transfer(to, amount) {
|
|
162
162
|
try {
|
|
@@ -197,14 +197,14 @@ var Wallet = class {
|
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
/**
|
|
200
|
-
*
|
|
200
|
+
* Get ETH balance
|
|
201
201
|
*/
|
|
202
202
|
async getEthBalance() {
|
|
203
203
|
const balance = await this.provider.getBalance(this.address);
|
|
204
204
|
return import_ethers.ethers.formatEther(balance);
|
|
205
205
|
}
|
|
206
206
|
/**
|
|
207
|
-
*
|
|
207
|
+
* Get USDC balance
|
|
208
208
|
*/
|
|
209
209
|
async getUsdcBalance() {
|
|
210
210
|
const balance = await this.usdcContract.balanceOf(this.address);
|
|
@@ -225,7 +225,7 @@ var AuditLog = class {
|
|
|
225
225
|
this.loadLastHash();
|
|
226
226
|
}
|
|
227
227
|
/**
|
|
228
|
-
*
|
|
228
|
+
* Record audit log
|
|
229
229
|
*/
|
|
230
230
|
async log(params) {
|
|
231
231
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -242,7 +242,7 @@ var AuditLog = class {
|
|
|
242
242
|
requester: params.requester,
|
|
243
243
|
prev_hash: this.lastHash,
|
|
244
244
|
hash: "",
|
|
245
|
-
//
|
|
245
|
+
// Filled after calculation
|
|
246
246
|
metadata: params.metadata
|
|
247
247
|
};
|
|
248
248
|
entry.hash = this.calculateHash(entry);
|
|
@@ -253,7 +253,7 @@ var AuditLog = class {
|
|
|
253
253
|
return entry;
|
|
254
254
|
}
|
|
255
255
|
/**
|
|
256
|
-
*
|
|
256
|
+
* Read logs for specified date
|
|
257
257
|
*/
|
|
258
258
|
read(date) {
|
|
259
259
|
const filePath = this.getFilePath(date || /* @__PURE__ */ new Date());
|
|
@@ -265,7 +265,7 @@ var AuditLog = class {
|
|
|
265
265
|
return lines.map((line) => JSON.parse(line));
|
|
266
266
|
}
|
|
267
267
|
/**
|
|
268
|
-
*
|
|
268
|
+
* Verify log integrity
|
|
269
269
|
*/
|
|
270
270
|
verify(date) {
|
|
271
271
|
const entries = this.read(date);
|
|
@@ -283,7 +283,7 @@ var AuditLog = class {
|
|
|
283
283
|
return { valid: errors.length === 0, errors };
|
|
284
284
|
}
|
|
285
285
|
/**
|
|
286
|
-
*
|
|
286
|
+
* Search logs
|
|
287
287
|
*/
|
|
288
288
|
search(filter) {
|
|
289
289
|
const results = [];
|
|
@@ -307,14 +307,14 @@ var AuditLog = class {
|
|
|
307
307
|
return results;
|
|
308
308
|
}
|
|
309
309
|
/**
|
|
310
|
-
*
|
|
310
|
+
* Get log file path
|
|
311
311
|
*/
|
|
312
312
|
getFilePath(date) {
|
|
313
313
|
const dateStr = date.toISOString().slice(0, 10);
|
|
314
314
|
return path.join(this.basePath, `audit_${dateStr}.jsonl`);
|
|
315
315
|
}
|
|
316
316
|
/**
|
|
317
|
-
*
|
|
317
|
+
* Calculate entry hash
|
|
318
318
|
*/
|
|
319
319
|
calculateHash(entry) {
|
|
320
320
|
const data = {
|
|
@@ -331,7 +331,7 @@ var AuditLog = class {
|
|
|
331
331
|
return crypto.createHash("sha256").update(str).digest("hex").slice(0, 16);
|
|
332
332
|
}
|
|
333
333
|
/**
|
|
334
|
-
*
|
|
334
|
+
* Load last log entry hash
|
|
335
335
|
*/
|
|
336
336
|
loadLastHash() {
|
|
337
337
|
const today = /* @__PURE__ */ new Date();
|
|
@@ -346,7 +346,7 @@ var AuditLog = class {
|
|
|
346
346
|
}
|
|
347
347
|
}
|
|
348
348
|
/**
|
|
349
|
-
*
|
|
349
|
+
* Ensure directory exists
|
|
350
350
|
*/
|
|
351
351
|
ensureDir() {
|
|
352
352
|
if (!fs.existsSync(this.basePath)) {
|
|
@@ -358,9 +358,9 @@ var AuditLog = class {
|
|
|
358
358
|
// src/wallet/SecureWallet.ts
|
|
359
359
|
var DEFAULT_LIMITS = {
|
|
360
360
|
singleMax: 100,
|
|
361
|
-
//
|
|
361
|
+
// Single max $100
|
|
362
362
|
dailyMax: 1e3,
|
|
363
|
-
//
|
|
363
|
+
// Daily max $1000
|
|
364
364
|
requireWhitelist: true
|
|
365
365
|
};
|
|
366
366
|
var SecureWallet = class {
|
|
@@ -381,21 +381,21 @@ var SecureWallet = class {
|
|
|
381
381
|
this.auditLog = new AuditLog(config.auditPath);
|
|
382
382
|
}
|
|
383
383
|
/**
|
|
384
|
-
*
|
|
384
|
+
* Get wallet address
|
|
385
385
|
*/
|
|
386
386
|
get address() {
|
|
387
387
|
return this.wallet.address;
|
|
388
388
|
}
|
|
389
389
|
/**
|
|
390
|
-
*
|
|
390
|
+
* Get balance
|
|
391
391
|
*/
|
|
392
392
|
async getBalance() {
|
|
393
393
|
return this.wallet.getBalance();
|
|
394
394
|
}
|
|
395
395
|
/**
|
|
396
|
-
*
|
|
396
|
+
* Secure transfer (with limit and whitelist checks)
|
|
397
397
|
*
|
|
398
|
-
*
|
|
398
|
+
* Supports two calling methods:
|
|
399
399
|
* - transfer({ to, amount, reason?, requester? })
|
|
400
400
|
* - transfer(to, amount)
|
|
401
401
|
*/
|
|
@@ -495,7 +495,7 @@ var SecureWallet = class {
|
|
|
495
495
|
return result;
|
|
496
496
|
}
|
|
497
497
|
/**
|
|
498
|
-
*
|
|
498
|
+
* Approve pending transfer
|
|
499
499
|
*/
|
|
500
500
|
async approve(requestId, approver) {
|
|
501
501
|
const pending = this.pendingTransfers.get(requestId);
|
|
@@ -536,7 +536,7 @@ var SecureWallet = class {
|
|
|
536
536
|
return result;
|
|
537
537
|
}
|
|
538
538
|
/**
|
|
539
|
-
*
|
|
539
|
+
* Reject pending transfer
|
|
540
540
|
*/
|
|
541
541
|
async reject(requestId, rejecter, reason) {
|
|
542
542
|
const pending = this.pendingTransfers.get(requestId);
|
|
@@ -551,7 +551,7 @@ var SecureWallet = class {
|
|
|
551
551
|
});
|
|
552
552
|
}
|
|
553
553
|
/**
|
|
554
|
-
*
|
|
554
|
+
* Add to whitelist
|
|
555
555
|
*/
|
|
556
556
|
async addToWhitelist(address, addedBy) {
|
|
557
557
|
const addr = address.toLowerCase();
|
|
@@ -564,7 +564,7 @@ var SecureWallet = class {
|
|
|
564
564
|
});
|
|
565
565
|
}
|
|
566
566
|
/**
|
|
567
|
-
*
|
|
567
|
+
* Remove from whitelist
|
|
568
568
|
*/
|
|
569
569
|
async removeFromWhitelist(address, removedBy) {
|
|
570
570
|
const addr = address.toLowerCase();
|
|
@@ -577,32 +577,32 @@ var SecureWallet = class {
|
|
|
577
577
|
});
|
|
578
578
|
}
|
|
579
579
|
/**
|
|
580
|
-
*
|
|
580
|
+
* Check if address is whitelisted
|
|
581
581
|
*/
|
|
582
582
|
isWhitelisted(address) {
|
|
583
583
|
return this.whitelist.has(address.toLowerCase());
|
|
584
584
|
}
|
|
585
585
|
/**
|
|
586
|
-
*
|
|
586
|
+
* Get pending transfers list
|
|
587
587
|
*/
|
|
588
588
|
getPendingTransfers() {
|
|
589
589
|
return Array.from(this.pendingTransfers.values()).filter((p) => p.status === "pending");
|
|
590
590
|
}
|
|
591
591
|
/**
|
|
592
|
-
*
|
|
592
|
+
* Get current limit config
|
|
593
593
|
*/
|
|
594
594
|
getLimits() {
|
|
595
595
|
return { ...this.limits };
|
|
596
596
|
}
|
|
597
597
|
/**
|
|
598
|
-
*
|
|
598
|
+
* Get daily used amount
|
|
599
599
|
*/
|
|
600
600
|
getDailyUsed() {
|
|
601
601
|
this.updateDailyTotal();
|
|
602
602
|
return this.dailyTotal;
|
|
603
603
|
}
|
|
604
604
|
/**
|
|
605
|
-
*
|
|
605
|
+
* Update daily limit counter
|
|
606
606
|
*/
|
|
607
607
|
updateDailyTotal() {
|
|
608
608
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
package/dist/wallet/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/wallet/index.ts","../../src/wallet/Wallet.ts","../../src/chains/index.ts","../../src/audit/AuditLog.ts","../../src/wallet/SecureWallet.ts","../../src/wallet/createWallet.ts","../../src/wallet/PermitWallet.ts"],"sourcesContent":["export { Wallet, type WalletConfig } from './Wallet.js';\nexport { SecureWallet } from './SecureWallet.js';\nexport { \n createWallet, \n loadWallet, \n getWalletAddress, \n walletExists,\n type CreateWalletOptions,\n type CreateWalletResult,\n type WalletData,\n} from './createWallet.js';\nexport { \n PermitWallet, \n formatPermitRequest,\n type PermitWalletConfig,\n type PermitData,\n type TransferWithPermitParams,\n type TransferWithPermitResult,\n} from './PermitWallet.js';\n","/**\n * Wallet - 基础托管钱包\n * \n * 功能:\n * - 查询余额\n * - 发送 USDC 转账\n */\n\nimport { ethers } from 'ethers';\nimport { getChain, ERC20_ABI } from '../chains/index.js';\nimport type {\n ChainName,\n ChainConfig,\n WalletBalance,\n TransferResult,\n} from '../types/index.js';\n\nexport interface WalletConfig {\n chain?: ChainName;\n privateKey?: string;\n rpcUrl?: string;\n}\n\nexport class Wallet {\n readonly chain: ChainName;\n readonly chainConfig: ChainConfig;\n readonly address: string;\n \n private wallet: ethers.Wallet;\n private provider: ethers.JsonRpcProvider;\n private usdcContract: ethers.Contract;\n\n constructor(config: WalletConfig = {}) {\n this.chain = config.chain || 'base_sepolia';\n this.chainConfig = getChain(this.chain);\n \n const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;\n if (!privateKey) {\n throw new Error('privateKey is required. Set via config or PAYMENT_AGENT_PRIVATE_KEY env var.');\n }\n\n const rpcUrl = config.rpcUrl || this.chainConfig.rpc;\n this.provider = new ethers.JsonRpcProvider(rpcUrl);\n this.wallet = new ethers.Wallet(privateKey, this.provider);\n this.address = this.wallet.address;\n \n this.usdcContract = new ethers.Contract(\n this.chainConfig.usdc,\n ERC20_ABI,\n this.wallet\n );\n }\n\n /**\n * 获取钱包余额\n */\n async getBalance(): Promise<WalletBalance> {\n const [ethBalance, usdcBalance] = await Promise.all([\n this.provider.getBalance(this.address),\n this.usdcContract.balanceOf(this.address),\n ]);\n\n return {\n address: this.address,\n eth: ethers.formatEther(ethBalance),\n usdc: (Number(usdcBalance) / 1e6).toFixed(2),\n chain: this.chain,\n };\n }\n\n /**\n * 发送 USDC 转账\n */\n async transfer(to: string, amount: number): Promise<TransferResult> {\n try {\n // 验证地址\n to = ethers.getAddress(to);\n \n // 转换金额(USDC 6位小数)\n const amountWei = BigInt(Math.floor(amount * 1e6));\n\n // 检查余额\n const balance = await this.usdcContract.balanceOf(this.address);\n if (BigInt(balance) < amountWei) {\n return {\n success: false,\n error: `Insufficient USDC balance: ${Number(balance) / 1e6} < ${amount}`,\n };\n }\n\n // 发送交易\n const tx = await this.usdcContract.transfer(to, amountWei);\n const receipt = await tx.wait();\n\n if (receipt.status === 1) {\n return {\n success: true,\n tx_hash: tx.hash,\n from: this.address,\n to,\n amount,\n gas_used: Number(receipt.gasUsed),\n block_number: receipt.blockNumber,\n explorer_url: `${this.chainConfig.explorerTx}${tx.hash}`,\n };\n } else {\n return {\n success: false,\n tx_hash: tx.hash,\n error: 'Transaction reverted',\n };\n }\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n }\n\n /**\n * 获取 ETH 余额\n */\n async getEthBalance(): Promise<string> {\n const balance = await this.provider.getBalance(this.address);\n return ethers.formatEther(balance);\n }\n\n /**\n * 获取 USDC 余额\n */\n async getUsdcBalance(): Promise<string> {\n const balance = await this.usdcContract.balanceOf(this.address);\n return (Number(balance) / 1e6).toFixed(2);\n }\n}\n","/**\n * 区块链配置\n */\n\nimport type { ChainConfig, ChainName } from '../types/index.js';\n\nexport const CHAINS: Record<ChainName, ChainConfig> = {\n // ============ 主网 ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n explorer: 'https://basescan.org/address/',\n explorerTx: 'https://basescan.org/tx/',\n avgBlockTime: 2,\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n rpc: 'https://polygon-rpc.com',\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n rpc: 'https://eth.llamarpc.com',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n explorer: 'https://etherscan.io/address/',\n explorerTx: 'https://etherscan.io/tx/',\n avgBlockTime: 12,\n },\n\n // ============ 测试网 ============\n base_sepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n rpc: 'https://sepolia.base.org',\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n sepolia: {\n name: 'Sepolia',\n chainId: 11155111,\n rpc: 'https://rpc.sepolia.org',\n usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n explorer: 'https://sepolia.etherscan.io/address/',\n explorerTx: 'https://sepolia.etherscan.io/tx/',\n avgBlockTime: 12,\n },\n};\n\n/**\n * 获取链配置\n */\nexport function getChain(name: ChainName): ChainConfig {\n const config = CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * 列出所有支持的链\n */\nexport function listChains(): ChainName[] {\n return Object.keys(CHAINS) as ChainName[];\n}\n\n/**\n * 根据 chainId 获取链配置\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(CHAINS).find(c => c.chainId === chainId);\n}\n\n/**\n * ERC20 ABI(最小化,仅包含需要的方法)\n */\nexport const ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function nonces(address owner) view returns (uint256)',\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event Approval(address indexed owner, address indexed spender, uint256 value)',\n];\n\nexport type { ChainConfig, ChainName };\n","/**\n * AuditLog - 不可篡改审计日志\n * \n * 特点:\n * - 链式哈希,任何修改都会破坏链条\n * - 按日期分文件存储\n * - JSONL 格式便于追加和解析\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as crypto from 'crypto';\nimport type { AuditEntry, AuditAction } from '../types/index.js';\n\nexport interface LogParams {\n action: AuditAction;\n request_id: string;\n from?: string;\n to?: string;\n amount?: number;\n tx_hash?: string;\n reason?: string;\n requester?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport class AuditLog {\n private basePath: string;\n private lastHash: string = '0000000000000000';\n\n constructor(basePath?: string) {\n this.basePath = basePath || path.join(process.cwd(), 'data', 'audit');\n this.ensureDir();\n this.loadLastHash();\n }\n\n /**\n * 记录审计日志\n */\n async log(params: LogParams): Promise<AuditEntry> {\n const now = new Date();\n \n const entry: AuditEntry = {\n timestamp: now.getTime() / 1000,\n datetime: now.toISOString(),\n action: params.action,\n request_id: params.request_id,\n from: params.from,\n to: params.to,\n amount: params.amount,\n tx_hash: params.tx_hash,\n reason: params.reason,\n requester: params.requester,\n prev_hash: this.lastHash,\n hash: '', // 计算后填充\n metadata: params.metadata,\n };\n\n // 计算哈希(不包含 hash 字段本身)\n entry.hash = this.calculateHash(entry);\n this.lastHash = entry.hash;\n\n // 写入文件\n const filePath = this.getFilePath(now);\n const line = JSON.stringify(entry) + '\\n';\n fs.appendFileSync(filePath, line, 'utf-8');\n\n return entry;\n }\n\n /**\n * 读取指定日期的日志\n */\n read(date?: Date): AuditEntry[] {\n const filePath = this.getFilePath(date || new Date());\n \n if (!fs.existsSync(filePath)) {\n return [];\n }\n\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.trim().split('\\n').filter(Boolean);\n \n return lines.map(line => JSON.parse(line) as AuditEntry);\n }\n\n /**\n * 验证日志完整性\n */\n verify(date?: Date): { valid: boolean; errors: string[] } {\n const entries = this.read(date);\n const errors: string[] = [];\n\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i];\n \n // 验证哈希\n const expectedHash = this.calculateHash(entry);\n if (entry.hash !== expectedHash) {\n errors.push(`Entry ${i}: hash mismatch (expected ${expectedHash}, got ${entry.hash})`);\n }\n\n // 验证链接\n if (i > 0 && entry.prev_hash !== entries[i - 1].hash) {\n errors.push(`Entry ${i}: prev_hash mismatch`);\n }\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n /**\n * 搜索日志\n */\n search(filter: Partial<{\n action: AuditAction;\n request_id: string;\n from: string;\n to: string;\n startDate: Date;\n endDate: Date;\n }>): AuditEntry[] {\n const results: AuditEntry[] = [];\n const startDate = filter.startDate || new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);\n const endDate = filter.endDate || new Date();\n\n // 遍历日期范围\n const current = new Date(startDate);\n while (current <= endDate) {\n const entries = this.read(current);\n \n for (const entry of entries) {\n let match = true;\n\n if (filter.action && entry.action !== filter.action) match = false;\n if (filter.request_id && entry.request_id !== filter.request_id) match = false;\n if (filter.from && entry.from?.toLowerCase() !== filter.from.toLowerCase()) match = false;\n if (filter.to && entry.to?.toLowerCase() !== filter.to.toLowerCase()) match = false;\n\n if (match) {\n results.push(entry);\n }\n }\n\n current.setDate(current.getDate() + 1);\n }\n\n return results;\n }\n\n /**\n * 获取日志文件路径\n */\n private getFilePath(date: Date): string {\n const dateStr = date.toISOString().slice(0, 10);\n return path.join(this.basePath, `audit_${dateStr}.jsonl`);\n }\n\n /**\n * 计算条目哈希\n */\n private calculateHash(entry: AuditEntry): string {\n const data = {\n timestamp: entry.timestamp,\n action: entry.action,\n request_id: entry.request_id,\n from: entry.from,\n to: entry.to,\n amount: entry.amount,\n tx_hash: entry.tx_hash,\n prev_hash: entry.prev_hash,\n };\n \n const str = JSON.stringify(data);\n return crypto.createHash('sha256').update(str).digest('hex').slice(0, 16);\n }\n\n /**\n * 加载最后一条日志的哈希\n */\n private loadLastHash(): void {\n const today = new Date();\n \n // 检查今天和昨天的日志\n for (let i = 0; i < 2; i++) {\n const date = new Date(today);\n date.setDate(date.getDate() - i);\n \n const entries = this.read(date);\n if (entries.length > 0) {\n this.lastHash = entries[entries.length - 1].hash;\n return;\n }\n }\n }\n\n /**\n * 确保目录存在\n */\n private ensureDir(): void {\n if (!fs.existsSync(this.basePath)) {\n fs.mkdirSync(this.basePath, { recursive: true });\n }\n }\n}\n","/**\n * SecureWallet - 安全托管钱包\n * \n * 在基础 Wallet 之上增加:\n * - 单笔限额控制\n * - 日限额控制\n * - 白名单机制\n * - 审计日志\n * - 超限审批队列\n */\n\nimport { Wallet, type WalletConfig } from './Wallet.js';\nimport { AuditLog } from '../audit/AuditLog.js';\nimport type {\n SecurityLimits,\n SecureWalletConfig,\n TransferResult,\n TransferParams,\n PendingTransfer,\n} from '../types/index.js';\n\nconst DEFAULT_LIMITS: SecurityLimits = {\n singleMax: 100, // 单笔最大 $100\n dailyMax: 1000, // 日最大 $1000\n requireWhitelist: true,\n};\n\nexport class SecureWallet {\n private wallet: Wallet;\n private limits: SecurityLimits;\n private whitelist: Set<string>;\n private auditLog: AuditLog;\n private dailyTotal: number = 0;\n private dailyDate: string = '';\n private pendingTransfers: Map<string, PendingTransfer> = new Map();\n\n constructor(config: SecureWalletConfig = {}) {\n this.wallet = new Wallet({\n chain: config.chain,\n privateKey: config.privateKey,\n });\n\n this.limits = { ...DEFAULT_LIMITS, ...config.limits };\n this.whitelist = new Set((config.whitelist || []).map(a => a.toLowerCase()));\n this.auditLog = new AuditLog(config.auditPath);\n }\n\n /**\n * 获取钱包地址\n */\n get address(): string {\n return this.wallet.address;\n }\n\n /**\n * 获取余额\n */\n async getBalance() {\n return this.wallet.getBalance();\n }\n\n /**\n * 安全转账(带限额和白名单检查)\n * \n * 支持两种调用方式:\n * - transfer({ to, amount, reason?, requester? })\n * - transfer(to, amount)\n */\n async transfer(paramsOrTo: TransferParams | string, amountArg?: number | string): Promise<TransferResult> {\n // 支持两种调用方式\n let params: TransferParams;\n if (typeof paramsOrTo === 'string') {\n params = { \n to: paramsOrTo, \n amount: typeof amountArg === 'string' ? parseFloat(amountArg) : (amountArg || 0)\n };\n } else {\n params = paramsOrTo;\n }\n \n const { to, amount, reason, requester } = params;\n const toAddress = to.toLowerCase();\n const requestId = `tr_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;\n\n // 记录请求\n await this.auditLog.log({\n action: 'transfer_request',\n request_id: requestId,\n from: this.wallet.address,\n to,\n amount,\n reason,\n requester,\n });\n\n // 1. 白名单检查\n if (this.limits.requireWhitelist && !this.whitelist.has(toAddress)) {\n await this.auditLog.log({\n action: 'transfer_failed',\n request_id: requestId,\n metadata: { error: 'Address not in whitelist' },\n });\n return { success: false, error: `Address not in whitelist: ${to}` };\n }\n\n // 2. 单笔限额检查\n if (amount > this.limits.singleMax) {\n // 加入审批队列\n const pending: PendingTransfer = {\n id: requestId,\n to,\n amount,\n reason,\n requester,\n created_at: new Date().toISOString(),\n status: 'pending',\n };\n this.pendingTransfers.set(requestId, pending);\n \n await this.auditLog.log({\n action: 'transfer_request',\n request_id: requestId,\n metadata: { pending: true, reason: 'Exceeds single limit' },\n });\n \n return {\n success: false,\n error: `Amount ${amount} exceeds single limit ${this.limits.singleMax}. Pending approval: ${requestId}`,\n };\n }\n\n // 3. 日限额检查\n this.updateDailyTotal();\n if (this.dailyTotal + amount > this.limits.dailyMax) {\n const pending: PendingTransfer = {\n id: requestId,\n to,\n amount,\n reason,\n requester,\n created_at: new Date().toISOString(),\n status: 'pending',\n };\n this.pendingTransfers.set(requestId, pending);\n \n await this.auditLog.log({\n action: 'transfer_request',\n request_id: requestId,\n metadata: { pending: true, reason: 'Exceeds daily limit' },\n });\n \n return {\n success: false,\n error: `Daily limit would be exceeded (${this.dailyTotal} + ${amount} > ${this.limits.dailyMax}). Pending approval: ${requestId}`,\n };\n }\n\n // 4. 执行转账\n const result = await this.wallet.transfer(to, amount);\n\n // 5. 记录结果\n if (result.success) {\n this.dailyTotal += amount;\n await this.auditLog.log({\n action: 'transfer_executed',\n request_id: requestId,\n from: this.wallet.address,\n to,\n amount,\n tx_hash: result.tx_hash,\n reason,\n requester,\n });\n } else {\n await this.auditLog.log({\n action: 'transfer_failed',\n request_id: requestId,\n metadata: { error: result.error },\n });\n }\n\n return result;\n }\n\n /**\n * 审批待处理转账\n */\n async approve(requestId: string, approver: string): Promise<TransferResult> {\n const pending = this.pendingTransfers.get(requestId);\n if (!pending) {\n return { success: false, error: `Pending transfer not found: ${requestId}` };\n }\n\n if (pending.status !== 'pending') {\n return { success: false, error: `Transfer already ${pending.status}` };\n }\n\n await this.auditLog.log({\n action: 'transfer_approved',\n request_id: requestId,\n metadata: { approver },\n });\n\n pending.status = 'approved';\n\n // 执行转账(跳过限额检查)\n const result = await this.wallet.transfer(pending.to, pending.amount);\n\n if (result.success) {\n pending.status = 'executed';\n this.dailyTotal += pending.amount;\n \n await this.auditLog.log({\n action: 'transfer_executed',\n request_id: requestId,\n from: this.wallet.address,\n to: pending.to,\n amount: pending.amount,\n tx_hash: result.tx_hash,\n reason: pending.reason,\n requester: pending.requester,\n metadata: { approved_by: approver },\n });\n } else {\n await this.auditLog.log({\n action: 'transfer_failed',\n request_id: requestId,\n metadata: { error: result.error },\n });\n }\n\n return result;\n }\n\n /**\n * 拒绝待处理转账\n */\n async reject(requestId: string, rejecter: string, reason?: string): Promise<void> {\n const pending = this.pendingTransfers.get(requestId);\n if (!pending) {\n throw new Error(`Pending transfer not found: ${requestId}`);\n }\n\n pending.status = 'rejected';\n\n await this.auditLog.log({\n action: 'transfer_rejected',\n request_id: requestId,\n metadata: { rejected_by: rejecter, reason },\n });\n }\n\n /**\n * 添加白名单地址\n */\n async addToWhitelist(address: string, addedBy: string): Promise<void> {\n const addr = address.toLowerCase();\n this.whitelist.add(addr);\n\n await this.auditLog.log({\n action: 'whitelist_add',\n request_id: `wl_${Date.now()}`,\n to: address,\n metadata: { added_by: addedBy },\n });\n }\n\n /**\n * 移除白名单地址\n */\n async removeFromWhitelist(address: string, removedBy: string): Promise<void> {\n const addr = address.toLowerCase();\n this.whitelist.delete(addr);\n\n await this.auditLog.log({\n action: 'whitelist_remove',\n request_id: `wl_${Date.now()}`,\n to: address,\n metadata: { removed_by: removedBy },\n });\n }\n\n /**\n * 检查地址是否在白名单\n */\n isWhitelisted(address: string): boolean {\n return this.whitelist.has(address.toLowerCase());\n }\n\n /**\n * 获取待处理转账列表\n */\n getPendingTransfers(): PendingTransfer[] {\n return Array.from(this.pendingTransfers.values())\n .filter(p => p.status === 'pending');\n }\n\n /**\n * 获取当前限额配置\n */\n getLimits(): SecurityLimits {\n return { ...this.limits };\n }\n\n /**\n * 获取今日已用额度\n */\n getDailyUsed(): number {\n this.updateDailyTotal();\n return this.dailyTotal;\n }\n\n /**\n * 更新日限额计数器\n */\n private updateDailyTotal(): void {\n const today = new Date().toISOString().slice(0, 10);\n if (this.dailyDate !== today) {\n this.dailyDate = today;\n this.dailyTotal = 0;\n }\n }\n}\n","/**\n * createWallet - Create a new wallet for Agent\n * \n * Features:\n * - Generate new Ethereum wallet\n * - Securely store private key (encrypted or plaintext, depending on config)\n * - Return wallet address (never return private key)\n */\n\nimport { ethers } from 'ethers';\nimport { writeFileSync, readFileSync, existsSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'crypto';\n\nexport interface CreateWalletOptions {\n /** Storage path, default ~/.moltspay/wallet.json */\n storagePath?: string;\n /** Encryption password (optional, plaintext if not provided) */\n password?: string;\n /** Wallet label/name */\n label?: string;\n /** Overwrite if wallet exists */\n overwrite?: boolean;\n}\n\nexport interface WalletData {\n address: string;\n label?: string;\n createdAt: string;\n encrypted: boolean;\n /** Encrypted or plaintext private key */\n privateKey: string;\n /** Encryption IV */\n iv?: string;\n /** Encryption salt */\n salt?: string;\n}\n\nexport interface CreateWalletResult {\n success: boolean;\n address?: string;\n storagePath?: string;\n error?: string;\n /** Whether newly created (false means loaded existing) */\n isNew?: boolean;\n}\n\nconst DEFAULT_STORAGE_DIR = join(process.env.HOME || '~', '.moltspay');\nconst DEFAULT_STORAGE_FILE = 'wallet.json';\n\n/**\n * Encrypt private key\n */\nfunction encryptPrivateKey(privateKey: string, password: string): { encrypted: string; iv: string; salt: string } {\n const salt = randomBytes(16);\n const key = scryptSync(password, salt, 32);\n const iv = randomBytes(16);\n \n const cipher = createCipheriv('aes-256-cbc', key, iv);\n let encrypted = cipher.update(privateKey, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n \n return {\n encrypted,\n iv: iv.toString('hex'),\n salt: salt.toString('hex'),\n };\n}\n\n/**\n * Decrypt private key\n */\nfunction decryptPrivateKey(encrypted: string, password: string, iv: string, salt: string): string {\n const key = scryptSync(password, Buffer.from(salt, 'hex'), 32);\n const decipher = createDecipheriv('aes-256-cbc', key, Buffer.from(iv, 'hex'));\n \n let decrypted = decipher.update(encrypted, 'hex', 'utf8');\n decrypted += decipher.final('utf8');\n \n return decrypted;\n}\n\n/**\n * Create new wallet\n * \n * @example\n * ```typescript\n * // Create unencrypted wallet\n * const result = await createWallet();\n * console.log('Wallet address:', result.address);\n * \n * // Create encrypted wallet\n * const result = await createWallet({ password: 'mySecurePassword' });\n * \n * // Specify storage path\n * const result = await createWallet({ storagePath: './my-wallet.json' });\n * ```\n */\nexport function createWallet(options: CreateWalletOptions = {}): CreateWalletResult {\n const storagePath = options.storagePath || join(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);\n \n // Check if exists\n if (existsSync(storagePath) && !options.overwrite) {\n // Load existing wallet\n try {\n const existing = JSON.parse(readFileSync(storagePath, 'utf8')) as WalletData;\n return {\n success: true,\n address: existing.address,\n storagePath,\n isNew: false,\n };\n } catch (error) {\n return {\n success: false,\n error: `Failed to load existing wallet: ${(error as Error).message}`,\n };\n }\n }\n\n try {\n // Create new wallet\n const wallet = ethers.Wallet.createRandom();\n \n // Prepare storage data\n const walletData: WalletData = {\n address: wallet.address,\n label: options.label,\n createdAt: new Date().toISOString(),\n encrypted: !!options.password,\n privateKey: '',\n };\n\n if (options.password) {\n // Encrypted storage\n const { encrypted, iv, salt } = encryptPrivateKey(wallet.privateKey, options.password);\n walletData.privateKey = encrypted;\n walletData.iv = iv;\n walletData.salt = salt;\n } else {\n // Plaintext storage (not recommended, but convenient for testing/dev)\n walletData.privateKey = wallet.privateKey;\n }\n\n // Ensure directory exists\n const dir = dirname(storagePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Write file\n writeFileSync(storagePath, JSON.stringify(walletData, null, 2), { mode: 0o600 });\n\n return {\n success: true,\n address: wallet.address,\n storagePath,\n isNew: true,\n };\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n}\n\n/**\n * Load existing wallet\n */\nexport function loadWallet(options: { storagePath?: string; password?: string } = {}): {\n success: boolean;\n address?: string;\n privateKey?: string;\n error?: string;\n} {\n const storagePath = options.storagePath || join(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);\n\n if (!existsSync(storagePath)) {\n return { success: false, error: 'Wallet not found. Run createWallet() first.' };\n }\n\n try {\n const data = JSON.parse(readFileSync(storagePath, 'utf8')) as WalletData;\n\n if (data.encrypted) {\n if (!options.password) {\n return { success: false, error: 'Wallet is encrypted. Password required.' };\n }\n const privateKey = decryptPrivateKey(data.privateKey, options.password, data.iv!, data.salt!);\n return { success: true, address: data.address, privateKey };\n } else {\n return { success: true, address: data.address, privateKey: data.privateKey };\n }\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n}\n\n/**\n * Get wallet address (no password required)\n */\nexport function getWalletAddress(storagePath?: string): string | null {\n const path = storagePath || join(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);\n \n if (!existsSync(path)) {\n return null;\n }\n\n try {\n const data = JSON.parse(readFileSync(path, 'utf8')) as WalletData;\n return data.address;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if wallet exists\n */\nexport function walletExists(storagePath?: string): boolean {\n const path = storagePath || join(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);\n return existsSync(path);\n}\n","/**\n * PermitWallet - Pay using Boss's Permit authorization\n * \n * Scenario:\n * - Agent doesn't have USDC, but Boss gave a Permit authorization\n * - Agent uses Permit signature + own wallet to execute transferFrom\n * - Agent only needs small amount of ETH for gas, USDC is deducted from Boss's wallet\n */\n\nimport { ethers } from 'ethers';\nimport { getChain, ERC20_ABI } from '../chains/index.js';\nimport { loadWallet } from './createWallet.js';\nimport type {\n ChainName,\n ChainConfig,\n TransferResult,\n PermitSignature,\n} from '../types/index.js';\n\nexport interface PermitData {\n /** Boss's wallet address (USDC holder) */\n owner: string;\n /** Agent's wallet address (authorized spender) */\n spender: string;\n /** Authorized amount (USDC, raw 6 decimal value) */\n value: string;\n /** Expiration timestamp */\n deadline: number;\n /** Signature v */\n v: number;\n /** Signature r */\n r: string;\n /** Signature s */\n s: string;\n}\n\nexport interface PermitWalletConfig {\n chain?: ChainName;\n /** Agent's private key (for executing transactions) */\n privateKey?: string;\n /** Load private key from file */\n walletPath?: string;\n /** Decryption password */\n walletPassword?: string;\n rpcUrl?: string;\n}\n\nexport interface TransferWithPermitParams {\n /** Recipient address */\n to: string;\n /** Amount (USDC) */\n amount: number;\n /** Boss-signed Permit data */\n permit: PermitData;\n}\n\nexport interface TransferWithPermitResult extends TransferResult {\n /** Permit transaction hash */\n permitTxHash?: string;\n /** Transfer transaction hash */\n transferTxHash?: string;\n}\n\n// Extended ABI to support permit and transferFrom\nconst PERMIT_ABI = [\n ...ERC20_ABI,\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'function transferFrom(address from, address to, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n];\n\nexport class PermitWallet {\n readonly chain: ChainName;\n readonly chainConfig: ChainConfig;\n readonly address: string;\n \n private wallet: ethers.Wallet;\n private provider: ethers.JsonRpcProvider;\n private usdcContract: ethers.Contract;\n\n constructor(config: PermitWalletConfig = {}) {\n this.chain = config.chain || 'base_sepolia';\n this.chainConfig = getChain(this.chain);\n \n // Get private key\n let privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;\n \n // Or load from file\n if (!privateKey && config.walletPath) {\n const loaded = loadWallet({ \n storagePath: config.walletPath, \n password: config.walletPassword \n });\n if (!loaded.success || !loaded.privateKey) {\n throw new Error(loaded.error || 'Failed to load wallet');\n }\n privateKey = loaded.privateKey;\n }\n \n if (!privateKey) {\n throw new Error('privateKey is required. Set via config, env var, or walletPath.');\n }\n\n const rpcUrl = config.rpcUrl || this.chainConfig.rpc;\n this.provider = new ethers.JsonRpcProvider(rpcUrl);\n this.wallet = new ethers.Wallet(privateKey, this.provider);\n this.address = this.wallet.address;\n \n this.usdcContract = new ethers.Contract(\n this.chainConfig.usdc,\n PERMIT_ABI,\n this.wallet\n );\n }\n\n /**\n * Check if Permit is valid (current allowance)\n */\n async checkPermitAllowance(owner: string): Promise<string> {\n const allowance = await this.usdcContract.allowance(owner, this.address);\n return (Number(allowance) / 1e6).toFixed(2);\n }\n\n /**\n * Pay using Permit authorization\n * \n * Flow:\n * 1. Call permit() to record Boss's authorization in the contract\n * 2. Call transferFrom() to transfer from Boss's wallet to recipient\n * \n * @example\n * ```typescript\n * const wallet = new PermitWallet({ chain: 'base' });\n * \n * // Boss-signed permit data\n * const permit = {\n * owner: '0xBOSS...',\n * spender: wallet.address,\n * value: '10000000', // 10 USDC\n * deadline: 1234567890,\n * v: 27,\n * r: '0x...',\n * s: '0x...'\n * };\n * \n * const result = await wallet.transferWithPermit({\n * to: '0xSELLER...',\n * amount: 3.99,\n * permit\n * });\n * ```\n */\n async transferWithPermit(params: TransferWithPermitParams): Promise<TransferWithPermitResult> {\n const { to, amount, permit } = params;\n\n try {\n // Validate addresses\n const toAddress = ethers.getAddress(to);\n const ownerAddress = ethers.getAddress(permit.owner);\n \n // Verify spender is this wallet\n if (ethers.getAddress(permit.spender).toLowerCase() !== this.address.toLowerCase()) {\n return {\n success: false,\n error: `Permit spender (${permit.spender}) doesn't match wallet address (${this.address})`,\n };\n }\n\n // Check deadline\n const now = Math.floor(Date.now() / 1000);\n if (permit.deadline < now) {\n return {\n success: false,\n error: `Permit expired at ${new Date(permit.deadline * 1000).toISOString()}`,\n };\n }\n\n // Convert amount\n const amountWei = BigInt(Math.floor(amount * 1e6));\n const permitValue = BigInt(permit.value);\n \n // Check if authorized amount is sufficient\n if (amountWei > permitValue) {\n return {\n success: false,\n error: `Permit value (${Number(permitValue) / 1e6} USDC) < transfer amount (${amount} USDC)`,\n };\n }\n\n // Check existing allowance\n const currentAllowance = await this.usdcContract.allowance(ownerAddress, this.address);\n \n let permitTxHash: string | undefined;\n \n // If allowance insufficient, execute permit first\n if (BigInt(currentAllowance) < amountWei) {\n console.log('Executing permit...');\n const permitTx = await this.usdcContract.permit(\n ownerAddress,\n this.address,\n permitValue,\n permit.deadline,\n permit.v,\n permit.r,\n permit.s\n );\n const permitReceipt = await permitTx.wait();\n \n if (permitReceipt.status !== 1) {\n return {\n success: false,\n error: 'Permit transaction failed',\n permitTxHash: permitTx.hash,\n };\n }\n permitTxHash = permitTx.hash;\n console.log('Permit executed:', permitTxHash);\n }\n\n // Execute transferFrom\n console.log('Executing transferFrom...');\n const transferTx = await this.usdcContract.transferFrom(\n ownerAddress,\n toAddress,\n amountWei\n );\n const transferReceipt = await transferTx.wait();\n\n if (transferReceipt.status === 1) {\n return {\n success: true,\n tx_hash: transferTx.hash,\n permitTxHash,\n transferTxHash: transferTx.hash,\n from: ownerAddress,\n to: toAddress,\n amount,\n gas_used: Number(transferReceipt.gasUsed),\n block_number: transferReceipt.blockNumber,\n explorer_url: `${this.chainConfig.explorerTx}${transferTx.hash}`,\n };\n } else {\n return {\n success: false,\n error: 'TransferFrom transaction failed',\n tx_hash: transferTx.hash,\n permitTxHash,\n };\n }\n } catch (error) {\n const message = (error as Error).message;\n \n // Parse common errors\n if (message.includes('ERC20InsufficientAllowance')) {\n return {\n success: false,\n error: 'Insufficient allowance. Permit may have been used or expired.',\n };\n }\n if (message.includes('ERC20InsufficientBalance')) {\n return {\n success: false,\n error: 'Boss wallet has insufficient USDC balance.',\n };\n }\n if (message.includes('InvalidSignature') || message.includes('invalid signature')) {\n return {\n success: false,\n error: 'Invalid permit signature. Ask Boss to re-sign.',\n };\n }\n \n return {\n success: false,\n error: message,\n };\n }\n }\n\n /**\n * Get ETH balance (for gas)\n */\n async getGasBalance(): Promise<string> {\n const balance = await this.provider.getBalance(this.address);\n return ethers.formatEther(balance);\n }\n\n /**\n * Check if there's enough gas\n */\n async hasEnoughGas(minEth: number = 0.001): Promise<boolean> {\n const balance = await this.getGasBalance();\n return parseFloat(balance) >= minEth;\n }\n}\n\n/**\n * Format Permit request message (to send to Boss)\n */\nexport function formatPermitRequest(params: {\n agentAddress: string;\n amount: number;\n deadlineHours?: number;\n chain?: ChainName;\n reason?: string;\n}): string {\n const { agentAddress, amount, deadlineHours = 24, chain = 'base', reason } = params;\n const chainConfig = getChain(chain);\n const deadline = Math.floor(Date.now() / 1000) + deadlineHours * 3600;\n const value = BigInt(Math.floor(amount * 1e6)).toString();\n\n return `🔐 **USDC Spending Allowance Request**\n\n${reason ? `**Purpose:** ${reason}\\n` : ''}\n**Authorization Details:**\n- Authorized address (Agent): \\`${agentAddress}\\`\n- Amount: ${amount} USDC\n- Valid for: ${deadlineHours} hours\n- Chain: ${chainConfig.name}\n\n**Please sign the following EIP-2612 Permit with your wallet:**\n\n\\`\\`\\`json\n{\n \"types\": {\n \"Permit\": [\n { \"name\": \"owner\", \"type\": \"address\" },\n { \"name\": \"spender\", \"type\": \"address\" },\n { \"name\": \"value\", \"type\": \"uint256\" },\n { \"name\": \"nonce\", \"type\": \"uint256\" },\n { \"name\": \"deadline\", \"type\": \"uint256\" }\n ]\n },\n \"primaryType\": \"Permit\",\n \"domain\": {\n \"name\": \"USD Coin\",\n \"version\": \"2\",\n \"chainId\": ${chainConfig.chainId},\n \"verifyingContract\": \"${chainConfig.usdc}\"\n },\n \"message\": {\n \"owner\": \"<YOUR_WALLET_ADDRESS>\",\n \"spender\": \"${agentAddress}\",\n \"value\": \"${value}\",\n \"nonce\": \"<GET_FROM_CONTRACT>\",\n \"deadline\": ${deadline}\n }\n}\n\\`\\`\\`\n\nAfter signing, send { v, r, s, deadline } to the Agent.\n\n⚠️ Note: This authorization only allows the Agent to spend up to ${amount} USDC from your wallet. Your private key is never exposed.`;\n}\n"],"mappings":"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","names":["import_ethers","path","import_ethers"]}
|
|
1
|
+
{"version":3,"sources":["../../src/wallet/index.ts","../../src/wallet/Wallet.ts","../../src/chains/index.ts","../../src/audit/AuditLog.ts","../../src/wallet/SecureWallet.ts","../../src/wallet/createWallet.ts","../../src/wallet/PermitWallet.ts"],"sourcesContent":["export { Wallet, type WalletConfig } from './Wallet.js';\nexport { SecureWallet } from './SecureWallet.js';\nexport { \n createWallet, \n loadWallet, \n getWalletAddress, \n walletExists,\n type CreateWalletOptions,\n type CreateWalletResult,\n type WalletData,\n} from './createWallet.js';\nexport { \n PermitWallet, \n formatPermitRequest,\n type PermitWalletConfig,\n type PermitData,\n type TransferWithPermitParams,\n type TransferWithPermitResult,\n} from './PermitWallet.js';\n","/**\n * Wallet - Basic Custody Wallet\n * \n * Features:\n * - Query balance\n * - Send USDC transfer\n */\n\nimport { ethers } from 'ethers';\nimport { getChain, ERC20_ABI } from '../chains/index.js';\nimport type {\n ChainName,\n ChainConfig,\n WalletBalance,\n TransferResult,\n} from '../types/index.js';\n\nexport interface WalletConfig {\n chain?: ChainName;\n privateKey?: string;\n rpcUrl?: string;\n}\n\nexport class Wallet {\n readonly chain: ChainName;\n readonly chainConfig: ChainConfig;\n readonly address: string;\n \n private wallet: ethers.Wallet;\n private provider: ethers.JsonRpcProvider;\n private usdcContract: ethers.Contract;\n\n constructor(config: WalletConfig = {}) {\n this.chain = config.chain || 'base_sepolia';\n this.chainConfig = getChain(this.chain);\n \n const privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;\n if (!privateKey) {\n throw new Error('privateKey is required. Set via config or PAYMENT_AGENT_PRIVATE_KEY env var.');\n }\n\n const rpcUrl = config.rpcUrl || this.chainConfig.rpc;\n this.provider = new ethers.JsonRpcProvider(rpcUrl);\n this.wallet = new ethers.Wallet(privateKey, this.provider);\n this.address = this.wallet.address;\n \n this.usdcContract = new ethers.Contract(\n this.chainConfig.usdc,\n ERC20_ABI,\n this.wallet\n );\n }\n\n /**\n * Get wallet balance\n */\n async getBalance(): Promise<WalletBalance> {\n const [ethBalance, usdcBalance] = await Promise.all([\n this.provider.getBalance(this.address),\n this.usdcContract.balanceOf(this.address),\n ]);\n\n return {\n address: this.address,\n eth: ethers.formatEther(ethBalance),\n usdc: (Number(usdcBalance) / 1e6).toFixed(2),\n chain: this.chain,\n };\n }\n\n /**\n * Send USDC transfer\n */\n async transfer(to: string, amount: number): Promise<TransferResult> {\n try {\n // Validate address\n to = ethers.getAddress(to);\n \n // Convert amount (USDC 6 decimals)\n const amountWei = BigInt(Math.floor(amount * 1e6));\n\n // Check balance\n const balance = await this.usdcContract.balanceOf(this.address);\n if (BigInt(balance) < amountWei) {\n return {\n success: false,\n error: `Insufficient USDC balance: ${Number(balance) / 1e6} < ${amount}`,\n };\n }\n\n // Send transaction\n const tx = await this.usdcContract.transfer(to, amountWei);\n const receipt = await tx.wait();\n\n if (receipt.status === 1) {\n return {\n success: true,\n tx_hash: tx.hash,\n from: this.address,\n to,\n amount,\n gas_used: Number(receipt.gasUsed),\n block_number: receipt.blockNumber,\n explorer_url: `${this.chainConfig.explorerTx}${tx.hash}`,\n };\n } else {\n return {\n success: false,\n tx_hash: tx.hash,\n error: 'Transaction reverted',\n };\n }\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n }\n\n /**\n * Get ETH balance\n */\n async getEthBalance(): Promise<string> {\n const balance = await this.provider.getBalance(this.address);\n return ethers.formatEther(balance);\n }\n\n /**\n * Get USDC balance\n */\n async getUsdcBalance(): Promise<string> {\n const balance = await this.usdcContract.balanceOf(this.address);\n return (Number(balance) / 1e6).toFixed(2);\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName } from '../types/index.js';\n\nexport const CHAINS: Record<ChainName, ChainConfig> = {\n // ============ Mainnet ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n explorer: 'https://basescan.org/address/',\n explorerTx: 'https://basescan.org/tx/',\n avgBlockTime: 2,\n },\n polygon: {\n name: 'Polygon',\n chainId: 137,\n rpc: 'https://polygon-rpc.com',\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n ethereum: {\n name: 'Ethereum',\n chainId: 1,\n rpc: 'https://eth.llamarpc.com',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n explorer: 'https://etherscan.io/address/',\n explorerTx: 'https://etherscan.io/tx/',\n avgBlockTime: 12,\n },\n\n // ============ Testnet ============\n base_sepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n rpc: 'https://sepolia.base.org',\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n sepolia: {\n name: 'Sepolia',\n chainId: 11155111,\n rpc: 'https://rpc.sepolia.org',\n usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n explorer: 'https://sepolia.etherscan.io/address/',\n explorerTx: 'https://sepolia.etherscan.io/tx/',\n avgBlockTime: 12,\n },\n};\n\n/**\n * Get chain configuration\n */\nexport function getChain(name: ChainName): ChainConfig {\n const config = CHAINS[name];\n if (!config) {\n throw new Error(`Unsupported chain: ${name}. Supported: ${Object.keys(CHAINS).join(', ')}`);\n }\n return config;\n}\n\n/**\n * List all supported chains\n */\nexport function listChains(): ChainName[] {\n return Object.keys(CHAINS) as ChainName[];\n}\n\n/**\n * Get chain config by chainId\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(CHAINS).find(c => c.chainId === chainId);\n}\n\n/**\n * ERC20 ABI (minimal, only required methods)\n */\nexport const ERC20_ABI = [\n 'function balanceOf(address owner) view returns (uint256)',\n 'function transfer(address to, uint256 amount) returns (bool)',\n 'function approve(address spender, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n 'function decimals() view returns (uint8)',\n 'function symbol() view returns (string)',\n 'function name() view returns (string)',\n 'function nonces(address owner) view returns (uint256)',\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'event Transfer(address indexed from, address indexed to, uint256 value)',\n 'event Approval(address indexed owner, address indexed spender, uint256 value)',\n];\n\nexport type { ChainConfig, ChainName };\n","/**\n * AuditLog - Immutable Audit Log\n * \n * Features:\n * - Hash-chained, any modification breaks the chain\n * - Stored by date in separate files\n * - JSONL format for easy append and parse\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as crypto from 'crypto';\nimport type { AuditEntry, AuditAction } from '../types/index.js';\n\nexport interface LogParams {\n action: AuditAction;\n request_id: string;\n from?: string;\n to?: string;\n amount?: number;\n tx_hash?: string;\n reason?: string;\n requester?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport class AuditLog {\n private basePath: string;\n private lastHash: string = '0000000000000000';\n\n constructor(basePath?: string) {\n this.basePath = basePath || path.join(process.cwd(), 'data', 'audit');\n this.ensureDir();\n this.loadLastHash();\n }\n\n /**\n * Record audit log\n */\n async log(params: LogParams): Promise<AuditEntry> {\n const now = new Date();\n \n const entry: AuditEntry = {\n timestamp: now.getTime() / 1000,\n datetime: now.toISOString(),\n action: params.action,\n request_id: params.request_id,\n from: params.from,\n to: params.to,\n amount: params.amount,\n tx_hash: params.tx_hash,\n reason: params.reason,\n requester: params.requester,\n prev_hash: this.lastHash,\n hash: '', // Filled after calculation\n metadata: params.metadata,\n };\n\n // Calculate hash (excluding hash field itself)\n entry.hash = this.calculateHash(entry);\n this.lastHash = entry.hash;\n\n // Write to file\n const filePath = this.getFilePath(now);\n const line = JSON.stringify(entry) + '\\n';\n fs.appendFileSync(filePath, line, 'utf-8');\n\n return entry;\n }\n\n /**\n * Read logs for specified date\n */\n read(date?: Date): AuditEntry[] {\n const filePath = this.getFilePath(date || new Date());\n \n if (!fs.existsSync(filePath)) {\n return [];\n }\n\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.trim().split('\\n').filter(Boolean);\n \n return lines.map(line => JSON.parse(line) as AuditEntry);\n }\n\n /**\n * Verify log integrity\n */\n verify(date?: Date): { valid: boolean; errors: string[] } {\n const entries = this.read(date);\n const errors: string[] = [];\n\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i];\n \n // Verify hash\n const expectedHash = this.calculateHash(entry);\n if (entry.hash !== expectedHash) {\n errors.push(`Entry ${i}: hash mismatch (expected ${expectedHash}, got ${entry.hash})`);\n }\n\n // Verify chain\n if (i > 0 && entry.prev_hash !== entries[i - 1].hash) {\n errors.push(`Entry ${i}: prev_hash mismatch`);\n }\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n /**\n * Search logs\n */\n search(filter: Partial<{\n action: AuditAction;\n request_id: string;\n from: string;\n to: string;\n startDate: Date;\n endDate: Date;\n }>): AuditEntry[] {\n const results: AuditEntry[] = [];\n const startDate = filter.startDate || new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);\n const endDate = filter.endDate || new Date();\n\n // Iterate date range\n const current = new Date(startDate);\n while (current <= endDate) {\n const entries = this.read(current);\n \n for (const entry of entries) {\n let match = true;\n\n if (filter.action && entry.action !== filter.action) match = false;\n if (filter.request_id && entry.request_id !== filter.request_id) match = false;\n if (filter.from && entry.from?.toLowerCase() !== filter.from.toLowerCase()) match = false;\n if (filter.to && entry.to?.toLowerCase() !== filter.to.toLowerCase()) match = false;\n\n if (match) {\n results.push(entry);\n }\n }\n\n current.setDate(current.getDate() + 1);\n }\n\n return results;\n }\n\n /**\n * Get log file path\n */\n private getFilePath(date: Date): string {\n const dateStr = date.toISOString().slice(0, 10);\n return path.join(this.basePath, `audit_${dateStr}.jsonl`);\n }\n\n /**\n * Calculate entry hash\n */\n private calculateHash(entry: AuditEntry): string {\n const data = {\n timestamp: entry.timestamp,\n action: entry.action,\n request_id: entry.request_id,\n from: entry.from,\n to: entry.to,\n amount: entry.amount,\n tx_hash: entry.tx_hash,\n prev_hash: entry.prev_hash,\n };\n \n const str = JSON.stringify(data);\n return crypto.createHash('sha256').update(str).digest('hex').slice(0, 16);\n }\n\n /**\n * Load last log entry hash\n */\n private loadLastHash(): void {\n const today = new Date();\n \n // Check today and yesterday logs\n for (let i = 0; i < 2; i++) {\n const date = new Date(today);\n date.setDate(date.getDate() - i);\n \n const entries = this.read(date);\n if (entries.length > 0) {\n this.lastHash = entries[entries.length - 1].hash;\n return;\n }\n }\n }\n\n /**\n * Ensure directory exists\n */\n private ensureDir(): void {\n if (!fs.existsSync(this.basePath)) {\n fs.mkdirSync(this.basePath, { recursive: true });\n }\n }\n}\n","/**\n * SecureWallet - Secure Custody Wallet\n * \n * Built on top of basic Wallet with:\n * - Single transaction limit\n * - Daily limit\n * - Whitelist mechanism\n * - Audit logging\n * - Over-limit approval queue\n */\n\nimport { Wallet, type WalletConfig } from './Wallet.js';\nimport { AuditLog } from '../audit/AuditLog.js';\nimport type {\n SecurityLimits,\n SecureWalletConfig,\n TransferResult,\n TransferParams,\n PendingTransfer,\n} from '../types/index.js';\n\nconst DEFAULT_LIMITS: SecurityLimits = {\n singleMax: 100, // Single max $100\n dailyMax: 1000, // Daily max $1000\n requireWhitelist: true,\n};\n\nexport class SecureWallet {\n private wallet: Wallet;\n private limits: SecurityLimits;\n private whitelist: Set<string>;\n private auditLog: AuditLog;\n private dailyTotal: number = 0;\n private dailyDate: string = '';\n private pendingTransfers: Map<string, PendingTransfer> = new Map();\n\n constructor(config: SecureWalletConfig = {}) {\n this.wallet = new Wallet({\n chain: config.chain,\n privateKey: config.privateKey,\n });\n\n this.limits = { ...DEFAULT_LIMITS, ...config.limits };\n this.whitelist = new Set((config.whitelist || []).map(a => a.toLowerCase()));\n this.auditLog = new AuditLog(config.auditPath);\n }\n\n /**\n * Get wallet address\n */\n get address(): string {\n return this.wallet.address;\n }\n\n /**\n * Get balance\n */\n async getBalance() {\n return this.wallet.getBalance();\n }\n\n /**\n * Secure transfer (with limit and whitelist checks)\n * \n * Supports two calling methods:\n * - transfer({ to, amount, reason?, requester? })\n * - transfer(to, amount)\n */\n async transfer(paramsOrTo: TransferParams | string, amountArg?: number | string): Promise<TransferResult> {\n // Supports two calling methods\n let params: TransferParams;\n if (typeof paramsOrTo === 'string') {\n params = { \n to: paramsOrTo, \n amount: typeof amountArg === 'string' ? parseFloat(amountArg) : (amountArg || 0)\n };\n } else {\n params = paramsOrTo;\n }\n \n const { to, amount, reason, requester } = params;\n const toAddress = to.toLowerCase();\n const requestId = `tr_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;\n\n // Record request\n await this.auditLog.log({\n action: 'transfer_request',\n request_id: requestId,\n from: this.wallet.address,\n to,\n amount,\n reason,\n requester,\n });\n\n // 1. Whitelist check\n if (this.limits.requireWhitelist && !this.whitelist.has(toAddress)) {\n await this.auditLog.log({\n action: 'transfer_failed',\n request_id: requestId,\n metadata: { error: 'Address not in whitelist' },\n });\n return { success: false, error: `Address not in whitelist: ${to}` };\n }\n\n // 2. Single limit check\n if (amount > this.limits.singleMax) {\n // Add to approval queue\n const pending: PendingTransfer = {\n id: requestId,\n to,\n amount,\n reason,\n requester,\n created_at: new Date().toISOString(),\n status: 'pending',\n };\n this.pendingTransfers.set(requestId, pending);\n \n await this.auditLog.log({\n action: 'transfer_request',\n request_id: requestId,\n metadata: { pending: true, reason: 'Exceeds single limit' },\n });\n \n return {\n success: false,\n error: `Amount ${amount} exceeds single limit ${this.limits.singleMax}. Pending approval: ${requestId}`,\n };\n }\n\n // 3. Daily limit check\n this.updateDailyTotal();\n if (this.dailyTotal + amount > this.limits.dailyMax) {\n const pending: PendingTransfer = {\n id: requestId,\n to,\n amount,\n reason,\n requester,\n created_at: new Date().toISOString(),\n status: 'pending',\n };\n this.pendingTransfers.set(requestId, pending);\n \n await this.auditLog.log({\n action: 'transfer_request',\n request_id: requestId,\n metadata: { pending: true, reason: 'Exceeds daily limit' },\n });\n \n return {\n success: false,\n error: `Daily limit would be exceeded (${this.dailyTotal} + ${amount} > ${this.limits.dailyMax}). Pending approval: ${requestId}`,\n };\n }\n\n // 4. Execute transfer\n const result = await this.wallet.transfer(to, amount);\n\n // 5. Record result\n if (result.success) {\n this.dailyTotal += amount;\n await this.auditLog.log({\n action: 'transfer_executed',\n request_id: requestId,\n from: this.wallet.address,\n to,\n amount,\n tx_hash: result.tx_hash,\n reason,\n requester,\n });\n } else {\n await this.auditLog.log({\n action: 'transfer_failed',\n request_id: requestId,\n metadata: { error: result.error },\n });\n }\n\n return result;\n }\n\n /**\n * Approve pending transfer\n */\n async approve(requestId: string, approver: string): Promise<TransferResult> {\n const pending = this.pendingTransfers.get(requestId);\n if (!pending) {\n return { success: false, error: `Pending transfer not found: ${requestId}` };\n }\n\n if (pending.status !== 'pending') {\n return { success: false, error: `Transfer already ${pending.status}` };\n }\n\n await this.auditLog.log({\n action: 'transfer_approved',\n request_id: requestId,\n metadata: { approver },\n });\n\n pending.status = 'approved';\n\n // Execute transfer(Skip limit checks)\n const result = await this.wallet.transfer(pending.to, pending.amount);\n\n if (result.success) {\n pending.status = 'executed';\n this.dailyTotal += pending.amount;\n \n await this.auditLog.log({\n action: 'transfer_executed',\n request_id: requestId,\n from: this.wallet.address,\n to: pending.to,\n amount: pending.amount,\n tx_hash: result.tx_hash,\n reason: pending.reason,\n requester: pending.requester,\n metadata: { approved_by: approver },\n });\n } else {\n await this.auditLog.log({\n action: 'transfer_failed',\n request_id: requestId,\n metadata: { error: result.error },\n });\n }\n\n return result;\n }\n\n /**\n * Reject pending transfer\n */\n async reject(requestId: string, rejecter: string, reason?: string): Promise<void> {\n const pending = this.pendingTransfers.get(requestId);\n if (!pending) {\n throw new Error(`Pending transfer not found: ${requestId}`);\n }\n\n pending.status = 'rejected';\n\n await this.auditLog.log({\n action: 'transfer_rejected',\n request_id: requestId,\n metadata: { rejected_by: rejecter, reason },\n });\n }\n\n /**\n * Add to whitelist\n */\n async addToWhitelist(address: string, addedBy: string): Promise<void> {\n const addr = address.toLowerCase();\n this.whitelist.add(addr);\n\n await this.auditLog.log({\n action: 'whitelist_add',\n request_id: `wl_${Date.now()}`,\n to: address,\n metadata: { added_by: addedBy },\n });\n }\n\n /**\n * Remove from whitelist\n */\n async removeFromWhitelist(address: string, removedBy: string): Promise<void> {\n const addr = address.toLowerCase();\n this.whitelist.delete(addr);\n\n await this.auditLog.log({\n action: 'whitelist_remove',\n request_id: `wl_${Date.now()}`,\n to: address,\n metadata: { removed_by: removedBy },\n });\n }\n\n /**\n * Check if address is whitelisted\n */\n isWhitelisted(address: string): boolean {\n return this.whitelist.has(address.toLowerCase());\n }\n\n /**\n * Get pending transfers list\n */\n getPendingTransfers(): PendingTransfer[] {\n return Array.from(this.pendingTransfers.values())\n .filter(p => p.status === 'pending');\n }\n\n /**\n * Get current limit config\n */\n getLimits(): SecurityLimits {\n return { ...this.limits };\n }\n\n /**\n * Get daily used amount\n */\n getDailyUsed(): number {\n this.updateDailyTotal();\n return this.dailyTotal;\n }\n\n /**\n * Update daily limit counter\n */\n private updateDailyTotal(): void {\n const today = new Date().toISOString().slice(0, 10);\n if (this.dailyDate !== today) {\n this.dailyDate = today;\n this.dailyTotal = 0;\n }\n }\n}\n","/**\n * createWallet - Create a new wallet for Agent\n * \n * Features:\n * - Generate new Ethereum wallet\n * - Securely store private key (encrypted or plaintext, depending on config)\n * - Return wallet address (never return private key)\n */\n\nimport { ethers } from 'ethers';\nimport { writeFileSync, readFileSync, existsSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'crypto';\n\nexport interface CreateWalletOptions {\n /** Storage path, default ~/.moltspay/wallet.json */\n storagePath?: string;\n /** Encryption password (optional, plaintext if not provided) */\n password?: string;\n /** Wallet label/name */\n label?: string;\n /** Overwrite if wallet exists */\n overwrite?: boolean;\n}\n\nexport interface WalletData {\n address: string;\n label?: string;\n createdAt: string;\n encrypted: boolean;\n /** Encrypted or plaintext private key */\n privateKey: string;\n /** Encryption IV */\n iv?: string;\n /** Encryption salt */\n salt?: string;\n}\n\nexport interface CreateWalletResult {\n success: boolean;\n address?: string;\n storagePath?: string;\n error?: string;\n /** Whether newly created (false means loaded existing) */\n isNew?: boolean;\n}\n\nconst DEFAULT_STORAGE_DIR = join(process.env.HOME || '~', '.moltspay');\nconst DEFAULT_STORAGE_FILE = 'wallet.json';\n\n/**\n * Encrypt private key\n */\nfunction encryptPrivateKey(privateKey: string, password: string): { encrypted: string; iv: string; salt: string } {\n const salt = randomBytes(16);\n const key = scryptSync(password, salt, 32);\n const iv = randomBytes(16);\n \n const cipher = createCipheriv('aes-256-cbc', key, iv);\n let encrypted = cipher.update(privateKey, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n \n return {\n encrypted,\n iv: iv.toString('hex'),\n salt: salt.toString('hex'),\n };\n}\n\n/**\n * Decrypt private key\n */\nfunction decryptPrivateKey(encrypted: string, password: string, iv: string, salt: string): string {\n const key = scryptSync(password, Buffer.from(salt, 'hex'), 32);\n const decipher = createDecipheriv('aes-256-cbc', key, Buffer.from(iv, 'hex'));\n \n let decrypted = decipher.update(encrypted, 'hex', 'utf8');\n decrypted += decipher.final('utf8');\n \n return decrypted;\n}\n\n/**\n * Create new wallet\n * \n * @example\n * ```typescript\n * // Create unencrypted wallet\n * const result = await createWallet();\n * console.log('Wallet address:', result.address);\n * \n * // Create encrypted wallet\n * const result = await createWallet({ password: 'mySecurePassword' });\n * \n * // Specify storage path\n * const result = await createWallet({ storagePath: './my-wallet.json' });\n * ```\n */\nexport function createWallet(options: CreateWalletOptions = {}): CreateWalletResult {\n const storagePath = options.storagePath || join(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);\n \n // Check if exists\n if (existsSync(storagePath) && !options.overwrite) {\n // Load existing wallet\n try {\n const existing = JSON.parse(readFileSync(storagePath, 'utf8')) as WalletData;\n return {\n success: true,\n address: existing.address,\n storagePath,\n isNew: false,\n };\n } catch (error) {\n return {\n success: false,\n error: `Failed to load existing wallet: ${(error as Error).message}`,\n };\n }\n }\n\n try {\n // Create new wallet\n const wallet = ethers.Wallet.createRandom();\n \n // Prepare storage data\n const walletData: WalletData = {\n address: wallet.address,\n label: options.label,\n createdAt: new Date().toISOString(),\n encrypted: !!options.password,\n privateKey: '',\n };\n\n if (options.password) {\n // Encrypted storage\n const { encrypted, iv, salt } = encryptPrivateKey(wallet.privateKey, options.password);\n walletData.privateKey = encrypted;\n walletData.iv = iv;\n walletData.salt = salt;\n } else {\n // Plaintext storage (not recommended, but convenient for testing/dev)\n walletData.privateKey = wallet.privateKey;\n }\n\n // Ensure directory exists\n const dir = dirname(storagePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Write file\n writeFileSync(storagePath, JSON.stringify(walletData, null, 2), { mode: 0o600 });\n\n return {\n success: true,\n address: wallet.address,\n storagePath,\n isNew: true,\n };\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n}\n\n/**\n * Load existing wallet\n */\nexport function loadWallet(options: { storagePath?: string; password?: string } = {}): {\n success: boolean;\n address?: string;\n privateKey?: string;\n error?: string;\n} {\n const storagePath = options.storagePath || join(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);\n\n if (!existsSync(storagePath)) {\n return { success: false, error: 'Wallet not found. Run createWallet() first.' };\n }\n\n try {\n const data = JSON.parse(readFileSync(storagePath, 'utf8')) as WalletData;\n\n if (data.encrypted) {\n if (!options.password) {\n return { success: false, error: 'Wallet is encrypted. Password required.' };\n }\n const privateKey = decryptPrivateKey(data.privateKey, options.password, data.iv!, data.salt!);\n return { success: true, address: data.address, privateKey };\n } else {\n return { success: true, address: data.address, privateKey: data.privateKey };\n }\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n}\n\n/**\n * Get wallet address (no password required)\n */\nexport function getWalletAddress(storagePath?: string): string | null {\n const path = storagePath || join(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);\n \n if (!existsSync(path)) {\n return null;\n }\n\n try {\n const data = JSON.parse(readFileSync(path, 'utf8')) as WalletData;\n return data.address;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if wallet exists\n */\nexport function walletExists(storagePath?: string): boolean {\n const path = storagePath || join(DEFAULT_STORAGE_DIR, DEFAULT_STORAGE_FILE);\n return existsSync(path);\n}\n","/**\n * PermitWallet - Pay using Boss's Permit authorization\n * \n * Scenario:\n * - Agent doesn't have USDC, but Boss gave a Permit authorization\n * - Agent uses Permit signature + own wallet to execute transferFrom\n * - Agent only needs small amount of ETH for gas, USDC is deducted from Boss's wallet\n */\n\nimport { ethers } from 'ethers';\nimport { getChain, ERC20_ABI } from '../chains/index.js';\nimport { loadWallet } from './createWallet.js';\nimport type {\n ChainName,\n ChainConfig,\n TransferResult,\n PermitSignature,\n} from '../types/index.js';\n\nexport interface PermitData {\n /** Boss's wallet address (USDC holder) */\n owner: string;\n /** Agent's wallet address (authorized spender) */\n spender: string;\n /** Authorized amount (USDC, raw 6 decimal value) */\n value: string;\n /** Expiration timestamp */\n deadline: number;\n /** Signature v */\n v: number;\n /** Signature r */\n r: string;\n /** Signature s */\n s: string;\n}\n\nexport interface PermitWalletConfig {\n chain?: ChainName;\n /** Agent's private key (for executing transactions) */\n privateKey?: string;\n /** Load private key from file */\n walletPath?: string;\n /** Decryption password */\n walletPassword?: string;\n rpcUrl?: string;\n}\n\nexport interface TransferWithPermitParams {\n /** Recipient address */\n to: string;\n /** Amount (USDC) */\n amount: number;\n /** Boss-signed Permit data */\n permit: PermitData;\n}\n\nexport interface TransferWithPermitResult extends TransferResult {\n /** Permit transaction hash */\n permitTxHash?: string;\n /** Transfer transaction hash */\n transferTxHash?: string;\n}\n\n// Extended ABI to support permit and transferFrom\nconst PERMIT_ABI = [\n ...ERC20_ABI,\n 'function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)',\n 'function transferFrom(address from, address to, uint256 amount) returns (bool)',\n 'function allowance(address owner, address spender) view returns (uint256)',\n];\n\nexport class PermitWallet {\n readonly chain: ChainName;\n readonly chainConfig: ChainConfig;\n readonly address: string;\n \n private wallet: ethers.Wallet;\n private provider: ethers.JsonRpcProvider;\n private usdcContract: ethers.Contract;\n\n constructor(config: PermitWalletConfig = {}) {\n this.chain = config.chain || 'base_sepolia';\n this.chainConfig = getChain(this.chain);\n \n // Get private key\n let privateKey = config.privateKey || process.env.PAYMENT_AGENT_PRIVATE_KEY;\n \n // Or load from file\n if (!privateKey && config.walletPath) {\n const loaded = loadWallet({ \n storagePath: config.walletPath, \n password: config.walletPassword \n });\n if (!loaded.success || !loaded.privateKey) {\n throw new Error(loaded.error || 'Failed to load wallet');\n }\n privateKey = loaded.privateKey;\n }\n \n if (!privateKey) {\n throw new Error('privateKey is required. Set via config, env var, or walletPath.');\n }\n\n const rpcUrl = config.rpcUrl || this.chainConfig.rpc;\n this.provider = new ethers.JsonRpcProvider(rpcUrl);\n this.wallet = new ethers.Wallet(privateKey, this.provider);\n this.address = this.wallet.address;\n \n this.usdcContract = new ethers.Contract(\n this.chainConfig.usdc,\n PERMIT_ABI,\n this.wallet\n );\n }\n\n /**\n * Check if Permit is valid (current allowance)\n */\n async checkPermitAllowance(owner: string): Promise<string> {\n const allowance = await this.usdcContract.allowance(owner, this.address);\n return (Number(allowance) / 1e6).toFixed(2);\n }\n\n /**\n * Pay using Permit authorization\n * \n * Flow:\n * 1. Call permit() to record Boss's authorization in the contract\n * 2. Call transferFrom() to transfer from Boss's wallet to recipient\n * \n * @example\n * ```typescript\n * const wallet = new PermitWallet({ chain: 'base' });\n * \n * // Boss-signed permit data\n * const permit = {\n * owner: '0xBOSS...',\n * spender: wallet.address,\n * value: '10000000', // 10 USDC\n * deadline: 1234567890,\n * v: 27,\n * r: '0x...',\n * s: '0x...'\n * };\n * \n * const result = await wallet.transferWithPermit({\n * to: '0xSELLER...',\n * amount: 3.99,\n * permit\n * });\n * ```\n */\n async transferWithPermit(params: TransferWithPermitParams): Promise<TransferWithPermitResult> {\n const { to, amount, permit } = params;\n\n try {\n // Validate addresses\n const toAddress = ethers.getAddress(to);\n const ownerAddress = ethers.getAddress(permit.owner);\n \n // Verify spender is this wallet\n if (ethers.getAddress(permit.spender).toLowerCase() !== this.address.toLowerCase()) {\n return {\n success: false,\n error: `Permit spender (${permit.spender}) doesn't match wallet address (${this.address})`,\n };\n }\n\n // Check deadline\n const now = Math.floor(Date.now() / 1000);\n if (permit.deadline < now) {\n return {\n success: false,\n error: `Permit expired at ${new Date(permit.deadline * 1000).toISOString()}`,\n };\n }\n\n // Convert amount\n const amountWei = BigInt(Math.floor(amount * 1e6));\n const permitValue = BigInt(permit.value);\n \n // Check if authorized amount is sufficient\n if (amountWei > permitValue) {\n return {\n success: false,\n error: `Permit value (${Number(permitValue) / 1e6} USDC) < transfer amount (${amount} USDC)`,\n };\n }\n\n // Check existing allowance\n const currentAllowance = await this.usdcContract.allowance(ownerAddress, this.address);\n \n let permitTxHash: string | undefined;\n \n // If allowance insufficient, execute permit first\n if (BigInt(currentAllowance) < amountWei) {\n console.log('Executing permit...');\n const permitTx = await this.usdcContract.permit(\n ownerAddress,\n this.address,\n permitValue,\n permit.deadline,\n permit.v,\n permit.r,\n permit.s\n );\n const permitReceipt = await permitTx.wait();\n \n if (permitReceipt.status !== 1) {\n return {\n success: false,\n error: 'Permit transaction failed',\n permitTxHash: permitTx.hash,\n };\n }\n permitTxHash = permitTx.hash;\n console.log('Permit executed:', permitTxHash);\n }\n\n // Execute transferFrom\n console.log('Executing transferFrom...');\n const transferTx = await this.usdcContract.transferFrom(\n ownerAddress,\n toAddress,\n amountWei\n );\n const transferReceipt = await transferTx.wait();\n\n if (transferReceipt.status === 1) {\n return {\n success: true,\n tx_hash: transferTx.hash,\n permitTxHash,\n transferTxHash: transferTx.hash,\n from: ownerAddress,\n to: toAddress,\n amount,\n gas_used: Number(transferReceipt.gasUsed),\n block_number: transferReceipt.blockNumber,\n explorer_url: `${this.chainConfig.explorerTx}${transferTx.hash}`,\n };\n } else {\n return {\n success: false,\n error: 'TransferFrom transaction failed',\n tx_hash: transferTx.hash,\n permitTxHash,\n };\n }\n } catch (error) {\n const message = (error as Error).message;\n \n // Parse common errors\n if (message.includes('ERC20InsufficientAllowance')) {\n return {\n success: false,\n error: 'Insufficient allowance. Permit may have been used or expired.',\n };\n }\n if (message.includes('ERC20InsufficientBalance')) {\n return {\n success: false,\n error: 'Boss wallet has insufficient USDC balance.',\n };\n }\n if (message.includes('InvalidSignature') || message.includes('invalid signature')) {\n return {\n success: false,\n error: 'Invalid permit signature. Ask Boss to re-sign.',\n };\n }\n \n return {\n success: false,\n error: message,\n };\n }\n }\n\n /**\n * Get ETH balance (for gas)\n */\n async getGasBalance(): Promise<string> {\n const balance = await this.provider.getBalance(this.address);\n return ethers.formatEther(balance);\n }\n\n /**\n * Check if there's enough gas\n */\n async hasEnoughGas(minEth: number = 0.001): Promise<boolean> {\n const balance = await this.getGasBalance();\n return parseFloat(balance) >= minEth;\n }\n}\n\n/**\n * Format Permit request message (to send to Boss)\n */\nexport function formatPermitRequest(params: {\n agentAddress: string;\n amount: number;\n deadlineHours?: number;\n chain?: ChainName;\n reason?: string;\n}): string {\n const { agentAddress, amount, deadlineHours = 24, chain = 'base', reason } = params;\n const chainConfig = getChain(chain);\n const deadline = Math.floor(Date.now() / 1000) + deadlineHours * 3600;\n const value = BigInt(Math.floor(amount * 1e6)).toString();\n\n return `🔐 **USDC Spending Allowance Request**\n\n${reason ? `**Purpose:** ${reason}\\n` : ''}\n**Authorization Details:**\n- Authorized address (Agent): \\`${agentAddress}\\`\n- Amount: ${amount} USDC\n- Valid for: ${deadlineHours} hours\n- Chain: ${chainConfig.name}\n\n**Please sign the following EIP-2612 Permit with your wallet:**\n\n\\`\\`\\`json\n{\n \"types\": {\n \"Permit\": [\n { \"name\": \"owner\", \"type\": \"address\" },\n { \"name\": \"spender\", \"type\": \"address\" },\n { \"name\": \"value\", \"type\": \"uint256\" },\n { \"name\": \"nonce\", \"type\": \"uint256\" },\n { \"name\": \"deadline\", \"type\": \"uint256\" }\n ]\n },\n \"primaryType\": \"Permit\",\n \"domain\": {\n \"name\": \"USD Coin\",\n \"version\": \"2\",\n \"chainId\": ${chainConfig.chainId},\n \"verifyingContract\": \"${chainConfig.usdc}\"\n },\n \"message\": {\n \"owner\": \"<YOUR_WALLET_ADDRESS>\",\n \"spender\": \"${agentAddress}\",\n \"value\": \"${value}\",\n \"nonce\": \"<GET_FROM_CONTRACT>\",\n \"deadline\": ${deadline}\n }\n}\n\\`\\`\\`\n\nAfter signing, send { v, r, s, deadline } to the Agent.\n\n⚠️ Note: This authorization only allows the Agent to spend up to ${amount} USDC from your wallet. Your private key is never exposed.`;\n}\n"],"mappings":"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","names":["import_ethers","path","import_ethers"]}
|