@payzcore/node 1.0.1

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 ADDED
@@ -0,0 +1,188 @@
1
+ # @payzcore/node
2
+
3
+ Official Node.js SDK for the [PayzCore](https://payzcore.com) blockchain monitoring API.
4
+
5
+ Monitor incoming stablecoin transfers (USDT, USDC) across multiple chains (TRC20, BEP20, ERC20, Polygon, Arbitrum) with typed methods and automatic webhook verification.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @payzcore/node
11
+ ```
12
+
13
+ Requires Node.js 18+. Zero runtime dependencies.
14
+
15
+ ## Supported Chains & Tokens
16
+
17
+ | Chain | Network | Tokens |
18
+ |-------|---------|--------|
19
+ | `TRC20` | Tron | USDT, USDC |
20
+ | `BEP20` | BNB Smart Chain | USDT, USDC |
21
+ | `ERC20` | Ethereum | USDT, USDC |
22
+ | `POLYGON` | Polygon | USDT, USDC |
23
+ | `ARBITRUM` | Arbitrum One | USDT, USDC |
24
+
25
+ Token defaults to `'USDT'` if not specified, so existing code works without changes.
26
+
27
+ ## Quick Start
28
+
29
+ ```typescript
30
+ import PayzCore from '@payzcore/node'
31
+
32
+ const payz = new PayzCore('pk_live_xxx')
33
+
34
+ // Create a payment monitoring request
35
+ const { payment } = await payz.payments.create({
36
+ amount: 50,
37
+ chain: 'TRC20',
38
+ externalRef: 'user-123',
39
+ })
40
+
41
+ console.log(payment.address) // Blockchain address to monitor
42
+ console.log(payment.amount) // Amount with random cents (e.g. "50.07")
43
+ console.log(payment.token) // Token name (e.g. "USDT")
44
+ console.log(payment.qrCode) // QR code data URL
45
+ ```
46
+
47
+ ## Configuration
48
+
49
+ ```typescript
50
+ const payz = new PayzCore('pk_live_xxx', {
51
+ baseUrl: 'https://api.payzcore.com', // default
52
+ timeout: 30000, // default 30s
53
+ maxRetries: 2, // default 2 (retries on 5xx/network errors)
54
+ })
55
+ ```
56
+
57
+ ## Payments
58
+
59
+ ### Create
60
+
61
+ ```typescript
62
+ const { payment } = await payz.payments.create({
63
+ amount: 50,
64
+ chain: 'TRC20', // 'TRC20' | 'BEP20' | 'ERC20' | 'POLYGON' | 'ARBITRUM'
65
+ token: 'USDT', // 'USDT' | 'USDC' (optional, defaults to 'USDT')
66
+ externalRef: 'user-123', // your reference
67
+ externalOrderId: 'order-456', // optional
68
+ expiresIn: 3600, // optional, seconds (300–86400)
69
+ metadata: { type: 'topup' }, // optional
70
+ })
71
+
72
+ // payment.id, payment.address, payment.amount, payment.token, payment.expiresAt, payment.qrCode
73
+ ```
74
+
75
+ #### USDC on Polygon Example
76
+
77
+ ```typescript
78
+ const { payment } = await payz.payments.create({
79
+ amount: 100,
80
+ chain: 'POLYGON',
81
+ token: 'USDC',
82
+ externalRef: 'user-456',
83
+ })
84
+ ```
85
+
86
+ ### List
87
+
88
+ ```typescript
89
+ const { payments } = await payz.payments.list({
90
+ status: 'paid', // optional filter
91
+ limit: 20, // optional, max 100
92
+ offset: 0, // optional
93
+ })
94
+ ```
95
+
96
+ ### Get (Real-Time)
97
+
98
+ ```typescript
99
+ const { payment } = await payz.payments.get('payment-uuid')
100
+
101
+ // Triggers real-time blockchain check for pending payments
102
+ // payment.transactions[].txHash, payment.transactions[].amount, etc.
103
+ ```
104
+
105
+ ## Projects (Admin)
106
+
107
+ Requires a master key (`mk_xxx`):
108
+
109
+ ```typescript
110
+ const admin = new PayzCore('mk_xxx', { masterKey: true })
111
+
112
+ const { project } = await admin.projects.create({
113
+ name: 'My Store',
114
+ slug: 'my-store',
115
+ webhookUrl: 'https://mysite.com/webhooks',
116
+ })
117
+
118
+ const { projects } = await admin.projects.list()
119
+ ```
120
+
121
+ ## Webhook Verification
122
+
123
+ ```typescript
124
+ import { verifyWebhookSignature, constructEvent } from '@payzcore/node'
125
+
126
+ // In your webhook handler (Express, Next.js, etc.)
127
+ export async function POST(req: Request) {
128
+ const body = await req.text()
129
+ const signature = req.headers.get('x-payzcore-signature')!
130
+
131
+ // Option 1: Just verify
132
+ const isValid = verifyWebhookSignature(body, signature, 'whsec_xxx')
133
+
134
+ // Option 2: Verify + parse (throws WebhookSignatureError if invalid)
135
+ const event = constructEvent(body, signature, 'whsec_xxx')
136
+
137
+ if (event.event === 'payment.completed') {
138
+ console.log(event.paymentId, event.paidAmount)
139
+ }
140
+
141
+ return new Response('ok')
142
+ }
143
+ ```
144
+
145
+ ### Webhook Events
146
+
147
+ | Event | Description |
148
+ |-------|-------------|
149
+ | `payment.completed` | Payment fully received |
150
+ | `payment.overpaid` | Received more than expected |
151
+ | `payment.partial` | Partial payment received |
152
+ | `payment.expired` | Payment window expired |
153
+
154
+ ## Error Handling
155
+
156
+ All errors extend `PayzCoreError` with `status`, `code`, and optional `details`:
157
+
158
+ ```typescript
159
+ import { PayzCoreError, RateLimitError, ValidationError } from '@payzcore/node'
160
+
161
+ try {
162
+ await payz.payments.create({ ... })
163
+ } catch (err) {
164
+ if (err instanceof RateLimitError) {
165
+ console.log(err.retryAfter) // Unix timestamp
166
+ console.log(err.isDaily) // true if daily plan limit
167
+ } else if (err instanceof ValidationError) {
168
+ console.log(err.details) // field-level errors
169
+ } else if (err instanceof PayzCoreError) {
170
+ console.log(err.status, err.message)
171
+ }
172
+ }
173
+ ```
174
+
175
+ ### Error Classes
176
+
177
+ | Class | Status | When |
178
+ |-------|--------|------|
179
+ | `AuthenticationError` | 401 | Invalid/missing API key |
180
+ | `ForbiddenError` | 403 | Project deactivated |
181
+ | `NotFoundError` | 404 | Payment/resource not found |
182
+ | `ValidationError` | 400 | Invalid request body |
183
+ | `RateLimitError` | 429 | Rate limit or daily plan limit exceeded |
184
+ | `WebhookSignatureError` | — | Invalid webhook signature |
185
+
186
+ ## License
187
+
188
+ MIT
@@ -0,0 +1,231 @@
1
+ type Chain = 'TRC20' | 'BEP20' | 'ERC20' | 'POLYGON' | 'ARBITRUM';
2
+ type Token = 'USDT' | 'USDC';
3
+ type PaymentStatus = 'pending' | 'confirming' | 'partial' | 'paid' | 'overpaid' | 'expired' | 'cancelled';
4
+ type WebhookEventType = 'payment.completed' | 'payment.overpaid' | 'payment.partial' | 'payment.expired';
5
+ interface PayzCoreOptions {
6
+ /** API base URL. Default: https://api.payzcore.com */
7
+ baseUrl?: string;
8
+ /** Request timeout in ms. Default: 30000 */
9
+ timeout?: number;
10
+ /** Max retries on 5xx/network errors. Default: 2 */
11
+ maxRetries?: number;
12
+ /** Use master key auth (x-master-key header). Default: false */
13
+ masterKey?: boolean;
14
+ }
15
+ interface CreatePaymentParams {
16
+ amount: number;
17
+ chain: Chain;
18
+ /** Token to monitor. Default: 'USDT' */
19
+ token?: Token;
20
+ externalRef: string;
21
+ externalOrderId?: string;
22
+ /** Expiry in seconds (300–86400). Default: 3600 */
23
+ expiresIn?: number;
24
+ metadata?: Record<string, unknown>;
25
+ }
26
+ interface Payment {
27
+ id: string;
28
+ address: string;
29
+ amount: string;
30
+ chain: Chain;
31
+ token: string;
32
+ status: PaymentStatus;
33
+ expiresAt: string;
34
+ externalOrderId?: string;
35
+ qrCode?: string;
36
+ }
37
+ interface CreatePaymentResponse {
38
+ success: true;
39
+ existing: boolean;
40
+ payment: Payment;
41
+ }
42
+ interface PaymentListItem {
43
+ id: string;
44
+ externalRef: string;
45
+ externalOrderId?: string;
46
+ chain: Chain;
47
+ token: string;
48
+ address: string;
49
+ expectedAmount: string;
50
+ paidAmount: string;
51
+ status: PaymentStatus;
52
+ txHash: string | null;
53
+ expiresAt: string;
54
+ paidAt: string | null;
55
+ createdAt: string;
56
+ }
57
+ interface ListPaymentsParams {
58
+ status?: PaymentStatus;
59
+ limit?: number;
60
+ offset?: number;
61
+ }
62
+ interface ListPaymentsResponse {
63
+ success: true;
64
+ payments: PaymentListItem[];
65
+ }
66
+ interface Transaction {
67
+ txHash: string;
68
+ amount: string;
69
+ from: string;
70
+ confirmed: boolean;
71
+ }
72
+ interface PaymentDetail {
73
+ id: string;
74
+ status: PaymentStatus;
75
+ expectedAmount: string;
76
+ paidAmount: string;
77
+ address: string;
78
+ chain: Chain;
79
+ token: string;
80
+ txHash: string | null;
81
+ expiresAt: string;
82
+ transactions: Transaction[];
83
+ }
84
+ interface GetPaymentResponse {
85
+ success: true;
86
+ payment: PaymentDetail;
87
+ }
88
+ interface CreateProjectParams {
89
+ name: string;
90
+ slug: string;
91
+ webhookUrl?: string;
92
+ metadata?: Record<string, unknown>;
93
+ }
94
+ interface Project {
95
+ id: string;
96
+ name: string;
97
+ slug: string;
98
+ apiKey: string;
99
+ webhookSecret: string;
100
+ webhookUrl: string | null;
101
+ createdAt: string;
102
+ }
103
+ interface CreateProjectResponse {
104
+ success: true;
105
+ project: Project;
106
+ }
107
+ interface ProjectListItem {
108
+ id: string;
109
+ name: string;
110
+ slug: string;
111
+ apiKey: string;
112
+ webhookUrl: string | null;
113
+ isActive: boolean;
114
+ createdAt: string;
115
+ }
116
+ interface ListProjectsResponse {
117
+ success: true;
118
+ projects: ProjectListItem[];
119
+ }
120
+ interface WebhookPayload {
121
+ event: WebhookEventType;
122
+ paymentId: string;
123
+ externalRef: string;
124
+ externalOrderId?: string;
125
+ chain: Chain;
126
+ token: string;
127
+ address: string;
128
+ expectedAmount: string;
129
+ paidAmount: string;
130
+ txHash: string | null;
131
+ status: PaymentStatus;
132
+ paidAt: string | null;
133
+ metadata: Record<string, unknown>;
134
+ timestamp: string;
135
+ }
136
+ interface ApiErrorBody {
137
+ error: string;
138
+ details?: Array<{
139
+ code: string;
140
+ path?: string[];
141
+ message: string;
142
+ }>;
143
+ limit?: number;
144
+ plan?: string;
145
+ }
146
+
147
+ declare class HttpClient {
148
+ private readonly apiKey;
149
+ private readonly baseUrl;
150
+ private readonly timeout;
151
+ private readonly maxRetries;
152
+ private readonly useMasterKey;
153
+ constructor(apiKey: string, options?: PayzCoreOptions);
154
+ request<T>(method: string, path: string, body?: unknown): Promise<T>;
155
+ get<T>(path: string): Promise<T>;
156
+ post<T>(path: string, body: unknown): Promise<T>;
157
+ }
158
+
159
+ declare class Payments {
160
+ private readonly client;
161
+ constructor(client: HttpClient);
162
+ create(params: CreatePaymentParams): Promise<CreatePaymentResponse>;
163
+ list(params?: ListPaymentsParams): Promise<ListPaymentsResponse>;
164
+ get(id: string): Promise<GetPaymentResponse>;
165
+ }
166
+
167
+ declare class Projects {
168
+ private readonly client;
169
+ constructor(client: HttpClient);
170
+ create(params: CreateProjectParams): Promise<CreateProjectResponse>;
171
+ list(): Promise<ListProjectsResponse>;
172
+ }
173
+
174
+ /**
175
+ * Verify a webhook signature from PayzCore.
176
+ *
177
+ * @param body - Raw request body string
178
+ * @param signature - Value of X-PayzCore-Signature header
179
+ * @param secret - Webhook secret from project creation (whsec_xxx)
180
+ * @returns true if signature is valid
181
+ */
182
+ declare function verifyWebhookSignature(body: string, signature: string, secret: string): boolean;
183
+ /**
184
+ * Verify signature and parse the webhook payload.
185
+ * Throws WebhookSignatureError if signature is invalid.
186
+ *
187
+ * @param body - Raw request body string
188
+ * @param signature - Value of X-PayzCore-Signature header
189
+ * @param secret - Webhook secret from project creation (whsec_xxx)
190
+ * @returns Parsed and typed webhook payload
191
+ */
192
+ declare function constructEvent(body: string, signature: string, secret: string): WebhookPayload;
193
+
194
+ declare class PayzCoreError extends Error {
195
+ readonly status: number;
196
+ readonly code: string;
197
+ readonly details?: Array<{
198
+ code: string;
199
+ path?: string[];
200
+ message: string;
201
+ }>;
202
+ constructor(message: string, status: number, code: string, details?: ApiErrorBody['details']);
203
+ }
204
+ declare class AuthenticationError extends PayzCoreError {
205
+ constructor(message?: string);
206
+ }
207
+ declare class ForbiddenError extends PayzCoreError {
208
+ constructor(message?: string);
209
+ }
210
+ declare class NotFoundError extends PayzCoreError {
211
+ constructor(message?: string);
212
+ }
213
+ declare class ValidationError extends PayzCoreError {
214
+ constructor(message: string, details?: ApiErrorBody['details']);
215
+ }
216
+ declare class RateLimitError extends PayzCoreError {
217
+ readonly retryAfter: number | null;
218
+ readonly isDaily: boolean;
219
+ constructor(message: string, retryAfter?: number | null, isDaily?: boolean);
220
+ }
221
+ declare class WebhookSignatureError extends Error {
222
+ constructor(message?: string);
223
+ }
224
+
225
+ declare class PayzCore {
226
+ readonly payments: Payments;
227
+ readonly projects: Projects;
228
+ constructor(apiKey: string, options?: PayzCoreOptions);
229
+ }
230
+
231
+ export { AuthenticationError, type Chain, type CreatePaymentParams, type CreatePaymentResponse, type CreateProjectParams, type CreateProjectResponse, ForbiddenError, type GetPaymentResponse, type ListPaymentsParams, type ListPaymentsResponse, type ListProjectsResponse, NotFoundError, type Payment, type PaymentDetail, type PaymentListItem, type PaymentStatus, PayzCore, PayzCoreError, type PayzCoreOptions, type Project, type ProjectListItem, RateLimitError, type Token, type Transaction, ValidationError, type WebhookEventType, type WebhookPayload, WebhookSignatureError, constructEvent, PayzCore as default, verifyWebhookSignature };
@@ -0,0 +1,231 @@
1
+ type Chain = 'TRC20' | 'BEP20' | 'ERC20' | 'POLYGON' | 'ARBITRUM';
2
+ type Token = 'USDT' | 'USDC';
3
+ type PaymentStatus = 'pending' | 'confirming' | 'partial' | 'paid' | 'overpaid' | 'expired' | 'cancelled';
4
+ type WebhookEventType = 'payment.completed' | 'payment.overpaid' | 'payment.partial' | 'payment.expired';
5
+ interface PayzCoreOptions {
6
+ /** API base URL. Default: https://api.payzcore.com */
7
+ baseUrl?: string;
8
+ /** Request timeout in ms. Default: 30000 */
9
+ timeout?: number;
10
+ /** Max retries on 5xx/network errors. Default: 2 */
11
+ maxRetries?: number;
12
+ /** Use master key auth (x-master-key header). Default: false */
13
+ masterKey?: boolean;
14
+ }
15
+ interface CreatePaymentParams {
16
+ amount: number;
17
+ chain: Chain;
18
+ /** Token to monitor. Default: 'USDT' */
19
+ token?: Token;
20
+ externalRef: string;
21
+ externalOrderId?: string;
22
+ /** Expiry in seconds (300–86400). Default: 3600 */
23
+ expiresIn?: number;
24
+ metadata?: Record<string, unknown>;
25
+ }
26
+ interface Payment {
27
+ id: string;
28
+ address: string;
29
+ amount: string;
30
+ chain: Chain;
31
+ token: string;
32
+ status: PaymentStatus;
33
+ expiresAt: string;
34
+ externalOrderId?: string;
35
+ qrCode?: string;
36
+ }
37
+ interface CreatePaymentResponse {
38
+ success: true;
39
+ existing: boolean;
40
+ payment: Payment;
41
+ }
42
+ interface PaymentListItem {
43
+ id: string;
44
+ externalRef: string;
45
+ externalOrderId?: string;
46
+ chain: Chain;
47
+ token: string;
48
+ address: string;
49
+ expectedAmount: string;
50
+ paidAmount: string;
51
+ status: PaymentStatus;
52
+ txHash: string | null;
53
+ expiresAt: string;
54
+ paidAt: string | null;
55
+ createdAt: string;
56
+ }
57
+ interface ListPaymentsParams {
58
+ status?: PaymentStatus;
59
+ limit?: number;
60
+ offset?: number;
61
+ }
62
+ interface ListPaymentsResponse {
63
+ success: true;
64
+ payments: PaymentListItem[];
65
+ }
66
+ interface Transaction {
67
+ txHash: string;
68
+ amount: string;
69
+ from: string;
70
+ confirmed: boolean;
71
+ }
72
+ interface PaymentDetail {
73
+ id: string;
74
+ status: PaymentStatus;
75
+ expectedAmount: string;
76
+ paidAmount: string;
77
+ address: string;
78
+ chain: Chain;
79
+ token: string;
80
+ txHash: string | null;
81
+ expiresAt: string;
82
+ transactions: Transaction[];
83
+ }
84
+ interface GetPaymentResponse {
85
+ success: true;
86
+ payment: PaymentDetail;
87
+ }
88
+ interface CreateProjectParams {
89
+ name: string;
90
+ slug: string;
91
+ webhookUrl?: string;
92
+ metadata?: Record<string, unknown>;
93
+ }
94
+ interface Project {
95
+ id: string;
96
+ name: string;
97
+ slug: string;
98
+ apiKey: string;
99
+ webhookSecret: string;
100
+ webhookUrl: string | null;
101
+ createdAt: string;
102
+ }
103
+ interface CreateProjectResponse {
104
+ success: true;
105
+ project: Project;
106
+ }
107
+ interface ProjectListItem {
108
+ id: string;
109
+ name: string;
110
+ slug: string;
111
+ apiKey: string;
112
+ webhookUrl: string | null;
113
+ isActive: boolean;
114
+ createdAt: string;
115
+ }
116
+ interface ListProjectsResponse {
117
+ success: true;
118
+ projects: ProjectListItem[];
119
+ }
120
+ interface WebhookPayload {
121
+ event: WebhookEventType;
122
+ paymentId: string;
123
+ externalRef: string;
124
+ externalOrderId?: string;
125
+ chain: Chain;
126
+ token: string;
127
+ address: string;
128
+ expectedAmount: string;
129
+ paidAmount: string;
130
+ txHash: string | null;
131
+ status: PaymentStatus;
132
+ paidAt: string | null;
133
+ metadata: Record<string, unknown>;
134
+ timestamp: string;
135
+ }
136
+ interface ApiErrorBody {
137
+ error: string;
138
+ details?: Array<{
139
+ code: string;
140
+ path?: string[];
141
+ message: string;
142
+ }>;
143
+ limit?: number;
144
+ plan?: string;
145
+ }
146
+
147
+ declare class HttpClient {
148
+ private readonly apiKey;
149
+ private readonly baseUrl;
150
+ private readonly timeout;
151
+ private readonly maxRetries;
152
+ private readonly useMasterKey;
153
+ constructor(apiKey: string, options?: PayzCoreOptions);
154
+ request<T>(method: string, path: string, body?: unknown): Promise<T>;
155
+ get<T>(path: string): Promise<T>;
156
+ post<T>(path: string, body: unknown): Promise<T>;
157
+ }
158
+
159
+ declare class Payments {
160
+ private readonly client;
161
+ constructor(client: HttpClient);
162
+ create(params: CreatePaymentParams): Promise<CreatePaymentResponse>;
163
+ list(params?: ListPaymentsParams): Promise<ListPaymentsResponse>;
164
+ get(id: string): Promise<GetPaymentResponse>;
165
+ }
166
+
167
+ declare class Projects {
168
+ private readonly client;
169
+ constructor(client: HttpClient);
170
+ create(params: CreateProjectParams): Promise<CreateProjectResponse>;
171
+ list(): Promise<ListProjectsResponse>;
172
+ }
173
+
174
+ /**
175
+ * Verify a webhook signature from PayzCore.
176
+ *
177
+ * @param body - Raw request body string
178
+ * @param signature - Value of X-PayzCore-Signature header
179
+ * @param secret - Webhook secret from project creation (whsec_xxx)
180
+ * @returns true if signature is valid
181
+ */
182
+ declare function verifyWebhookSignature(body: string, signature: string, secret: string): boolean;
183
+ /**
184
+ * Verify signature and parse the webhook payload.
185
+ * Throws WebhookSignatureError if signature is invalid.
186
+ *
187
+ * @param body - Raw request body string
188
+ * @param signature - Value of X-PayzCore-Signature header
189
+ * @param secret - Webhook secret from project creation (whsec_xxx)
190
+ * @returns Parsed and typed webhook payload
191
+ */
192
+ declare function constructEvent(body: string, signature: string, secret: string): WebhookPayload;
193
+
194
+ declare class PayzCoreError extends Error {
195
+ readonly status: number;
196
+ readonly code: string;
197
+ readonly details?: Array<{
198
+ code: string;
199
+ path?: string[];
200
+ message: string;
201
+ }>;
202
+ constructor(message: string, status: number, code: string, details?: ApiErrorBody['details']);
203
+ }
204
+ declare class AuthenticationError extends PayzCoreError {
205
+ constructor(message?: string);
206
+ }
207
+ declare class ForbiddenError extends PayzCoreError {
208
+ constructor(message?: string);
209
+ }
210
+ declare class NotFoundError extends PayzCoreError {
211
+ constructor(message?: string);
212
+ }
213
+ declare class ValidationError extends PayzCoreError {
214
+ constructor(message: string, details?: ApiErrorBody['details']);
215
+ }
216
+ declare class RateLimitError extends PayzCoreError {
217
+ readonly retryAfter: number | null;
218
+ readonly isDaily: boolean;
219
+ constructor(message: string, retryAfter?: number | null, isDaily?: boolean);
220
+ }
221
+ declare class WebhookSignatureError extends Error {
222
+ constructor(message?: string);
223
+ }
224
+
225
+ declare class PayzCore {
226
+ readonly payments: Payments;
227
+ readonly projects: Projects;
228
+ constructor(apiKey: string, options?: PayzCoreOptions);
229
+ }
230
+
231
+ export { AuthenticationError, type Chain, type CreatePaymentParams, type CreatePaymentResponse, type CreateProjectParams, type CreateProjectResponse, ForbiddenError, type GetPaymentResponse, type ListPaymentsParams, type ListPaymentsResponse, type ListProjectsResponse, NotFoundError, type Payment, type PaymentDetail, type PaymentListItem, type PaymentStatus, PayzCore, PayzCoreError, type PayzCoreOptions, type Project, type ProjectListItem, RateLimitError, type Token, type Transaction, ValidationError, type WebhookEventType, type WebhookPayload, WebhookSignatureError, constructEvent, PayzCore as default, verifyWebhookSignature };