@dominusnode/sdk 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/LICENSE +21 -0
- package/README.md +679 -0
- package/dist/cjs/admin.d.ts +71 -0
- package/dist/cjs/admin.js +60 -0
- package/dist/cjs/auth.d.ts +47 -0
- package/dist/cjs/auth.js +46 -0
- package/dist/cjs/client.d.ts +56 -0
- package/dist/cjs/client.js +109 -0
- package/dist/cjs/constants.d.ts +8 -0
- package/dist/cjs/constants.js +11 -0
- package/dist/cjs/errors.d.ts +36 -0
- package/dist/cjs/errors.js +86 -0
- package/dist/cjs/http.d.ts +19 -0
- package/dist/cjs/http.js +195 -0
- package/dist/cjs/index.d.ts +30 -0
- package/dist/cjs/index.js +58 -0
- package/dist/cjs/keys.d.ts +27 -0
- package/dist/cjs/keys.js +22 -0
- package/dist/cjs/plans.d.ts +37 -0
- package/dist/cjs/plans.js +22 -0
- package/dist/cjs/proxy.d.ts +62 -0
- package/dist/cjs/proxy.js +71 -0
- package/dist/cjs/resources/agent-wallet.d.ts +52 -0
- package/dist/cjs/resources/agent-wallet.js +64 -0
- package/dist/cjs/resources/teams.d.ts +93 -0
- package/dist/cjs/resources/teams.js +82 -0
- package/dist/cjs/resources/wallet-auth.d.ts +66 -0
- package/dist/cjs/resources/wallet-auth.js +105 -0
- package/dist/cjs/resources/x402.d.ts +39 -0
- package/dist/cjs/resources/x402.js +25 -0
- package/dist/cjs/sessions.d.ts +15 -0
- package/dist/cjs/sessions.js +14 -0
- package/dist/cjs/slots.d.ts +9 -0
- package/dist/cjs/slots.js +19 -0
- package/dist/cjs/token-manager.d.ts +21 -0
- package/dist/cjs/token-manager.js +105 -0
- package/dist/cjs/types.d.ts +154 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/usage.d.ts +80 -0
- package/dist/cjs/usage.js +56 -0
- package/dist/cjs/wallet.d.ts +59 -0
- package/dist/cjs/wallet.js +56 -0
- package/dist/esm/admin.d.ts +71 -0
- package/dist/esm/admin.js +56 -0
- package/dist/esm/auth.d.ts +47 -0
- package/dist/esm/auth.js +42 -0
- package/dist/esm/client.d.ts +56 -0
- package/dist/esm/client.js +105 -0
- package/dist/esm/constants.d.ts +8 -0
- package/dist/esm/constants.js +8 -0
- package/dist/esm/errors.d.ts +36 -0
- package/dist/esm/errors.js +72 -0
- package/dist/esm/http.d.ts +19 -0
- package/dist/esm/http.js +191 -0
- package/dist/esm/index.d.ts +30 -0
- package/dist/esm/index.js +23 -0
- package/dist/esm/keys.d.ts +27 -0
- package/dist/esm/keys.js +18 -0
- package/dist/esm/plans.d.ts +37 -0
- package/dist/esm/plans.js +18 -0
- package/dist/esm/proxy.d.ts +62 -0
- package/dist/esm/proxy.js +67 -0
- package/dist/esm/resources/agent-wallet.d.ts +52 -0
- package/dist/esm/resources/agent-wallet.js +60 -0
- package/dist/esm/resources/teams.d.ts +93 -0
- package/dist/esm/resources/teams.js +78 -0
- package/dist/esm/resources/wallet-auth.d.ts +66 -0
- package/dist/esm/resources/wallet-auth.js +101 -0
- package/dist/esm/resources/x402.d.ts +39 -0
- package/dist/esm/resources/x402.js +21 -0
- package/dist/esm/sessions.d.ts +15 -0
- package/dist/esm/sessions.js +10 -0
- package/dist/esm/slots.d.ts +9 -0
- package/dist/esm/slots.js +15 -0
- package/dist/esm/token-manager.d.ts +21 -0
- package/dist/esm/token-manager.js +101 -0
- package/dist/esm/types.d.ts +154 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/usage.d.ts +80 -0
- package/dist/esm/usage.js +52 -0
- package/dist/esm/wallet.d.ts +59 -0
- package/dist/esm/wallet.js +52 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +31 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dominus Node
|
|
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,679 @@
|
|
|
1
|
+
# @dominusnode/sdk -- Official Dominus Node Node.js SDK
|
|
2
|
+
|
|
3
|
+
The official Node.js/TypeScript SDK for the [Dominus Node](https://dominusnode.com) rotating proxy-as-a-service platform. Manage proxy connections, API keys, wallet balances, usage tracking, and more -- all from a single, strongly-typed client.
|
|
4
|
+
|
|
5
|
+
- **Zero dependencies** -- uses the Node.js 18+ built-in `fetch` API
|
|
6
|
+
- **Dual CJS + ESM output** -- works with `require()` and `import` out of the box
|
|
7
|
+
- **Full TypeScript support** -- every request and response is fully typed
|
|
8
|
+
- **Auto token refresh** -- JWT expiry is handled transparently via base64 decode (no crypto dependency)
|
|
9
|
+
- **Rate limit auto-retry** -- 429 responses are automatically retried after the server-specified delay
|
|
10
|
+
- **Typed error hierarchy** -- catch specific error classes instead of parsing status codes
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @dominusnode/sdk
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
yarn add @dominusnode/sdk
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pnpm add @dominusnode/sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Requirements:** Node.js 18.0.0 or later (uses built-in `fetch`).
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { DominusNodeClient } from '@dominusnode/sdk';
|
|
32
|
+
|
|
33
|
+
// Connect with API key
|
|
34
|
+
const client = new DominusNodeClient({ baseUrl: 'https://api.dominusnode.com' });
|
|
35
|
+
await client.connectWithKey('dn_live_your_api_key');
|
|
36
|
+
|
|
37
|
+
// Check balance
|
|
38
|
+
const balance = await client.wallet.getBalance();
|
|
39
|
+
console.log(`Balance: $${balance.balanceUsd}`);
|
|
40
|
+
|
|
41
|
+
// Build proxy URL
|
|
42
|
+
const proxyUrl = client.proxy.buildUrl('dn_live_your_key', {
|
|
43
|
+
protocol: 'http',
|
|
44
|
+
country: 'US',
|
|
45
|
+
state: 'california',
|
|
46
|
+
city: 'losangeles',
|
|
47
|
+
});
|
|
48
|
+
console.log(proxyUrl);
|
|
49
|
+
// => http://user-country_US-state_california-city_losangeles:dn_live_your_key@proxy.dominusnode.com:8080
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Authentication
|
|
53
|
+
|
|
54
|
+
The SDK supports three authentication modes. All authenticated requests automatically include a Bearer token, and expired tokens are refreshed transparently.
|
|
55
|
+
|
|
56
|
+
### API Key
|
|
57
|
+
|
|
58
|
+
Best for server-side scripts and backend integrations. The key is exchanged for a JWT token pair on the first call.
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
const client = new DominusNodeClient({ baseUrl: 'https://api.dominusnode.com' });
|
|
62
|
+
await client.connectWithKey('dn_live_your_api_key');
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Email + Password
|
|
66
|
+
|
|
67
|
+
Best for interactive applications where the user logs in with credentials. Supports MFA (TOTP or backup codes).
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const client = new DominusNodeClient({ baseUrl: 'https://api.dominusnode.com' });
|
|
71
|
+
const result = await client.connectWithCredentials('user@example.com', 'SecurePass123!');
|
|
72
|
+
|
|
73
|
+
if (result.mfaRequired) {
|
|
74
|
+
// User has 2FA enabled -- need TOTP code
|
|
75
|
+
await client.completeMfa('123456');
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Pre-authenticated
|
|
80
|
+
|
|
81
|
+
Use when you already have valid JWT tokens (e.g., stored from a previous session).
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
const client = new DominusNodeClient({
|
|
85
|
+
baseUrl: 'https://api.dominusnode.com',
|
|
86
|
+
accessToken: 'existing_jwt',
|
|
87
|
+
refreshToken: 'existing_refresh_token',
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Disconnecting
|
|
92
|
+
|
|
93
|
+
Clear all stored tokens locally. Call `client.auth.logout()` first if you also want to revoke refresh tokens server-side.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
await client.auth.logout(); // Revoke server-side refresh tokens
|
|
97
|
+
client.disconnect(); // Clear local token state
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Configuration
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
interface DominusNodeConfig {
|
|
104
|
+
baseUrl?: string; // Default: 'https://api.dominusnode.com'
|
|
105
|
+
accessToken?: string; // Pre-existing access token
|
|
106
|
+
refreshToken?: string; // Pre-existing refresh token
|
|
107
|
+
proxyHost?: string; // Default: 'proxy.dominusnode.com'
|
|
108
|
+
httpProxyPort?: number; // Default: 8080
|
|
109
|
+
socks5ProxyPort?: number; // Default: 1080
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
All fields are optional. The defaults point to the Dominus Node production endpoints.
|
|
114
|
+
|
|
115
|
+
## Resources
|
|
116
|
+
|
|
117
|
+
The `DominusNodeClient` exposes eight resource modules, each grouping related API operations.
|
|
118
|
+
|
|
119
|
+
### Auth
|
|
120
|
+
|
|
121
|
+
Registration, login, MFA management, password changes, and session introspection.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Register a new account
|
|
125
|
+
const { user } = await client.auth.register('user@example.com', 'SecurePass123!');
|
|
126
|
+
|
|
127
|
+
// Login (returns token + user, or mfaRequired flag)
|
|
128
|
+
const result = await client.auth.login('user@example.com', 'SecurePass123!');
|
|
129
|
+
|
|
130
|
+
// MFA verify with TOTP code
|
|
131
|
+
await client.auth.verifyMfa('123456');
|
|
132
|
+
|
|
133
|
+
// MFA verify with backup code
|
|
134
|
+
await client.auth.verifyMfa('12345678', { isBackupCode: true });
|
|
135
|
+
|
|
136
|
+
// MFA setup -- returns secret, otpauthUri, and backup codes
|
|
137
|
+
const setup = await client.auth.mfaSetup();
|
|
138
|
+
// setup.secret, setup.otpauthUri, setup.backupCodes
|
|
139
|
+
|
|
140
|
+
// MFA enable (confirm with a valid TOTP code)
|
|
141
|
+
await client.auth.mfaEnable('123456');
|
|
142
|
+
|
|
143
|
+
// MFA disable (requires current password + TOTP code)
|
|
144
|
+
await client.auth.mfaDisable('password', '123456');
|
|
145
|
+
|
|
146
|
+
// MFA status
|
|
147
|
+
const status = await client.auth.mfaStatus();
|
|
148
|
+
// status.enabled, status.backupCodesRemaining
|
|
149
|
+
|
|
150
|
+
// Change password
|
|
151
|
+
await client.auth.changePassword('oldpass', 'newpass');
|
|
152
|
+
|
|
153
|
+
// Logout (revokes refresh tokens server-side)
|
|
154
|
+
await client.auth.logout();
|
|
155
|
+
|
|
156
|
+
// Session info (get current user from the JWT)
|
|
157
|
+
const me = await client.auth.me();
|
|
158
|
+
// me.user.id, me.user.email, me.user.is_admin
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Keys
|
|
162
|
+
|
|
163
|
+
Create, list, and revoke API keys. API keys use the `dn_live_` prefix and are authenticated via SHA-256 hash for fast O(1) lookup.
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// Create a new API key
|
|
167
|
+
const key = await client.keys.create('my-scraper');
|
|
168
|
+
// key.key is the full API key (dn_live_xxx) -- shown only once, save it!
|
|
169
|
+
// key.id, key.prefix, key.label, key.created_at
|
|
170
|
+
|
|
171
|
+
// List all API keys (raw key is never returned after creation)
|
|
172
|
+
const keys = await client.keys.list();
|
|
173
|
+
// keys.keys[0].id, .prefix, .label, .created_at, .revoked_at
|
|
174
|
+
|
|
175
|
+
// Revoke an API key by ID
|
|
176
|
+
await client.keys.revoke('key-id');
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Wallet
|
|
180
|
+
|
|
181
|
+
Check balances, view transaction history, top up via Stripe or cryptocurrency, and get spending forecasts.
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
// Get current balance
|
|
185
|
+
const balance = await client.wallet.getBalance();
|
|
186
|
+
// balance.balanceCents -- integer cents (e.g., 1050)
|
|
187
|
+
// balance.balanceUsd -- decimal USD (e.g., 10.50)
|
|
188
|
+
// balance.currency -- "USD"
|
|
189
|
+
// balance.lastToppedUp -- ISO timestamp or null
|
|
190
|
+
|
|
191
|
+
// Transaction history (paginated)
|
|
192
|
+
const txs = await client.wallet.getTransactions({ limit: 50, offset: 0 });
|
|
193
|
+
// txs.transactions[0].type -- "topup" | "debit" | "refund"
|
|
194
|
+
// txs.transactions[0].amountCents -- integer cents
|
|
195
|
+
// txs.transactions[0].amountUsd -- decimal USD
|
|
196
|
+
// txs.transactions[0].description
|
|
197
|
+
// txs.transactions[0].createdAt
|
|
198
|
+
|
|
199
|
+
// Top up with Stripe (amount in cents)
|
|
200
|
+
const checkout = await client.wallet.topUpStripe(1000); // $10.00
|
|
201
|
+
// checkout.url -- redirect user to this Stripe Checkout URL
|
|
202
|
+
// checkout.sessionId -- Stripe session ID
|
|
203
|
+
|
|
204
|
+
// Top up with crypto (amount in cents, currency code)
|
|
205
|
+
const invoice = await client.wallet.topUpCrypto(1000, 'btc');
|
|
206
|
+
// invoice.invoiceId -- NOWPayments invoice ID
|
|
207
|
+
// invoice.invoiceUrl -- redirect user to pay
|
|
208
|
+
// invoice.payCurrency -- e.g., "btc"
|
|
209
|
+
// invoice.priceAmount -- amount in USD
|
|
210
|
+
|
|
211
|
+
// Spending forecast
|
|
212
|
+
const forecast = await client.wallet.getForecast();
|
|
213
|
+
// forecast.dailyAvgCents -- average daily spend
|
|
214
|
+
// forecast.daysRemaining -- estimated days until balance runs out (null if no usage)
|
|
215
|
+
// forecast.trend -- "up" | "down" | "stable"
|
|
216
|
+
// forecast.trendPct -- percentage change
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Usage
|
|
220
|
+
|
|
221
|
+
Query usage records, daily breakdowns, top hosts, and export data as CSV.
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
// Usage records with summary (paginated, filterable by date)
|
|
225
|
+
const usage = await client.usage.get({ from: '2024-01-01', to: '2024-01-31', limit: 100 });
|
|
226
|
+
// usage.summary.totalBytes, .totalCostCents, .requestCount, .totalGB, .totalCostUsd
|
|
227
|
+
// usage.records[0].bytesIn, .bytesOut, .totalBytes, .costCents, .targetHost, .createdAt
|
|
228
|
+
// usage.pagination.limit, .offset, .total
|
|
229
|
+
// usage.period.since, .until
|
|
230
|
+
|
|
231
|
+
// Daily breakdown (for charts)
|
|
232
|
+
const daily = await client.usage.getDaily({ from: '2024-01-01', to: '2024-01-31' });
|
|
233
|
+
// daily.days[0].date, .totalBytes, .totalGB, .totalCostCents, .totalCostUsd, .requestCount
|
|
234
|
+
|
|
235
|
+
// Top target hosts by bandwidth
|
|
236
|
+
const hosts = await client.usage.getTopHosts({ limit: 10 });
|
|
237
|
+
// hosts.hosts[0].targetHost, .totalBytes, .totalGB, .requestCount
|
|
238
|
+
|
|
239
|
+
// CSV export
|
|
240
|
+
const csv = await client.usage.exportCsv({ from: '2024-01-01', to: '2024-01-31' });
|
|
241
|
+
// csv is a raw CSV string
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Plans
|
|
245
|
+
|
|
246
|
+
List available pricing plans, view the current user's plan, and change plans.
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
// List all available plans (no auth required)
|
|
250
|
+
const plans = await client.plans.list();
|
|
251
|
+
// plans.plans[0].id, .name, .pricePerGbCents, .pricePerGbUsd,
|
|
252
|
+
// .monthlyBandwidthBytes, .monthlyBandwidthGB, .isDefault
|
|
253
|
+
|
|
254
|
+
// Get the current user's plan and monthly usage
|
|
255
|
+
const plan = await client.plans.getUserPlan();
|
|
256
|
+
// plan.plan -- the PlanEntry object
|
|
257
|
+
// plan.usage.monthlyUsageBytes, .monthlyUsageGB, .limitBytes, .limitGB, .percentUsed
|
|
258
|
+
|
|
259
|
+
// Change plan
|
|
260
|
+
const result = await client.plans.changePlan('vol100');
|
|
261
|
+
// result.message, result.plan
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Sessions
|
|
265
|
+
|
|
266
|
+
View active proxy sessions for the authenticated user.
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// Get all active proxy sessions
|
|
270
|
+
const sessions = await client.sessions.getActive();
|
|
271
|
+
// sessions.sessions[0].id, .startedAt, .status
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Proxy
|
|
275
|
+
|
|
276
|
+
Build proxy URLs for direct use with HTTP clients, and query proxy health/status/config.
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
// Build a basic HTTP proxy URL (no network call -- pure string construction)
|
|
280
|
+
const httpUrl = client.proxy.buildUrl('dn_live_key');
|
|
281
|
+
// => http://user:dn_live_key@proxy.dominusnode.com:8080
|
|
282
|
+
|
|
283
|
+
// Build a SOCKS5 proxy URL
|
|
284
|
+
const socksUrl = client.proxy.buildUrl('dn_live_key', { protocol: 'socks5' });
|
|
285
|
+
// => socks5://user:dn_live_key@proxy.dominusnode.com:1080
|
|
286
|
+
|
|
287
|
+
// Geo-targeted with sticky session
|
|
288
|
+
const geoUrl = client.proxy.buildUrl('dn_live_key', {
|
|
289
|
+
country: 'US',
|
|
290
|
+
state: 'california',
|
|
291
|
+
city: 'losangeles',
|
|
292
|
+
sessionId: 'sticky123',
|
|
293
|
+
});
|
|
294
|
+
// => http://user-country_US-state_california-city_losangeles-session_sticky123:dn_live_key@proxy.dominusnode.com:8080
|
|
295
|
+
|
|
296
|
+
// ASN targeting
|
|
297
|
+
const asnUrl = client.proxy.buildUrl('dn_live_key', { asn: 7922 });
|
|
298
|
+
// => http://user-asn_7922:dn_live_key@proxy.dominusnode.com:8080
|
|
299
|
+
|
|
300
|
+
// Proxy health (no auth required)
|
|
301
|
+
const health = await client.proxy.getHealth();
|
|
302
|
+
// health.status, .activeSessions, .uptimeSeconds
|
|
303
|
+
|
|
304
|
+
// Proxy status (auth required -- includes provider info)
|
|
305
|
+
const status = await client.proxy.getStatus();
|
|
306
|
+
// status.providers[0].name, .state, .consecutiveFailures, .avgLatencyMs
|
|
307
|
+
// status.endpoints.http, .endpoints.socks5
|
|
308
|
+
// status.supportedCountries
|
|
309
|
+
|
|
310
|
+
// Proxy config (auth required)
|
|
311
|
+
const config = await client.proxy.getConfig();
|
|
312
|
+
// config.httpProxy, .socks5Proxy, .supportedCountries, .blockedCountries, .geoTargeting
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Admin (requires admin privileges)
|
|
316
|
+
|
|
317
|
+
User management, revenue analytics, and system statistics. All endpoints require the authenticated user to have `is_admin: true`.
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
// List users (paginated)
|
|
321
|
+
const users = await client.admin.listUsers({ page: 1, limit: 25 });
|
|
322
|
+
// users.users[0].id, .email, .status, .is_admin, .created_at, .balance_cents
|
|
323
|
+
// users.pagination.page, .limit, .total, .totalPages
|
|
324
|
+
|
|
325
|
+
// Get a specific user
|
|
326
|
+
const user = await client.admin.getUser('user-id');
|
|
327
|
+
// user.user.id, .email, .status, ...
|
|
328
|
+
|
|
329
|
+
// Suspend a user account
|
|
330
|
+
await client.admin.suspendUser('user-id');
|
|
331
|
+
|
|
332
|
+
// Reactivate a suspended user
|
|
333
|
+
await client.admin.activateUser('user-id');
|
|
334
|
+
|
|
335
|
+
// Soft-delete a user account
|
|
336
|
+
await client.admin.deleteUser('user-id');
|
|
337
|
+
|
|
338
|
+
// Revenue statistics (filterable by date range)
|
|
339
|
+
const revenue = await client.admin.getRevenue({ since: '2024-01-01', until: '2024-01-31' });
|
|
340
|
+
// revenue.totalRevenueCents, .totalRevenueUsd, .avgTransactionCents, .transactionCount
|
|
341
|
+
|
|
342
|
+
// Daily revenue breakdown
|
|
343
|
+
const daily = await client.admin.getDailyRevenue({ since: '2024-01-01', until: '2024-01-31' });
|
|
344
|
+
// daily.days[0].date, .revenueCents, .revenueUsd
|
|
345
|
+
|
|
346
|
+
// System-wide statistics
|
|
347
|
+
const stats = await client.admin.getStats();
|
|
348
|
+
// stats.active_sessions, .total_users, .total_bandwidth_bytes
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## Error Handling
|
|
352
|
+
|
|
353
|
+
The SDK throws typed error classes instead of generic errors. Every error extends `DominusNodeError`, which itself extends the built-in `Error` class.
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
import {
|
|
357
|
+
DominusNodeClient,
|
|
358
|
+
AuthenticationError,
|
|
359
|
+
InsufficientBalanceError,
|
|
360
|
+
RateLimitError,
|
|
361
|
+
ValidationError,
|
|
362
|
+
NotFoundError,
|
|
363
|
+
} from '@dominusnode/sdk';
|
|
364
|
+
|
|
365
|
+
try {
|
|
366
|
+
await client.wallet.getBalance();
|
|
367
|
+
} catch (err) {
|
|
368
|
+
if (err instanceof AuthenticationError) {
|
|
369
|
+
// 401 -- not authenticated or token refresh failed
|
|
370
|
+
console.error('Not authenticated -- login or provide API key');
|
|
371
|
+
} else if (err instanceof InsufficientBalanceError) {
|
|
372
|
+
// 402 -- wallet balance too low
|
|
373
|
+
console.error('Wallet balance too low -- top up first');
|
|
374
|
+
} else if (err instanceof RateLimitError) {
|
|
375
|
+
// 429 -- rate limited (SDK already retried once automatically)
|
|
376
|
+
console.error(`Rate limited -- retry after ${err.retryAfterSeconds}s`);
|
|
377
|
+
} else if (err instanceof ValidationError) {
|
|
378
|
+
// 400 -- invalid request parameters
|
|
379
|
+
console.error(`Invalid input: ${err.message}`);
|
|
380
|
+
} else if (err instanceof NotFoundError) {
|
|
381
|
+
// 404 -- resource not found
|
|
382
|
+
console.error(`Not found: ${err.message}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Error Hierarchy
|
|
388
|
+
|
|
389
|
+
All errors include a `statusCode` property (when applicable) and a descriptive `message`.
|
|
390
|
+
|
|
391
|
+
| Error Class | HTTP Status | Description |
|
|
392
|
+
|---|---|---|
|
|
393
|
+
| `DominusNodeError` | (varies) | Base class for all SDK errors |
|
|
394
|
+
| `AuthenticationError` | 401 | Invalid credentials or expired/revoked tokens |
|
|
395
|
+
| `AuthorizationError` | 403 | Insufficient permissions (e.g., non-admin accessing admin routes) |
|
|
396
|
+
| `InsufficientBalanceError` | 402 | Wallet balance too low for the operation |
|
|
397
|
+
| `RateLimitError` | 429 | Too many requests -- has `retryAfterSeconds` property |
|
|
398
|
+
| `ValidationError` | 400 | Invalid request parameters |
|
|
399
|
+
| `NotFoundError` | 404 | Requested resource does not exist |
|
|
400
|
+
| `ConflictError` | 409 | Resource conflict (e.g., duplicate email registration) |
|
|
401
|
+
| `ServerError` | 500+ | Server-side error |
|
|
402
|
+
| `NetworkError` | -- | Connection failure, DNS resolution error, or timeout |
|
|
403
|
+
| `ProxyError` | -- | Proxy-specific error -- has optional `proxyErrorCode` property |
|
|
404
|
+
|
|
405
|
+
## Using the Proxy URL
|
|
406
|
+
|
|
407
|
+
The `proxy.buildUrl()` method returns a standard proxy URL string that works with any HTTP client that supports proxy configuration.
|
|
408
|
+
|
|
409
|
+
### With undici (ProxyAgent)
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
import { DominusNodeClient } from '@dominusnode/sdk';
|
|
413
|
+
import { ProxyAgent } from 'undici';
|
|
414
|
+
|
|
415
|
+
const client = new DominusNodeClient({ baseUrl: 'https://api.dominusnode.com' });
|
|
416
|
+
await client.connectWithKey('dn_live_key');
|
|
417
|
+
|
|
418
|
+
const proxyUrl = client.proxy.buildUrl('dn_live_key', { country: 'US' });
|
|
419
|
+
const agent = new ProxyAgent(proxyUrl);
|
|
420
|
+
|
|
421
|
+
const response = await fetch('http://httpbin.org/ip', { dispatcher: agent });
|
|
422
|
+
const data = await response.json();
|
|
423
|
+
console.log(data.origin); // US IP address
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### With curl (command line)
|
|
427
|
+
|
|
428
|
+
```bash
|
|
429
|
+
curl -x http://user:dn_live_your_key@proxy.dominusnode.com:8080 http://httpbin.org/ip
|
|
430
|
+
curl -x http://user:dn_live_your_key@proxy.dominusnode.com:8080 https://httpbin.org/ip
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### With axios
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
import axios from 'axios';
|
|
437
|
+
import { HttpsProxyAgent } from 'https-proxy-agent';
|
|
438
|
+
|
|
439
|
+
const proxyUrl = client.proxy.buildUrl('dn_live_key', { country: 'DE' });
|
|
440
|
+
const agent = new HttpsProxyAgent(proxyUrl);
|
|
441
|
+
|
|
442
|
+
const { data } = await axios.get('https://httpbin.org/ip', { httpsAgent: agent });
|
|
443
|
+
console.log(data.origin); // German IP address
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Geo-Targeting Options
|
|
447
|
+
|
|
448
|
+
The proxy URL username field encodes geo-targeting and session parameters using the format `user-param_value-param_value`:
|
|
449
|
+
|
|
450
|
+
| Option | Type | Description | Example |
|
|
451
|
+
|---|---|---|---|
|
|
452
|
+
| `protocol` | `"http"` or `"socks5"` | Proxy protocol (default: `"http"`) | `{ protocol: 'socks5' }` |
|
|
453
|
+
| `country` | `string` | ISO 3166-1 alpha-2 country code | `{ country: 'US' }` |
|
|
454
|
+
| `state` | `string` | State or region name | `{ state: 'california' }` |
|
|
455
|
+
| `city` | `string` | City name (no spaces) | `{ city: 'losangeles' }` |
|
|
456
|
+
| `asn` | `number` | Autonomous System Number | `{ asn: 7922 }` |
|
|
457
|
+
| `sessionId` | `string` | Sticky session identifier | `{ sessionId: 'abc123' }` |
|
|
458
|
+
|
|
459
|
+
## Auto Token Refresh
|
|
460
|
+
|
|
461
|
+
The SDK automatically manages JWT token lifecycle. You do not need to handle token refresh manually.
|
|
462
|
+
|
|
463
|
+
The token refresh flow works as follows:
|
|
464
|
+
|
|
465
|
+
1. Before each request, the SDK checks the access token's `exp` claim (decoded from base64, no crypto library needed).
|
|
466
|
+
2. If the token expires within 60 seconds, the SDK proactively refreshes it using the stored refresh token.
|
|
467
|
+
3. If a request returns 401, the SDK force-refreshes the token and retries the request once.
|
|
468
|
+
4. Concurrent requests that trigger refresh are deduplicated -- only one refresh call is made.
|
|
469
|
+
5. If the refresh token itself is expired or revoked, an `AuthenticationError` is thrown and all stored tokens are cleared.
|
|
470
|
+
|
|
471
|
+
## TypeScript Support
|
|
472
|
+
|
|
473
|
+
All types are exported from the package. Use `import type` for type-only imports:
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
import type {
|
|
477
|
+
// Core types
|
|
478
|
+
User,
|
|
479
|
+
ApiKey,
|
|
480
|
+
Wallet,
|
|
481
|
+
WalletTransaction,
|
|
482
|
+
UsageRecord,
|
|
483
|
+
TopHost,
|
|
484
|
+
Plan,
|
|
485
|
+
ActiveSession,
|
|
486
|
+
ProxyUrlOptions,
|
|
487
|
+
ProxyHealth,
|
|
488
|
+
ProxyConfig,
|
|
489
|
+
StripeCheckout,
|
|
490
|
+
CryptoInvoice,
|
|
491
|
+
AdminUser,
|
|
492
|
+
RevenueStats,
|
|
493
|
+
DailyRevenue,
|
|
494
|
+
SystemStats,
|
|
495
|
+
MfaStatus,
|
|
496
|
+
MfaSetup,
|
|
497
|
+
LoginResult,
|
|
498
|
+
TokenPair,
|
|
499
|
+
|
|
500
|
+
// Config
|
|
501
|
+
DominusNodeConfig,
|
|
502
|
+
|
|
503
|
+
// Response types
|
|
504
|
+
WalletBalanceResponse,
|
|
505
|
+
TransactionsResponse,
|
|
506
|
+
StripeCheckoutResponse,
|
|
507
|
+
CryptoInvoiceResponse,
|
|
508
|
+
ForecastResponse,
|
|
509
|
+
UsageSummary,
|
|
510
|
+
UsageResponse,
|
|
511
|
+
DailyUsageDay,
|
|
512
|
+
DailyUsageResponse,
|
|
513
|
+
TopHostEntry,
|
|
514
|
+
TopHostsResponse,
|
|
515
|
+
PlanEntry,
|
|
516
|
+
ListPlansResponse,
|
|
517
|
+
UserPlanResponse,
|
|
518
|
+
ChangePlanResponse,
|
|
519
|
+
ActiveSessionEntry,
|
|
520
|
+
ActiveSessionsResponse,
|
|
521
|
+
CreateKeyResponse,
|
|
522
|
+
ListKeysResponse,
|
|
523
|
+
ProxyHealthResponse,
|
|
524
|
+
ProxyStatusResponse,
|
|
525
|
+
ListUsersResponse,
|
|
526
|
+
GetUserResponse,
|
|
527
|
+
RevenueResponse,
|
|
528
|
+
DailyRevenueEntry,
|
|
529
|
+
DailyRevenueResponse,
|
|
530
|
+
} from '@dominusnode/sdk';
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
## CommonJS Usage
|
|
534
|
+
|
|
535
|
+
The SDK ships dual CJS + ESM builds. CommonJS usage works with `require()`:
|
|
536
|
+
|
|
537
|
+
```javascript
|
|
538
|
+
const { DominusNodeClient } = require('@dominusnode/sdk');
|
|
539
|
+
|
|
540
|
+
async function main() {
|
|
541
|
+
const client = new DominusNodeClient({ baseUrl: 'https://api.dominusnode.com' });
|
|
542
|
+
await client.connectWithKey('dn_live_your_key');
|
|
543
|
+
|
|
544
|
+
const balance = await client.wallet.getBalance();
|
|
545
|
+
console.log(`Balance: $${balance.balanceUsd}`);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
main().catch(console.error);
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
## Complete Example
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
import { DominusNodeClient, AuthenticationError, InsufficientBalanceError } from '@dominusnode/sdk';
|
|
555
|
+
|
|
556
|
+
async function main() {
|
|
557
|
+
// Initialize client
|
|
558
|
+
const client = new DominusNodeClient({
|
|
559
|
+
baseUrl: 'https://api.dominusnode.com',
|
|
560
|
+
proxyHost: 'proxy.dominusnode.com',
|
|
561
|
+
httpProxyPort: 8080,
|
|
562
|
+
socks5ProxyPort: 1080,
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
try {
|
|
566
|
+
// Authenticate
|
|
567
|
+
await client.connectWithKey('dn_live_your_api_key');
|
|
568
|
+
|
|
569
|
+
// Check who we are
|
|
570
|
+
const { user } = await client.auth.me();
|
|
571
|
+
console.log(`Logged in as: ${user.email}`);
|
|
572
|
+
|
|
573
|
+
// Check balance
|
|
574
|
+
const balance = await client.wallet.getBalance();
|
|
575
|
+
console.log(`Balance: $${balance.balanceUsd} (${balance.balanceCents} cents)`);
|
|
576
|
+
|
|
577
|
+
// If balance is low, create a Stripe checkout
|
|
578
|
+
if (balance.balanceCents < 500) {
|
|
579
|
+
const checkout = await client.wallet.topUpStripe(2000); // $20.00
|
|
580
|
+
console.log(`Top up here: ${checkout.url}`);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// List API keys
|
|
584
|
+
const { keys } = await client.keys.list();
|
|
585
|
+
console.log(`You have ${keys.length} API key(s)`);
|
|
586
|
+
|
|
587
|
+
// Check current plan
|
|
588
|
+
const plan = await client.plans.getUserPlan();
|
|
589
|
+
console.log(`Plan: ${plan.plan.name} ($${plan.plan.pricePerGbUsd}/GB)`);
|
|
590
|
+
if (plan.usage.percentUsed !== null) {
|
|
591
|
+
console.log(`Monthly usage: ${plan.usage.percentUsed.toFixed(1)}%`);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Get usage stats for this month
|
|
595
|
+
const now = new Date();
|
|
596
|
+
const firstOfMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-01`;
|
|
597
|
+
const usage = await client.usage.get({ from: firstOfMonth });
|
|
598
|
+
console.log(`This month: ${usage.summary.totalGB.toFixed(2)} GB, $${usage.summary.totalCostUsd}`);
|
|
599
|
+
|
|
600
|
+
// Build a geo-targeted proxy URL
|
|
601
|
+
const proxyUrl = client.proxy.buildUrl('dn_live_your_api_key', {
|
|
602
|
+
country: 'US',
|
|
603
|
+
state: 'california',
|
|
604
|
+
});
|
|
605
|
+
console.log(`Proxy URL: ${proxyUrl}`);
|
|
606
|
+
|
|
607
|
+
// Check active sessions
|
|
608
|
+
const sessions = await client.sessions.getActive();
|
|
609
|
+
console.log(`Active sessions: ${sessions.sessions.length}`);
|
|
610
|
+
|
|
611
|
+
} catch (err) {
|
|
612
|
+
if (err instanceof AuthenticationError) {
|
|
613
|
+
console.error('Authentication failed:', err.message);
|
|
614
|
+
} else if (err instanceof InsufficientBalanceError) {
|
|
615
|
+
console.error('Insufficient balance:', err.message);
|
|
616
|
+
} else {
|
|
617
|
+
throw err;
|
|
618
|
+
}
|
|
619
|
+
} finally {
|
|
620
|
+
client.disconnect();
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
main();
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
## API Reference Summary
|
|
628
|
+
|
|
629
|
+
| Resource | Method | Description |
|
|
630
|
+
|---|---|---|
|
|
631
|
+
| `auth` | `register(email, password)` | Create a new account |
|
|
632
|
+
| `auth` | `login(email, password)` | Login with credentials |
|
|
633
|
+
| `auth` | `verifyMfa(code, opts?)` | Complete MFA verification |
|
|
634
|
+
| `auth` | `mfaSetup()` | Begin MFA setup (returns secret + backup codes) |
|
|
635
|
+
| `auth` | `mfaEnable(code)` | Confirm and enable MFA |
|
|
636
|
+
| `auth` | `mfaDisable(password, code)` | Disable MFA |
|
|
637
|
+
| `auth` | `mfaStatus()` | Check MFA status |
|
|
638
|
+
| `auth` | `changePassword(current, new)` | Change password |
|
|
639
|
+
| `auth` | `logout()` | Revoke refresh tokens server-side |
|
|
640
|
+
| `auth` | `me()` | Get current user info |
|
|
641
|
+
| `auth` | `verifyKey(apiKey)` | Exchange API key for JWT tokens |
|
|
642
|
+
| `auth` | `refresh(refreshToken)` | Refresh access token (used internally) |
|
|
643
|
+
| `keys` | `create(label?)` | Create a new API key |
|
|
644
|
+
| `keys` | `list()` | List all API keys |
|
|
645
|
+
| `keys` | `revoke(id)` | Revoke an API key |
|
|
646
|
+
| `wallet` | `getBalance()` | Get current balance |
|
|
647
|
+
| `wallet` | `getTransactions(opts?)` | Transaction history (paginated) |
|
|
648
|
+
| `wallet` | `topUpStripe(amountCents)` | Create Stripe checkout session |
|
|
649
|
+
| `wallet` | `topUpCrypto(amountCents, currency)` | Create crypto invoice |
|
|
650
|
+
| `wallet` | `getForecast()` | Spending forecast |
|
|
651
|
+
| `usage` | `get(opts?)` | Usage records with summary |
|
|
652
|
+
| `usage` | `getDaily(opts?)` | Daily usage aggregation |
|
|
653
|
+
| `usage` | `getTopHosts(opts?)` | Top target hosts by bandwidth |
|
|
654
|
+
| `usage` | `exportCsv(opts?)` | Export usage as CSV |
|
|
655
|
+
| `plans` | `list()` | List available plans |
|
|
656
|
+
| `plans` | `getUserPlan()` | Get current user's plan |
|
|
657
|
+
| `plans` | `changePlan(planId)` | Change plan |
|
|
658
|
+
| `sessions` | `getActive()` | Get active proxy sessions |
|
|
659
|
+
| `proxy` | `buildUrl(apiKey, opts?)` | Build proxy URL string (no network call) |
|
|
660
|
+
| `proxy` | `getHealth()` | Proxy health (no auth) |
|
|
661
|
+
| `proxy` | `getStatus()` | Proxy status with provider info |
|
|
662
|
+
| `proxy` | `getConfig()` | Proxy configuration |
|
|
663
|
+
| `admin` | `listUsers(opts?)` | List all users (paginated) |
|
|
664
|
+
| `admin` | `getUser(id)` | Get user details |
|
|
665
|
+
| `admin` | `suspendUser(id)` | Suspend a user |
|
|
666
|
+
| `admin` | `activateUser(id)` | Reactivate a user |
|
|
667
|
+
| `admin` | `deleteUser(id)` | Soft-delete a user |
|
|
668
|
+
| `admin` | `getRevenue(opts?)` | Revenue statistics |
|
|
669
|
+
| `admin` | `getDailyRevenue(opts?)` | Daily revenue breakdown |
|
|
670
|
+
| `admin` | `getStats()` | System-wide statistics |
|
|
671
|
+
|
|
672
|
+
## Requirements
|
|
673
|
+
|
|
674
|
+
- **Node.js 18+** (uses built-in `fetch` -- no polyfill needed)
|
|
675
|
+
- **No external dependencies** -- the SDK has zero production dependencies
|
|
676
|
+
|
|
677
|
+
## License
|
|
678
|
+
|
|
679
|
+
MIT
|