@profullstack/coinpay 0.6.11 → 0.9.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 +39 -0
- package/README.md +189 -0
- package/bin/coinpay.js +1869 -93
- package/package.json +41 -9
- package/src/auth.js +2 -1
- package/src/card-payments.js +23 -14
- package/src/client.d.ts +52 -0
- package/src/client.js +93 -9
- package/src/finances-tui.js +1005 -0
- package/src/finances.d.ts +333 -0
- package/src/finances.js +445 -0
- package/src/index.d.ts +37 -1
- package/src/index.js +67 -0
- package/src/invoices.d.ts +78 -0
- package/src/invoices.js +250 -0
- package/src/lightning.js +8 -3
- package/src/swap.js +36 -5
- package/src/taskmarket.js +329 -0
- package/src/tokens.d.ts +14 -0
- package/src/tokens.js +34 -0
- package/src/wallet.d.ts +11 -0
- package/src/wallet.js +283 -25
- package/src/webhooks.js +37 -3
- package/src/x402-browser.js +318 -0
- package/src/x402-pay-server.js +272 -0
- package/src/x402-v2.js +416 -0
- package/src/x402.js +164 -19
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@profullstack/coinpay",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "CoinPay SDK & CLI
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "CoinPay SDK & CLI \u2014 Accept cryptocurrency and card payments (BTC, ETH, SOL, POL, BCH, USDC) with wallet, swap and a live finances dashboard",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"types": "./src/index.d.ts",
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
"import": "./src/payments.js",
|
|
18
18
|
"types": "./src/payments.d.ts"
|
|
19
19
|
},
|
|
20
|
+
"./tokens": {
|
|
21
|
+
"import": "./src/tokens.js",
|
|
22
|
+
"types": "./src/tokens.d.ts"
|
|
23
|
+
},
|
|
20
24
|
"./card-payments": {
|
|
21
25
|
"import": "./src/card-payments.js",
|
|
22
26
|
"types": "./src/card-payments.d.ts"
|
|
@@ -32,6 +36,28 @@
|
|
|
32
36
|
"./swap": {
|
|
33
37
|
"import": "./src/swap.js",
|
|
34
38
|
"types": "./src/swap.d.ts"
|
|
39
|
+
},
|
|
40
|
+
"./x402": {
|
|
41
|
+
"import": "./src/x402.js"
|
|
42
|
+
},
|
|
43
|
+
"./x402-v2": {
|
|
44
|
+
"import": "./src/x402-v2.js"
|
|
45
|
+
},
|
|
46
|
+
"./x402-browser": {
|
|
47
|
+
"import": "./src/x402-browser.js"
|
|
48
|
+
},
|
|
49
|
+
"./x402-pay-server": {
|
|
50
|
+
"import": "./src/x402-pay-server.js"
|
|
51
|
+
},
|
|
52
|
+
"./taskmarket": {
|
|
53
|
+
"import": "./src/taskmarket.js"
|
|
54
|
+
},
|
|
55
|
+
"./finances": {
|
|
56
|
+
"import": "./src/finances.js",
|
|
57
|
+
"types": "./src/finances.d.ts"
|
|
58
|
+
},
|
|
59
|
+
"./finances-tui": {
|
|
60
|
+
"import": "./src/finances-tui.js"
|
|
35
61
|
}
|
|
36
62
|
},
|
|
37
63
|
"files": [
|
|
@@ -70,7 +96,12 @@
|
|
|
70
96
|
"payment-gateway",
|
|
71
97
|
"merchant",
|
|
72
98
|
"bip39",
|
|
73
|
-
"mnemonic"
|
|
99
|
+
"mnemonic",
|
|
100
|
+
"finances",
|
|
101
|
+
"tui",
|
|
102
|
+
"dashboard",
|
|
103
|
+
"plaid",
|
|
104
|
+
"simplefin"
|
|
74
105
|
],
|
|
75
106
|
"author": "Profullstack, Inc.",
|
|
76
107
|
"license": "MIT",
|
|
@@ -87,15 +118,16 @@
|
|
|
87
118
|
"node": ">=20.0.0"
|
|
88
119
|
},
|
|
89
120
|
"devDependencies": {
|
|
90
|
-
"vitest": "^2.1.8",
|
|
91
121
|
"eslint": "^8.57.0",
|
|
92
|
-
"prettier": "^3.4.1"
|
|
122
|
+
"prettier": "^3.4.1",
|
|
123
|
+
"vitest": "^4.1.0"
|
|
93
124
|
},
|
|
94
|
-
"peerDependencies": {},
|
|
95
125
|
"dependencies": {
|
|
96
|
-
"@
|
|
97
|
-
"@scure/bip32": "^1.5.0",
|
|
126
|
+
"@inquirer/prompts": "^8.3.0",
|
|
98
127
|
"@noble/curves": "^1.6.0",
|
|
99
|
-
"@noble/hashes": "^1.5.0"
|
|
128
|
+
"@noble/hashes": "^1.5.0",
|
|
129
|
+
"@profullstack/hqtui": "^0.1.11",
|
|
130
|
+
"@scure/bip32": "^1.5.0",
|
|
131
|
+
"@scure/bip39": "^1.4.0"
|
|
100
132
|
}
|
|
101
133
|
}
|
package/src/auth.js
CHANGED
|
@@ -58,7 +58,8 @@ export async function loginMerchant(client, { email, password }) {
|
|
|
58
58
|
* @returns {Promise<Object>} Merchant information
|
|
59
59
|
*/
|
|
60
60
|
export async function getMe(client) {
|
|
61
|
+
// GET — the /auth/me endpoint is GET-only (a POST returns 405).
|
|
61
62
|
return client.request('/auth/me', {
|
|
62
|
-
method: '
|
|
63
|
+
method: 'GET',
|
|
63
64
|
});
|
|
64
65
|
}
|
package/src/card-payments.js
CHANGED
|
@@ -309,13 +309,21 @@ export async function createCardEscrow(client, businessId, amountUSD, descriptio
|
|
|
309
309
|
// Convert USD to cents
|
|
310
310
|
const amountCents = Math.round(amountUSD * 100);
|
|
311
311
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
312
|
+
// `CoinPayClient.request(endpoint, options)` takes TWO arguments. Every call
|
|
313
|
+
// in this file passed three, in the shape `request(method, path, body)` — so
|
|
314
|
+
// `endpoint` received 'POST', the URL became `baseUrl + 'POST'`, and `options`
|
|
315
|
+
// received the path as a string. These calls failed 100% of the time, which
|
|
316
|
+
// made releasing or refunding a card escrow unreachable through the SDK.
|
|
317
|
+
return client.request('/api/stripe/payments/create', {
|
|
318
|
+
method: 'POST',
|
|
319
|
+
body: JSON.stringify({
|
|
320
|
+
businessId,
|
|
321
|
+
amount: amountCents,
|
|
322
|
+
currency: 'usd',
|
|
323
|
+
description,
|
|
324
|
+
metadata,
|
|
325
|
+
escrowMode: true,
|
|
326
|
+
}),
|
|
319
327
|
});
|
|
320
328
|
}
|
|
321
329
|
|
|
@@ -346,7 +354,7 @@ export async function listCardEscrows(client, options = {}) {
|
|
|
346
354
|
const queryString = queryParams.toString();
|
|
347
355
|
const url = `/api/stripe/escrows${queryString ? `?${queryString}` : ''}`;
|
|
348
356
|
|
|
349
|
-
return client.request('GET'
|
|
357
|
+
return client.request(url, { method: 'GET' });
|
|
350
358
|
}
|
|
351
359
|
|
|
352
360
|
/**
|
|
@@ -360,8 +368,9 @@ export async function listCardEscrows(client, options = {}) {
|
|
|
360
368
|
* const result = await releaseCardEscrow(client, 'escrow-123');
|
|
361
369
|
*/
|
|
362
370
|
export async function releaseCardEscrow(client, escrowId) {
|
|
363
|
-
return client.request('
|
|
364
|
-
|
|
371
|
+
return client.request('/api/stripe/escrow/release', {
|
|
372
|
+
method: 'POST',
|
|
373
|
+
body: JSON.stringify({ escrowId }),
|
|
365
374
|
});
|
|
366
375
|
}
|
|
367
376
|
|
|
@@ -386,9 +395,9 @@ export async function releaseCardEscrow(client, escrowId) {
|
|
|
386
395
|
* });
|
|
387
396
|
*/
|
|
388
397
|
export async function refundCardEscrow(client, escrowId, options = {}) {
|
|
389
|
-
return client.request('
|
|
390
|
-
|
|
391
|
-
...options,
|
|
398
|
+
return client.request('/api/stripe/escrow/refund', {
|
|
399
|
+
method: 'POST',
|
|
400
|
+
body: JSON.stringify({ escrowId, ...options }),
|
|
392
401
|
});
|
|
393
402
|
}
|
|
394
403
|
|
|
@@ -404,7 +413,7 @@ export async function refundCardEscrow(client, escrowId, options = {}) {
|
|
|
404
413
|
* console.log(status.escrow_status); // 'pending', 'released', 'refunded'
|
|
405
414
|
*/
|
|
406
415
|
export async function getCardEscrowStatus(client, escrowId) {
|
|
407
|
-
return client.request(
|
|
416
|
+
return client.request(`/api/stripe/transactions/${escrowId}`, { method: 'GET' });
|
|
408
417
|
}
|
|
409
418
|
|
|
410
419
|
/**
|
package/src/client.d.ts
CHANGED
|
@@ -41,6 +41,14 @@ export interface ListPaymentsParams {
|
|
|
41
41
|
offset?: number;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/** Parameters for supported coin/token discovery */
|
|
45
|
+
export interface SupportedCoinsParams {
|
|
46
|
+
/** Business ID. Required for merchant JWTs; optional with business API keys if it matches key scope. */
|
|
47
|
+
businessId?: string;
|
|
48
|
+
/** If true, only active wallets are returned. */
|
|
49
|
+
activeOnly?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
/** Options for the `waitForPayment` polling method */
|
|
45
53
|
export interface WaitForPaymentOptions {
|
|
46
54
|
/** Polling interval in milliseconds (default: `5000`) */
|
|
@@ -109,6 +117,36 @@ export interface ListPaymentsResponse {
|
|
|
109
117
|
payments: Payment[];
|
|
110
118
|
}
|
|
111
119
|
|
|
120
|
+
/** Supported payment coin record */
|
|
121
|
+
export interface SupportedCoin {
|
|
122
|
+
symbol: string;
|
|
123
|
+
name: string;
|
|
124
|
+
is_active: boolean;
|
|
125
|
+
has_wallet: boolean;
|
|
126
|
+
wallet_source: 'business' | 'merchant_global';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Checkout token record with lower-case code accepted by createPayment currency */
|
|
130
|
+
export interface SupportedToken extends SupportedCoin {
|
|
131
|
+
code: string;
|
|
132
|
+
ticker: string;
|
|
133
|
+
chain?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Response from supported coin discovery */
|
|
137
|
+
export interface SupportedCoinsResponse {
|
|
138
|
+
success: boolean;
|
|
139
|
+
coins: SupportedCoin[];
|
|
140
|
+
business_id: string;
|
|
141
|
+
merchant_id?: string;
|
|
142
|
+
total: number;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Response from token discovery */
|
|
146
|
+
export interface TokensResponse extends SupportedCoinsResponse {
|
|
147
|
+
tokens: SupportedToken[];
|
|
148
|
+
}
|
|
149
|
+
|
|
112
150
|
/**
|
|
113
151
|
* CoinPay API Client
|
|
114
152
|
*
|
|
@@ -186,6 +224,20 @@ export class CoinPayClient {
|
|
|
186
224
|
*/
|
|
187
225
|
listPayments(params: ListPaymentsParams): Promise<ListPaymentsResponse>;
|
|
188
226
|
|
|
227
|
+
/**
|
|
228
|
+
* List supported payment coins for a business.
|
|
229
|
+
*
|
|
230
|
+
* Business wallets win; merchant global wallets are used as fallback.
|
|
231
|
+
*/
|
|
232
|
+
getSupportedCoins(params?: SupportedCoinsParams): Promise<SupportedCoinsResponse>;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* List checkout-friendly tokens for a business.
|
|
236
|
+
*
|
|
237
|
+
* Returns lower-case `code` values accepted by `createPayment({ currency })`.
|
|
238
|
+
*/
|
|
239
|
+
getTokens(params?: SupportedCoinsParams): Promise<TokensResponse>;
|
|
240
|
+
|
|
189
241
|
/**
|
|
190
242
|
* Get a URL pointing to the QR code image for a payment.
|
|
191
243
|
*
|
package/src/client.js
CHANGED
|
@@ -279,6 +279,45 @@ export class CoinPayClient {
|
|
|
279
279
|
return this.request(`/payments?${params.toString()}`);
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
+
/**
|
|
283
|
+
* Get supported payment coins for a business.
|
|
284
|
+
*
|
|
285
|
+
* Business API keys derive the business from the key. Passing businessId is
|
|
286
|
+
* still allowed and must match the key scope. Merchant JWTs require
|
|
287
|
+
* businessId.
|
|
288
|
+
*
|
|
289
|
+
* @param {Object} [params]
|
|
290
|
+
* @param {string} [params.businessId] - Business ID
|
|
291
|
+
* @param {boolean} [params.activeOnly] - Only return active wallets
|
|
292
|
+
* @returns {Promise<Object>} Supported coins response
|
|
293
|
+
*/
|
|
294
|
+
async getSupportedCoins({ businessId, activeOnly } = {}) {
|
|
295
|
+
const params = new URLSearchParams();
|
|
296
|
+
if (businessId) params.set('business_id', businessId);
|
|
297
|
+
if (activeOnly) params.set('active_only', 'true');
|
|
298
|
+
const query = params.toString();
|
|
299
|
+
return this.request(`/supported-coins${query ? `?${query}` : ''}`);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Get payment-option tokens for a business.
|
|
304
|
+
*
|
|
305
|
+
* Returns lower-case `code` values accepted by /payments/create, plus
|
|
306
|
+
* display fields for checkout coin pickers.
|
|
307
|
+
*
|
|
308
|
+
* @param {Object} [params]
|
|
309
|
+
* @param {string} [params.businessId] - Business ID
|
|
310
|
+
* @param {boolean} [params.activeOnly] - Only return active wallets
|
|
311
|
+
* @returns {Promise<Object>} Tokens response
|
|
312
|
+
*/
|
|
313
|
+
async getTokens({ businessId, activeOnly } = {}) {
|
|
314
|
+
const params = new URLSearchParams();
|
|
315
|
+
if (businessId) params.set('business_id', businessId);
|
|
316
|
+
if (activeOnly) params.set('active_only', 'true');
|
|
317
|
+
const query = params.toString();
|
|
318
|
+
return this.request(`/tokens${query ? `?${query}` : ''}`);
|
|
319
|
+
}
|
|
320
|
+
|
|
282
321
|
/**
|
|
283
322
|
* Get payment QR code URL
|
|
284
323
|
*
|
|
@@ -415,23 +454,61 @@ export class CoinPayClient {
|
|
|
415
454
|
|
|
416
455
|
/**
|
|
417
456
|
* Create a new business
|
|
457
|
+
*
|
|
458
|
+
* Field names are snake_case because that is what the API reads. This used to
|
|
459
|
+
* send `webhookUrl`, which POST /api/businesses does not look at -- it reads
|
|
460
|
+
* `input.webhook_url` -- so every business created through the SDK came back
|
|
461
|
+
* with a null webhook_url and no webhook secret, silently. The value was
|
|
462
|
+
* accepted, echoed nowhere, and dropped.
|
|
463
|
+
*
|
|
464
|
+
* `category` is required by the API and was not sent at all, so
|
|
465
|
+
* `coinpay business create` failed outright with "Select a valid business
|
|
466
|
+
* category" and there was no flag to supply one. Valid slugs live in
|
|
467
|
+
* src/lib/business/taxonomy.ts.
|
|
468
|
+
*
|
|
418
469
|
* @param {Object} params - Business parameters
|
|
419
470
|
* @param {string} params.name - Business name
|
|
471
|
+
* @param {string} params.category - Taxonomy slug; required by the API
|
|
472
|
+
* @param {string} [params.description]
|
|
420
473
|
* @param {string} [params.webhookUrl] - Webhook URL
|
|
474
|
+
* @param {string} [params.webhookSecret] - Supply one, or the API generates it
|
|
421
475
|
* @param {Object} [params.walletAddresses] - Wallet addresses by chain
|
|
422
476
|
* @returns {Promise<Object>} Created business
|
|
423
477
|
*/
|
|
424
|
-
async createBusiness({
|
|
478
|
+
async createBusiness({
|
|
479
|
+
name,
|
|
480
|
+
category,
|
|
481
|
+
description,
|
|
482
|
+
webhookUrl,
|
|
483
|
+
webhookSecret,
|
|
484
|
+
walletAddresses,
|
|
485
|
+
}) {
|
|
425
486
|
return this.request('/businesses', {
|
|
426
487
|
method: 'POST',
|
|
427
488
|
body: JSON.stringify({
|
|
428
489
|
name,
|
|
429
|
-
|
|
490
|
+
category,
|
|
491
|
+
description,
|
|
492
|
+
webhook_url: webhookUrl,
|
|
493
|
+
webhook_secret: webhookSecret,
|
|
430
494
|
walletAddresses,
|
|
431
495
|
}),
|
|
432
496
|
});
|
|
433
497
|
}
|
|
434
498
|
|
|
499
|
+
/**
|
|
500
|
+
* The taxonomy a business may be created with.
|
|
501
|
+
*
|
|
502
|
+
* Fetched rather than bundled: a copy inside the SDK goes stale the moment a
|
|
503
|
+
* category is added, and a stale copy is how "Select a valid business category"
|
|
504
|
+
* happens a second time.
|
|
505
|
+
*
|
|
506
|
+
* @returns {Promise<Object>} { success, categories: [{ slug, label, group, baseRisk }] }
|
|
507
|
+
*/
|
|
508
|
+
async listBusinessCategories() {
|
|
509
|
+
return this.request('/businesses/categories', { method: 'GET' });
|
|
510
|
+
}
|
|
511
|
+
|
|
435
512
|
/**
|
|
436
513
|
* Update business
|
|
437
514
|
* @param {string} businessId - Business ID
|
|
@@ -685,22 +762,29 @@ export class CoinPayClient {
|
|
|
685
762
|
|
|
686
763
|
/**
|
|
687
764
|
* Create Stripe Connect onboarding link
|
|
688
|
-
*
|
|
765
|
+
*
|
|
689
766
|
* Generates a Stripe Express onboarding link for a merchant.
|
|
690
767
|
* The merchant must complete this onboarding before they can accept card payments.
|
|
691
|
-
*
|
|
768
|
+
*
|
|
769
|
+
* Country is required on the first onboarding call and is locked at Stripe
|
|
770
|
+
* account creation — it cannot be changed afterward. Subsequent calls (e.g.
|
|
771
|
+
* to finish remaining requirements) may omit it; the server reuses the
|
|
772
|
+
* country stored on the business. All Stripe Connect supported countries are
|
|
773
|
+
* accepted (US, CA, GB, AU, DE, FR, JP, SG, ...). See
|
|
774
|
+
* https://stripe.com/global for the full list.
|
|
775
|
+
*
|
|
692
776
|
* @param {string} businessId - Business ID
|
|
693
777
|
* @param {Object} [params] - Optional parameters
|
|
694
778
|
* @param {string} [params.email] - Merchant email (pre-fills onboarding form)
|
|
695
|
-
* @param {string} [params.country
|
|
779
|
+
* @param {string} [params.country] - ISO-3166-1 alpha-2 country code (e.g. 'US', 'CA', 'GB'). Required on first onboarding.
|
|
696
780
|
* @returns {Promise<Object>} Onboarding link and account ID
|
|
697
|
-
*
|
|
781
|
+
*
|
|
698
782
|
* @example
|
|
699
783
|
* const onboarding = await client.createStripeOnboardingLink('business-id', {
|
|
700
784
|
* email: 'merchant@example.com',
|
|
701
|
-
* country: '
|
|
785
|
+
* country: 'CA'
|
|
702
786
|
* });
|
|
703
|
-
*
|
|
787
|
+
*
|
|
704
788
|
* // Redirect merchant to onboarding.onboarding_url
|
|
705
789
|
*/
|
|
706
790
|
async createStripeOnboardingLink(businessId, params = {}) {
|
|
@@ -913,4 +997,4 @@ export class CoinPayClient {
|
|
|
913
997
|
}
|
|
914
998
|
}
|
|
915
999
|
|
|
916
|
-
export default CoinPayClient;
|
|
1000
|
+
export default CoinPayClient;
|