moltspay 1.3.0 → 1.4.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.
- package/README.md +221 -38
- package/dist/cdp/index.d.mts +4 -4
- package/dist/cdp/index.d.ts +4 -4
- package/dist/cdp/index.js +57 -0
- package/dist/cdp/index.js.map +1 -1
- package/dist/cdp/index.mjs +57 -0
- package/dist/cdp/index.mjs.map +1 -1
- package/dist/chains/index.d.mts +9 -8
- package/dist/chains/index.d.ts +9 -8
- package/dist/chains/index.js +57 -0
- package/dist/chains/index.js.map +1 -1
- package/dist/chains/index.mjs +57 -0
- package/dist/chains/index.mjs.map +1 -1
- package/dist/cli/index.js +1975 -273
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +1977 -265
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/index.d.mts +36 -3
- package/dist/client/index.d.ts +36 -3
- package/dist/client/index.js +540 -32
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +548 -30
- package/dist/client/index.mjs.map +1 -1
- package/dist/facilitators/index.d.mts +220 -1
- package/dist/facilitators/index.d.ts +220 -1
- package/dist/facilitators/index.js +664 -1
- package/dist/facilitators/index.js.map +1 -1
- package/dist/facilitators/index.mjs +670 -1
- package/dist/facilitators/index.mjs.map +1 -1
- package/dist/{index-On9ZaGDW.d.mts → index-D_2FkLwV.d.mts} +6 -2
- package/dist/{index-On9ZaGDW.d.ts → index-D_2FkLwV.d.ts} +6 -2
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1413 -146
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1421 -144
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +13 -3
- package/dist/server/index.d.ts +13 -3
- package/dist/server/index.js +905 -52
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +915 -52
- package/dist/server/index.mjs.map +1 -1
- package/dist/verify/index.d.mts +1 -1
- package/dist/verify/index.d.ts +1 -1
- package/dist/verify/index.js +57 -0
- package/dist/verify/index.js.map +1 -1
- package/dist/verify/index.mjs +57 -0
- package/dist/verify/index.mjs.map +1 -1
- package/dist/wallet/index.d.mts +3 -3
- package/dist/wallet/index.d.ts +3 -3
- package/dist/wallet/index.js +57 -0
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +57 -0
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +4 -1
- package/schemas/moltspay.services.schema.json +27 -132
package/README.md
CHANGED
|
@@ -21,11 +21,12 @@ MoltsPay enables agent-to-agent commerce using the [x402 protocol](https://www.x
|
|
|
21
21
|
|
|
22
22
|
- 🔌 **Skill Integration** - Add `moltspay.services.json` to any existing skill
|
|
23
23
|
- 🎫 **x402 Protocol** - HTTP-native payments (402 Payment Required)
|
|
24
|
-
- 💨 **Gasless** - Both client and server pay no gas (
|
|
24
|
+
- 💨 **Gasless** - Both client and server pay no gas (facilitators handle it)
|
|
25
25
|
- ✅ **Payment Verification** - Automatic on-chain verification
|
|
26
26
|
- 🔒 **Secure Wallet** - Spending limits, whitelist, and audit logging
|
|
27
|
-
- ⛓️ **Multi-chain** - Base, Polygon,
|
|
27
|
+
- ⛓️ **Multi-chain** - Base, Polygon, Solana, BNB, Tempo (mainnet & testnet)
|
|
28
28
|
- 🤖 **Agent-to-Agent** - Complete A2A payment flow support
|
|
29
|
+
- 🌐 **Multi-VM** - EVM chains + Solana (SVM) with unified API
|
|
29
30
|
|
|
30
31
|
## Installation
|
|
31
32
|
|
|
@@ -51,8 +52,9 @@ export async function textToVideo({ prompt }) {
|
|
|
51
52
|
{
|
|
52
53
|
"provider": {
|
|
53
54
|
"name": "My Video Service",
|
|
54
|
-
"wallet": "
|
|
55
|
-
"
|
|
55
|
+
"wallet": "0xYOUR_EVM_WALLET_ADDRESS",
|
|
56
|
+
"solana_wallet": "YOUR_SOLANA_ADDRESS",
|
|
57
|
+
"chains": ["base", "polygon", "solana", "bnb"]
|
|
56
58
|
},
|
|
57
59
|
"services": [{
|
|
58
60
|
"id": "text-to-video",
|
|
@@ -63,6 +65,8 @@ export async function textToVideo({ prompt }) {
|
|
|
63
65
|
}
|
|
64
66
|
```
|
|
65
67
|
|
|
68
|
+
**Note:** `solana_wallet` is optional - only needed if accepting Solana payments.
|
|
69
|
+
|
|
66
70
|
**3. Start server:**
|
|
67
71
|
```bash
|
|
68
72
|
npx moltspay start ./my-skill --port 3000
|
|
@@ -74,15 +78,15 @@ That's it! Your skill now accepts x402 payments.
|
|
|
74
78
|
|
|
75
79
|
**1. Initialize wallet (one time):**
|
|
76
80
|
```bash
|
|
77
|
-
npx moltspay init
|
|
78
|
-
#
|
|
81
|
+
npx moltspay init # EVM wallet (Base, Polygon, BNB, etc.)
|
|
82
|
+
npx moltspay init --chain solana # Solana wallet (mainnet & devnet)
|
|
79
83
|
```
|
|
80
84
|
|
|
81
85
|
**2. Fund your wallet (US users):**
|
|
82
86
|
```bash
|
|
83
|
-
npx moltspay fund
|
|
87
|
+
npx moltspay fund 5
|
|
84
88
|
# Opens Coinbase Pay - use debit card or Apple Pay
|
|
85
|
-
# USDC arrives in
|
|
89
|
+
# USDC arrives in < 1 minutes. No ETH needed!
|
|
86
90
|
```
|
|
87
91
|
|
|
88
92
|
Or send USDC directly to your wallet address from any exchange.
|
|
@@ -102,30 +106,43 @@ Want to test before using real money? Use our testnet faucets:
|
|
|
102
106
|
|
|
103
107
|
```bash
|
|
104
108
|
# 1. Create wallet (if you don't have one)
|
|
105
|
-
npx moltspay init
|
|
109
|
+
npx moltspay init # EVM wallet (Base, Polygon, BNB, etc.)
|
|
110
|
+
npx moltspay init --chain solana # Solana wallet (mainnet & devnet)
|
|
106
111
|
|
|
107
|
-
# 2. Get free testnet tokens
|
|
112
|
+
# 2. Get free testnet tokens (pick one or all!)
|
|
108
113
|
npx moltspay faucet # Base Sepolia (1 USDC, once per 24h)
|
|
109
|
-
npx moltspay faucet --chain
|
|
114
|
+
npx moltspay faucet --chain solana_devnet # Solana devnet (1 USDC)
|
|
115
|
+
npx moltspay faucet --chain bnb_testnet # BNB testnet (1 USDC + 0.001 tBNB for gas)
|
|
116
|
+
npx moltspay faucet --chain tempo_moderato # Tempo testnet (1 pathUSD)
|
|
110
117
|
|
|
111
|
-
# 3. Test payments
|
|
112
|
-
#
|
|
113
|
-
npx moltspay pay https://moltspay.com/a/
|
|
118
|
+
# 3. Test payments on different chains
|
|
119
|
+
# Base Sepolia (CDP, gasless)
|
|
120
|
+
npx moltspay pay https://moltspay.com/a/zen7 text-to-video \
|
|
114
121
|
--chain base_sepolia --prompt "a robot dancing"
|
|
115
122
|
|
|
116
|
-
#
|
|
123
|
+
# Solana devnet (SPL transfer)
|
|
124
|
+
npx moltspay pay https://moltspay.com/a/zen7 text-to-video \
|
|
125
|
+
--chain solana_devnet --prompt "a cat playing piano"
|
|
126
|
+
|
|
127
|
+
# BNB testnet (gas sponsored)
|
|
128
|
+
npx moltspay pay https://moltspay.com/a/zen7 text-to-video \
|
|
129
|
+
--chain bnb_testnet --prompt "a sunset timelapse"
|
|
130
|
+
|
|
131
|
+
# Tempo Moderato (gas-free, MPP protocol)
|
|
117
132
|
npx moltspay pay https://server.com service-id \
|
|
118
133
|
--chain tempo_moderato --prompt "test"
|
|
119
134
|
```
|
|
120
135
|
|
|
121
136
|
## Payment Protocols
|
|
122
137
|
|
|
123
|
-
MoltsPay supports
|
|
138
|
+
MoltsPay supports multiple payment protocols, each optimized for different chains:
|
|
124
139
|
|
|
125
140
|
| Protocol | Chains | Gas | Description |
|
|
126
141
|
|----------|--------|-----|-------------|
|
|
127
|
-
| x402 | Base, Polygon
|
|
128
|
-
|
|
|
142
|
+
| x402 + CDP | Base, Polygon | Gasless (CDP pays) | HTTP 402 + EIP-3009 signatures |
|
|
143
|
+
| x402 + SOL | Solana | Gasless (server pays) | HTTP 402 + SPL transfer |
|
|
144
|
+
| x402 + BNB | BNB | Gasless (server pays) | HTTP 402 + EIP-712 intent signing |
|
|
145
|
+
| MPP | Tempo | Gas-free native | HTTP 402 + WWW-Authenticate |
|
|
129
146
|
|
|
130
147
|
### How x402 Protocol Works
|
|
131
148
|
|
|
@@ -180,6 +197,58 @@ Client Server
|
|
|
180
197
|
|
|
181
198
|
**Key insight:** On Tempo, the client executes the transfer directly (gas-free), then retries with the transaction hash. No CDP facilitator needed.
|
|
182
199
|
|
|
200
|
+
### How Solana Protocol Works
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
Client Server (Fee Payer) Solana Network
|
|
204
|
+
│ │ │
|
|
205
|
+
│ POST /execute │ │
|
|
206
|
+
│ ─────────────────────────> │ │
|
|
207
|
+
│ │ │
|
|
208
|
+
│ 402 + payment requirements │ │
|
|
209
|
+
│ (includes solana_wallet) │ │
|
|
210
|
+
│ <───────────────────────── │ │
|
|
211
|
+
│ │ │
|
|
212
|
+
│ [Sign SPL Transfer] │ │
|
|
213
|
+
│ [NO GAS - just signing] │ │
|
|
214
|
+
│ │ │
|
|
215
|
+
│ POST + X-Payment (signature) │ │
|
|
216
|
+
│ ─────────────────────────> │ Execute transfer │
|
|
217
|
+
│ │ (server pays ~$0.001 SOL) │
|
|
218
|
+
│ │ ─────────────────────────> │
|
|
219
|
+
│ │ │
|
|
220
|
+
│ 200 OK + result │ │
|
|
221
|
+
│ <───────────────────────── │ │
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**Key insight:** Client only signs the SPL transfer (gasless). Server acts as fee payer and executes the transaction on-chain.
|
|
225
|
+
|
|
226
|
+
### How BNB Protocol Works
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
Client Server BNB Network
|
|
230
|
+
│ │ │
|
|
231
|
+
│ POST /execute │ │
|
|
232
|
+
│ ─────────────────────────> │ │
|
|
233
|
+
│ │ │
|
|
234
|
+
│ 402 + payment requirements │ │
|
|
235
|
+
│ (includes bnbSpender) │ │
|
|
236
|
+
│ <───────────────────────── │ │
|
|
237
|
+
│ │ │
|
|
238
|
+
│ [Sign EIP-712 intent] │ │
|
|
239
|
+
│ [NO GAS - just signing] │ │
|
|
240
|
+
│ │ │
|
|
241
|
+
│ POST + X-Payment (signature) │ │
|
|
242
|
+
│ ─────────────────────────> │ Execute transferFrom │
|
|
243
|
+
│ │ (server pays ~$0.0001 gas) │
|
|
244
|
+
│ │ ─────────────────────────> │
|
|
245
|
+
│ │ │
|
|
246
|
+
│ 200 OK + result │ │
|
|
247
|
+
│ <───────────────────────── │ │
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Key insight:** Client only signs an intent (gasless). Server executes the actual transfer and pays the minimal gas (~$0.0001). This is the "pay-for-success" model - payment only happens if service succeeds.
|
|
251
|
+
|
|
183
252
|
## Skill Structure
|
|
184
253
|
|
|
185
254
|
MoltsPay reads your skill's existing structure:
|
|
@@ -305,9 +374,11 @@ Clients can then pay using `--chain base_sepolia` and get free testnet USDC via
|
|
|
305
374
|
|
|
306
375
|
```bash
|
|
307
376
|
# === Client Commands ===
|
|
308
|
-
npx moltspay init # Create wallet
|
|
377
|
+
npx moltspay init # Create wallet (EVM + Solana)
|
|
309
378
|
npx moltspay fund <amount> # Fund wallet via Coinbase (US)
|
|
310
|
-
npx moltspay faucet # Get free testnet USDC
|
|
379
|
+
npx moltspay faucet # Get free testnet USDC (Base Sepolia)
|
|
380
|
+
npx moltspay faucet --chain solana_devnet # Get Solana devnet USDC
|
|
381
|
+
npx moltspay faucet --chain bnb_testnet # Get BNB testnet USDC + tBNB
|
|
311
382
|
npx moltspay faucet --chain tempo_moderato # Get Tempo testnet tokens
|
|
312
383
|
npx moltspay status # Check balance (all chains)
|
|
313
384
|
npx moltspay config # Update limits
|
|
@@ -326,7 +397,12 @@ npx moltspay services --json # Output as JSON
|
|
|
326
397
|
# === Pay with Chain Selection ===
|
|
327
398
|
npx moltspay pay <url> <service> --chain base # Pay on Base (default)
|
|
328
399
|
npx moltspay pay <url> <service> --chain polygon # Pay on Polygon
|
|
329
|
-
npx moltspay pay <url> <service> --chain base_sepolia # Pay on testnet
|
|
400
|
+
npx moltspay pay <url> <service> --chain base_sepolia # Pay on Base testnet
|
|
401
|
+
npx moltspay pay <url> <service> --chain solana # Pay on Solana
|
|
402
|
+
npx moltspay pay <url> <service> --chain solana_devnet # Pay on Solana devnet
|
|
403
|
+
npx moltspay pay <url> <service> --chain bnb # Pay on BNB
|
|
404
|
+
npx moltspay pay <url> <service> --chain bnb_testnet # Pay on BNB testnet
|
|
405
|
+
npx moltspay pay <url> <service> --chain tempo_moderato # Pay on Tempo
|
|
330
406
|
|
|
331
407
|
# === Server Commands ===
|
|
332
408
|
npx moltspay start <skill-dir> # Start server
|
|
@@ -335,7 +411,7 @@ npx moltspay validate <path> # Validate manifest
|
|
|
335
411
|
|
|
336
412
|
# === Options ===
|
|
337
413
|
--port <port> # Server port (default 3000)
|
|
338
|
-
--chain <chain> # Chain: base, polygon,
|
|
414
|
+
--chain <chain> # Chain: base, polygon, solana, bnb, tempo_moderato, + testnets
|
|
339
415
|
--token <token> # Token: USDC, USDT
|
|
340
416
|
--max-per-tx <amount> # Spending limit per transaction
|
|
341
417
|
--max-per-day <amount> # Daily spending limit
|
|
@@ -377,15 +453,120 @@ server.listen(3000);
|
|
|
377
453
|
|
|
378
454
|
## Supported Chains
|
|
379
455
|
|
|
380
|
-
| Chain | ID | Type |
|
|
381
|
-
|
|
382
|
-
| Base | 8453 | Mainnet |
|
|
383
|
-
| Polygon | 137 | Mainnet | |
|
|
384
|
-
|
|
|
385
|
-
|
|
|
386
|
-
|
|
|
456
|
+
| Chain | ID | Type | Facilitator | Gas Model |
|
|
457
|
+
|-------|-----|------|-------------|-----------|
|
|
458
|
+
| Base | 8453 | Mainnet | CDP | Gasless (CDP pays) |
|
|
459
|
+
| Polygon | 137 | Mainnet | CDP | Gasless (CDP pays) |
|
|
460
|
+
| Base Sepolia | 84532 | Testnet | CDP | Gasless (CDP pays) |
|
|
461
|
+
| Solana | - | Mainnet | SOL | Gasless (server pays) |
|
|
462
|
+
| Solana Devnet | - | Testnet | SOL | Gasless (server pays) |
|
|
463
|
+
| BNB | 56 | Mainnet | BNB | Gasless (server pays) |
|
|
464
|
+
| BNB Testnet | 97 | Testnet | BNB | Gasless (server pays) |
|
|
465
|
+
| Tempo Moderato | 42431 | Testnet | Tempo | Gas-free native |
|
|
466
|
+
|
|
467
|
+
**Notes:**
|
|
468
|
+
- Ethereum mainnet NOT recommended (gas too expensive)
|
|
469
|
+
- Each chain uses a specialized facilitator for optimal UX
|
|
470
|
+
|
|
471
|
+
### Facilitator Architecture
|
|
472
|
+
|
|
473
|
+
A **facilitator** is the entity that executes the on-chain payment and pays the gas fees. MoltsPay supports two types:
|
|
474
|
+
|
|
475
|
+
| Type | Facilitator | Who Pays Gas? | Trust Model |
|
|
476
|
+
|------|-------------|---------------|-------------|
|
|
477
|
+
| **External** | CDP (Coinbase) | Coinbase | Trust Coinbase infrastructure |
|
|
478
|
+
| **Self-hosted** | SOL, BNB, Tempo | Your server | Trust your own server |
|
|
479
|
+
|
|
480
|
+
**External Facilitator (CDP):**
|
|
481
|
+
- Uses Coinbase Developer Platform as a third-party settlement service
|
|
482
|
+
- Coinbase handles all on-chain execution and gas fees
|
|
483
|
+
- Requires CDP API credentials
|
|
484
|
+
- Supported chains: Base, Polygon
|
|
485
|
+
|
|
486
|
+
**Self-hosted Facilitator (SOL, BNB, Tempo):**
|
|
487
|
+
- Your MoltsPay server acts as the facilitator
|
|
488
|
+
- Server pays gas fees (~$0.001 per tx)
|
|
489
|
+
- No external dependency - fully self-sovereign
|
|
490
|
+
- You control the entire payment flow
|
|
491
|
+
|
|
492
|
+
**Why Self-hosted is More Decentralized:**
|
|
493
|
+
|
|
494
|
+
| Aspect | CDP (External) | Self-hosted |
|
|
495
|
+
|--------|----------------|-------------|
|
|
496
|
+
| Single point of failure | ❌ Coinbase down = everyone stuck | ✅ Each provider independent |
|
|
497
|
+
| Censorship risk | ❌ Coinbase can block accounts | ✅ Cannot be censored |
|
|
498
|
+
| Dependency | ❌ Relies on third-party | ✅ Fully autonomous |
|
|
499
|
+
|
|
500
|
+
This self-hosted approach is a key innovation: **any service provider can become their own facilitator** without relying on third-party infrastructure. Unlike CDP where all users depend on Coinbase, self-hosted facilitators create a truly decentralized network with no single point of failure.
|
|
387
501
|
|
|
388
|
-
|
|
502
|
+
**Note:** Clients never need to know the facilitator's private keys. They only sign their own payments - the facilitator handles settlement transparently.
|
|
503
|
+
|
|
504
|
+
### Facilitators Explained
|
|
505
|
+
|
|
506
|
+
| Facilitator | Chains | How It Works |
|
|
507
|
+
|-------------|--------|--------------|
|
|
508
|
+
| **CDP** | Base, Polygon | Client signs EIP-3009, Coinbase executes transfer |
|
|
509
|
+
| **SOL** | Solana | Client signs SPL transfer, server executes as fee payer |
|
|
510
|
+
| **BNB** | BNB | Client signs EIP-712 intent, server executes transfer |
|
|
511
|
+
| **Tempo** | Tempo Moderato | Client executes TIP-20 transfer (native gas-free) |
|
|
512
|
+
|
|
513
|
+
### Solana Support
|
|
514
|
+
|
|
515
|
+
Solana uses the **SolanaFacilitator** with SPL token transfers. Key differences:
|
|
516
|
+
|
|
517
|
+
- **Gasless for users** - Server acts as fee payer (~$0.001 SOL per tx)
|
|
518
|
+
- **Separate wallet** - Solana uses ed25519 keys (different from EVM's secp256k1)
|
|
519
|
+
- **Wallet stored at** `~/.moltspay/wallet-solana.json`
|
|
520
|
+
- **Token** - Official Circle USDC SPL token
|
|
521
|
+
|
|
522
|
+
```bash
|
|
523
|
+
# Initialize includes Solana wallet automatically
|
|
524
|
+
npx moltspay init
|
|
525
|
+
|
|
526
|
+
# Check Solana balance
|
|
527
|
+
npx moltspay status
|
|
528
|
+
|
|
529
|
+
# Get free devnet USDC
|
|
530
|
+
npx moltspay faucet --chain solana_devnet
|
|
531
|
+
|
|
532
|
+
# Pay on Solana
|
|
533
|
+
npx moltspay pay https://server.com service-id --chain solana --prompt "test"
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
**USDC Addresses:**
|
|
537
|
+
| Network | Mint Address |
|
|
538
|
+
|---------|--------------|
|
|
539
|
+
| Mainnet | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` |
|
|
540
|
+
| Devnet | `4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU` |
|
|
541
|
+
|
|
542
|
+
### BNB Chain Support
|
|
543
|
+
|
|
544
|
+
BNB uses the **BNBFacilitator** with a pre-approval flow. Since CDP doesn't support BNB, we use a different approach:
|
|
545
|
+
|
|
546
|
+
1. Client signs an EIP-712 payment intent (no gas needed)
|
|
547
|
+
2. Server validates and executes the transfer
|
|
548
|
+
3. Server sponsors gas (~$0.0001 per tx)
|
|
549
|
+
|
|
550
|
+
```bash
|
|
551
|
+
# Get free testnet USDC + tBNB for gas
|
|
552
|
+
npx moltspay faucet --chain bnb_testnet
|
|
553
|
+
|
|
554
|
+
# Pay on BNB (client pays no gas!)
|
|
555
|
+
npx moltspay pay https://server.com service-id --chain bnb_testnet --prompt "test"
|
|
556
|
+
|
|
557
|
+
# Check BNB balance
|
|
558
|
+
npx moltspay status
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
**Important:** BNB tokens use 18 decimals (not 6 like Base/Polygon).
|
|
562
|
+
|
|
563
|
+
**Token Addresses (BNB Mainnet):**
|
|
564
|
+
| Token | Address |
|
|
565
|
+
|-------|---------|
|
|
566
|
+
| USDC | `0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d` |
|
|
567
|
+
| USDT | `0x55d398326f99059fF775485246999027B3197955` |
|
|
568
|
+
|
|
569
|
+
### Tempo Testnet
|
|
389
570
|
|
|
390
571
|
Tempo Moderato is a gas-free testnet that supports the **MPP (Machine Payments Protocol)**. Perfect for testing agent-to-agent payments without any gas fees.
|
|
391
572
|
|
|
@@ -408,24 +589,26 @@ npx moltspay status
|
|
|
408
589
|
|
|
409
590
|
## Live Example: Zen7 Video Generation
|
|
410
591
|
|
|
411
|
-
Live service at `https://
|
|
592
|
+
Live service at `https://moltspay.com/a/zen7`
|
|
412
593
|
|
|
413
594
|
**Services:**
|
|
414
|
-
- `text-to-video` - $0.
|
|
415
|
-
- `image-to-video` - $
|
|
595
|
+
- `text-to-video` - $0.01 USDC - Generate video from text prompt
|
|
596
|
+
- `image-to-video` - $0.01 USDC - Animate a static image
|
|
416
597
|
|
|
417
|
-
**Supported Chains:** Base, Polygon
|
|
598
|
+
**Supported Chains:** Base, Polygon, Solana, BNB, Tempo (mainnet & testnet)
|
|
418
599
|
|
|
419
600
|
**Try it:**
|
|
420
601
|
```bash
|
|
421
602
|
# List services
|
|
422
|
-
npx moltspay services https://
|
|
603
|
+
npx moltspay services https://moltspay.com/a/zen7
|
|
423
604
|
|
|
424
605
|
# Pay on Base (default)
|
|
425
|
-
npx moltspay pay https://
|
|
606
|
+
npx moltspay pay https://moltspay.com/a/zen7 text-to-video --prompt "a happy cat"
|
|
426
607
|
|
|
427
|
-
# Pay on
|
|
428
|
-
npx moltspay pay https://
|
|
608
|
+
# Pay on different chains
|
|
609
|
+
npx moltspay pay https://moltspay.com/a/zen7 text-to-video --chain polygon --prompt "a happy cat"
|
|
610
|
+
npx moltspay pay https://moltspay.com/a/zen7 text-to-video --chain bnb_testnet --prompt "a happy cat"
|
|
611
|
+
npx moltspay pay https://moltspay.com/a/zen7 text-to-video --chain solana_devnet --prompt "a happy cat"
|
|
429
612
|
```
|
|
430
613
|
|
|
431
614
|
## Use Cases
|
package/dist/cdp/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { E as EvmChainName } from '../index-D_2FkLwV.mjs';
|
|
2
2
|
import { getChain } from '../chains/index.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -14,7 +14,7 @@ interface CDPWalletConfig {
|
|
|
14
14
|
/** Storage directory (default: ~/.moltspay) */
|
|
15
15
|
storageDir?: string;
|
|
16
16
|
/** Chain name */
|
|
17
|
-
chain?:
|
|
17
|
+
chain?: EvmChainName;
|
|
18
18
|
/** CDP API credentials (or use env vars) */
|
|
19
19
|
apiKeyId?: string;
|
|
20
20
|
apiKeySecret?: string;
|
|
@@ -26,7 +26,7 @@ interface CDPWalletData {
|
|
|
26
26
|
/** CDP wallet ID */
|
|
27
27
|
walletId: string;
|
|
28
28
|
/** Chain */
|
|
29
|
-
chain:
|
|
29
|
+
chain: EvmChainName;
|
|
30
30
|
/** Created timestamp */
|
|
31
31
|
createdAt: string;
|
|
32
32
|
/** CDP account data (for restoration) */
|
|
@@ -75,7 +75,7 @@ declare function getCDPWalletAddress(storageDir?: string): string | null;
|
|
|
75
75
|
*/
|
|
76
76
|
declare class CDPWallet {
|
|
77
77
|
readonly address: string;
|
|
78
|
-
readonly chain:
|
|
78
|
+
readonly chain: EvmChainName;
|
|
79
79
|
readonly chainConfig: ReturnType<typeof getChain>;
|
|
80
80
|
private storageDir;
|
|
81
81
|
constructor(config?: CDPWalletConfig);
|
package/dist/cdp/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { E as EvmChainName } from '../index-D_2FkLwV.js';
|
|
2
2
|
import { getChain } from '../chains/index.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -14,7 +14,7 @@ interface CDPWalletConfig {
|
|
|
14
14
|
/** Storage directory (default: ~/.moltspay) */
|
|
15
15
|
storageDir?: string;
|
|
16
16
|
/** Chain name */
|
|
17
|
-
chain?:
|
|
17
|
+
chain?: EvmChainName;
|
|
18
18
|
/** CDP API credentials (or use env vars) */
|
|
19
19
|
apiKeyId?: string;
|
|
20
20
|
apiKeySecret?: string;
|
|
@@ -26,7 +26,7 @@ interface CDPWalletData {
|
|
|
26
26
|
/** CDP wallet ID */
|
|
27
27
|
walletId: string;
|
|
28
28
|
/** Chain */
|
|
29
|
-
chain:
|
|
29
|
+
chain: EvmChainName;
|
|
30
30
|
/** Created timestamp */
|
|
31
31
|
createdAt: string;
|
|
32
32
|
/** CDP account data (for restoration) */
|
|
@@ -75,7 +75,7 @@ declare function getCDPWalletAddress(storageDir?: string): string | null;
|
|
|
75
75
|
*/
|
|
76
76
|
declare class CDPWallet {
|
|
77
77
|
readonly address: string;
|
|
78
|
-
readonly chain:
|
|
78
|
+
readonly chain: EvmChainName;
|
|
79
79
|
readonly chainConfig: ReturnType<typeof getChain>;
|
|
80
80
|
private storageDir;
|
|
81
81
|
constructor(config?: CDPWalletConfig);
|
package/dist/cdp/index.js
CHANGED
|
@@ -147,6 +147,63 @@ var CHAINS = {
|
|
|
147
147
|
explorerTx: "https://explore.testnet.tempo.xyz/tx/",
|
|
148
148
|
avgBlockTime: 0.5
|
|
149
149
|
// ~500ms finality
|
|
150
|
+
},
|
|
151
|
+
// ============ BNB Chain Testnet ============
|
|
152
|
+
bnb_testnet: {
|
|
153
|
+
name: "BNB Testnet",
|
|
154
|
+
chainId: 97,
|
|
155
|
+
rpc: "https://data-seed-prebsc-1-s1.binance.org:8545",
|
|
156
|
+
tokens: {
|
|
157
|
+
// Note: BNB uses 18 decimals for stablecoins (unlike Base/Polygon which use 6)
|
|
158
|
+
// Using official Binance-Peg testnet tokens
|
|
159
|
+
USDC: {
|
|
160
|
+
address: "0x64544969ed7EBf5f083679233325356EbE738930",
|
|
161
|
+
// Testnet USDC
|
|
162
|
+
decimals: 18,
|
|
163
|
+
symbol: "USDC",
|
|
164
|
+
eip712Name: "USD Coin"
|
|
165
|
+
},
|
|
166
|
+
USDT: {
|
|
167
|
+
address: "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd",
|
|
168
|
+
// Testnet USDT
|
|
169
|
+
decimals: 18,
|
|
170
|
+
symbol: "USDT",
|
|
171
|
+
eip712Name: "Tether USD"
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
usdc: "0x64544969ed7EBf5f083679233325356EbE738930",
|
|
175
|
+
explorer: "https://testnet.bscscan.com/address/",
|
|
176
|
+
explorerTx: "https://testnet.bscscan.com/tx/",
|
|
177
|
+
avgBlockTime: 3,
|
|
178
|
+
// BNB-specific: requires approval for pay-for-success flow
|
|
179
|
+
requiresApproval: true
|
|
180
|
+
},
|
|
181
|
+
// ============ BNB Chain Mainnet ============
|
|
182
|
+
bnb: {
|
|
183
|
+
name: "BNB Smart Chain",
|
|
184
|
+
chainId: 56,
|
|
185
|
+
rpc: "https://bsc-dataseed.binance.org",
|
|
186
|
+
tokens: {
|
|
187
|
+
// Note: BNB uses 18 decimals for stablecoins
|
|
188
|
+
USDC: {
|
|
189
|
+
address: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
|
|
190
|
+
decimals: 18,
|
|
191
|
+
symbol: "USDC",
|
|
192
|
+
eip712Name: "USD Coin"
|
|
193
|
+
},
|
|
194
|
+
USDT: {
|
|
195
|
+
address: "0x55d398326f99059fF775485246999027B3197955",
|
|
196
|
+
decimals: 18,
|
|
197
|
+
symbol: "USDT",
|
|
198
|
+
eip712Name: "Tether USD"
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
usdc: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
|
|
202
|
+
explorer: "https://bscscan.com/address/",
|
|
203
|
+
explorerTx: "https://bscscan.com/tx/",
|
|
204
|
+
avgBlockTime: 3,
|
|
205
|
+
// BNB-specific: requires approval for pay-for-success flow
|
|
206
|
+
requiresApproval: true
|
|
150
207
|
}
|
|
151
208
|
};
|
|
152
209
|
function getChain(name) {
|
package/dist/cdp/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cdp/index.ts","../../src/chains/index.ts"],"sourcesContent":["/**\n * CDP (Coinbase Developer Platform) Wallet Integration\n * \n * Creates and manages wallets via Coinbase's CDP SDK.\n * These wallets are hosted by Coinbase, making them easy to use for AI Agents.\n * \n * @see https://docs.cdp.coinbase.com/\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { ChainName } from '../types/index.js';\nimport { getChain } from '../chains/index.js';\n\n// CDP config file location\nconst DEFAULT_STORAGE_DIR = path.join(process.env.HOME || '.', '.moltspay');\nconst CDP_CONFIG_FILE = 'cdp-wallet.json';\n\nexport interface CDPWalletConfig {\n /** Storage directory (default: ~/.moltspay) */\n storageDir?: string;\n /** Chain name */\n chain?: ChainName;\n /** CDP API credentials (or use env vars) */\n apiKeyId?: string;\n apiKeySecret?: string;\n walletSecret?: string;\n}\n\nexport interface CDPWalletData {\n /** Wallet address */\n address: string;\n /** CDP wallet ID */\n walletId: string;\n /** Chain */\n chain: ChainName;\n /** Created timestamp */\n createdAt: string;\n /** CDP account data (for restoration) */\n accountData?: string;\n}\n\nexport interface CDPInitResult {\n success: boolean;\n address?: string;\n walletId?: string;\n isNew?: boolean;\n error?: string;\n storagePath?: string;\n}\n\n/**\n * Check if CDP SDK is available\n */\nexport function isCDPAvailable(): boolean {\n try {\n require.resolve('@coinbase/cdp-sdk');\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get CDP credentials from environment\n */\nfunction getCDPCredentials(config: CDPWalletConfig): {\n apiKeyId: string;\n apiKeySecret: string;\n walletSecret?: string;\n} | null {\n const apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;\n const apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;\n const walletSecret = config.walletSecret || process.env.CDP_WALLET_SECRET;\n\n if (!apiKeyId || !apiKeySecret) {\n return null;\n }\n\n return { apiKeyId, apiKeySecret, walletSecret };\n}\n\n/**\n * Initialize CDP wallet\n * \n * Creates a new CDP wallet or loads existing one.\n * \n * @example\n * ```bash\n * # Set credentials\n * export CDP_API_KEY_ID=your-key-id\n * export CDP_API_KEY_SECRET=your-key-secret\n * \n * # Initialize\n * npx moltspay init --cdp --chain base\n * ```\n */\nexport async function initCDPWallet(config: CDPWalletConfig = {}): Promise<CDPInitResult> {\n const storageDir = config.storageDir || DEFAULT_STORAGE_DIR;\n const chain = config.chain || 'base';\n const storagePath = path.join(storageDir, CDP_CONFIG_FILE);\n\n // Check for existing wallet\n if (fs.existsSync(storagePath)) {\n try {\n const data = JSON.parse(fs.readFileSync(storagePath, 'utf-8')) as CDPWalletData;\n return {\n success: true,\n address: data.address,\n walletId: data.walletId,\n isNew: false,\n storagePath,\n };\n } catch (error) {\n // Continue to create new\n }\n }\n\n // Check CDP availability\n if (!isCDPAvailable()) {\n return {\n success: false,\n error: 'CDP SDK not installed. Run: npm install @coinbase/cdp-sdk',\n };\n }\n\n // Get credentials\n const creds = getCDPCredentials(config);\n if (!creds) {\n return {\n success: false,\n error: 'CDP credentials not found. Set CDP_API_KEY_ID and CDP_API_KEY_SECRET environment variables.',\n };\n }\n\n try {\n // Dynamic import to avoid errors when CDP SDK is not installed\n const { CdpClient } = await import('@coinbase/cdp-sdk');\n\n // Initialize CDP client\n const cdp = new CdpClient({\n apiKeyId: creds.apiKeyId,\n apiKeySecret: creds.apiKeySecret,\n walletSecret: creds.walletSecret,\n });\n\n // Create EVM account\n const account = await cdp.evm.createAccount();\n\n // Ensure storage directory exists\n if (!fs.existsSync(storageDir)) {\n fs.mkdirSync(storageDir, { recursive: true });\n }\n\n // Save wallet data\n const walletData: CDPWalletData = {\n address: account.address,\n walletId: account.address, // CDP uses address as ID for EVM\n chain,\n createdAt: new Date().toISOString(),\n };\n\n fs.writeFileSync(storagePath, JSON.stringify(walletData, null, 2), { mode: 0o600 });\n\n return {\n success: true,\n address: account.address,\n walletId: account.address,\n isNew: true,\n storagePath,\n };\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n}\n\n/**\n * Load existing CDP wallet\n */\nexport function loadCDPWallet(config: CDPWalletConfig = {}): CDPWalletData | null {\n const storageDir = config.storageDir || DEFAULT_STORAGE_DIR;\n const storagePath = path.join(storageDir, CDP_CONFIG_FILE);\n\n if (!fs.existsSync(storagePath)) {\n return null;\n }\n\n try {\n return JSON.parse(fs.readFileSync(storagePath, 'utf-8')) as CDPWalletData;\n } catch {\n return null;\n }\n}\n\n/**\n * Get CDP wallet address (quick check without full init)\n */\nexport function getCDPWalletAddress(storageDir?: string): string | null {\n const data = loadCDPWallet({ storageDir });\n return data?.address || null;\n}\n\n/**\n * CDP Wallet class for making payments\n * \n * Uses CDP SDK for wallet operations with x402 support.\n */\nexport class CDPWallet {\n readonly address: string;\n readonly chain: ChainName;\n readonly chainConfig: ReturnType<typeof getChain>;\n private storageDir: string;\n\n constructor(config: CDPWalletConfig = {}) {\n this.storageDir = config.storageDir || DEFAULT_STORAGE_DIR;\n this.chain = config.chain || 'base';\n this.chainConfig = getChain(this.chain);\n\n // Load existing wallet\n const data = loadCDPWallet(config);\n if (!data) {\n throw new Error('CDP wallet not initialized. Run: npx moltspay init --cdp');\n }\n this.address = data.address;\n }\n\n /**\n * Get USDC balance\n */\n async getBalance(): Promise<{ usdc: string; eth: string }> {\n // Use ethers to check balance (read-only, no CDP needed)\n const { ethers } = await import('ethers');\n const provider = new ethers.JsonRpcProvider(this.chainConfig.rpc);\n \n const usdcContract = new ethers.Contract(\n this.chainConfig.usdc,\n ['function balanceOf(address) view returns (uint256)'],\n provider\n );\n\n const [usdcBalance, ethBalance] = await Promise.all([\n usdcContract.balanceOf(this.address),\n provider.getBalance(this.address),\n ]);\n\n return {\n usdc: (Number(usdcBalance) / 1e6).toFixed(2),\n eth: ethers.formatEther(ethBalance),\n };\n }\n\n /**\n * Transfer USDC to a recipient\n * \n * Requires CDP SDK and credentials to sign transactions.\n */\n async transfer(params: { to: string; amount: number }): Promise<{\n success: boolean;\n txHash?: string;\n error?: string;\n explorerUrl?: string;\n }> {\n if (!isCDPAvailable()) {\n return { success: false, error: 'CDP SDK not installed' };\n }\n\n const creds = getCDPCredentials({});\n if (!creds) {\n return { success: false, error: 'CDP credentials not found' };\n }\n\n try {\n const { CdpClient } = await import('@coinbase/cdp-sdk');\n const { ethers } = await import('ethers');\n\n const cdp = new CdpClient({\n apiKeyId: creds.apiKeyId,\n apiKeySecret: creds.apiKeySecret,\n walletSecret: creds.walletSecret,\n });\n\n // Get the account\n const account = await cdp.evm.getAccount({ address: this.address as `0x${string}` });\n\n // Build transfer transaction\n const amountWei = BigInt(Math.floor(params.amount * 1e6));\n const iface = new ethers.Interface([\n 'function transfer(address to, uint256 amount) returns (bool)',\n ]);\n const callData = iface.encodeFunctionData('transfer', [params.to, amountWei]);\n\n // Send transaction (use any to avoid type issues with CDP SDK versions)\n const txOptions: any = {\n to: this.chainConfig.usdc,\n data: callData,\n };\n const tx = await account.sendTransaction(txOptions);\n\n return {\n success: true,\n txHash: tx.transactionHash,\n explorerUrl: `${this.chainConfig.explorerTx}${tx.transactionHash}`,\n };\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n }\n\n /**\n * Create viem-compatible signer for x402\n * \n * This allows using CDP wallet with x402 protocol.\n */\n async getViemAccount(): Promise<unknown> {\n if (!isCDPAvailable()) {\n throw new Error('CDP SDK not installed');\n }\n\n const creds = getCDPCredentials({});\n if (!creds) {\n throw new Error('CDP credentials not found');\n }\n\n const { CdpClient } = await import('@coinbase/cdp-sdk');\n const { toAccount } = await import('viem/accounts');\n\n const cdp = new CdpClient({\n apiKeyId: creds.apiKeyId,\n apiKeySecret: creds.apiKeySecret,\n walletSecret: creds.walletSecret,\n });\n\n const account = await cdp.evm.getAccount({ address: this.address as `0x${string}` });\n return toAccount(account);\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName, TokenSymbol } 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 tokens: {\n USDC: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USD Coin', // EIP-712 domain name\n },\n USDT: {\n address: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2',\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // deprecated, for backward compat\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-bor-rpc.publicnode.com',\n tokens: {\n USDC: {\n address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',\n decimals: 6,\n symbol: 'USDT',\n eip712Name: '(PoS) Tether USD', // Polygon uses this name\n },\n },\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n // ============ Testnet ============\n base_sepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n rpc: 'https://sepolia.base.org',\n tokens: {\n USDC: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USDC', // Testnet USDC uses 'USDC' not 'USD Coin'\n },\n USDT: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Same as USDC on testnet (no official USDT)\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'USDC', // Uses same contract as USDC\n },\n },\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n // ============ Tempo Testnet (Moderato) ============\n tempo_moderato: {\n name: 'Tempo Moderato',\n chainId: 42431,\n rpc: 'https://rpc.moderato.tempo.xyz',\n tokens: {\n // TIP-20 stablecoins on Tempo testnet (from mppx SDK)\n // Note: Tempo uses USD as native gas token, not ETH\n USDC: {\n address: '0x20c0000000000000000000000000000000000000', // pathUSD - primary testnet stablecoin\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'pathUSD',\n },\n USDT: {\n address: '0x20c0000000000000000000000000000000000001', // alphaUSD\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'alphaUSD',\n },\n },\n usdc: '0x20c0000000000000000000000000000000000000',\n explorer: 'https://explore.testnet.tempo.xyz/address/',\n explorerTx: 'https://explore.testnet.tempo.xyz/tx/',\n avgBlockTime: 0.5, // ~500ms finality\n },\n};\n\n/**\n * Get token address for a chain\n */\nexport function getTokenAddress(chainName: ChainName, token: TokenSymbol): string {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n const tokenConfig = chain.tokens[token];\n if (!tokenConfig) {\n throw new Error(`Token ${token} not supported on ${chainName}`);\n }\n return tokenConfig.address;\n}\n\n/**\n * Get token config for a chain\n */\nexport function getTokenConfig(chainName: ChainName, token: TokenSymbol) {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n return chain.tokens[token];\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, TokenSymbol };\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cdp/index.ts","../../src/chains/index.ts"],"sourcesContent":["/**\n * CDP (Coinbase Developer Platform) Wallet Integration\n * \n * Creates and manages wallets via Coinbase's CDP SDK.\n * These wallets are hosted by Coinbase, making them easy to use for AI Agents.\n * \n * @see https://docs.cdp.coinbase.com/\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport type { EvmChainName } from '../types/index.js';\nimport { getChain } from '../chains/index.js';\n\n// CDP config file location\nconst DEFAULT_STORAGE_DIR = path.join(process.env.HOME || '.', '.moltspay');\nconst CDP_CONFIG_FILE = 'cdp-wallet.json';\n\nexport interface CDPWalletConfig {\n /** Storage directory (default: ~/.moltspay) */\n storageDir?: string;\n /** Chain name */\n chain?: EvmChainName;\n /** CDP API credentials (or use env vars) */\n apiKeyId?: string;\n apiKeySecret?: string;\n walletSecret?: string;\n}\n\nexport interface CDPWalletData {\n /** Wallet address */\n address: string;\n /** CDP wallet ID */\n walletId: string;\n /** Chain */\n chain: EvmChainName;\n /** Created timestamp */\n createdAt: string;\n /** CDP account data (for restoration) */\n accountData?: string;\n}\n\nexport interface CDPInitResult {\n success: boolean;\n address?: string;\n walletId?: string;\n isNew?: boolean;\n error?: string;\n storagePath?: string;\n}\n\n/**\n * Check if CDP SDK is available\n */\nexport function isCDPAvailable(): boolean {\n try {\n require.resolve('@coinbase/cdp-sdk');\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get CDP credentials from environment\n */\nfunction getCDPCredentials(config: CDPWalletConfig): {\n apiKeyId: string;\n apiKeySecret: string;\n walletSecret?: string;\n} | null {\n const apiKeyId = config.apiKeyId || process.env.CDP_API_KEY_ID;\n const apiKeySecret = config.apiKeySecret || process.env.CDP_API_KEY_SECRET;\n const walletSecret = config.walletSecret || process.env.CDP_WALLET_SECRET;\n\n if (!apiKeyId || !apiKeySecret) {\n return null;\n }\n\n return { apiKeyId, apiKeySecret, walletSecret };\n}\n\n/**\n * Initialize CDP wallet\n * \n * Creates a new CDP wallet or loads existing one.\n * \n * @example\n * ```bash\n * # Set credentials\n * export CDP_API_KEY_ID=your-key-id\n * export CDP_API_KEY_SECRET=your-key-secret\n * \n * # Initialize\n * npx moltspay init --cdp --chain base\n * ```\n */\nexport async function initCDPWallet(config: CDPWalletConfig = {}): Promise<CDPInitResult> {\n const storageDir = config.storageDir || DEFAULT_STORAGE_DIR;\n const chain = config.chain || 'base';\n const storagePath = path.join(storageDir, CDP_CONFIG_FILE);\n\n // Check for existing wallet\n if (fs.existsSync(storagePath)) {\n try {\n const data = JSON.parse(fs.readFileSync(storagePath, 'utf-8')) as CDPWalletData;\n return {\n success: true,\n address: data.address,\n walletId: data.walletId,\n isNew: false,\n storagePath,\n };\n } catch (error) {\n // Continue to create new\n }\n }\n\n // Check CDP availability\n if (!isCDPAvailable()) {\n return {\n success: false,\n error: 'CDP SDK not installed. Run: npm install @coinbase/cdp-sdk',\n };\n }\n\n // Get credentials\n const creds = getCDPCredentials(config);\n if (!creds) {\n return {\n success: false,\n error: 'CDP credentials not found. Set CDP_API_KEY_ID and CDP_API_KEY_SECRET environment variables.',\n };\n }\n\n try {\n // Dynamic import to avoid errors when CDP SDK is not installed\n const { CdpClient } = await import('@coinbase/cdp-sdk');\n\n // Initialize CDP client\n const cdp = new CdpClient({\n apiKeyId: creds.apiKeyId,\n apiKeySecret: creds.apiKeySecret,\n walletSecret: creds.walletSecret,\n });\n\n // Create EVM account\n const account = await cdp.evm.createAccount();\n\n // Ensure storage directory exists\n if (!fs.existsSync(storageDir)) {\n fs.mkdirSync(storageDir, { recursive: true });\n }\n\n // Save wallet data\n const walletData: CDPWalletData = {\n address: account.address,\n walletId: account.address, // CDP uses address as ID for EVM\n chain,\n createdAt: new Date().toISOString(),\n };\n\n fs.writeFileSync(storagePath, JSON.stringify(walletData, null, 2), { mode: 0o600 });\n\n return {\n success: true,\n address: account.address,\n walletId: account.address,\n isNew: true,\n storagePath,\n };\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n}\n\n/**\n * Load existing CDP wallet\n */\nexport function loadCDPWallet(config: CDPWalletConfig = {}): CDPWalletData | null {\n const storageDir = config.storageDir || DEFAULT_STORAGE_DIR;\n const storagePath = path.join(storageDir, CDP_CONFIG_FILE);\n\n if (!fs.existsSync(storagePath)) {\n return null;\n }\n\n try {\n return JSON.parse(fs.readFileSync(storagePath, 'utf-8')) as CDPWalletData;\n } catch {\n return null;\n }\n}\n\n/**\n * Get CDP wallet address (quick check without full init)\n */\nexport function getCDPWalletAddress(storageDir?: string): string | null {\n const data = loadCDPWallet({ storageDir });\n return data?.address || null;\n}\n\n/**\n * CDP Wallet class for making payments\n * \n * Uses CDP SDK for wallet operations with x402 support.\n */\nexport class CDPWallet {\n readonly address: string;\n readonly chain: EvmChainName;\n readonly chainConfig: ReturnType<typeof getChain>;\n private storageDir: string;\n\n constructor(config: CDPWalletConfig = {}) {\n this.storageDir = config.storageDir || DEFAULT_STORAGE_DIR;\n this.chain = config.chain || 'base';\n this.chainConfig = getChain(this.chain);\n\n // Load existing wallet\n const data = loadCDPWallet(config);\n if (!data) {\n throw new Error('CDP wallet not initialized. Run: npx moltspay init --cdp');\n }\n this.address = data.address;\n }\n\n /**\n * Get USDC balance\n */\n async getBalance(): Promise<{ usdc: string; eth: string }> {\n // Use ethers to check balance (read-only, no CDP needed)\n const { ethers } = await import('ethers');\n const provider = new ethers.JsonRpcProvider(this.chainConfig.rpc);\n \n const usdcContract = new ethers.Contract(\n this.chainConfig.usdc,\n ['function balanceOf(address) view returns (uint256)'],\n provider\n );\n\n const [usdcBalance, ethBalance] = await Promise.all([\n usdcContract.balanceOf(this.address),\n provider.getBalance(this.address),\n ]);\n\n return {\n usdc: (Number(usdcBalance) / 1e6).toFixed(2),\n eth: ethers.formatEther(ethBalance),\n };\n }\n\n /**\n * Transfer USDC to a recipient\n * \n * Requires CDP SDK and credentials to sign transactions.\n */\n async transfer(params: { to: string; amount: number }): Promise<{\n success: boolean;\n txHash?: string;\n error?: string;\n explorerUrl?: string;\n }> {\n if (!isCDPAvailable()) {\n return { success: false, error: 'CDP SDK not installed' };\n }\n\n const creds = getCDPCredentials({});\n if (!creds) {\n return { success: false, error: 'CDP credentials not found' };\n }\n\n try {\n const { CdpClient } = await import('@coinbase/cdp-sdk');\n const { ethers } = await import('ethers');\n\n const cdp = new CdpClient({\n apiKeyId: creds.apiKeyId,\n apiKeySecret: creds.apiKeySecret,\n walletSecret: creds.walletSecret,\n });\n\n // Get the account\n const account = await cdp.evm.getAccount({ address: this.address as `0x${string}` });\n\n // Build transfer transaction\n const amountWei = BigInt(Math.floor(params.amount * 1e6));\n const iface = new ethers.Interface([\n 'function transfer(address to, uint256 amount) returns (bool)',\n ]);\n const callData = iface.encodeFunctionData('transfer', [params.to, amountWei]);\n\n // Send transaction (use any to avoid type issues with CDP SDK versions)\n const txOptions: any = {\n to: this.chainConfig.usdc,\n data: callData,\n };\n const tx = await account.sendTransaction(txOptions);\n\n return {\n success: true,\n txHash: tx.transactionHash,\n explorerUrl: `${this.chainConfig.explorerTx}${tx.transactionHash}`,\n };\n } catch (error) {\n return {\n success: false,\n error: (error as Error).message,\n };\n }\n }\n\n /**\n * Create viem-compatible signer for x402\n * \n * This allows using CDP wallet with x402 protocol.\n */\n async getViemAccount(): Promise<unknown> {\n if (!isCDPAvailable()) {\n throw new Error('CDP SDK not installed');\n }\n\n const creds = getCDPCredentials({});\n if (!creds) {\n throw new Error('CDP credentials not found');\n }\n\n const { CdpClient } = await import('@coinbase/cdp-sdk');\n const { toAccount } = await import('viem/accounts');\n\n const cdp = new CdpClient({\n apiKeyId: creds.apiKeyId,\n apiKeySecret: creds.apiKeySecret,\n walletSecret: creds.walletSecret,\n });\n\n const account = await cdp.evm.getAccount({ address: this.address as `0x${string}` });\n return toAccount(account);\n }\n}\n","/**\n * Blockchain Configuration\n */\n\nimport type { ChainConfig, ChainName, EvmChainName, TokenSymbol } from '../types/index.js';\n\nexport const CHAINS: Record<EvmChainName, ChainConfig> = {\n // ============ Mainnet ============\n base: {\n name: 'Base',\n chainId: 8453,\n rpc: 'https://mainnet.base.org',\n tokens: {\n USDC: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USD Coin', // EIP-712 domain name\n },\n USDT: {\n address: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2',\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // deprecated, for backward compat\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-bor-rpc.publicnode.com',\n tokens: {\n USDC: {\n address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',\n decimals: 6,\n symbol: 'USDT',\n eip712Name: '(PoS) Tether USD', // Polygon uses this name\n },\n },\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n explorer: 'https://polygonscan.com/address/',\n explorerTx: 'https://polygonscan.com/tx/',\n avgBlockTime: 2,\n },\n // ============ Testnet ============\n base_sepolia: {\n name: 'Base Sepolia',\n chainId: 84532,\n rpc: 'https://sepolia.base.org',\n tokens: {\n USDC: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'USDC', // Testnet USDC uses 'USDC' not 'USD Coin'\n },\n USDT: {\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', // Same as USDC on testnet (no official USDT)\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'USDC', // Uses same contract as USDC\n },\n },\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n explorer: 'https://sepolia.basescan.org/address/',\n explorerTx: 'https://sepolia.basescan.org/tx/',\n avgBlockTime: 2,\n },\n // ============ Tempo Testnet (Moderato) ============\n tempo_moderato: {\n name: 'Tempo Moderato',\n chainId: 42431,\n rpc: 'https://rpc.moderato.tempo.xyz',\n tokens: {\n // TIP-20 stablecoins on Tempo testnet (from mppx SDK)\n // Note: Tempo uses USD as native gas token, not ETH\n USDC: {\n address: '0x20c0000000000000000000000000000000000000', // pathUSD - primary testnet stablecoin\n decimals: 6,\n symbol: 'USDC',\n eip712Name: 'pathUSD',\n },\n USDT: {\n address: '0x20c0000000000000000000000000000000000001', // alphaUSD\n decimals: 6,\n symbol: 'USDT',\n eip712Name: 'alphaUSD',\n },\n },\n usdc: '0x20c0000000000000000000000000000000000000',\n explorer: 'https://explore.testnet.tempo.xyz/address/',\n explorerTx: 'https://explore.testnet.tempo.xyz/tx/',\n avgBlockTime: 0.5, // ~500ms finality\n },\n // ============ BNB Chain Testnet ============\n bnb_testnet: {\n name: 'BNB Testnet',\n chainId: 97,\n rpc: 'https://data-seed-prebsc-1-s1.binance.org:8545',\n tokens: {\n // Note: BNB uses 18 decimals for stablecoins (unlike Base/Polygon which use 6)\n // Using official Binance-Peg testnet tokens\n USDC: {\n address: '0x64544969ed7EBf5f083679233325356EbE738930', // Testnet USDC\n decimals: 18,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0x337610d27c682E347C9cD60BD4b3b107C9d34dDd', // Testnet USDT\n decimals: 18,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x64544969ed7EBf5f083679233325356EbE738930',\n explorer: 'https://testnet.bscscan.com/address/',\n explorerTx: 'https://testnet.bscscan.com/tx/',\n avgBlockTime: 3,\n // BNB-specific: requires approval for pay-for-success flow\n requiresApproval: true,\n },\n // ============ BNB Chain Mainnet ============\n bnb: {\n name: 'BNB Smart Chain',\n chainId: 56,\n rpc: 'https://bsc-dataseed.binance.org',\n tokens: {\n // Note: BNB uses 18 decimals for stablecoins\n USDC: {\n address: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n decimals: 18,\n symbol: 'USDC',\n eip712Name: 'USD Coin',\n },\n USDT: {\n address: '0x55d398326f99059fF775485246999027B3197955',\n decimals: 18,\n symbol: 'USDT',\n eip712Name: 'Tether USD',\n },\n },\n usdc: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n explorer: 'https://bscscan.com/address/',\n explorerTx: 'https://bscscan.com/tx/',\n avgBlockTime: 3,\n // BNB-specific: requires approval for pay-for-success flow\n requiresApproval: true,\n },\n};\n\n/**\n * Get token address for a chain\n */\nexport function getTokenAddress(chainName: EvmChainName, token: TokenSymbol): string {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n const tokenConfig = chain.tokens[token];\n if (!tokenConfig) {\n throw new Error(`Token ${token} not supported on ${chainName}`);\n }\n return tokenConfig.address;\n}\n\n/**\n * Get token config for a chain\n */\nexport function getTokenConfig(chainName: EvmChainName, token: TokenSymbol) {\n const chain = CHAINS[chainName];\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n return chain.tokens[token];\n}\n\n/**\n * Get chain configuration\n */\nexport function getChain(name: EvmChainName): 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 EVM chains\n */\nexport function listChains(): EvmChainName[] {\n return Object.keys(CHAINS) as EvmChainName[];\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, EvmChainName, TokenSymbol };\n"],"mappings":"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","names":[]}
|