@cryptumpay/node-sdk 2.0.35

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CryptumPay
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,280 @@
1
+ # CryptumPay Node.js SDK
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@cryptumpay/node-sdk.svg)](https://www.npmjs.com/package/@cryptumpay/node-sdk)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@cryptumpay/node-sdk.svg)](https://www.npmjs.com/package/@cryptumpay/node-sdk)
5
+ [![license](https://img.shields.io/npm/l/@cryptumpay/node-sdk.svg)](https://github.com/cryptumpay/node-sdk/blob/main/LICENSE)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
7
+
8
+ Official Node.js SDK for CryptumPay API with built-in request signing and full TypeScript support.
9
+
10
+ ---
11
+
12
+ ## TL;DR
13
+
14
+ - SDK is **server-side only**
15
+ - You create an order on your backend
16
+ - CryptumPay returns **CryptumPay Order ID** (`response.data.id`)
17
+ - This ID is used by the widget or payment links
18
+ - Payment is considered successful **only when order status is `PAID`**
19
+
20
+ ---
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install @cryptumpay/node-sdk
26
+ ```
27
+
28
+ or
29
+
30
+ ```bash
31
+ yarn add @cryptumpay/node-sdk
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Requirements
37
+
38
+ - Node.js >= 18.0.0
39
+ - TypeScript >= 5.0 (optional but recommended)
40
+
41
+ ---
42
+
43
+ ## Quick Start
44
+
45
+ ```ts
46
+ import { CryptumPayClient, CryptumPaySigner } from '@cryptumpay/node-sdk';
47
+
48
+ const client = new CryptumPayClient(
49
+ new CryptumPaySigner(
50
+ process.env.CRYPTUMPAY_API_KEY!,
51
+ process.env.CRYPTUMPAY_API_SECRET!
52
+ )
53
+ );
54
+ ```
55
+
56
+ > ⚠️ Never expose API keys in frontend or public repositories.
57
+
58
+ ---
59
+
60
+ ## Order ID Terminology (IMPORTANT)
61
+
62
+ There are **two different order identifiers** involved in the integration.
63
+
64
+ ### Merchant Order ID
65
+
66
+ - Generated by **your system**
67
+ - Any format (e.g. `order-12345`)
68
+ - Optional
69
+ - Passed via `projectDataOrderId`
70
+ - Stored only as metadata
71
+
72
+ ### CryptumPay Order ID
73
+
74
+ - Generated by **CryptumPay**
75
+ - Returned by the SDK as `response.data.id`
76
+ - **Required** for widget and payment links
77
+ - Used to fetch order data and track payment status
78
+
79
+ > ⚠️ Modal-View Widget **accepts only CryptumPay Order ID**.
80
+
81
+ ---
82
+
83
+ ## Integration Methods
84
+
85
+ CryptumPay supports two integration approaches.
86
+
87
+ ### 🖼️ Modal-View Widget (Recommended)
88
+
89
+ Embedded modal payment interface displayed on top of your website.
90
+
91
+ **Typical use cases:**
92
+ - E-commerce checkout
93
+ - SaaS subscriptions
94
+ - On-site payments
95
+
96
+ **High-level flow:**
97
+ 1. User clicks CryptumPay button on frontend
98
+ 2. Widget triggers `onCreateOrder` callback
99
+ 3. Frontend calls your backend
100
+ 4. Backend creates an order via SDK
101
+ 5. Backend returns **CryptumPay Order ID**
102
+ 6. Widget displays payment modal
103
+ 7. User completes payment
104
+ 8. Order status becomes `PAID`
105
+ 9. Widget triggers `onFinishOrder`
106
+
107
+ ---
108
+
109
+ ### 🔗 Direct Payment Links
110
+
111
+ Hosted CryptumPay payment page accessed via URL.
112
+
113
+ **Typical use cases:**
114
+ - Email invoices
115
+ - Messenger payments (Telegram, WhatsApp)
116
+ - Manual payments
117
+ - Testing and development
118
+
119
+ ---
120
+
121
+ ## Creating an Order
122
+
123
+ ```ts
124
+ const response = await client.createOrder({
125
+ title: 'Order #12345',
126
+ description: 'Payment for order',
127
+ fiatAmount: '99.99',
128
+ fiatCurrency: 'usd',
129
+ projectDataOrderId: 'order-12345',
130
+ projectDataUserEmail: 'customer@example.com',
131
+ url: 'https://yoursite.com/orders/12345',
132
+ });
133
+ ```
134
+
135
+ ### Order creation parameters
136
+
137
+ | Field | Required | Description |
138
+ |------|---------|-------------|
139
+ | `title` | ✅ | Short order title |
140
+ | `description` | ✅ | Order description |
141
+ | `fiatAmount` | ✅ | Amount in fiat currency |
142
+ | `fiatCurrency` | ✅ | Fiat currency (`USD`, `EUR`, case-insensitive) |
143
+ | `projectDataOrderId` | ❌ | Merchant internal order ID |
144
+ | `projectDataUserEmail` | ❌ | Customer email |
145
+ | `projectDataUserId` | ❌ | Customer ID |
146
+ | `projectDataMeta` | ❌ | Custom metadata |
147
+ | `url` | ❌ | Redirect URL after payment |
148
+
149
+ > 💡 Only the first four fields affect the payment amount.
150
+
151
+ ---
152
+
153
+ ## Modal-View Widget – Backend Example
154
+
155
+ ```ts
156
+ fastify.post('/api/payments/create', async (request, reply) => {
157
+ const response = await cryptumPay.createOrder({
158
+ title: `Order #${request.body.orderId}`,
159
+ description: 'Payment',
160
+ fiatAmount: request.body.amount,
161
+ fiatCurrency: request.body.currency,
162
+ projectDataOrderId: request.body.orderId,
163
+ projectDataUserEmail: request.body.userEmail,
164
+ });
165
+
166
+ if (response.errorObject) {
167
+ return reply.status(response.errorObject.httpCode).send(response.errorObject);
168
+ }
169
+
170
+ return reply.send({
171
+ id: response.data.id, // CryptumPay Order ID
172
+ });
173
+ });
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Direct Payment Link Example
179
+
180
+ ```ts
181
+ const response = await client.createOrder({...});
182
+
183
+ const paymentUrl = `https://pay.cryptumpay.com/m/${response.data.id}`;
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Retrieving an Order
189
+
190
+ ```ts
191
+ const response = await client.getOrder(orderId);
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Order Lifecycle and Statuses
197
+
198
+ | Status | Code | Description |
199
+ |------|------|-------------|
200
+ | `IN_PROGRESS` | 0 | Order created, waiting for user action |
201
+ | `UNDER_REVIEW` | 1 | Payment under review |
202
+ | `CANCELED` | 2 | Order canceled or expired |
203
+ | `PAID` | 3 | Payment successfully completed |
204
+
205
+ - Order is considered paid **only when status is `PAID`**
206
+ - One order = one payment
207
+ - Payment addresses are single-use
208
+ - Orders expire at `expiresAt`
209
+
210
+ ---
211
+
212
+ ## Payment Confirmation
213
+
214
+ You may:
215
+ - Poll order status using `getOrder`
216
+ - Receive webhook notifications
217
+
218
+ Webhooks are optional and configured in the merchant console.
219
+
220
+ ---
221
+
222
+ ## Error Handling
223
+
224
+ - `httpCode` always matches HTTP status
225
+ - Partial success states do not exist
226
+ - Requests can be safely retried
227
+
228
+ ```ts
229
+ if (response.errorObject) {
230
+ console.error(response.errorObject);
231
+ }
232
+ ```
233
+
234
+ Full error list is available in the documentation.
235
+
236
+ ---
237
+
238
+ ## Environment Variables
239
+
240
+ ```env
241
+ CRYPTUMPAY_API_KEY=your_api_key
242
+ CRYPTUMPAY_API_SECRET=your_api_secret
243
+ ```
244
+
245
+ ---
246
+
247
+ ## API Methods
248
+
249
+ | Method | Description |
250
+ |--------|-------------|
251
+ | `createOrder(params)` | Create a new order |
252
+ | `getOrder(orderId)` | Retrieve order details |
253
+
254
+ ---
255
+
256
+ ## Security Notice
257
+
258
+ - SDK is **server-side only**
259
+ - Never expose API keys
260
+ - Validate all incoming data
261
+
262
+ ---
263
+
264
+ ## Documentation
265
+
266
+ - API Docs: https://docs.cryptumpay.com
267
+ - Merchant Console: https://console.cryptumpay.com
268
+
269
+ ---
270
+
271
+ ## Disclaimer
272
+
273
+ This SDK is provided "as is". CryptumPay is not responsible for losses caused by improper usage or infrastructure misconfiguration.
274
+
275
+ ---
276
+
277
+ ## License
278
+
279
+ MIT © CryptumPay
280
+
@@ -0,0 +1,9 @@
1
+ import { ISigner, TResponse, TCreateOrderRequest, TCreateOrderResponse, TGetOrderResponse } from './types';
2
+ export declare class CryptumPayClient {
3
+ #private;
4
+ constructor(signer: ISigner, baseUrl?: string);
5
+ private makeRequest;
6
+ createOrder(params: TCreateOrderRequest): Promise<TResponse<TCreateOrderResponse>>;
7
+ getOrder(orderId: string): Promise<TResponse<TGetOrderResponse>>;
8
+ }
9
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,OAAO,EAGP,SAAS,EAET,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB,qBAAa,gBAAgB;;gBAKd,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM;YAiBhC,WAAW;IAyDZ,WAAW,CAAE,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;IAInF,QAAQ,CAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;CAG/E"}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CryptumPayClient = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const https_1 = require("https");
9
+ class CryptumPayClient {
10
+ #baseUrl;
11
+ #axios;
12
+ #signer;
13
+ constructor(signer, baseUrl) {
14
+ if (!signer || typeof signer.signRequest !== 'function') {
15
+ throw new Error('CryptumPayClient requires a valid signer');
16
+ }
17
+ baseUrl = baseUrl || 'https://project-api.cryptumpay.com';
18
+ this.#baseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
19
+ this.#signer = signer;
20
+ this.#axios = axios_1.default.create({
21
+ httpsAgent: new https_1.Agent({
22
+ rejectUnauthorized: false,
23
+ }),
24
+ });
25
+ }
26
+ async makeRequest(path, method, params) {
27
+ try {
28
+ const { headers, body } = this.#signer.signRequest(path, method, params);
29
+ const response = await this.#axios({
30
+ url: `${this.#baseUrl}${path}`,
31
+ method,
32
+ headers,
33
+ data: body,
34
+ });
35
+ response.data = response.data || {};
36
+ const { data, errorObject } = response.data;
37
+ if (errorObject) {
38
+ return {
39
+ data: null,
40
+ errorObject,
41
+ };
42
+ }
43
+ if (typeof data === 'object') {
44
+ return {
45
+ data,
46
+ errorObject: null,
47
+ };
48
+ }
49
+ throw new Error('Invalid response format from API');
50
+ }
51
+ catch (err) {
52
+ if (axios_1.default.isAxiosError(err)) {
53
+ const errorResponse = err.response?.data || {};
54
+ const errorObject = errorResponse.errorObject || {};
55
+ return {
56
+ data: null,
57
+ errorObject: {
58
+ httpCode: err.response?.status || 400,
59
+ appCode: errorObject.appCode || -1,
60
+ data: errorObject.data,
61
+ message: errorObject.message,
62
+ },
63
+ };
64
+ }
65
+ else {
66
+ return {
67
+ data: null,
68
+ errorObject: {
69
+ httpCode: 400,
70
+ appCode: -1,
71
+ message: err instanceof Error ? err.message : 'An unexpected error occurred',
72
+ },
73
+ };
74
+ }
75
+ }
76
+ }
77
+ async createOrder(params) {
78
+ return await this.makeRequest('/v1/orders', 'POST', params);
79
+ }
80
+ async getOrder(orderId) {
81
+ return await this.makeRequest(`/v1/orders/${orderId}`, 'GET');
82
+ }
83
+ }
84
+ exports.CryptumPayClient = CryptumPayClient;
85
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from './client';
2
+ export * from './signer';
3
+ export * from './types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC"}
package/build/index.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./client"), exports);
18
+ __exportStar(require("./signer"), exports);
19
+ __exportStar(require("./types"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,2CAAyB;AACzB,0CAAwB"}
@@ -0,0 +1,9 @@
1
+ import { ISigner, TContent, TMethod, TSignResult } from './types';
2
+ export declare class CryptumPaySigner implements ISigner {
3
+ #private;
4
+ constructor(key: string | undefined, secret: string | undefined);
5
+ formatBody(content: TContent): string;
6
+ signRequest(path: string, method: TMethod, content: TContent): TSignResult;
7
+ verifyCallback(signature: string, content: TContent): boolean;
8
+ }
9
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAY,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE5E,qBAAa,gBAAiB,YAAW,OAAO;;gBAI1B,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS;IAahE,UAAU,CAAE,OAAO,EAAE,QAAQ,GAAG,MAAM;IAItC,WAAW,CAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,GAAG,WAAW;IAiC3E,cAAc,CAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO;CAQtE"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CryptumPaySigner = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ class CryptumPaySigner {
9
+ #key;
10
+ #secret;
11
+ constructor(key, secret) {
12
+ if (!key) {
13
+ throw new Error('SignatureService requires a key');
14
+ }
15
+ if (!secret) {
16
+ throw new Error('SignatureService requires a secret');
17
+ }
18
+ this.#key = key;
19
+ this.#secret = secret;
20
+ }
21
+ formatBody(content) {
22
+ return typeof content === 'string' ? content : JSON.stringify(content || {});
23
+ }
24
+ signRequest(path, method, content) {
25
+ const body = this.formatBody(content);
26
+ const timestamp = Date.now().toString();
27
+ const bodyHash = crypto_1.default.createHash('sha256').update(body).digest('hex');
28
+ if (typeof path === 'string' && path.length > 0) {
29
+ if (!path.startsWith('/')) {
30
+ path = '/' + path;
31
+ }
32
+ if (path.endsWith('/')) {
33
+ path = path.slice(0, -1);
34
+ }
35
+ }
36
+ else {
37
+ path = '/';
38
+ }
39
+ const prehash = [bodyHash, method?.toUpperCase(), path, timestamp, this.#key].join('|');
40
+ const signature = crypto_1.default.createHmac('sha256', this.#secret).update(prehash).digest('hex');
41
+ const headers = {
42
+ 'Content-Type': 'application/json',
43
+ 'x-api-key': this.#key,
44
+ 'x-signature': signature,
45
+ 'x-timestamp': timestamp,
46
+ };
47
+ return {
48
+ headers,
49
+ body,
50
+ };
51
+ }
52
+ verifyCallback(signature, content) {
53
+ const rawBody = typeof content === 'string' ? content : JSON.stringify(content ?? {});
54
+ const bodyHash = crypto_1.default.createHash('sha256').update(rawBody).digest('hex');
55
+ const prehash = [bodyHash, this.#key].join('|');
56
+ const expectedSignature = crypto_1.default.createHmac('sha256', this.#secret).update(prehash).digest('hex');
57
+ return signature === expectedSignature;
58
+ }
59
+ }
60
+ exports.CryptumPaySigner = CryptumPaySigner;
61
+ //# sourceMappingURL=signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.js","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ export type THeaders = {
2
+ 'Content-Type': string;
3
+ 'x-api-key': string;
4
+ 'x-signature': string;
5
+ 'x-timestamp': string;
6
+ };
7
+ export type TSignResult = {
8
+ headers: THeaders;
9
+ body: string;
10
+ };
11
+ export type TContent = Record<string, any> | string | undefined | null;
12
+ export type TMethod = 'POST' | 'PUT' | 'GET' | 'DELETE' | 'PATCH';
13
+ export interface ISigner {
14
+ signRequest(path: string, method: TMethod, content: TContent): {
15
+ headers: THeaders;
16
+ body: string;
17
+ };
18
+ }
19
+ export type TCreateOrderRequest = {
20
+ title: string;
21
+ description: string;
22
+ fiatAmount: string;
23
+ fiatCurrency: string;
24
+ projectDataMeta?: string;
25
+ projectDataOrderId?: string;
26
+ projectDataUserEmail?: string;
27
+ projectDataUserId?: string;
28
+ url?: string;
29
+ };
30
+ export type TSuccessResponse<T> = {
31
+ data: T;
32
+ errorObject: null;
33
+ };
34
+ export type TErrorResponse = {
35
+ data: null;
36
+ errorObject: {
37
+ httpCode: number;
38
+ appCode: number;
39
+ data?: any;
40
+ message?: string;
41
+ };
42
+ };
43
+ export type TResponse<T> = TSuccessResponse<T> | TErrorResponse;
44
+ export type TCreateOrderResponse = {
45
+ id: string;
46
+ project: {
47
+ id: string;
48
+ feePercent: number;
49
+ logoUrl: string;
50
+ title: string;
51
+ url: string;
52
+ };
53
+ expiresAt: number;
54
+ customerOrderRequest: {
55
+ fiatTicker: string;
56
+ fiatAmount: string;
57
+ title: string;
58
+ description: string;
59
+ url: string;
60
+ projectData: Record<string, any>;
61
+ };
62
+ };
63
+ export type TGetOrderResponse = {
64
+ id: string;
65
+ project: {
66
+ id: string;
67
+ feePercent: number;
68
+ logoUrl: string;
69
+ title: string;
70
+ url: string;
71
+ };
72
+ expiresAt: number;
73
+ customerOrderRequest: {
74
+ fiatTicker: string;
75
+ fiatAmount: string;
76
+ title: string;
77
+ description: string;
78
+ url: string;
79
+ projectData: Record<string, any>;
80
+ };
81
+ hasCustomerOrder: boolean;
82
+ financeSummary?: {
83
+ status: number;
84
+ accrued: boolean;
85
+ income?: {
86
+ amount: string;
87
+ currency: string;
88
+ } | undefined;
89
+ } | undefined;
90
+ };
91
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/build/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@cryptumpay/node-sdk",
3
+ "version": "2.0.35",
4
+ "description": "Official Node.js SDK for CryptumPay API with built-in request signing and TypeScript support",
5
+ "main": "build/index.js",
6
+ "types": "build/index.d.ts",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/cryptumpay/node-sdk.git"
10
+ },
11
+ "homepage": "https://github.com/cryptumpay/node-sdk#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/cryptumpay/node-sdk/issues"
14
+ },
15
+ "scripts": {
16
+ "build": "rm -rf build && ./node_modules/.bin/tsc",
17
+ "submit": "npm run lint && npm run build && npm run test && npm publish --access public",
18
+ "git-tag": "VERSION=`cat package.json | jq .version -r` && git tag $VERSION",
19
+ "release": "npm run git-tag && git push origin master && npm run submit",
20
+ "test": "./node_modules/.bin/jest . --forceExit",
21
+ "test:coverage": "npm run test --coverage",
22
+ "lint": "./node_modules/.bin/eslint src/**/*.ts",
23
+ "prepare": "husky"
24
+ },
25
+ "keywords": [
26
+ "cryptumpay"
27
+ ],
28
+ "author": "@cryptumpay",
29
+ "license": "MIT",
30
+ "engines": {
31
+ "node": ">=18.0.0"
32
+ },
33
+ "dependencies": {
34
+ "axios": "^1.13.2"
35
+ },
36
+ "devDependencies": {
37
+ "@stylistic/eslint-plugin": "2.9.0",
38
+ "@tsconfig/node18": "18.2.4",
39
+ "@types/jest": "^29.5.12",
40
+ "@types/node": "22.7.6",
41
+ "@typescript-eslint/parser": "8.10.0",
42
+ "eslint": "9.13.0",
43
+ "eslint-plugin-import": "2.31.0",
44
+ "husky": "9.1.6",
45
+ "jest": "29.7.0",
46
+ "ts-jest": "29.1.2",
47
+ "ts-node": "10.9.2",
48
+ "typescript": "5.6.3"
49
+ },
50
+ "files": [
51
+ "build"
52
+ ],
53
+ "publishConfig": {
54
+ "access": "public"
55
+ }
56
+ }