@profullstack/coinpay 0.1.0 → 0.3.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/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +781 -143
- package/bin/coinpay.js +38 -14
- package/package.json +29 -12
- package/src/client.d.ts +266 -0
- package/src/client.js +170 -23
- package/src/index.d.ts +37 -0
- package/src/index.js +33 -1
- package/src/payments.d.ts +153 -0
- package/src/payments.js +78 -18
- package/src/webhooks.d.ts +134 -0
package/bin/coinpay.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { CoinPayClient } from '../src/client.js';
|
|
9
|
-
import { PaymentStatus,
|
|
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://
|
|
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
|
-
--
|
|
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, POL, BCH, USDC_ETH, USDC_POL, USDC_SOL)
|
|
158
|
+
--description <text> Payment description
|
|
158
159
|
|
|
159
160
|
${colors.cyan}Examples:${colors.reset}
|
|
160
|
-
|
|
161
|
-
coinpay
|
|
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_POL
|
|
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,
|
|
237
|
+
const { 'business-id': businessId, amount, currency = 'USD', blockchain, description } = flags;
|
|
222
238
|
|
|
223
|
-
if (!businessId || !amount || !
|
|
224
|
-
print.error('Required: --business-id, --amount, --
|
|
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
|
-
|
|
249
|
+
blockchain,
|
|
233
250
|
description,
|
|
234
251
|
});
|
|
235
252
|
|
|
236
253
|
print.success('Payment created');
|
|
237
|
-
|
|
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('
|
|
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(
|
|
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,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@profullstack/coinpay",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "CoinPay SDK & CLI
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "CoinPay SDK & CLI — Accept cryptocurrency payments (BTC, ETH, SOL, POL, BCH, USDC) in your Node.js application",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
|
+
"types": "./src/index.d.ts",
|
|
7
8
|
"bin": {
|
|
8
9
|
"coinpay": "./bin/coinpay.js"
|
|
9
10
|
},
|
|
@@ -24,22 +25,44 @@
|
|
|
24
25
|
"files": [
|
|
25
26
|
"src",
|
|
26
27
|
"bin",
|
|
27
|
-
"README.md"
|
|
28
|
+
"README.md",
|
|
29
|
+
"CHANGELOG.md",
|
|
30
|
+
"LICENSE"
|
|
28
31
|
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:watch": "vitest",
|
|
35
|
+
"lint": "eslint src bin test",
|
|
36
|
+
"format": "prettier --write src bin test",
|
|
37
|
+
"prepublishOnly": "npm run test && npm run lint"
|
|
38
|
+
},
|
|
29
39
|
"keywords": [
|
|
30
40
|
"coinpay",
|
|
31
41
|
"profullstack",
|
|
32
42
|
"cryptocurrency",
|
|
43
|
+
"crypto",
|
|
33
44
|
"payments",
|
|
34
45
|
"bitcoin",
|
|
35
46
|
"ethereum",
|
|
36
47
|
"solana",
|
|
37
48
|
"polygon",
|
|
49
|
+
"usdc",
|
|
50
|
+
"stablecoin",
|
|
51
|
+
"non-custodial",
|
|
52
|
+
"wallet",
|
|
38
53
|
"sdk",
|
|
39
|
-
"cli"
|
|
54
|
+
"cli",
|
|
55
|
+
"web3",
|
|
56
|
+
"blockchain",
|
|
57
|
+
"payment-gateway",
|
|
58
|
+
"merchant"
|
|
40
59
|
],
|
|
41
60
|
"author": "Profullstack, Inc.",
|
|
42
61
|
"license": "MIT",
|
|
62
|
+
"homepage": "https://coinpayportal.com",
|
|
63
|
+
"bugs": {
|
|
64
|
+
"url": "https://github.com/profullstack/coinpayportal/issues"
|
|
65
|
+
},
|
|
43
66
|
"repository": {
|
|
44
67
|
"type": "git",
|
|
45
68
|
"url": "https://github.com/profullstack/coinpayportal.git",
|
|
@@ -54,11 +77,5 @@
|
|
|
54
77
|
"prettier": "^3.4.1"
|
|
55
78
|
},
|
|
56
79
|
"peerDependencies": {},
|
|
57
|
-
"dependencies": {}
|
|
58
|
-
|
|
59
|
-
"test": "vitest run",
|
|
60
|
-
"test:watch": "vitest",
|
|
61
|
-
"lint": "eslint src bin test",
|
|
62
|
-
"format": "prettier --write src bin test"
|
|
63
|
-
}
|
|
64
|
-
}
|
|
80
|
+
"dependencies": {}
|
|
81
|
+
}
|
package/src/client.d.ts
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CoinPay API Client
|
|
3
|
+
* Main client class for interacting with the CoinPay API
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Options for constructing a CoinPayClient */
|
|
7
|
+
export interface CoinPayClientOptions {
|
|
8
|
+
/** Your CoinPay API key (starts with `cp_live_` or `cp_test_`) */
|
|
9
|
+
apiKey: string;
|
|
10
|
+
/** API base URL (default: `https://coinpayportal.com/api`) */
|
|
11
|
+
baseUrl?: string;
|
|
12
|
+
/** Request timeout in milliseconds (default: `30000`) */
|
|
13
|
+
timeout?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Parameters for creating a payment */
|
|
17
|
+
export interface PaymentParams {
|
|
18
|
+
/** Business ID from your CoinPay dashboard */
|
|
19
|
+
businessId: string;
|
|
20
|
+
/** Amount in fiat currency (e.g., `100.00`) */
|
|
21
|
+
amount: number;
|
|
22
|
+
/** Fiat currency code (default: `'USD'`) */
|
|
23
|
+
currency?: string;
|
|
24
|
+
/** Blockchain/cryptocurrency code: `BTC`, `ETH`, `SOL`, `POL`, `BCH`, `USDC_ETH`, `USDC_POL`, `USDC_SOL` */
|
|
25
|
+
blockchain: string;
|
|
26
|
+
/** Payment description shown to the customer */
|
|
27
|
+
description?: string;
|
|
28
|
+
/** Custom metadata attached to the payment (e.g., `{ orderId: 'ORD-123' }`) */
|
|
29
|
+
metadata?: Record<string, unknown>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Parameters for listing payments */
|
|
33
|
+
export interface ListPaymentsParams {
|
|
34
|
+
/** Business ID */
|
|
35
|
+
businessId: string;
|
|
36
|
+
/** Filter by payment status */
|
|
37
|
+
status?: string;
|
|
38
|
+
/** Number of results to return (default: `20`) */
|
|
39
|
+
limit?: number;
|
|
40
|
+
/** Pagination offset (default: `0`) */
|
|
41
|
+
offset?: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Options for the `waitForPayment` polling method */
|
|
45
|
+
export interface WaitForPaymentOptions {
|
|
46
|
+
/** Polling interval in milliseconds (default: `5000`) */
|
|
47
|
+
interval?: number;
|
|
48
|
+
/** Maximum wait time in milliseconds (default: `3600000` — 1 hour) */
|
|
49
|
+
timeout?: number;
|
|
50
|
+
/** Payment statuses that stop polling (default: `['confirmed', 'forwarded', 'expired', 'failed']`) */
|
|
51
|
+
targetStatuses?: string[];
|
|
52
|
+
/** Callback invoked when the payment status changes */
|
|
53
|
+
onStatusChange?: (status: string, payment: Record<string, unknown>) => void;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Parameters for creating a business */
|
|
57
|
+
export interface CreateBusinessParams {
|
|
58
|
+
/** Business name */
|
|
59
|
+
name: string;
|
|
60
|
+
/** Webhook URL for payment notifications */
|
|
61
|
+
webhookUrl?: string;
|
|
62
|
+
/** Wallet addresses keyed by blockchain code */
|
|
63
|
+
walletAddresses?: Record<string, string>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Generic API response envelope */
|
|
67
|
+
export interface ApiResponse<T = Record<string, unknown>> {
|
|
68
|
+
success: boolean;
|
|
69
|
+
[key: string]: unknown;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Payment object returned by the API */
|
|
73
|
+
export interface Payment {
|
|
74
|
+
id: string;
|
|
75
|
+
business_id: string;
|
|
76
|
+
amount: number;
|
|
77
|
+
currency: string;
|
|
78
|
+
blockchain: string;
|
|
79
|
+
crypto_amount: string;
|
|
80
|
+
payment_address: string;
|
|
81
|
+
qr_code?: string;
|
|
82
|
+
status: string;
|
|
83
|
+
tx_hash?: string;
|
|
84
|
+
expires_at?: string;
|
|
85
|
+
created_at: string;
|
|
86
|
+
metadata?: Record<string, unknown>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Response from payment creation */
|
|
90
|
+
export interface CreatePaymentResponse {
|
|
91
|
+
success: boolean;
|
|
92
|
+
payment: Payment;
|
|
93
|
+
usage?: {
|
|
94
|
+
current: number;
|
|
95
|
+
limit: number;
|
|
96
|
+
remaining: number;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Response from getting a single payment */
|
|
101
|
+
export interface GetPaymentResponse {
|
|
102
|
+
success: boolean;
|
|
103
|
+
payment: Payment;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Response from listing payments */
|
|
107
|
+
export interface ListPaymentsResponse {
|
|
108
|
+
success: boolean;
|
|
109
|
+
payments: Payment[];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* CoinPay API Client
|
|
114
|
+
*
|
|
115
|
+
* The primary class for interacting with the CoinPay payment API.
|
|
116
|
+
* Handles authentication, request signing, and provides methods
|
|
117
|
+
* for all API operations.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* import { CoinPayClient } from '@profullstack/coinpay';
|
|
122
|
+
*
|
|
123
|
+
* const client = new CoinPayClient({ apiKey: 'cp_live_xxxxx' });
|
|
124
|
+
*
|
|
125
|
+
* const payment = await client.createPayment({
|
|
126
|
+
* businessId: 'biz_123',
|
|
127
|
+
* amount: 99.99,
|
|
128
|
+
* blockchain: 'BTC',
|
|
129
|
+
* });
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export class CoinPayClient {
|
|
133
|
+
/**
|
|
134
|
+
* Create a new CoinPay client
|
|
135
|
+
* @throws {Error} If `apiKey` is not provided
|
|
136
|
+
*/
|
|
137
|
+
constructor(options: CoinPayClientOptions);
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Make an authenticated API request.
|
|
141
|
+
*
|
|
142
|
+
* Automatically adds `Authorization: Bearer <apiKey>` and `Content-Type: application/json` headers.
|
|
143
|
+
* Handles timeouts via `AbortController`.
|
|
144
|
+
*
|
|
145
|
+
* @param endpoint - API endpoint path (e.g., `/payments/create`)
|
|
146
|
+
* @param options - Standard `fetch` options (method, body, headers, etc.)
|
|
147
|
+
* @returns Parsed JSON response
|
|
148
|
+
* @throws {Error} On HTTP errors (non-2xx) or timeout
|
|
149
|
+
*/
|
|
150
|
+
request(endpoint: string, options?: RequestInit): Promise<Record<string, unknown>>;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Create a new payment request.
|
|
154
|
+
*
|
|
155
|
+
* Generates a unique blockchain address and optional QR code for the customer to pay.
|
|
156
|
+
*
|
|
157
|
+
* @returns Created payment with `payment_address`, `crypto_amount`, and `qr_code`
|
|
158
|
+
*/
|
|
159
|
+
createPayment(params: PaymentParams): Promise<CreatePaymentResponse>;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get payment details by ID.
|
|
163
|
+
*
|
|
164
|
+
* @param paymentId - Payment ID (e.g., `'pay_abc123'`)
|
|
165
|
+
* @returns Payment details including current status
|
|
166
|
+
*/
|
|
167
|
+
getPayment(paymentId: string): Promise<GetPaymentResponse>;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Poll until a payment reaches a terminal status.
|
|
171
|
+
*
|
|
172
|
+
* Terminal statuses: `confirmed`, `forwarded`, `expired`, `failed`.
|
|
173
|
+
* For production, prefer webhooks over polling.
|
|
174
|
+
*
|
|
175
|
+
* @param paymentId - Payment ID
|
|
176
|
+
* @param options - Polling configuration
|
|
177
|
+
* @returns Final payment details
|
|
178
|
+
* @throws {Error} If timeout is reached before a terminal status
|
|
179
|
+
*/
|
|
180
|
+
waitForPayment(paymentId: string, options?: WaitForPaymentOptions): Promise<GetPaymentResponse>;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* List payments for a business.
|
|
184
|
+
*
|
|
185
|
+
* @returns Paginated list of payments
|
|
186
|
+
*/
|
|
187
|
+
listPayments(params: ListPaymentsParams): Promise<ListPaymentsResponse>;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Get a URL pointing to the QR code image for a payment.
|
|
191
|
+
*
|
|
192
|
+
* The URL returns binary PNG data suitable for `<img src="...">`.
|
|
193
|
+
* This method is synchronous — it does not make a network request.
|
|
194
|
+
*
|
|
195
|
+
* @param paymentId - Payment ID
|
|
196
|
+
* @returns Full URL to the QR code PNG endpoint
|
|
197
|
+
*/
|
|
198
|
+
getPaymentQRUrl(paymentId: string): string;
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Fetch the QR code image as binary data.
|
|
202
|
+
*
|
|
203
|
+
* @param paymentId - Payment ID
|
|
204
|
+
* @returns QR code PNG image as an `ArrayBuffer`
|
|
205
|
+
*/
|
|
206
|
+
getPaymentQR(paymentId: string): Promise<ArrayBuffer>;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Get the exchange rate for a cryptocurrency.
|
|
210
|
+
*
|
|
211
|
+
* @param cryptocurrency - Crypto code (e.g., `'BTC'`, `'ETH'`)
|
|
212
|
+
* @param fiatCurrency - Fiat code (default: `'USD'`)
|
|
213
|
+
*/
|
|
214
|
+
getExchangeRate(cryptocurrency: string, fiatCurrency?: string): Promise<Record<string, unknown>>;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Get exchange rates for multiple cryptocurrencies in a single request.
|
|
218
|
+
*
|
|
219
|
+
* @param cryptocurrencies - Array of crypto codes
|
|
220
|
+
* @param fiatCurrency - Fiat code (default: `'USD'`)
|
|
221
|
+
*/
|
|
222
|
+
getExchangeRates(cryptocurrencies: string[], fiatCurrency?: string): Promise<Record<string, unknown>>;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Get business details.
|
|
226
|
+
*
|
|
227
|
+
* @param businessId - Business ID
|
|
228
|
+
*/
|
|
229
|
+
getBusiness(businessId: string): Promise<Record<string, unknown>>;
|
|
230
|
+
|
|
231
|
+
/** List all businesses associated with your API key. */
|
|
232
|
+
listBusinesses(): Promise<Record<string, unknown>>;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Create a new business.
|
|
236
|
+
*
|
|
237
|
+
* @param params - Business creation parameters
|
|
238
|
+
*/
|
|
239
|
+
createBusiness(params: CreateBusinessParams): Promise<Record<string, unknown>>;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Update an existing business.
|
|
243
|
+
*
|
|
244
|
+
* @param businessId - Business ID
|
|
245
|
+
* @param params - Fields to update
|
|
246
|
+
*/
|
|
247
|
+
updateBusiness(businessId: string, params: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Get webhook delivery logs for a business.
|
|
251
|
+
*
|
|
252
|
+
* @param businessId - Business ID
|
|
253
|
+
* @param limit - Number of log entries (default: `50`)
|
|
254
|
+
*/
|
|
255
|
+
getWebhookLogs(businessId: string, limit?: number): Promise<Record<string, unknown>>;
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Send a test webhook event to your configured endpoint.
|
|
259
|
+
*
|
|
260
|
+
* @param businessId - Business ID
|
|
261
|
+
* @param eventType - Event type to simulate (default: `'payment.completed'`)
|
|
262
|
+
*/
|
|
263
|
+
testWebhook(businessId: string, eventType?: string): Promise<Record<string, unknown>>;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export default CoinPayClient;
|