@payotex.com/node 1.0.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/README.md +184 -0
- package/dist/index.cjs +135 -0
- package/dist/index.d.cts +120 -0
- package/dist/index.d.ts +120 -0
- package/dist/index.js +108 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# @payotex/node
|
|
2
|
+
|
|
3
|
+
Server-side SDK for Payotex crypto payment processing. Accept cryptocurrency payments with cross-chain swap support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @payotex/node
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- Node.js 18+ (uses native `fetch`)
|
|
14
|
+
- Zero runtime dependencies
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { Payotex } from '@payotex/node';
|
|
20
|
+
|
|
21
|
+
const payotex = new Payotex({
|
|
22
|
+
secretKey: 'sk_live_your_secret_key_here',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Create a checkout session
|
|
26
|
+
const session = await payotex.checkout.create({
|
|
27
|
+
amount: '49.99',
|
|
28
|
+
currency: 'USD',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
console.log(session.sessionId); // Redirect user to pay
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## API Reference
|
|
35
|
+
|
|
36
|
+
### Constructor
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
const payotex = new Payotex({
|
|
40
|
+
secretKey: 'sk_live_...', // Required. Your secret API key.
|
|
41
|
+
baseUrl: 'https://payotex.com', // Optional. Defaults to https://payotex.com
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Keys
|
|
46
|
+
|
|
47
|
+
#### `payotex.keys.create(params)`
|
|
48
|
+
|
|
49
|
+
Create a new API key pair for a merchant.
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
const keys = await payotex.keys.create({
|
|
53
|
+
payoutChain: 'ETH',
|
|
54
|
+
payoutToken: 'ETH.USDC-0XA0B86991C6218B36C1D19D4A2E9EB0CE3606EB48',
|
|
55
|
+
payoutAddress: '0xYourAddress...',
|
|
56
|
+
// Optional secondary payout
|
|
57
|
+
payoutChain2: 'BTC',
|
|
58
|
+
payoutToken2: 'BTC.BTC',
|
|
59
|
+
payoutAddress2: 'bc1q...',
|
|
60
|
+
label: 'My Store',
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
console.log(keys.secretKey); // sk_live_...
|
|
64
|
+
console.log(keys.publishableKey); // pk_live_...
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### `payotex.keys.verify()`
|
|
68
|
+
|
|
69
|
+
Verify the current API key and get merchant configuration.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
const info = await payotex.keys.verify();
|
|
73
|
+
console.log(info.payoutChain); // "ETH"
|
|
74
|
+
console.log(info.configValid); // true
|
|
75
|
+
console.log(info.isActive); // true
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Checkout
|
|
79
|
+
|
|
80
|
+
#### `payotex.checkout.create(params)`
|
|
81
|
+
|
|
82
|
+
Create a new checkout session.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const session = await payotex.checkout.create({
|
|
86
|
+
amount: '100.00', // Required. Amount as string or number.
|
|
87
|
+
currency: 'USD', // Required. USD, EUR, GBP, or crypto asset.
|
|
88
|
+
metadata: { // Optional. Custom metadata (max 4096 chars).
|
|
89
|
+
orderId: 'order-123',
|
|
90
|
+
customerId: 'cust-456',
|
|
91
|
+
},
|
|
92
|
+
expiresIn: 60, // Optional. Minutes until expiry (5-1440, default 30).
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
console.log(session.sessionId); // Use to track payment
|
|
96
|
+
console.log(session.status); // "pending"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Sessions
|
|
100
|
+
|
|
101
|
+
#### `payotex.sessions.get(sessionId)`
|
|
102
|
+
|
|
103
|
+
Get details for a checkout session. This is a public endpoint (no auth required).
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
const details = await payotex.sessions.get('session-id-here');
|
|
107
|
+
console.log(details.status); // "pending" | "paid" | "expired"
|
|
108
|
+
console.log(details.payotex_fee_percent);
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### `payotex.sessions.getAssets(sessionId)`
|
|
112
|
+
|
|
113
|
+
Get available payment assets for a session.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const assets = await payotex.sessions.getAssets('session-id-here');
|
|
117
|
+
assets.forEach(asset => {
|
|
118
|
+
console.log(`${asset.symbol} on ${asset.chain}`);
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### `payotex.sessions.createQuote(sessionId, params)`
|
|
123
|
+
|
|
124
|
+
Create a swap quote for a session.
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const quote = await payotex.sessions.createQuote('session-id-here', {
|
|
128
|
+
fromAsset: 'BTC.BTC',
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
console.log(quote.inbound_address); // Where to send funds
|
|
132
|
+
console.log(quote.expected_amount_in); // Amount to send
|
|
133
|
+
console.log(quote.expected_amount_out); // Amount merchant receives
|
|
134
|
+
console.log(quote.memo); // Include in transaction if present
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Error Handling
|
|
138
|
+
|
|
139
|
+
All methods throw on errors. Errors from the API include a `status` code and `response` object.
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
try {
|
|
143
|
+
const session = await payotex.checkout.create({
|
|
144
|
+
amount: '100',
|
|
145
|
+
currency: 'USD',
|
|
146
|
+
});
|
|
147
|
+
} catch (err) {
|
|
148
|
+
console.error(err.message); // Human-readable error
|
|
149
|
+
console.error(err.status); // HTTP status code (e.g., 400, 401)
|
|
150
|
+
console.error(err.response); // Full API response body
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## TypeScript
|
|
155
|
+
|
|
156
|
+
All types are exported from the main entry point:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import {
|
|
160
|
+
Payotex,
|
|
161
|
+
PayotexConfig,
|
|
162
|
+
CreateKeysRequest,
|
|
163
|
+
CreateKeysResponse,
|
|
164
|
+
VerifyKeyResponse,
|
|
165
|
+
CreateCheckoutSessionRequest,
|
|
166
|
+
CheckoutSession,
|
|
167
|
+
SessionDetails,
|
|
168
|
+
SessionAsset,
|
|
169
|
+
CreateQuoteRequest,
|
|
170
|
+
SessionQuote,
|
|
171
|
+
PayotexError,
|
|
172
|
+
} from '@payotex/node';
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Security Best Practices
|
|
176
|
+
|
|
177
|
+
- **Never expose your secret key (`sk_live_`) client-side.** Use it only in server-side code.
|
|
178
|
+
- Use the publishable key (`pk_live_`) for client-side integrations.
|
|
179
|
+
- Store your secret key in environment variables, never in source code.
|
|
180
|
+
- The SDK validates key format on initialization and rejects publishable keys to prevent misuse.
|
|
181
|
+
|
|
182
|
+
## License
|
|
183
|
+
|
|
184
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// packages/node/src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Payotex: () => Payotex
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// packages/node/src/client.ts
|
|
28
|
+
var DEFAULT_BASE_URL = "https://payotex.com";
|
|
29
|
+
var Payotex = class {
|
|
30
|
+
secretKey;
|
|
31
|
+
baseUrl;
|
|
32
|
+
constructor(config) {
|
|
33
|
+
if (!config.secretKey) {
|
|
34
|
+
throw new Error("Payotex: secretKey is required");
|
|
35
|
+
}
|
|
36
|
+
if (!config.secretKey.startsWith("sk_live_")) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
"Payotex: Invalid key format. Use your secret key (sk_live_...). Never use publishable keys (pk_live_) server-side."
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
this.secretKey = config.secretKey;
|
|
42
|
+
this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
43
|
+
}
|
|
44
|
+
async request(method, path, body, auth = true) {
|
|
45
|
+
const headers = {
|
|
46
|
+
"Content-Type": "application/json"
|
|
47
|
+
};
|
|
48
|
+
if (auth) {
|
|
49
|
+
headers["Authorization"] = `Bearer ${this.secretKey}`;
|
|
50
|
+
}
|
|
51
|
+
const url = `${this.baseUrl}${path}`;
|
|
52
|
+
const options = { method, headers };
|
|
53
|
+
if (body && (method === "POST" || method === "PUT" || method === "PATCH")) {
|
|
54
|
+
options.body = JSON.stringify(body);
|
|
55
|
+
}
|
|
56
|
+
const response = await fetch(url, options);
|
|
57
|
+
const data = await response.json();
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
const err = new Error(data.error || `HTTP ${response.status}`);
|
|
60
|
+
err.status = response.status;
|
|
61
|
+
err.response = data;
|
|
62
|
+
throw err;
|
|
63
|
+
}
|
|
64
|
+
return data;
|
|
65
|
+
}
|
|
66
|
+
keys = {
|
|
67
|
+
create: async (params) => {
|
|
68
|
+
if (!params.payoutChain || !params.payoutToken || !params.payoutAddress) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
"payoutChain, payoutToken, and payoutAddress are required"
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return this.request(
|
|
74
|
+
"POST",
|
|
75
|
+
"/api/merchant/keys",
|
|
76
|
+
params
|
|
77
|
+
);
|
|
78
|
+
},
|
|
79
|
+
verify: async () => {
|
|
80
|
+
return this.request("GET", "/api/merchant/keys/verify");
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
checkout = {
|
|
84
|
+
create: async (params) => {
|
|
85
|
+
if (!params.amount) {
|
|
86
|
+
throw new Error("amount is required");
|
|
87
|
+
}
|
|
88
|
+
if (!params.currency) {
|
|
89
|
+
throw new Error("currency is required");
|
|
90
|
+
}
|
|
91
|
+
const amount = typeof params.amount === "number" ? params.amount.toString() : params.amount;
|
|
92
|
+
if (isNaN(parseFloat(amount)) || parseFloat(amount) <= 0) {
|
|
93
|
+
throw new Error("amount must be a positive number");
|
|
94
|
+
}
|
|
95
|
+
return this.request("POST", "/api/merchant/checkout", {
|
|
96
|
+
...params,
|
|
97
|
+
amount
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
sessions = {
|
|
102
|
+
get: async (sessionId) => {
|
|
103
|
+
if (!sessionId) throw new Error("sessionId is required");
|
|
104
|
+
return this.request(
|
|
105
|
+
"GET",
|
|
106
|
+
`/api/merchant/session/${encodeURIComponent(sessionId)}`,
|
|
107
|
+
void 0,
|
|
108
|
+
false
|
|
109
|
+
);
|
|
110
|
+
},
|
|
111
|
+
getAssets: async (sessionId) => {
|
|
112
|
+
if (!sessionId) throw new Error("sessionId is required");
|
|
113
|
+
return this.request(
|
|
114
|
+
"GET",
|
|
115
|
+
`/api/merchant/session/${encodeURIComponent(sessionId)}/assets`,
|
|
116
|
+
void 0,
|
|
117
|
+
false
|
|
118
|
+
);
|
|
119
|
+
},
|
|
120
|
+
createQuote: async (sessionId, params) => {
|
|
121
|
+
if (!sessionId) throw new Error("sessionId is required");
|
|
122
|
+
if (!params.fromAsset) throw new Error("fromAsset is required");
|
|
123
|
+
return this.request(
|
|
124
|
+
"POST",
|
|
125
|
+
`/api/merchant/session/${encodeURIComponent(sessionId)}/quote`,
|
|
126
|
+
params,
|
|
127
|
+
false
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
133
|
+
0 && (module.exports = {
|
|
134
|
+
Payotex
|
|
135
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
interface PayotexConfig {
|
|
2
|
+
secretKey: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
}
|
|
5
|
+
interface CreateKeysRequest {
|
|
6
|
+
payoutChain: string;
|
|
7
|
+
payoutToken: string;
|
|
8
|
+
payoutAddress: string;
|
|
9
|
+
payoutChain2?: string;
|
|
10
|
+
payoutToken2?: string;
|
|
11
|
+
payoutAddress2?: string;
|
|
12
|
+
label?: string;
|
|
13
|
+
}
|
|
14
|
+
interface CreateKeysResponse {
|
|
15
|
+
id: string;
|
|
16
|
+
secretKey: string;
|
|
17
|
+
publishableKey: string;
|
|
18
|
+
secretKeyPrefix: string;
|
|
19
|
+
publishableKeyPrefix: string;
|
|
20
|
+
payoutChain: string;
|
|
21
|
+
payoutToken: string;
|
|
22
|
+
payoutAddress: string;
|
|
23
|
+
payoutChain2?: string;
|
|
24
|
+
payoutToken2?: string;
|
|
25
|
+
payoutAddress2?: string;
|
|
26
|
+
configHash: string;
|
|
27
|
+
message: string;
|
|
28
|
+
}
|
|
29
|
+
interface VerifyKeyResponse {
|
|
30
|
+
id: string;
|
|
31
|
+
payoutChain: string;
|
|
32
|
+
payoutToken: string;
|
|
33
|
+
payoutAddress: string;
|
|
34
|
+
configHash: string;
|
|
35
|
+
configValid: boolean;
|
|
36
|
+
isActive: boolean;
|
|
37
|
+
createdAt: string;
|
|
38
|
+
}
|
|
39
|
+
interface CreateCheckoutSessionRequest {
|
|
40
|
+
amount: string | number;
|
|
41
|
+
currency: string;
|
|
42
|
+
metadata?: Record<string, any>;
|
|
43
|
+
expiresIn?: number;
|
|
44
|
+
}
|
|
45
|
+
interface CheckoutSession {
|
|
46
|
+
sessionId: string;
|
|
47
|
+
amount: string;
|
|
48
|
+
currency: string;
|
|
49
|
+
status: "pending" | "paid" | "expired";
|
|
50
|
+
expiresAt: string;
|
|
51
|
+
}
|
|
52
|
+
interface SessionDetails {
|
|
53
|
+
id: string;
|
|
54
|
+
amount: string;
|
|
55
|
+
currency: string;
|
|
56
|
+
status: "pending" | "paid" | "expired";
|
|
57
|
+
expiresAt: string;
|
|
58
|
+
payoutChain: string;
|
|
59
|
+
payoutChain2?: string;
|
|
60
|
+
payoutToken?: string;
|
|
61
|
+
payoutToken2?: string;
|
|
62
|
+
payotex_fee_percent: number;
|
|
63
|
+
}
|
|
64
|
+
interface SessionAsset {
|
|
65
|
+
chain: string;
|
|
66
|
+
asset: string;
|
|
67
|
+
symbol: string;
|
|
68
|
+
name: string;
|
|
69
|
+
decimals: number;
|
|
70
|
+
priceUsd?: number;
|
|
71
|
+
}
|
|
72
|
+
interface CreateQuoteRequest {
|
|
73
|
+
fromAsset: string;
|
|
74
|
+
}
|
|
75
|
+
interface SessionQuote {
|
|
76
|
+
inbound_address: string;
|
|
77
|
+
expected_amount_out: string;
|
|
78
|
+
expected_amount_in: string;
|
|
79
|
+
fees: {
|
|
80
|
+
total: string;
|
|
81
|
+
slippage_bps: number;
|
|
82
|
+
};
|
|
83
|
+
payotex_fee_percent: number;
|
|
84
|
+
expiry: number;
|
|
85
|
+
payout_chain: string;
|
|
86
|
+
payout_address: string;
|
|
87
|
+
from_asset: string;
|
|
88
|
+
to_asset: string;
|
|
89
|
+
session_id: string;
|
|
90
|
+
session_amount: string;
|
|
91
|
+
session_currency: string;
|
|
92
|
+
memo?: string;
|
|
93
|
+
total_swap_seconds?: number;
|
|
94
|
+
router?: string;
|
|
95
|
+
}
|
|
96
|
+
interface PayotexError {
|
|
97
|
+
error: string;
|
|
98
|
+
status: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
declare class Payotex {
|
|
102
|
+
private secretKey;
|
|
103
|
+
private baseUrl;
|
|
104
|
+
constructor(config: PayotexConfig);
|
|
105
|
+
private request;
|
|
106
|
+
keys: {
|
|
107
|
+
create: (params: CreateKeysRequest) => Promise<CreateKeysResponse>;
|
|
108
|
+
verify: () => Promise<VerifyKeyResponse>;
|
|
109
|
+
};
|
|
110
|
+
checkout: {
|
|
111
|
+
create: (params: CreateCheckoutSessionRequest) => Promise<CheckoutSession>;
|
|
112
|
+
};
|
|
113
|
+
sessions: {
|
|
114
|
+
get: (sessionId: string) => Promise<SessionDetails>;
|
|
115
|
+
getAssets: (sessionId: string) => Promise<SessionAsset[]>;
|
|
116
|
+
createQuote: (sessionId: string, params: CreateQuoteRequest) => Promise<SessionQuote>;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { type CheckoutSession, type CreateCheckoutSessionRequest, type CreateKeysRequest, type CreateKeysResponse, type CreateQuoteRequest, Payotex, type PayotexConfig, type PayotexError, type SessionAsset, type SessionDetails, type SessionQuote, type VerifyKeyResponse };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
interface PayotexConfig {
|
|
2
|
+
secretKey: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
}
|
|
5
|
+
interface CreateKeysRequest {
|
|
6
|
+
payoutChain: string;
|
|
7
|
+
payoutToken: string;
|
|
8
|
+
payoutAddress: string;
|
|
9
|
+
payoutChain2?: string;
|
|
10
|
+
payoutToken2?: string;
|
|
11
|
+
payoutAddress2?: string;
|
|
12
|
+
label?: string;
|
|
13
|
+
}
|
|
14
|
+
interface CreateKeysResponse {
|
|
15
|
+
id: string;
|
|
16
|
+
secretKey: string;
|
|
17
|
+
publishableKey: string;
|
|
18
|
+
secretKeyPrefix: string;
|
|
19
|
+
publishableKeyPrefix: string;
|
|
20
|
+
payoutChain: string;
|
|
21
|
+
payoutToken: string;
|
|
22
|
+
payoutAddress: string;
|
|
23
|
+
payoutChain2?: string;
|
|
24
|
+
payoutToken2?: string;
|
|
25
|
+
payoutAddress2?: string;
|
|
26
|
+
configHash: string;
|
|
27
|
+
message: string;
|
|
28
|
+
}
|
|
29
|
+
interface VerifyKeyResponse {
|
|
30
|
+
id: string;
|
|
31
|
+
payoutChain: string;
|
|
32
|
+
payoutToken: string;
|
|
33
|
+
payoutAddress: string;
|
|
34
|
+
configHash: string;
|
|
35
|
+
configValid: boolean;
|
|
36
|
+
isActive: boolean;
|
|
37
|
+
createdAt: string;
|
|
38
|
+
}
|
|
39
|
+
interface CreateCheckoutSessionRequest {
|
|
40
|
+
amount: string | number;
|
|
41
|
+
currency: string;
|
|
42
|
+
metadata?: Record<string, any>;
|
|
43
|
+
expiresIn?: number;
|
|
44
|
+
}
|
|
45
|
+
interface CheckoutSession {
|
|
46
|
+
sessionId: string;
|
|
47
|
+
amount: string;
|
|
48
|
+
currency: string;
|
|
49
|
+
status: "pending" | "paid" | "expired";
|
|
50
|
+
expiresAt: string;
|
|
51
|
+
}
|
|
52
|
+
interface SessionDetails {
|
|
53
|
+
id: string;
|
|
54
|
+
amount: string;
|
|
55
|
+
currency: string;
|
|
56
|
+
status: "pending" | "paid" | "expired";
|
|
57
|
+
expiresAt: string;
|
|
58
|
+
payoutChain: string;
|
|
59
|
+
payoutChain2?: string;
|
|
60
|
+
payoutToken?: string;
|
|
61
|
+
payoutToken2?: string;
|
|
62
|
+
payotex_fee_percent: number;
|
|
63
|
+
}
|
|
64
|
+
interface SessionAsset {
|
|
65
|
+
chain: string;
|
|
66
|
+
asset: string;
|
|
67
|
+
symbol: string;
|
|
68
|
+
name: string;
|
|
69
|
+
decimals: number;
|
|
70
|
+
priceUsd?: number;
|
|
71
|
+
}
|
|
72
|
+
interface CreateQuoteRequest {
|
|
73
|
+
fromAsset: string;
|
|
74
|
+
}
|
|
75
|
+
interface SessionQuote {
|
|
76
|
+
inbound_address: string;
|
|
77
|
+
expected_amount_out: string;
|
|
78
|
+
expected_amount_in: string;
|
|
79
|
+
fees: {
|
|
80
|
+
total: string;
|
|
81
|
+
slippage_bps: number;
|
|
82
|
+
};
|
|
83
|
+
payotex_fee_percent: number;
|
|
84
|
+
expiry: number;
|
|
85
|
+
payout_chain: string;
|
|
86
|
+
payout_address: string;
|
|
87
|
+
from_asset: string;
|
|
88
|
+
to_asset: string;
|
|
89
|
+
session_id: string;
|
|
90
|
+
session_amount: string;
|
|
91
|
+
session_currency: string;
|
|
92
|
+
memo?: string;
|
|
93
|
+
total_swap_seconds?: number;
|
|
94
|
+
router?: string;
|
|
95
|
+
}
|
|
96
|
+
interface PayotexError {
|
|
97
|
+
error: string;
|
|
98
|
+
status: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
declare class Payotex {
|
|
102
|
+
private secretKey;
|
|
103
|
+
private baseUrl;
|
|
104
|
+
constructor(config: PayotexConfig);
|
|
105
|
+
private request;
|
|
106
|
+
keys: {
|
|
107
|
+
create: (params: CreateKeysRequest) => Promise<CreateKeysResponse>;
|
|
108
|
+
verify: () => Promise<VerifyKeyResponse>;
|
|
109
|
+
};
|
|
110
|
+
checkout: {
|
|
111
|
+
create: (params: CreateCheckoutSessionRequest) => Promise<CheckoutSession>;
|
|
112
|
+
};
|
|
113
|
+
sessions: {
|
|
114
|
+
get: (sessionId: string) => Promise<SessionDetails>;
|
|
115
|
+
getAssets: (sessionId: string) => Promise<SessionAsset[]>;
|
|
116
|
+
createQuote: (sessionId: string, params: CreateQuoteRequest) => Promise<SessionQuote>;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { type CheckoutSession, type CreateCheckoutSessionRequest, type CreateKeysRequest, type CreateKeysResponse, type CreateQuoteRequest, Payotex, type PayotexConfig, type PayotexError, type SessionAsset, type SessionDetails, type SessionQuote, type VerifyKeyResponse };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// packages/node/src/client.ts
|
|
2
|
+
var DEFAULT_BASE_URL = "https://payotex.com";
|
|
3
|
+
var Payotex = class {
|
|
4
|
+
secretKey;
|
|
5
|
+
baseUrl;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
if (!config.secretKey) {
|
|
8
|
+
throw new Error("Payotex: secretKey is required");
|
|
9
|
+
}
|
|
10
|
+
if (!config.secretKey.startsWith("sk_live_")) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
"Payotex: Invalid key format. Use your secret key (sk_live_...). Never use publishable keys (pk_live_) server-side."
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
this.secretKey = config.secretKey;
|
|
16
|
+
this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
17
|
+
}
|
|
18
|
+
async request(method, path, body, auth = true) {
|
|
19
|
+
const headers = {
|
|
20
|
+
"Content-Type": "application/json"
|
|
21
|
+
};
|
|
22
|
+
if (auth) {
|
|
23
|
+
headers["Authorization"] = `Bearer ${this.secretKey}`;
|
|
24
|
+
}
|
|
25
|
+
const url = `${this.baseUrl}${path}`;
|
|
26
|
+
const options = { method, headers };
|
|
27
|
+
if (body && (method === "POST" || method === "PUT" || method === "PATCH")) {
|
|
28
|
+
options.body = JSON.stringify(body);
|
|
29
|
+
}
|
|
30
|
+
const response = await fetch(url, options);
|
|
31
|
+
const data = await response.json();
|
|
32
|
+
if (!response.ok) {
|
|
33
|
+
const err = new Error(data.error || `HTTP ${response.status}`);
|
|
34
|
+
err.status = response.status;
|
|
35
|
+
err.response = data;
|
|
36
|
+
throw err;
|
|
37
|
+
}
|
|
38
|
+
return data;
|
|
39
|
+
}
|
|
40
|
+
keys = {
|
|
41
|
+
create: async (params) => {
|
|
42
|
+
if (!params.payoutChain || !params.payoutToken || !params.payoutAddress) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
"payoutChain, payoutToken, and payoutAddress are required"
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return this.request(
|
|
48
|
+
"POST",
|
|
49
|
+
"/api/merchant/keys",
|
|
50
|
+
params
|
|
51
|
+
);
|
|
52
|
+
},
|
|
53
|
+
verify: async () => {
|
|
54
|
+
return this.request("GET", "/api/merchant/keys/verify");
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
checkout = {
|
|
58
|
+
create: async (params) => {
|
|
59
|
+
if (!params.amount) {
|
|
60
|
+
throw new Error("amount is required");
|
|
61
|
+
}
|
|
62
|
+
if (!params.currency) {
|
|
63
|
+
throw new Error("currency is required");
|
|
64
|
+
}
|
|
65
|
+
const amount = typeof params.amount === "number" ? params.amount.toString() : params.amount;
|
|
66
|
+
if (isNaN(parseFloat(amount)) || parseFloat(amount) <= 0) {
|
|
67
|
+
throw new Error("amount must be a positive number");
|
|
68
|
+
}
|
|
69
|
+
return this.request("POST", "/api/merchant/checkout", {
|
|
70
|
+
...params,
|
|
71
|
+
amount
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
sessions = {
|
|
76
|
+
get: async (sessionId) => {
|
|
77
|
+
if (!sessionId) throw new Error("sessionId is required");
|
|
78
|
+
return this.request(
|
|
79
|
+
"GET",
|
|
80
|
+
`/api/merchant/session/${encodeURIComponent(sessionId)}`,
|
|
81
|
+
void 0,
|
|
82
|
+
false
|
|
83
|
+
);
|
|
84
|
+
},
|
|
85
|
+
getAssets: async (sessionId) => {
|
|
86
|
+
if (!sessionId) throw new Error("sessionId is required");
|
|
87
|
+
return this.request(
|
|
88
|
+
"GET",
|
|
89
|
+
`/api/merchant/session/${encodeURIComponent(sessionId)}/assets`,
|
|
90
|
+
void 0,
|
|
91
|
+
false
|
|
92
|
+
);
|
|
93
|
+
},
|
|
94
|
+
createQuote: async (sessionId, params) => {
|
|
95
|
+
if (!sessionId) throw new Error("sessionId is required");
|
|
96
|
+
if (!params.fromAsset) throw new Error("fromAsset is required");
|
|
97
|
+
return this.request(
|
|
98
|
+
"POST",
|
|
99
|
+
`/api/merchant/session/${encodeURIComponent(sessionId)}/quote`,
|
|
100
|
+
params,
|
|
101
|
+
false
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
export {
|
|
107
|
+
Payotex
|
|
108
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@payotex.com/node",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Server-side SDK for Payotex crypto payment processing",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": ["dist"],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
18
|
+
"test": "node --experimental-vm-modules ../../node_modules/.bin/vitest run --config vitest.config.ts"
|
|
19
|
+
},
|
|
20
|
+
"keywords": ["payotex", "crypto", "payments", "checkout", "cross-chain", "swap", "bitcoin", "ethereum"],
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"tsup": "^8.0.0",
|
|
27
|
+
"typescript": "^5.0.0",
|
|
28
|
+
"vitest": "^1.0.0"
|
|
29
|
+
}
|
|
30
|
+
}
|