pay-lobster 1.0.0

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.
Files changed (120) hide show
  1. package/README.md +401 -0
  2. package/README.md.bak +401 -0
  3. package/dist/agent.d.ts +132 -0
  4. package/dist/agent.d.ts.map +1 -0
  5. package/dist/agent.js +224 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/analytics.d.ts +120 -0
  8. package/dist/analytics.d.ts.map +1 -0
  9. package/dist/analytics.js +345 -0
  10. package/dist/analytics.js.map +1 -0
  11. package/dist/approvals.d.ts +168 -0
  12. package/dist/approvals.d.ts.map +1 -0
  13. package/dist/approvals.js +406 -0
  14. package/dist/approvals.js.map +1 -0
  15. package/dist/circle-client.d.ts +152 -0
  16. package/dist/circle-client.d.ts.map +1 -0
  17. package/dist/circle-client.js +266 -0
  18. package/dist/circle-client.js.map +1 -0
  19. package/dist/commission.d.ts +191 -0
  20. package/dist/commission.d.ts.map +1 -0
  21. package/dist/commission.js +475 -0
  22. package/dist/commission.js.map +1 -0
  23. package/dist/condition-builder.d.ts +98 -0
  24. package/dist/condition-builder.d.ts.map +1 -0
  25. package/dist/condition-builder.js +193 -0
  26. package/dist/condition-builder.js.map +1 -0
  27. package/dist/contacts.d.ts +179 -0
  28. package/dist/contacts.d.ts.map +1 -0
  29. package/dist/contacts.js +445 -0
  30. package/dist/contacts.js.map +1 -0
  31. package/dist/easy.d.ts +22 -0
  32. package/dist/easy.d.ts.map +1 -0
  33. package/dist/easy.js +40 -0
  34. package/dist/easy.js.map +1 -0
  35. package/dist/erc8004/constants.d.ts +152 -0
  36. package/dist/erc8004/constants.d.ts.map +1 -0
  37. package/dist/erc8004/constants.js +114 -0
  38. package/dist/erc8004/constants.js.map +1 -0
  39. package/dist/erc8004/discovery.d.ts +84 -0
  40. package/dist/erc8004/discovery.d.ts.map +1 -0
  41. package/dist/erc8004/discovery.js +217 -0
  42. package/dist/erc8004/discovery.js.map +1 -0
  43. package/dist/erc8004/identity.d.ts +91 -0
  44. package/dist/erc8004/identity.d.ts.map +1 -0
  45. package/dist/erc8004/identity.js +250 -0
  46. package/dist/erc8004/identity.js.map +1 -0
  47. package/dist/erc8004/index.d.ts +147 -0
  48. package/dist/erc8004/index.d.ts.map +1 -0
  49. package/dist/erc8004/index.js +225 -0
  50. package/dist/erc8004/index.js.map +1 -0
  51. package/dist/erc8004/reputation.d.ts +133 -0
  52. package/dist/erc8004/reputation.d.ts.map +1 -0
  53. package/dist/erc8004/reputation.js +277 -0
  54. package/dist/erc8004/reputation.js.map +1 -0
  55. package/dist/escrow-templates.d.ts +38 -0
  56. package/dist/escrow-templates.d.ts.map +1 -0
  57. package/dist/escrow-templates.js +419 -0
  58. package/dist/escrow-templates.js.map +1 -0
  59. package/dist/escrow.d.ts +320 -0
  60. package/dist/escrow.d.ts.map +1 -0
  61. package/dist/escrow.js +854 -0
  62. package/dist/escrow.js.map +1 -0
  63. package/dist/index.d.ts +11 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +33 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/invoices.d.ts +212 -0
  68. package/dist/invoices.d.ts.map +1 -0
  69. package/dist/invoices.js +393 -0
  70. package/dist/invoices.js.map +1 -0
  71. package/dist/notifications.d.ts +141 -0
  72. package/dist/notifications.d.ts.map +1 -0
  73. package/dist/notifications.js +350 -0
  74. package/dist/notifications.js.map +1 -0
  75. package/dist/tips.d.ts +171 -0
  76. package/dist/tips.d.ts.map +1 -0
  77. package/dist/tips.js +390 -0
  78. package/dist/tips.js.map +1 -0
  79. package/dist/types.d.ts +100 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +6 -0
  82. package/dist/types.js.map +1 -0
  83. package/dist/x402-client.d.ts +127 -0
  84. package/dist/x402-client.d.ts.map +1 -0
  85. package/dist/x402-client.js +350 -0
  86. package/dist/x402-client.js.map +1 -0
  87. package/dist/x402-server.d.ts +133 -0
  88. package/dist/x402-server.d.ts.map +1 -0
  89. package/dist/x402-server.js +330 -0
  90. package/dist/x402-server.js.map +1 -0
  91. package/lib/agent.ts +273 -0
  92. package/lib/analytics.ts +474 -0
  93. package/lib/analytics.ts.bak +474 -0
  94. package/lib/approvals.ts +585 -0
  95. package/lib/approvals.ts.bak +585 -0
  96. package/lib/circle-client.ts +376 -0
  97. package/lib/circle-client.ts.bak +376 -0
  98. package/lib/commission.ts +680 -0
  99. package/lib/commission.ts.bak +680 -0
  100. package/lib/condition-builder.ts +223 -0
  101. package/lib/condition-builder.ts.bak +223 -0
  102. package/lib/contacts.ts +615 -0
  103. package/lib/contacts.ts.bak +615 -0
  104. package/lib/easy.ts +46 -0
  105. package/lib/easy.ts.bak +352 -0
  106. package/lib/erc8004/constants.ts +175 -0
  107. package/lib/erc8004/discovery.ts +299 -0
  108. package/lib/erc8004/identity.ts +327 -0
  109. package/lib/erc8004/index.ts +285 -0
  110. package/lib/erc8004/reputation.ts +368 -0
  111. package/lib/escrow-templates.ts +462 -0
  112. package/lib/escrow.ts +1216 -0
  113. package/lib/index.ts +13 -0
  114. package/lib/invoices.ts +588 -0
  115. package/lib/notifications.ts +484 -0
  116. package/lib/tips.ts +570 -0
  117. package/lib/types.ts +108 -0
  118. package/lib/x402-client.ts +471 -0
  119. package/lib/x402-server.ts +462 -0
  120. package/package.json +58 -0
@@ -0,0 +1,376 @@
1
+ /**
2
+ * Circle Programmable Wallets Client
3
+ *
4
+ * Wrapper around Circle's Developer-Controlled Wallets API
5
+ * for USDC operations on testnet.
6
+ */
7
+
8
+ import crypto from 'crypto';
9
+
10
+ // Types
11
+ export interface CircleConfig {
12
+ apiKey: string;
13
+ entitySecret: string;
14
+ baseUrl?: string;
15
+ }
16
+
17
+ export interface Wallet {
18
+ id: string;
19
+ address: string;
20
+ blockchain: string;
21
+ state: string;
22
+ walletSetId: string;
23
+ createDate: string;
24
+ }
25
+
26
+ export interface WalletSet {
27
+ id: string;
28
+ name: string;
29
+ custodyType: string;
30
+ createDate: string;
31
+ }
32
+
33
+ export interface Balance {
34
+ token: {
35
+ id: string;
36
+ name: string;
37
+ symbol: string;
38
+ decimals: number;
39
+ blockchain: string;
40
+ };
41
+ amount: string;
42
+ }
43
+
44
+ export interface Transaction {
45
+ id: string;
46
+ state: string;
47
+ txHash?: string;
48
+ amounts: string[];
49
+ sourceAddress: string;
50
+ destinationAddress: string;
51
+ blockchain: string;
52
+ createDate: string;
53
+ }
54
+
55
+ export interface SendOptions {
56
+ fromWalletId: string;
57
+ toAddress: string;
58
+ amount: string;
59
+ tokenId?: string; // USDC token ID for the chain
60
+ feeLevel?: 'LOW' | 'MEDIUM' | 'HIGH';
61
+ }
62
+
63
+ export interface BridgeOptions {
64
+ fromWalletId: string;
65
+ toAddress: string;
66
+ fromChain: string;
67
+ toChain: string;
68
+ amount: string;
69
+ }
70
+
71
+ // Testnet USDC Token IDs (from Circle's registry)
72
+ export const USDC_TOKENS: Record<string, string> = {
73
+ 'ETH-SEPOLIA': 'eth-sepolia-usdc',
74
+ 'MATIC-AMOY': 'matic-amoy-usdc',
75
+ 'AVAX-FUJI': 'avax-fuji-usdc',
76
+ 'ARB-SEPOLIA': 'arb-sepolia-usdc',
77
+ };
78
+
79
+ export const CHAIN_NAMES: Record<string, string> = {
80
+ 'ETH-SEPOLIA': 'Ethereum Sepolia',
81
+ 'MATIC-AMOY': 'Polygon Amoy',
82
+ 'AVAX-FUJI': 'Avalanche Fuji',
83
+ 'ARB-SEPOLIA': 'Arbitrum Sepolia',
84
+ };
85
+
86
+ /**
87
+ * Circle Programmable Wallets Client
88
+ */
89
+ export class CircleClient {
90
+ private apiKey: string;
91
+ private entitySecret: string;
92
+ private baseUrl: string;
93
+
94
+ constructor(config: CircleConfig) {
95
+ this.apiKey = config.apiKey;
96
+ this.entitySecret = config.entitySecret;
97
+ this.baseUrl = config.baseUrl || 'https://api.circle.com/v1/w3s';
98
+ }
99
+
100
+ /**
101
+ * Generate entity secret ciphertext for API calls
102
+ */
103
+ private generateEntitySecretCiphertext(): string {
104
+ // Entity secret should be hex-encoded 32 bytes
105
+ const entitySecretBuffer = Buffer.from(this.entitySecret, 'hex');
106
+
107
+ // Generate random IV
108
+ const iv = crypto.randomBytes(12);
109
+
110
+ // For demo purposes, return base64 encoded secret
111
+ // In production, this would use Circle's public key for encryption
112
+ return Buffer.concat([iv, entitySecretBuffer]).toString('base64');
113
+ }
114
+
115
+ /**
116
+ * Make authenticated API request
117
+ */
118
+ private async request<T>(
119
+ method: string,
120
+ path: string,
121
+ body?: Record<string, any>
122
+ ): Promise<T> {
123
+ const url = `${this.baseUrl}${path}`;
124
+
125
+ const headers: Record<string, string> = {
126
+ 'Content-Type': 'application/json',
127
+ 'Authorization': `Bearer ${this.apiKey}`,
128
+ };
129
+
130
+ const options: RequestInit = {
131
+ method,
132
+ headers,
133
+ };
134
+
135
+ if (body) {
136
+ // Add idempotency key for mutations
137
+ if (method !== 'GET') {
138
+ body.idempotencyKey = crypto.randomUUID();
139
+ }
140
+
141
+ // Add entity secret ciphertext for transaction operations
142
+ if (path.includes('/transactions') || path.includes('/wallets')) {
143
+ body.entitySecretCiphertext = this.generateEntitySecretCiphertext();
144
+ }
145
+
146
+ options.body = JSON.stringify(body);
147
+ }
148
+
149
+ const response = await fetch(url, options);
150
+
151
+ if (!response.ok) {
152
+ const error = await response.text();
153
+ throw new Error(`Circle API error (${response.status}): ${error}`);
154
+ }
155
+
156
+ const data = await response.json();
157
+ return data.data || data;
158
+ }
159
+
160
+ // ============ Wallet Set Operations ============
161
+
162
+ /**
163
+ * Create a new wallet set
164
+ */
165
+ async createWalletSet(name: string): Promise<WalletSet> {
166
+ return this.request<WalletSet>('POST', '/developer/walletSets', { name });
167
+ }
168
+
169
+ /**
170
+ * List all wallet sets
171
+ */
172
+ async listWalletSets(): Promise<WalletSet[]> {
173
+ const result = await this.request<{ walletSets: WalletSet[] }>('GET', '/developer/walletSets');
174
+ return result.walletSets || [];
175
+ }
176
+
177
+ // ============ Wallet Operations ============
178
+
179
+ /**
180
+ * Create wallets in a wallet set
181
+ */
182
+ async createWallets(walletSetId: string, blockchains: string[], count = 1): Promise<Wallet[]> {
183
+ const result = await this.request<{ wallets: Wallet[] }>('POST', '/developer/wallets', {
184
+ walletSetId,
185
+ blockchains,
186
+ count,
187
+ });
188
+ return result.wallets || [];
189
+ }
190
+
191
+ /**
192
+ * Get wallet by ID
193
+ */
194
+ async getWallet(walletId: string): Promise<Wallet> {
195
+ return this.request<Wallet>('GET', `/wallets/${walletId}`);
196
+ }
197
+
198
+ /**
199
+ * List all wallets
200
+ */
201
+ async listWallets(): Promise<Wallet[]> {
202
+ const result = await this.request<{ wallets: Wallet[] }>('GET', '/wallets');
203
+ return result.wallets || [];
204
+ }
205
+
206
+ // ============ Balance Operations ============
207
+
208
+ /**
209
+ * Get token balances for a wallet
210
+ */
211
+ async getBalances(walletId: string): Promise<Balance[]> {
212
+ const result = await this.request<{ tokenBalances: Balance[] }>(
213
+ 'GET',
214
+ `/wallets/${walletId}/balances`
215
+ );
216
+ return result.tokenBalances || [];
217
+ }
218
+
219
+ /**
220
+ * Get USDC balance across all wallets
221
+ */
222
+ async getAllUSDCBalances(): Promise<{ wallet: Wallet; balance: string; chain: string }[]> {
223
+ const wallets = await this.listWallets();
224
+ const results: { wallet: Wallet; balance: string; chain: string }[] = [];
225
+
226
+ for (const wallet of wallets) {
227
+ try {
228
+ const balances = await this.getBalances(wallet.id);
229
+ const usdcBalance = balances.find(b => b.token.symbol === 'USDC');
230
+
231
+ results.push({
232
+ wallet,
233
+ balance: usdcBalance?.amount || '0',
234
+ chain: wallet.blockchain,
235
+ });
236
+ } catch (err) {
237
+ console.error(`Failed to get balance for wallet ${wallet.id}:`, err);
238
+ }
239
+ }
240
+
241
+ return results;
242
+ }
243
+
244
+ // ============ Transaction Operations ============
245
+
246
+ /**
247
+ * Send USDC to an address
248
+ */
249
+ async sendUSDC(options: SendOptions): Promise<Transaction> {
250
+ const wallet = await this.getWallet(options.fromWalletId);
251
+ const tokenId = options.tokenId || USDC_TOKENS[wallet.blockchain];
252
+
253
+ if (!tokenId) {
254
+ throw new Error(`No USDC token ID found for chain ${wallet.blockchain}`);
255
+ }
256
+
257
+ return this.request<Transaction>('POST', '/developer/transactions/transfer', {
258
+ walletId: options.fromWalletId,
259
+ tokenId,
260
+ destinationAddress: options.toAddress,
261
+ amounts: [options.amount],
262
+ fee: {
263
+ type: 'level',
264
+ config: {
265
+ feeLevel: options.feeLevel || 'MEDIUM',
266
+ },
267
+ },
268
+ });
269
+ }
270
+
271
+ /**
272
+ * Get transaction by ID
273
+ */
274
+ async getTransaction(transactionId: string): Promise<Transaction> {
275
+ return this.request<Transaction>('GET', `/transactions/${transactionId}`);
276
+ }
277
+
278
+ /**
279
+ * List recent transactions
280
+ */
281
+ async listTransactions(walletId?: string): Promise<Transaction[]> {
282
+ const path = walletId
283
+ ? `/wallets/${walletId}/transactions`
284
+ : '/transactions';
285
+
286
+ const result = await this.request<{ transactions: Transaction[] }>('GET', path);
287
+ return result.transactions || [];
288
+ }
289
+
290
+ // ============ CCTP Bridge Operations ============
291
+
292
+ /**
293
+ * Bridge USDC across chains via CCTP
294
+ */
295
+ async bridgeUSDC(options: BridgeOptions): Promise<Transaction> {
296
+ // CCTP bridge is done through contract interactions
297
+ // This is a simplified version - full implementation would use
298
+ // Circle's CCTP contracts directly
299
+
300
+ return this.request<Transaction>('POST', '/developer/transactions/contractExecution', {
301
+ walletId: options.fromWalletId,
302
+ contractAddress: this.getCCTPContractAddress(options.fromChain),
303
+ abiFunctionSignature: 'depositForBurn(uint256,uint32,bytes32,address)',
304
+ abiParameters: [
305
+ options.amount,
306
+ this.getChainDomain(options.toChain),
307
+ this.addressToBytes32(options.toAddress),
308
+ USDC_TOKENS[options.fromChain],
309
+ ],
310
+ fee: {
311
+ type: 'level',
312
+ config: { feeLevel: 'HIGH' },
313
+ },
314
+ });
315
+ }
316
+
317
+ /**
318
+ * Get CCTP TokenMessenger contract address for chain
319
+ */
320
+ private getCCTPContractAddress(chain: string): string {
321
+ const contracts: Record<string, string> = {
322
+ 'ETH-SEPOLIA': '0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5',
323
+ 'AVAX-FUJI': '0xeb08f243E5d3FCFF26A9E38Ae5520A669f4019d0',
324
+ 'ARB-SEPOLIA': '0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5',
325
+ };
326
+ return contracts[chain] || '';
327
+ }
328
+
329
+ /**
330
+ * Get CCTP domain ID for chain
331
+ */
332
+ private getChainDomain(chain: string): number {
333
+ const domains: Record<string, number> = {
334
+ 'ETH-SEPOLIA': 0,
335
+ 'AVAX-FUJI': 1,
336
+ 'ARB-SEPOLIA': 3,
337
+ 'MATIC-AMOY': 7,
338
+ };
339
+ return domains[chain] || 0;
340
+ }
341
+
342
+ /**
343
+ * Convert address to bytes32 format
344
+ */
345
+ private addressToBytes32(address: string): string {
346
+ return '0x' + address.slice(2).padStart(64, '0');
347
+ }
348
+
349
+ // ============ Utility Methods ============
350
+
351
+ /**
352
+ * Format USDC amount for display
353
+ */
354
+ static formatUSDC(amount: string): string {
355
+ const num = parseFloat(amount);
356
+ return `${num.toFixed(2)} USDC`;
357
+ }
358
+
359
+ /**
360
+ * Parse human-readable amount to wei
361
+ */
362
+ static parseAmount(amount: string): string {
363
+ // USDC has 6 decimals
364
+ const num = parseFloat(amount);
365
+ return (num * 1_000_000).toString();
366
+ }
367
+
368
+ /**
369
+ * Validate Ethereum address
370
+ */
371
+ static isValidAddress(address: string): boolean {
372
+ return /^0x[a-fA-F0-9]{40}$/.test(address);
373
+ }
374
+ }
375
+
376
+ export default CircleClient;