@profullstack/coinpay 0.1.0 → 0.2.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 CHANGED
@@ -1,6 +1,16 @@
1
1
  # @profullstack/coinpay
2
2
 
3
- CoinPay SDK & CLI - Cryptocurrency payment integration for Node.js
3
+ CoinPay SDK & CLI - Accept cryptocurrency payments in your application.
4
+
5
+ ## Overview
6
+
7
+ CoinPay allows merchants to accept cryptocurrency payments from their customers. When a customer wants to pay:
8
+
9
+ 1. **Your server** calls the CoinPay API to create a payment request
10
+ 2. **CoinPay** generates a unique payment address and QR code
11
+ 3. **Your customer** sends cryptocurrency to that address
12
+ 4. **CoinPay** monitors the blockchain and notifies you via webhook when payment is confirmed
13
+ 5. **Funds** are automatically forwarded to your configured wallet (minus a small fee)
4
14
 
5
15
  ## Installation
6
16
 
@@ -17,48 +27,88 @@ pnpm add -g @profullstack/coinpay
17
27
 
18
28
  ## Quick Start
19
29
 
20
- ### SDK Usage
30
+ ### 1. Get Your API Key
31
+
32
+ 1. Sign up at [coinpayportal.com](https://coinpayportal.com)
33
+ 2. Create a business in your dashboard
34
+ 3. Configure your wallet addresses for each cryptocurrency you want to accept
35
+ 4. Copy your API key (starts with `cp_live_`)
36
+
37
+ ### 2. Create a Payment (SDK)
21
38
 
22
39
  ```javascript
23
40
  import { CoinPayClient } from '@profullstack/coinpay';
24
41
 
25
- // Initialize the client
42
+ // Initialize with your API key
26
43
  const coinpay = new CoinPayClient({
27
- apiKey: 'your-api-key',
44
+ apiKey: 'cp_live_your_api_key_here',
28
45
  });
29
46
 
30
- // Create a payment
47
+ // Create a payment when customer checks out
31
48
  const payment = await coinpay.createPayment({
32
- businessId: 'biz_123',
33
- amount: 100,
34
- currency: 'USD',
35
- cryptocurrency: 'BTC',
36
- description: 'Order #12345',
49
+ businessId: 'your-business-id', // From your dashboard
50
+ amount: 99.99, // Amount in fiat currency
51
+ currency: 'USD', // Fiat currency (default: USD)
52
+ blockchain: 'BTC', // Cryptocurrency to accept
53
+ description: 'Order #12345', // Shown to customer
54
+ metadata: { // Your custom data
55
+ orderId: '12345',
56
+ customerEmail: 'customer@example.com'
57
+ }
37
58
  });
38
59
 
39
- console.log(`Payment address: ${payment.address}`);
40
- console.log(`Amount: ${payment.cryptoAmount} ${payment.cryptocurrency}`);
60
+ // Display to customer
61
+ console.log('Send payment to:', payment.payment.payment_address);
62
+ console.log('Amount:', payment.payment.crypto_amount, payment.payment.blockchain);
63
+ console.log('QR Code:', payment.payment.qr_code);
41
64
  ```
42
65
 
43
- ### CLI Usage
66
+ ### 3. Create a Payment (cURL)
44
67
 
45
68
  ```bash
46
- # Configure your API key
47
- coinpay config set-key sk_live_xxxxx
69
+ curl -X POST https://coinpayportal.com/api/payments/create \
70
+ -H "Authorization: Bearer cp_live_your_api_key_here" \
71
+ -H "Content-Type: application/json" \
72
+ -d '{
73
+ "business_id": "your-business-id",
74
+ "amount": 99.99,
75
+ "currency": "USD",
76
+ "blockchain": "BTC",
77
+ "description": "Order #12345",
78
+ "metadata": {
79
+ "orderId": "12345",
80
+ "customerEmail": "customer@example.com"
81
+ }
82
+ }'
83
+ ```
48
84
 
49
- # Create a payment
50
- coinpay payment create --business-id biz_123 --amount 100 --currency USD --crypto BTC
85
+ ### 4. Create a Payment (CLI)
51
86
 
52
- # Get payment details
53
- coinpay payment get pay_abc123
54
-
55
- # List payments
56
- coinpay payment list --business-id biz_123
87
+ ```bash
88
+ # Configure your API key (one-time setup)
89
+ coinpay config set-key cp_live_your_api_key_here
57
90
 
58
- # Get exchange rates
59
- coinpay rates get BTC
91
+ # Create a payment
92
+ coinpay payment create \
93
+ --business-id your-business-id \
94
+ --amount 99.99 \
95
+ --blockchain BTC \
96
+ --description "Order #12345"
60
97
  ```
61
98
 
99
+ ## Supported Blockchains
100
+
101
+ | Blockchain | Code | Description |
102
+ |------------|------|-------------|
103
+ | Bitcoin | `BTC` | Native Bitcoin |
104
+ | Bitcoin Cash | `BCH` | Bitcoin Cash |
105
+ | Ethereum | `ETH` | Native Ether |
106
+ | Polygon | `MATIC` | Native MATIC |
107
+ | Solana | `SOL` | Native SOL |
108
+ | USDC (Ethereum) | `USDC_ETH` | USDC on Ethereum |
109
+ | USDC (Polygon) | `USDC_MATIC` | USDC on Polygon |
110
+ | USDC (Solana) | `USDC_SOL` | USDC on Solana |
111
+
62
112
  ## SDK API Reference
63
113
 
64
114
  ### CoinPayClient
@@ -67,39 +117,136 @@ coinpay rates get BTC
67
117
  import { CoinPayClient } from '@profullstack/coinpay';
68
118
 
69
119
  const client = new CoinPayClient({
70
- apiKey: 'your-api-key',
71
- baseUrl: 'https://coinpay.dev/api', // optional
72
- timeout: 30000, // optional, in milliseconds
120
+ apiKey: 'cp_live_xxxxx', // Required: Your API key
121
+ baseUrl: 'https://coinpayportal.com/api', // Optional: API URL
122
+ timeout: 30000, // Optional: Request timeout (ms)
73
123
  });
74
124
  ```
75
125
 
76
- ### Payments
126
+ ### Creating Payments
77
127
 
78
128
  ```javascript
79
129
  // Create a payment
80
130
  const payment = await client.createPayment({
81
- businessId: 'biz_123',
82
- amount: 100,
83
- currency: 'USD',
84
- cryptocurrency: 'BTC',
85
- description: 'Order #12345',
86
- metadata: JSON.stringify({ orderId: '12345' }),
87
- callbackUrl: 'https://your-site.com/webhook',
131
+ businessId: 'biz_123', // Required: Your business ID
132
+ amount: 100, // Required: Amount in fiat
133
+ currency: 'USD', // Optional: Fiat currency (default: USD)
134
+ blockchain: 'ETH', // Required: Blockchain to use
135
+ description: 'Order #123', // Optional: Description for customer
136
+ metadata: { ... }, // Optional: Your custom data
137
+ });
138
+
139
+ // Response structure
140
+ {
141
+ success: true,
142
+ payment: {
143
+ id: 'pay_abc123',
144
+ business_id: 'biz_123',
145
+ amount: 100,
146
+ currency: 'USD',
147
+ blockchain: 'ETH',
148
+ crypto_amount: '0.0456',
149
+ payment_address: '0x1234...5678',
150
+ qr_code: 'data:image/png;base64,...',
151
+ status: 'pending',
152
+ expires_at: '2024-01-01T01:00:00.000Z',
153
+ created_at: '2024-01-01T00:00:00.000Z'
154
+ },
155
+ usage: {
156
+ current: 45,
157
+ limit: 100,
158
+ remaining: 55
159
+ }
160
+ }
161
+ ```
162
+
163
+ ### Checking Payment Status
164
+
165
+ There are two ways to know when a payment is complete:
166
+
167
+ #### Option 1: Polling (Simple)
168
+
169
+ Use `getPayment()` to check status, or `waitForPayment()` to poll until complete:
170
+
171
+ ```javascript
172
+ // Check status once
173
+ const result = await client.getPayment('pay_abc123');
174
+ console.log(result.payment.status);
175
+
176
+ // Or wait for payment to complete (polls automatically)
177
+ const payment = await client.waitForPayment('pay_abc123', {
178
+ interval: 5000, // Check every 5 seconds
179
+ timeout: 600000, // Give up after 10 minutes
180
+ onStatusChange: (status, payment) => {
181
+ console.log(`Status changed to: ${status}`);
182
+ }
88
183
  });
89
184
 
90
- // Get payment by ID
91
- const payment = await client.getPayment('pay_abc123');
185
+ if (payment.payment.status === 'confirmed' || payment.payment.status === 'forwarded') {
186
+ console.log('Payment successful!');
187
+ } else {
188
+ console.log('Payment failed or expired');
189
+ }
190
+ ```
191
+
192
+ #### Option 2: Webhooks (Recommended for Production)
193
+
194
+ Configure a webhook URL in your business settings to receive real-time notifications:
195
+
196
+ ```javascript
197
+ // Your webhook endpoint receives POST requests like:
198
+ {
199
+ "event": "payment.confirmed",
200
+ "data": {
201
+ "payment": {
202
+ "id": "pay_abc123",
203
+ "status": "confirmed",
204
+ "metadata": { "orderId": "12345" }
205
+ }
206
+ }
207
+ }
208
+ ```
209
+
210
+ See [Webhook Integration](#webhook-integration) for full details.
211
+
212
+ **Payment Statuses:**
213
+ - `pending` - Waiting for payment
214
+ - `detected` - Payment detected, waiting for confirmations
215
+ - `confirmed` - Payment confirmed on blockchain
216
+ - `forwarding` - Forwarding to your wallet
217
+ - `forwarded` - Successfully sent to your wallet
218
+ - `expired` - Payment request expired
219
+ - `failed` - Payment failed
220
+
221
+ ### Getting QR Code
222
+
223
+ The QR code endpoint returns binary PNG image data.
224
+
225
+ ```javascript
226
+ // Get QR code URL for use in HTML <img> tags
227
+ const qrUrl = client.getPaymentQRUrl('pay_abc123');
228
+ // Returns: "https://coinpayportal.com/api/payments/pay_abc123/qr"
229
+
230
+ // Use directly in HTML
231
+ // <img src={qrUrl} alt="Payment QR Code" />
232
+
233
+ // Get QR code as binary data (for server-side processing)
234
+ const imageData = await client.getPaymentQR('pay_abc123');
92
235
 
93
- // List payments
236
+ // Save to file (Node.js)
237
+ import fs from 'fs';
238
+ fs.writeFileSync('payment-qr.png', Buffer.from(imageData));
239
+ ```
240
+
241
+ ### Listing Payments
242
+
243
+ ```javascript
94
244
  const payments = await client.listPayments({
95
245
  businessId: 'biz_123',
96
- status: 'completed', // optional
97
- limit: 20, // optional
98
- offset: 0, // optional
246
+ status: 'completed', // Optional filter
247
+ limit: 20, // Optional (default: 20)
248
+ offset: 0, // Optional pagination
99
249
  });
100
-
101
- // Get payment QR code
102
- const qr = await client.getPaymentQR('pay_abc123', 'png');
103
250
  ```
104
251
 
105
252
  ### Exchange Rates
@@ -107,47 +254,100 @@ const qr = await client.getPaymentQR('pay_abc123', 'png');
107
254
  ```javascript
108
255
  // Get single rate
109
256
  const rate = await client.getExchangeRate('BTC', 'USD');
257
+ // { from: 'BTC', to: 'USD', rate: 43250.00 }
110
258
 
111
259
  // Get multiple rates
112
260
  const rates = await client.getExchangeRates(['BTC', 'ETH', 'SOL'], 'USD');
113
261
  ```
114
262
 
115
- ### Businesses
263
+ ## Direct API Usage (fetch/curl)
264
+
265
+ ### Create Payment
116
266
 
117
267
  ```javascript
118
- // Create a business
119
- const business = await client.createBusiness({
120
- name: 'My Store',
121
- webhookUrl: 'https://your-site.com/webhook',
122
- walletAddresses: {
123
- BTC: 'bc1q...',
124
- ETH: '0x...',
268
+ // Using fetch
269
+ const response = await fetch('https://coinpayportal.com/api/payments/create', {
270
+ method: 'POST',
271
+ headers: {
272
+ 'Authorization': 'Bearer cp_live_your_api_key',
273
+ 'Content-Type': 'application/json',
125
274
  },
275
+ body: JSON.stringify({
276
+ business_id: 'your-business-id',
277
+ amount: 50.00,
278
+ currency: 'USD',
279
+ blockchain: 'ETH',
280
+ description: 'Premium subscription',
281
+ metadata: {
282
+ userId: 'user_123',
283
+ plan: 'premium'
284
+ }
285
+ }),
126
286
  });
127
287
 
128
- // Get business
129
- const business = await client.getBusiness('biz_123');
288
+ const data = await response.json();
289
+ console.log(data.payment.payment_address);
290
+ ```
291
+
292
+ ```bash
293
+ # Using cURL
294
+ curl -X POST https://coinpayportal.com/api/payments/create \
295
+ -H "Authorization: Bearer cp_live_your_api_key" \
296
+ -H "Content-Type: application/json" \
297
+ -d '{
298
+ "business_id": "your-business-id",
299
+ "amount": 50.00,
300
+ "currency": "USD",
301
+ "blockchain": "ETH",
302
+ "description": "Premium subscription"
303
+ }'
304
+ ```
130
305
 
131
- // List businesses
132
- const businesses = await client.listBusinesses();
306
+ ### Get Payment Status
133
307
 
134
- // Update business
135
- const updated = await client.updateBusiness('biz_123', {
136
- name: 'Updated Name',
308
+ ```javascript
309
+ const response = await fetch('https://coinpayportal.com/api/payments/pay_abc123', {
310
+ headers: {
311
+ 'Authorization': 'Bearer cp_live_your_api_key',
312
+ },
137
313
  });
314
+ const data = await response.json();
138
315
  ```
139
316
 
140
- ### Webhooks
317
+ ```bash
318
+ curl https://coinpayportal.com/api/payments/pay_abc123 \
319
+ -H "Authorization: Bearer cp_live_your_api_key"
320
+ ```
141
321
 
142
- ```javascript
143
- // Get webhook logs
144
- const logs = await client.getWebhookLogs('biz_123', 50);
322
+ ## Webhook Integration
145
323
 
146
- // Test webhook
147
- const result = await client.testWebhook('biz_123', 'payment.completed');
324
+ When payment status changes, CoinPay sends a POST request to your configured webhook URL:
325
+
326
+ ```javascript
327
+ // Webhook payload
328
+ {
329
+ "event": "payment.confirmed",
330
+ "timestamp": "2024-01-01T00:15:00.000Z",
331
+ "data": {
332
+ "payment": {
333
+ "id": "pay_abc123",
334
+ "business_id": "biz_123",
335
+ "amount": 100.00,
336
+ "currency": "USD",
337
+ "crypto_amount": "0.0456",
338
+ "blockchain": "ETH",
339
+ "status": "confirmed",
340
+ "tx_hash": "0xabc...def",
341
+ "metadata": {
342
+ "orderId": "12345"
343
+ }
344
+ }
345
+ },
346
+ "signature": "sha256_hmac_signature"
347
+ }
148
348
  ```
149
349
 
150
- ## Webhook Verification
350
+ ### Verifying Webhooks
151
351
 
152
352
  ```javascript
153
353
  import { verifyWebhookSignature, createWebhookHandler } from '@profullstack/coinpay';
@@ -163,101 +363,98 @@ const isValid = verifyWebhookSignature({
163
363
  app.post('/webhook', createWebhookHandler({
164
364
  secret: 'your-webhook-secret',
165
365
  onEvent: async (event) => {
166
- console.log('Received event:', event.type);
167
-
168
366
  switch (event.type) {
169
- case 'payment.completed':
170
- // Handle completed payment
367
+ case 'payment.confirmed':
368
+ // Mark order as paid
369
+ await markOrderPaid(event.data.payment.metadata.orderId);
370
+ break;
371
+ case 'payment.forwarded':
372
+ // Funds received in your wallet
171
373
  break;
172
374
  case 'payment.expired':
173
375
  // Handle expired payment
174
376
  break;
175
377
  }
176
378
  },
177
- onError: (error) => {
178
- console.error('Webhook error:', error);
179
- },
180
379
  }));
181
380
  ```
182
381
 
183
- ## Webhook Events
382
+ ### Webhook Events
184
383
 
185
384
  | Event | Description |
186
385
  |-------|-------------|
187
- | `payment.created` | Payment was created |
188
- | `payment.pending` | Payment is pending confirmation |
189
- | `payment.confirming` | Payment is being confirmed |
190
- | `payment.completed` | Payment completed successfully |
191
- | `payment.expired` | Payment expired |
386
+ | `payment.created` | Payment request created |
387
+ | `payment.detected` | Payment detected on blockchain |
388
+ | `payment.confirmed` | Payment confirmed (safe to fulfill order) |
389
+ | `payment.forwarding` | Forwarding funds to your wallet |
390
+ | `payment.forwarded` | Funds sent to your wallet |
391
+ | `payment.expired` | Payment request expired |
192
392
  | `payment.failed` | Payment failed |
193
- | `payment.refunded` | Payment was refunded |
194
393
 
195
- ## CLI Commands
394
+ ## CLI Reference
196
395
 
197
396
  ### Configuration
198
397
 
199
398
  ```bash
200
- coinpay config set-key <api-key> # Set API key
201
- coinpay config set-url <base-url> # Set custom API URL
202
- coinpay config show # Show current config
399
+ # Set your API key
400
+ coinpay config set-key cp_live_xxxxx
401
+
402
+ # Set custom API URL (for development)
403
+ coinpay config set-url http://localhost:3000/api
404
+
405
+ # Show current configuration
406
+ coinpay config show
203
407
  ```
204
408
 
205
409
  ### Payments
206
410
 
207
411
  ```bash
208
- coinpay payment create [options]
209
- --business-id <id> Business ID (required)
210
- --amount <amount> Amount in fiat (required)
211
- --currency <code> Fiat currency (required)
212
- --crypto <code> Cryptocurrency (required)
213
- --description <text> Description (optional)
214
-
215
- coinpay payment get <payment-id>
216
- coinpay payment list --business-id <id> [--status <status>] [--limit <n>]
217
- coinpay payment qr <payment-id> [--format png|svg]
412
+ # Create a payment
413
+ coinpay payment create \
414
+ --business-id biz_123 \
415
+ --amount 100 \
416
+ --blockchain BTC \
417
+ --description "Order #12345"
418
+
419
+ # Get payment details
420
+ coinpay payment get pay_abc123
421
+
422
+ # List payments
423
+ coinpay payment list --business-id biz_123 --status pending --limit 10
424
+
425
+ # Get QR code (saves as PNG file)
426
+ coinpay payment qr pay_abc123 --output payment-qr.png
218
427
  ```
219
428
 
220
429
  ### Businesses
221
430
 
222
431
  ```bash
223
- coinpay business create --name <name> [--webhook-url <url>]
224
- coinpay business get <business-id>
432
+ # List your businesses
225
433
  coinpay business list
226
- coinpay business update <business-id> [--name <name>] [--webhook-url <url>]
227
- ```
228
434
 
229
- ### Exchange Rates
435
+ # Get business details
436
+ coinpay business get biz_123
230
437
 
231
- ```bash
232
- coinpay rates get <crypto> [--fiat <currency>]
233
- coinpay rates list [--fiat <currency>]
438
+ # Create a business
439
+ coinpay business create --name "My Store" --webhook-url https://mysite.com/webhook
234
440
  ```
235
441
 
236
- ### Webhooks
442
+ ### Exchange Rates
237
443
 
238
444
  ```bash
239
- coinpay webhook logs <business-id> [--limit <n>]
240
- coinpay webhook test <business-id> [--event <type>]
241
- ```
242
-
243
- ## Supported Cryptocurrencies
244
-
245
- - **BTC** - Bitcoin
246
- - **BCH** - Bitcoin Cash
247
- - **ETH** - Ethereum
248
- - **MATIC** - Polygon
249
- - **SOL** - Solana
250
-
251
- ## Supported Fiat Currencies
445
+ # Get rate for a cryptocurrency
446
+ coinpay rates get BTC
252
447
 
253
- - USD, EUR, GBP, CAD, AUD, and more
448
+ # Get all rates
449
+ coinpay rates list
450
+ ```
254
451
 
255
452
  ## Environment Variables
256
453
 
257
454
  | Variable | Description |
258
455
  |----------|-------------|
259
456
  | `COINPAY_API_KEY` | API key (overrides config file) |
260
- | `COINPAY_BASE_URL` | Custom API URL |
457
+ | `COINPAY_BASE_URL` | Custom API URL (for development) |
261
458
 
262
459
  ## Error Handling
263
460
 
@@ -268,13 +465,91 @@ try {
268
465
  if (error.status === 401) {
269
466
  console.error('Invalid API key');
270
467
  } else if (error.status === 400) {
271
- console.error('Invalid request:', error.response);
468
+ console.error('Invalid request:', error.response?.error);
469
+ } else if (error.status === 429) {
470
+ console.error('Rate limit exceeded or transaction limit reached');
471
+ console.error('Usage:', error.response?.usage);
272
472
  } else {
273
473
  console.error('Error:', error.message);
274
474
  }
275
475
  }
276
476
  ```
277
477
 
478
+ ## Common Integration Patterns
479
+
480
+ ### E-commerce Checkout
481
+
482
+ ```javascript
483
+ // In your checkout handler
484
+ app.post('/checkout', async (req, res) => {
485
+ const { orderId, amount, cryptocurrency } = req.body;
486
+
487
+ const payment = await coinpay.createPayment({
488
+ businessId: process.env.COINPAY_BUSINESS_ID,
489
+ amount,
490
+ blockchain: cryptocurrency,
491
+ description: `Order #${orderId}`,
492
+ metadata: { orderId }
493
+ });
494
+
495
+ // Save payment ID to your order
496
+ await db.orders.update(orderId, {
497
+ paymentId: payment.payment.id,
498
+ paymentAddress: payment.payment.payment_address
499
+ });
500
+
501
+ res.json({
502
+ paymentAddress: payment.payment.payment_address,
503
+ amount: payment.payment.crypto_amount,
504
+ qrCode: payment.payment.qr_code,
505
+ expiresAt: payment.payment.expires_at
506
+ });
507
+ });
508
+
509
+ // Webhook handler
510
+ app.post('/webhook/coinpay', createWebhookHandler({
511
+ secret: process.env.COINPAY_WEBHOOK_SECRET,
512
+ onEvent: async (event) => {
513
+ if (event.type === 'payment.confirmed') {
514
+ const { orderId } = event.data.payment.metadata;
515
+ await db.orders.update(orderId, { status: 'paid' });
516
+ await sendOrderConfirmationEmail(orderId);
517
+ }
518
+ }
519
+ }));
520
+ ```
521
+
522
+ ### Subscription Payments
523
+
524
+ ```javascript
525
+ // Create subscription payment
526
+ const payment = await coinpay.createPayment({
527
+ businessId: process.env.COINPAY_BUSINESS_ID,
528
+ amount: 9.99,
529
+ blockchain: 'USDC_MATIC', // Stablecoin for predictable pricing
530
+ description: 'Monthly subscription',
531
+ metadata: {
532
+ userId: user.id,
533
+ subscriptionId: subscription.id,
534
+ period: '2024-01'
535
+ }
536
+ });
537
+ ```
538
+
539
+ ## Testing
540
+
541
+ For development and testing, you can:
542
+
543
+ 1. Use the dashboard's "Create Test Payment" feature
544
+ 2. Set a custom `baseUrl` pointing to your local development server
545
+ 3. Use testnet addresses (when supported)
546
+
547
+ ## Support
548
+
549
+ - Documentation: [docs.coinpayportal.com](https://docs.coinpayportal.com)
550
+ - Email: support@coinpayportal.com
551
+ - Status: [status.coinpayportal.com](https://status.coinpayportal.com)
552
+
278
553
  ## License
279
554
 
280
555
  MIT
package/bin/coinpay.js CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { CoinPayClient } from '../src/client.js';
9
- import { PaymentStatus, Cryptocurrency, FiatCurrency } from '../src/payments.js';
9
+ import { PaymentStatus, Blockchain, FiatCurrency } from '../src/payments.js';
10
10
  import { readFileSync, writeFileSync, existsSync } from 'fs';
11
11
  import { homedir } from 'os';
12
12
  import { join } from 'path';
@@ -70,7 +70,7 @@ function getApiKey() {
70
70
  */
71
71
  function getBaseUrl() {
72
72
  const config = loadConfig();
73
- return process.env.COINPAY_BASE_URL || config.baseUrl || 'https://coinpay.dev/api';
73
+ return process.env.COINPAY_BASE_URL || config.baseUrl || 'https://coinpayportal.com/api';
74
74
  }
75
75
 
76
76
  /**
@@ -152,15 +152,31 @@ ${colors.cyan}Options:${colors.reset}
152
152
  --version, -v Show version
153
153
  --json Output as JSON
154
154
  --business-id <id> Business ID for operations
155
- --amount <amount> Payment amount
156
- --currency <code> Fiat currency (USD, EUR, etc.)
157
- --crypto <code> Cryptocurrency (BTC, ETH, etc.)
155
+ --amount <amount> Payment amount in fiat currency
156
+ --currency <code> Fiat currency (USD, EUR, etc.) - default: USD
157
+ --blockchain <code> Blockchain (BTC, ETH, SOL, MATIC, BCH, USDC_ETH, USDC_MATIC, USDC_SOL)
158
+ --description <text> Payment description
158
159
 
159
160
  ${colors.cyan}Examples:${colors.reset}
160
- coinpay config set-key sk_live_xxxxx
161
- coinpay payment create --business-id biz_123 --amount 100 --currency USD --crypto BTC
161
+ # Configure your API key (get it from your CoinPay dashboard)
162
+ coinpay config set-key cp_live_xxxxx
163
+
164
+ # Create a $100 Bitcoin payment
165
+ coinpay payment create --business-id biz_123 --amount 100 --blockchain BTC
166
+
167
+ # Create a $50 Ethereum payment with description
168
+ coinpay payment create --business-id biz_123 --amount 50 --blockchain ETH --description "Order #12345"
169
+
170
+ # Create a USDC payment on Polygon
171
+ coinpay payment create --business-id biz_123 --amount 25 --blockchain USDC_MATIC
172
+
173
+ # Get payment status
162
174
  coinpay payment get pay_abc123
175
+
176
+ # Get exchange rates
163
177
  coinpay rates get BTC
178
+
179
+ # List your businesses
164
180
  coinpay business list
165
181
 
166
182
  ${colors.cyan}Environment Variables:${colors.reset}
@@ -218,10 +234,11 @@ async function handlePayment(subcommand, args, flags) {
218
234
 
219
235
  switch (subcommand) {
220
236
  case 'create': {
221
- const { 'business-id': businessId, amount, currency, crypto, description } = flags;
237
+ const { 'business-id': businessId, amount, currency = 'USD', blockchain, description } = flags;
222
238
 
223
- if (!businessId || !amount || !currency || !crypto) {
224
- print.error('Required: --business-id, --amount, --currency, --crypto');
239
+ if (!businessId || !amount || !blockchain) {
240
+ print.error('Required: --business-id, --amount, --blockchain');
241
+ print.info('Example: coinpay payment create --business-id biz_123 --amount 100 --blockchain BTC');
225
242
  return;
226
243
  }
227
244
 
@@ -229,12 +246,19 @@ async function handlePayment(subcommand, args, flags) {
229
246
  businessId,
230
247
  amount: parseFloat(amount),
231
248
  currency,
232
- cryptocurrency: crypto,
249
+ blockchain,
233
250
  description,
234
251
  });
235
252
 
236
253
  print.success('Payment created');
237
- print.json(payment);
254
+ if (payment.payment) {
255
+ print.info(`Payment Address: ${payment.payment.payment_address}`);
256
+ print.info(`Amount: ${payment.payment.crypto_amount} ${payment.payment.blockchain}`);
257
+ print.info(`Expires: ${payment.payment.expires_at}`);
258
+ }
259
+ if (!flags.json) {
260
+ print.json(payment);
261
+ }
238
262
  break;
239
263
  }
240
264
 
@@ -364,7 +388,7 @@ async function handleRates(subcommand, args, flags) {
364
388
  const { fiat } = flags;
365
389
 
366
390
  if (!crypto) {
367
- print.error('Cryptocurrency code required (BTC, ETH, etc.)');
391
+ print.error('Blockchain code required (BTC, ETH, SOL, etc.)');
368
392
  return;
369
393
  }
370
394
 
@@ -375,7 +399,7 @@ async function handleRates(subcommand, args, flags) {
375
399
 
376
400
  case 'list': {
377
401
  const { fiat } = flags;
378
- const cryptos = Object.values(Cryptocurrency);
402
+ const cryptos = Object.values(Blockchain);
379
403
  const rates = await client.getExchangeRates(cryptos, fiat);
380
404
  print.json(rates);
381
405
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/coinpay",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "CoinPay SDK & CLI - Cryptocurrency payment integration for Node.js",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/client.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Main client class for interacting with the CoinPay API
4
4
  */
5
5
 
6
- const DEFAULT_BASE_URL = 'https://coinpay.dev/api';
6
+ const DEFAULT_BASE_URL = 'https://coinpayportal.com/api';
7
7
 
8
8
  /**
9
9
  * CoinPay API Client
@@ -17,7 +17,7 @@ export class CoinPayClient {
17
17
  * Create a new CoinPay client
18
18
  * @param {Object} options - Client options
19
19
  * @param {string} options.apiKey - Your CoinPay API key
20
- * @param {string} [options.baseUrl] - API base URL (default: https://coinpay.dev/api)
20
+ * @param {string} [options.baseUrl] - API base URL (default: https://coinpayportal.com/api)
21
21
  * @param {number} [options.timeout] - Request timeout in ms (default: 30000)
22
22
  */
23
23
  constructor({ apiKey, baseUrl = DEFAULT_BASE_URL, timeout = 30000 }) {
@@ -47,7 +47,7 @@ export class CoinPayClient {
47
47
  signal: controller.signal,
48
48
  headers: {
49
49
  'Content-Type': 'application/json',
50
- 'X-API-Key': this.#apiKey,
50
+ 'Authorization': `Bearer ${this.#apiKey}`,
51
51
  ...options.headers,
52
52
  },
53
53
  });
@@ -74,48 +74,142 @@ export class CoinPayClient {
74
74
 
75
75
  /**
76
76
  * Create a new payment
77
+ *
78
+ * This is the primary method for merchants to create payment requests.
79
+ * When a customer needs to pay, call this method to generate a unique
80
+ * payment address and QR code.
81
+ *
77
82
  * @param {Object} params - Payment parameters
78
- * @param {string} params.businessId - Business ID
79
- * @param {number} params.amount - Amount in fiat currency
80
- * @param {string} params.currency - Fiat currency code (USD, EUR, etc.)
81
- * @param {string} params.cryptocurrency - Cryptocurrency code (BTC, ETH, etc.)
82
- * @param {string} [params.description] - Payment description
83
- * @param {string} [params.metadata] - Custom metadata (JSON string)
84
- * @param {string} [params.callbackUrl] - Webhook callback URL
85
- * @returns {Promise<Object>} Created payment
83
+ * @param {string} params.businessId - Business ID (from your CoinPay dashboard)
84
+ * @param {number} params.amount - Amount in fiat currency (e.g., 100.00)
85
+ * @param {string} [params.currency='USD'] - Fiat currency code (USD, EUR, etc.)
86
+ * @param {string} params.blockchain - Blockchain/cryptocurrency (BTC, ETH, SOL, MATIC, BCH, USDC_ETH, USDC_MATIC, USDC_SOL)
87
+ * @param {string} [params.description] - Payment description (shown to customer)
88
+ * @param {Object} [params.metadata] - Custom metadata (e.g., { orderId: 'ORD-123', customerId: 'CUST-456' })
89
+ * @returns {Promise<Object>} Created payment with address and QR code
90
+ *
91
+ * @example
92
+ * // Create a $50 payment in Bitcoin
93
+ * const payment = await client.createPayment({
94
+ * businessId: 'your-business-id',
95
+ * amount: 50.00,
96
+ * currency: 'USD',
97
+ * blockchain: 'BTC',
98
+ * description: 'Order #12345',
99
+ * metadata: { orderId: '12345', customerEmail: 'customer@example.com' }
100
+ * });
101
+ *
102
+ * // Display payment.payment_address and payment.qr_code to customer
86
103
  */
87
104
  async createPayment({
88
105
  businessId,
89
106
  amount,
90
- currency,
91
- cryptocurrency,
107
+ currency = 'USD',
108
+ blockchain,
92
109
  description,
93
110
  metadata,
94
- callbackUrl,
95
111
  }) {
112
+ // Map to API field names (snake_case)
96
113
  return this.request('/payments/create', {
97
114
  method: 'POST',
98
115
  body: JSON.stringify({
99
- businessId,
116
+ business_id: businessId,
100
117
  amount,
101
118
  currency,
102
- cryptocurrency,
119
+ blockchain: blockchain?.toUpperCase(),
103
120
  description,
104
121
  metadata,
105
- callbackUrl,
106
122
  }),
107
123
  });
108
124
  }
109
125
 
110
126
  /**
111
127
  * Get payment by ID
128
+ *
129
+ * Use this to check the current status of a payment. You can poll this
130
+ * endpoint to wait for payment completion, or use webhooks for real-time
131
+ * notifications.
132
+ *
112
133
  * @param {string} paymentId - Payment ID
113
- * @returns {Promise<Object>} Payment details
134
+ * @returns {Promise<Object>} Payment details including status
135
+ *
136
+ * @example
137
+ * const result = await client.getPayment('pay_abc123');
138
+ * console.log(result.payment.status); // 'pending', 'confirmed', 'forwarded', etc.
114
139
  */
115
140
  async getPayment(paymentId) {
116
141
  return this.request(`/payments/${paymentId}`);
117
142
  }
118
143
 
144
+ /**
145
+ * Wait for payment to reach a terminal status
146
+ *
147
+ * Polls the payment status until it reaches a terminal state (confirmed,
148
+ * forwarded, expired, or failed). Useful for simple integrations that
149
+ * don't use webhooks.
150
+ *
151
+ * For production use, webhooks are recommended over polling.
152
+ *
153
+ * @param {string} paymentId - Payment ID
154
+ * @param {Object} [options] - Polling options
155
+ * @param {number} [options.interval=5000] - Polling interval in ms (default: 5 seconds)
156
+ * @param {number} [options.timeout=3600000] - Maximum wait time in ms (default: 1 hour)
157
+ * @param {string[]} [options.targetStatuses] - Statuses to wait for (default: ['confirmed', 'forwarded', 'expired', 'failed'])
158
+ * @param {Function} [options.onStatusChange] - Callback when status changes
159
+ * @returns {Promise<Object>} Final payment details
160
+ *
161
+ * @example
162
+ * // Simple usage - wait for payment to complete
163
+ * const payment = await client.waitForPayment('pay_abc123');
164
+ * if (payment.payment.status === 'confirmed' || payment.payment.status === 'forwarded') {
165
+ * console.log('Payment successful!');
166
+ * }
167
+ *
168
+ * @example
169
+ * // With status change callback
170
+ * const payment = await client.waitForPayment('pay_abc123', {
171
+ * interval: 3000,
172
+ * timeout: 600000, // 10 minutes
173
+ * onStatusChange: (status, payment) => {
174
+ * console.log(`Payment status: ${status}`);
175
+ * }
176
+ * });
177
+ */
178
+ async waitForPayment(paymentId, options = {}) {
179
+ const {
180
+ interval = 5000,
181
+ timeout = 3600000,
182
+ targetStatuses = ['confirmed', 'forwarded', 'expired', 'failed'],
183
+ onStatusChange,
184
+ } = options;
185
+
186
+ const startTime = Date.now();
187
+ let lastStatus = null;
188
+
189
+ while (Date.now() - startTime < timeout) {
190
+ const result = await this.getPayment(paymentId);
191
+ const currentStatus = result.payment?.status;
192
+
193
+ // Notify on status change
194
+ if (currentStatus !== lastStatus) {
195
+ if (onStatusChange && lastStatus !== null) {
196
+ onStatusChange(currentStatus, result.payment);
197
+ }
198
+ lastStatus = currentStatus;
199
+ }
200
+
201
+ // Check if we've reached a target status
202
+ if (targetStatuses.includes(currentStatus)) {
203
+ return result;
204
+ }
205
+
206
+ // Wait before next poll
207
+ await new Promise(resolve => setTimeout(resolve, interval));
208
+ }
209
+
210
+ throw new Error(`Payment status check timed out after ${timeout}ms`);
211
+ }
212
+
119
213
  /**
120
214
  * List payments for a business
121
215
  * @param {Object} params - Query parameters
@@ -140,13 +234,66 @@ export class CoinPayClient {
140
234
  }
141
235
 
142
236
  /**
143
- * Get payment QR code
237
+ * Get payment QR code URL
238
+ *
239
+ * Returns the URL to the QR code image endpoint. The endpoint returns
240
+ * binary PNG image data that can be used directly in an <img> tag.
241
+ *
144
242
  * @param {string} paymentId - Payment ID
145
- * @param {string} [format] - QR code format (png, svg)
146
- * @returns {Promise<Object>} QR code data
243
+ * @returns {string} URL to the QR code image
244
+ *
245
+ * @example
246
+ * // Get QR code URL for use in HTML
247
+ * const qrUrl = client.getPaymentQRUrl('pay_abc123');
248
+ * // Use in HTML: <img src={qrUrl} alt="Payment QR Code" />
147
249
  */
148
- async getPaymentQR(paymentId, format = 'png') {
149
- return this.request(`/payments/${paymentId}/qr?format=${format}`);
250
+ getPaymentQRUrl(paymentId) {
251
+ return `${this.#baseUrl}/payments/${paymentId}/qr`;
252
+ }
253
+
254
+ /**
255
+ * Get payment QR code as binary image data
256
+ *
257
+ * Fetches the QR code image as binary data (ArrayBuffer).
258
+ * Useful for server-side processing or saving to file.
259
+ *
260
+ * @param {string} paymentId - Payment ID
261
+ * @returns {Promise<ArrayBuffer>} QR code image as binary data
262
+ *
263
+ * @example
264
+ * // Get QR code as binary data
265
+ * const imageData = await client.getPaymentQR('pay_abc123');
266
+ * // Save to file (Node.js)
267
+ * fs.writeFileSync('qr.png', Buffer.from(imageData));
268
+ */
269
+ async getPaymentQR(paymentId) {
270
+ const url = `${this.#baseUrl}/payments/${paymentId}/qr`;
271
+ const controller = new AbortController();
272
+ const timeoutId = setTimeout(() => controller.abort(), this.#timeout);
273
+
274
+ try {
275
+ const response = await fetch(url, {
276
+ signal: controller.signal,
277
+ headers: {
278
+ 'Authorization': `Bearer ${this.#apiKey}`,
279
+ },
280
+ });
281
+
282
+ if (!response.ok) {
283
+ const error = new Error(`HTTP ${response.status}`);
284
+ error.status = response.status;
285
+ throw error;
286
+ }
287
+
288
+ return response.arrayBuffer();
289
+ } catch (error) {
290
+ if (error.name === 'AbortError') {
291
+ throw new Error(`Request timeout after ${this.#timeout}ms`);
292
+ }
293
+ throw error;
294
+ } finally {
295
+ clearTimeout(timeoutId);
296
+ }
150
297
  }
151
298
 
152
299
  /**
package/src/index.js CHANGED
@@ -3,10 +3,31 @@
3
3
  * Cryptocurrency payment integration for Node.js
4
4
  *
5
5
  * @module @profullstack/coinpay
6
+ *
7
+ * @example
8
+ * // Quick start
9
+ * import { CoinPayClient, Blockchain } from '@profullstack/coinpay';
10
+ *
11
+ * const client = new CoinPayClient({ apiKey: 'cp_live_xxxxx' });
12
+ *
13
+ * const payment = await client.createPayment({
14
+ * businessId: 'your-business-id',
15
+ * amount: 100,
16
+ * blockchain: Blockchain.BTC,
17
+ * description: 'Order #12345'
18
+ * });
6
19
  */
7
20
 
8
21
  import { CoinPayClient } from './client.js';
9
- import { createPayment, getPayment, listPayments } from './payments.js';
22
+ import {
23
+ createPayment,
24
+ getPayment,
25
+ listPayments,
26
+ Blockchain,
27
+ Cryptocurrency,
28
+ PaymentStatus,
29
+ FiatCurrency,
30
+ } from './payments.js';
10
31
  import {
11
32
  verifyWebhookSignature,
12
33
  generateWebhookSignature,
@@ -16,10 +37,21 @@ import {
16
37
  } from './webhooks.js';
17
38
 
18
39
  export {
40
+ // Client
19
41
  CoinPayClient,
42
+
43
+ // Payment functions
20
44
  createPayment,
21
45
  getPayment,
22
46
  listPayments,
47
+
48
+ // Constants
49
+ Blockchain,
50
+ Cryptocurrency, // Deprecated, use Blockchain
51
+ PaymentStatus,
52
+ FiatCurrency,
53
+
54
+ // Webhook utilities
23
55
  verifyWebhookSignature,
24
56
  generateWebhookSignature,
25
57
  parseWebhookPayload,
package/src/payments.js CHANGED
@@ -1,33 +1,65 @@
1
1
  /**
2
2
  * Payment utilities for CoinPay SDK
3
+ *
4
+ * This module provides helper functions for creating and managing cryptocurrency payments.
5
+ *
6
+ * @example
7
+ * // Quick payment creation
8
+ * import { createPayment } from '@coinpay/sdk';
9
+ *
10
+ * const payment = await createPayment({
11
+ * apiKey: 'cp_live_xxxxx',
12
+ * businessId: 'your-business-id',
13
+ * amount: 100.00,
14
+ * blockchain: 'ETH',
15
+ * description: 'Order #12345'
16
+ * });
3
17
  */
4
18
 
5
19
  import { CoinPayClient } from './client.js';
6
20
 
7
21
  /**
8
22
  * Create a payment using a client instance or API key
23
+ *
24
+ * This is a convenience function for creating payments without manually
25
+ * instantiating a client. For multiple operations, create a client instance
26
+ * and reuse it.
27
+ *
9
28
  * @param {Object} params - Payment parameters
10
- * @param {string} params.apiKey - API key (if not using client)
11
- * @param {CoinPayClient} [params.client] - Existing client instance
12
- * @param {string} params.businessId - Business ID
13
- * @param {number} params.amount - Amount in fiat currency
14
- * @param {string} params.currency - Fiat currency code
15
- * @param {string} params.cryptocurrency - Cryptocurrency code
16
- * @param {string} [params.description] - Payment description
17
- * @param {string} [params.metadata] - Custom metadata
18
- * @param {string} [params.callbackUrl] - Webhook callback URL
19
- * @returns {Promise<Object>} Created payment
29
+ * @param {string} params.apiKey - API key (required if not using client)
30
+ * @param {CoinPayClient} [params.client] - Existing client instance (optional)
31
+ * @param {string} params.businessId - Business ID from your CoinPay dashboard
32
+ * @param {number} params.amount - Amount in fiat currency (e.g., 100.00)
33
+ * @param {string} [params.currency='USD'] - Fiat currency code (USD, EUR, etc.)
34
+ * @param {string} params.blockchain - Blockchain to use (BTC, ETH, SOL, MATIC, BCH, USDC_ETH, USDC_MATIC, USDC_SOL)
35
+ * @param {string} [params.description] - Payment description shown to customer
36
+ * @param {Object} [params.metadata] - Custom metadata for your records
37
+ * @returns {Promise<Object>} Created payment with address and QR code
38
+ *
39
+ * @example
40
+ * // Create a Bitcoin payment
41
+ * const payment = await createPayment({
42
+ * apiKey: 'cp_live_xxxxx',
43
+ * businessId: 'biz_123',
44
+ * amount: 50.00,
45
+ * currency: 'USD',
46
+ * blockchain: 'BTC',
47
+ * description: 'Premium subscription',
48
+ * metadata: { userId: 'user_456', plan: 'premium' }
49
+ * });
50
+ *
51
+ * console.log('Payment address:', payment.payment.payment_address);
52
+ * console.log('Amount in BTC:', payment.payment.crypto_amount);
20
53
  */
21
54
  export async function createPayment({
22
55
  apiKey,
23
56
  client,
24
57
  businessId,
25
58
  amount,
26
- currency,
27
- cryptocurrency,
59
+ currency = 'USD',
60
+ blockchain,
28
61
  description,
29
62
  metadata,
30
- callbackUrl,
31
63
  }) {
32
64
  const coinpay = client || new CoinPayClient({ apiKey });
33
65
 
@@ -35,10 +67,9 @@ export async function createPayment({
35
67
  businessId,
36
68
  amount,
37
69
  currency,
38
- cryptocurrency,
70
+ blockchain,
39
71
  description,
40
72
  metadata,
41
- callbackUrl,
42
73
  });
43
74
  }
44
75
 
@@ -91,16 +122,44 @@ export const PaymentStatus = {
91
122
  };
92
123
 
93
124
  /**
94
- * Supported cryptocurrencies
125
+ * Supported blockchains/cryptocurrencies
126
+ *
127
+ * Use these constants when creating payments to ensure valid blockchain values.
128
+ *
129
+ * @example
130
+ * import { Blockchain, createPayment } from '@coinpay/sdk';
131
+ *
132
+ * const payment = await createPayment({
133
+ * apiKey: 'cp_live_xxxxx',
134
+ * businessId: 'biz_123',
135
+ * amount: 100,
136
+ * blockchain: Blockchain.ETH
137
+ * });
95
138
  */
96
- export const Cryptocurrency = {
139
+ export const Blockchain = {
140
+ /** Bitcoin */
97
141
  BTC: 'BTC',
142
+ /** Bitcoin Cash */
98
143
  BCH: 'BCH',
144
+ /** Ethereum */
99
145
  ETH: 'ETH',
146
+ /** Polygon (MATIC) */
100
147
  MATIC: 'MATIC',
148
+ /** Solana */
101
149
  SOL: 'SOL',
150
+ /** USDC on Ethereum */
151
+ USDC_ETH: 'USDC_ETH',
152
+ /** USDC on Polygon */
153
+ USDC_MATIC: 'USDC_MATIC',
154
+ /** USDC on Solana */
155
+ USDC_SOL: 'USDC_SOL',
102
156
  };
103
157
 
158
+ /**
159
+ * @deprecated Use Blockchain instead
160
+ */
161
+ export const Cryptocurrency = Blockchain;
162
+
104
163
  /**
105
164
  * Supported fiat currencies
106
165
  */
@@ -117,6 +176,7 @@ export default {
117
176
  getPayment,
118
177
  listPayments,
119
178
  PaymentStatus,
179
+ Blockchain,
120
180
  Cryptocurrency,
121
181
  FiatCurrency,
122
182
  };