@profullstack/coinpay 0.6.10 → 0.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@profullstack/coinpay",
3
- "version": "0.6.10",
3
+ "version": "0.8.0",
4
4
  "description": "CoinPay SDK & CLI — Accept cryptocurrency payments (BTC, ETH, SOL, POL, BCH, USDC) with wallet and swap support",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -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,18 @@
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"
35
51
  }
36
52
  },
37
53
  "files": [
@@ -87,7 +103,7 @@
87
103
  "node": ">=20.0.0"
88
104
  },
89
105
  "devDependencies": {
90
- "vitest": "^2.1.8",
106
+ "vitest": "^4.1.0",
91
107
  "eslint": "^8.57.0",
92
108
  "prettier": "^3.4.1"
93
109
  },
@@ -96,6 +112,7 @@
96
112
  "@scure/bip39": "^1.4.0",
97
113
  "@scure/bip32": "^1.5.0",
98
114
  "@noble/curves": "^1.6.0",
99
- "@noble/hashes": "^1.5.0"
115
+ "@noble/hashes": "^1.5.0",
116
+ "@inquirer/prompts": "^8.3.0"
100
117
  }
101
118
  }
package/src/auth.js CHANGED
@@ -18,6 +18,9 @@
18
18
  * @returns {Promise<Object>} { success: boolean, merchant: Object, token: string }
19
19
  */
20
20
  export async function registerMerchant(client, { email, password, name }) {
21
+ if (!email) throw new Error('Email is required');
22
+ if (!password) throw new Error('Password is required');
23
+
21
24
  return client.requestUnauthenticated('/auth/register', {
22
25
  method: 'POST',
23
26
  body: JSON.stringify({
@@ -37,6 +40,9 @@ export async function registerMerchant(client, { email, password, name }) {
37
40
  * @returns {Promise<Object>} { success: boolean, merchant: Object, token: string }
38
41
  */
39
42
  export async function loginMerchant(client, { email, password }) {
43
+ if (!email) throw new Error('Email is required');
44
+ if (!password) throw new Error('Password is required');
45
+
40
46
  return client.requestUnauthenticated('/auth/login', {
41
47
  method: 'POST',
42
48
  body: JSON.stringify({
@@ -52,7 +58,8 @@ export async function loginMerchant(client, { email, password }) {
52
58
  * @returns {Promise<Object>} Merchant information
53
59
  */
54
60
  export async function getMe(client) {
61
+ // GET — the /auth/me endpoint is GET-only (a POST returns 405).
55
62
  return client.request('/auth/me', {
56
- method: 'POST',
63
+ method: 'GET',
57
64
  });
58
65
  }
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
  *
@@ -685,22 +724,29 @@ export class CoinPayClient {
685
724
 
686
725
  /**
687
726
  * Create Stripe Connect onboarding link
688
- *
727
+ *
689
728
  * Generates a Stripe Express onboarding link for a merchant.
690
729
  * The merchant must complete this onboarding before they can accept card payments.
691
- *
730
+ *
731
+ * Country is required on the first onboarding call and is locked at Stripe
732
+ * account creation — it cannot be changed afterward. Subsequent calls (e.g.
733
+ * to finish remaining requirements) may omit it; the server reuses the
734
+ * country stored on the business. All Stripe Connect supported countries are
735
+ * accepted (US, CA, GB, AU, DE, FR, JP, SG, ...). See
736
+ * https://stripe.com/global for the full list.
737
+ *
692
738
  * @param {string} businessId - Business ID
693
739
  * @param {Object} [params] - Optional parameters
694
740
  * @param {string} [params.email] - Merchant email (pre-fills onboarding form)
695
- * @param {string} [params.country='US'] - Country code (US, CA, GB, etc.)
741
+ * @param {string} [params.country] - ISO-3166-1 alpha-2 country code (e.g. 'US', 'CA', 'GB'). Required on first onboarding.
696
742
  * @returns {Promise<Object>} Onboarding link and account ID
697
- *
743
+ *
698
744
  * @example
699
745
  * const onboarding = await client.createStripeOnboardingLink('business-id', {
700
746
  * email: 'merchant@example.com',
701
- * country: 'US'
747
+ * country: 'CA'
702
748
  * });
703
- *
749
+ *
704
750
  * // Redirect merchant to onboarding.onboarding_url
705
751
  */
706
752
  async createStripeOnboardingLink(businessId, params = {}) {
@@ -826,6 +872,91 @@ export class CoinPayClient {
826
872
  method: 'DELETE',
827
873
  });
828
874
  }
875
+
876
+ // ── OAuth Client Methods ─────────────────────────────────
877
+
878
+ /**
879
+ * List OAuth clients
880
+ *
881
+ * Returns all OAuth clients registered under your account.
882
+ *
883
+ * @returns {Promise<Object>} List of OAuth clients
884
+ *
885
+ * @example
886
+ * const result = await client.listOAuthClients();
887
+ * for (const app of result.clients) {
888
+ * console.log(app.client_id, app.name);
889
+ * }
890
+ */
891
+ async listOAuthClients() {
892
+ return this.request('/oauth/clients');
893
+ }
894
+
895
+ /**
896
+ * Create a new OAuth client
897
+ *
898
+ * Registers a new OAuth application. Returns the client_id and client_secret.
899
+ * Store the client_secret securely — it is only shown once.
900
+ *
901
+ * @param {Object} params - OAuth client parameters
902
+ * @param {string} params.name - Application name
903
+ * @param {string[]} params.redirectUris - Authorized redirect URIs
904
+ * @param {string[]} [params.scopes] - Requested scopes (e.g., ['openid', 'profile'])
905
+ * @param {string} [params.description] - Application description
906
+ * @returns {Promise<Object>} Created OAuth client with client_id and client_secret
907
+ *
908
+ * @example
909
+ * const app = await client.createOAuthClient({
910
+ * name: 'My App',
911
+ * redirectUris: ['https://myapp.com/callback'],
912
+ * scopes: ['openid', 'profile'],
913
+ * description: 'My awesome application',
914
+ * });
915
+ * console.log('Client ID:', app.client_id);
916
+ * console.log('Client Secret:', app.client_secret);
917
+ */
918
+ async createOAuthClient({ name, redirectUris, scopes, description }) {
919
+ return this.request('/oauth/clients', {
920
+ method: 'POST',
921
+ body: JSON.stringify({
922
+ name,
923
+ redirect_uris: redirectUris,
924
+ scopes,
925
+ description,
926
+ }),
927
+ });
928
+ }
929
+
930
+ /**
931
+ * Get an OAuth client by ID
932
+ *
933
+ * @param {string} id - OAuth client ID
934
+ * @returns {Promise<Object>} OAuth client details
935
+ *
936
+ * @example
937
+ * const app = await client.getOAuthClient('oac_abc123');
938
+ * console.log(app.name, app.redirect_uris);
939
+ */
940
+ async getOAuthClient(id) {
941
+ return this.request(`/oauth/clients/${id}`);
942
+ }
943
+
944
+ /**
945
+ * Delete an OAuth client
946
+ *
947
+ * Permanently removes an OAuth client and revokes all associated tokens.
948
+ *
949
+ * @param {string} id - OAuth client ID
950
+ * @returns {Promise<Object>} Deletion confirmation
951
+ *
952
+ * @example
953
+ * await client.deleteOAuthClient('oac_abc123');
954
+ */
955
+ async deleteOAuthClient(id) {
956
+ return this.request(`/oauth/clients/${id}`, {
957
+ method: 'DELETE',
958
+ });
959
+ }
829
960
  }
830
961
 
831
- export default CoinPayClient;
962
+ export default CoinPayClient;
package/src/index.d.ts CHANGED
@@ -12,9 +12,22 @@ export type {
12
12
  PaymentParams,
13
13
  ListPaymentsParams,
14
14
  WaitForPaymentOptions,
15
- CreateBusinessParams
15
+ CreateBusinessParams,
16
+ SupportedCoinsParams,
17
+ SupportedCoin,
18
+ SupportedToken,
19
+ SupportedCoinsResponse,
20
+ TokensResponse,
16
21
  } from './client.js';
17
22
 
23
+ export {
24
+ getTokens,
25
+ getSupportedCoins,
26
+ } from './tokens.js';
27
+ export type {
28
+ TokenDiscoveryParams,
29
+ } from './tokens.js';
30
+
18
31
  // Payment exports
19
32
  export {
20
33
  createPayment,
@@ -31,6 +44,26 @@ export type {
31
44
  ListPaymentsFnParams
32
45
  } from './payments.js';
33
46
 
47
+ // Invoice exports
48
+ export {
49
+ createInvoice,
50
+ getInvoice,
51
+ listInvoices,
52
+ updateInvoice,
53
+ deleteInvoice,
54
+ sendInvoice,
55
+ getInvoicePaymentData,
56
+ InvoiceStatus,
57
+ } from './invoices.js';
58
+ export type {
59
+ Invoice,
60
+ InvoiceStatusType,
61
+ CreateInvoiceParams,
62
+ ListInvoicesParams,
63
+ UpdateInvoiceParams,
64
+ ListInvoicesResult,
65
+ } from './invoices.js';
66
+
34
67
  // Webhook exports
35
68
  export {
36
69
  verifyWebhookSignature,
package/src/index.js CHANGED
@@ -46,6 +46,11 @@ import {
46
46
  PaymentStatus,
47
47
  FiatCurrency,
48
48
  } from './payments.js';
49
+ import {
50
+ getTokens,
51
+ getSupportedCoins,
52
+ getSupportedCoins as getSupportedPaymentCoins,
53
+ } from './tokens.js';
49
54
  import {
50
55
  verifyWebhookSignature,
51
56
  generateWebhookSignature,
@@ -66,6 +71,18 @@ import {
66
71
  authenticateEscrow,
67
72
  } from './escrow.js';
68
73
 
74
+ // Invoice exports
75
+ import {
76
+ createInvoice,
77
+ getInvoice,
78
+ listInvoices,
79
+ updateInvoice,
80
+ deleteInvoice,
81
+ sendInvoice,
82
+ getInvoicePaymentData,
83
+ InvoiceStatus,
84
+ } from './invoices.js';
85
+
69
86
  // Wallet exports
70
87
  import {
71
88
  WalletClient,
@@ -156,6 +173,7 @@ import {
156
173
  verifyX402Payment,
157
174
  settleX402Payment,
158
175
  buildPaymentRequired,
176
+ expectedForProof,
159
177
  convertUsdToAssetAmount,
160
178
  PAYMENT_METHODS,
161
179
  USDC_CONTRACTS,
@@ -170,6 +188,9 @@ export {
170
188
  createPayment,
171
189
  getPayment,
172
190
  listPayments,
191
+ getTokens,
192
+ getSupportedCoins,
193
+ getSupportedPaymentCoins,
173
194
 
174
195
  // Escrow functions
175
196
  createEscrow,
@@ -182,6 +203,16 @@ export {
182
203
  waitForEscrow,
183
204
  authenticateEscrow,
184
205
 
206
+ // Invoice functions
207
+ createInvoice,
208
+ getInvoice,
209
+ listInvoices,
210
+ updateInvoice,
211
+ deleteInvoice,
212
+ sendInvoice,
213
+ getInvoicePaymentData,
214
+ InvoiceStatus,
215
+
185
216
  // Wallet
186
217
  WalletClient,
187
218
  WalletChain,
@@ -263,6 +294,7 @@ export {
263
294
  verifyX402Payment,
264
295
  settleX402Payment,
265
296
  buildPaymentRequired,
297
+ expectedForProof,
266
298
  convertUsdToAssetAmount,
267
299
  PAYMENT_METHODS,
268
300
  USDC_CONTRACTS,
@@ -0,0 +1,77 @@
1
+ import type { CoinPayClient } from './client.js';
2
+
3
+ export const InvoiceStatus: {
4
+ readonly DRAFT: 'draft';
5
+ readonly SENT: 'sent';
6
+ readonly PAID: 'paid';
7
+ readonly OVERDUE: 'overdue';
8
+ readonly CANCELLED: 'cancelled';
9
+ };
10
+
11
+ export type InvoiceStatusType = (typeof InvoiceStatus)[keyof typeof InvoiceStatus];
12
+
13
+ export interface Invoice {
14
+ id: string;
15
+ invoiceNumber?: string;
16
+ businessId?: string;
17
+ clientId?: string;
18
+ currency?: string;
19
+ amount?: number;
20
+ cryptoCurrency?: string;
21
+ cryptoAmount?: string | number;
22
+ status?: InvoiceStatusType;
23
+ dueDate?: string;
24
+ notes?: string;
25
+ walletId?: string;
26
+ merchantWalletAddress?: string;
27
+ paymentAddress?: string;
28
+ stripeCheckoutUrl?: string;
29
+ paidAt?: string;
30
+ sentAt?: string;
31
+ createdAt?: string;
32
+ updatedAt?: string;
33
+ }
34
+
35
+ export interface CreateInvoiceParams {
36
+ businessId?: string;
37
+ clientId?: string;
38
+ currency: string;
39
+ amount: number;
40
+ cryptoCurrency?: string;
41
+ dueDate?: string;
42
+ notes?: string;
43
+ walletId?: string;
44
+ merchantWalletAddress?: string;
45
+ }
46
+
47
+ export interface ListInvoicesParams {
48
+ businessId?: string;
49
+ status?: InvoiceStatusType;
50
+ clientId?: string;
51
+ dateFrom?: string;
52
+ dateTo?: string;
53
+ }
54
+
55
+ export interface UpdateInvoiceParams {
56
+ amount?: number;
57
+ currency?: string;
58
+ cryptoCurrency?: string;
59
+ dueDate?: string;
60
+ notes?: string;
61
+ clientId?: string;
62
+ walletId?: string;
63
+ merchantWalletAddress?: string;
64
+ }
65
+
66
+ export interface ListInvoicesResult {
67
+ invoices: Invoice[];
68
+ total?: number;
69
+ }
70
+
71
+ export function createInvoice(client: CoinPayClient, options: CreateInvoiceParams): Promise<Invoice>;
72
+ export function listInvoices(client: CoinPayClient, filters?: ListInvoicesParams): Promise<ListInvoicesResult>;
73
+ export function getInvoice(client: CoinPayClient, id: string): Promise<Invoice>;
74
+ export function updateInvoice(client: CoinPayClient, id: string, updates: UpdateInvoiceParams): Promise<Invoice>;
75
+ export function deleteInvoice(client: CoinPayClient, id: string): Promise<Record<string, unknown>>;
76
+ export function sendInvoice(client: CoinPayClient, id: string): Promise<Record<string, unknown>>;
77
+ export function getInvoicePaymentData(client: CoinPayClient, id: string): Promise<Record<string, unknown>>;