@ktmcp-cli/nowpayments 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/.env.example +17 -0
- package/AGENT.md +513 -0
- package/INSTALL.md +392 -0
- package/LICENSE +21 -0
- package/OPENCLAW.md +628 -0
- package/PROJECT_SUMMARY.md +305 -0
- package/README.md +375 -0
- package/banner.png +0 -0
- package/bin/nowpayments.js +89 -0
- package/examples/basic-payment.js +66 -0
- package/examples/invoice-flow.js +78 -0
- package/examples/monitor-payment.js +94 -0
- package/logo.png +0 -0
- package/openapi.json +2791 -0
- package/package.json +40 -0
- package/src/commands/auth.js +65 -0
- package/src/commands/currencies.js +95 -0
- package/src/commands/estimate.js +85 -0
- package/src/commands/invoice.js +188 -0
- package/src/commands/payment.js +241 -0
- package/src/commands/payout.js +184 -0
- package/src/commands/status.js +28 -0
- package/src/lib/api.js +133 -0
- package/src/lib/auth.js +70 -0
- package/src/lib/config.js +110 -0
- package/test.sh +250 -0
package/.env.example
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# NOWPayments CLI Environment Configuration
|
|
2
|
+
|
|
3
|
+
# API Key (required)
|
|
4
|
+
# Get your API key from: https://nowpayments.io
|
|
5
|
+
NOWPAYMENTS_API_KEY=your_api_key_here
|
|
6
|
+
|
|
7
|
+
# Use sandbox environment (optional)
|
|
8
|
+
# Set to true for testing, false for production
|
|
9
|
+
NOWPAYMENTS_SANDBOX=false
|
|
10
|
+
|
|
11
|
+
# IPN Secret for webhook verification (optional)
|
|
12
|
+
# Used to verify IPN callback signatures
|
|
13
|
+
NOWPAYMENTS_IPN_SECRET=your_ipn_secret
|
|
14
|
+
|
|
15
|
+
# Default currencies (optional)
|
|
16
|
+
NOWPAYMENTS_DEFAULT_CURRENCY=USD
|
|
17
|
+
NOWPAYMENTS_DEFAULT_PAY_CURRENCY=BTC
|
package/AGENT.md
ADDED
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
# NOWPayments CLI - AI Agent Usage Guide
|
|
2
|
+
|
|
3
|
+
This guide provides patterns and examples for AI assistants (like Claude, ChatGPT, or custom agents) using the NOWPayments CLI.
|
|
4
|
+
|
|
5
|
+
## Why This CLI is Agent-Friendly
|
|
6
|
+
|
|
7
|
+
1. **Predictable JSON Output**: Use `--json` flag for consistent, parseable responses
|
|
8
|
+
2. **Clear Exit Codes**: Success (0) and failure (1) for easy status checking
|
|
9
|
+
3. **Composable Commands**: Unix philosophy - do one thing well
|
|
10
|
+
4. **Self-Documenting**: Built-in help text for all commands
|
|
11
|
+
5. **Error Messages**: Structured, informative error responses
|
|
12
|
+
|
|
13
|
+
## Agent Integration Patterns
|
|
14
|
+
|
|
15
|
+
### Pattern 1: Status Checking
|
|
16
|
+
|
|
17
|
+
Before executing operations, verify API connectivity:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
nowpayments status
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Agent Decision Tree:**
|
|
24
|
+
- Success → Proceed with operations
|
|
25
|
+
- Failure → Inform user of connectivity issues
|
|
26
|
+
|
|
27
|
+
### Pattern 2: Currency Validation
|
|
28
|
+
|
|
29
|
+
Before creating payments, validate cryptocurrency support:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Check if BTC is supported
|
|
33
|
+
nowpayments currencies info BTC
|
|
34
|
+
|
|
35
|
+
# Get all available currencies
|
|
36
|
+
nowpayments --json currencies list --available
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Agent Logic:**
|
|
40
|
+
```javascript
|
|
41
|
+
// Pseudo-code for agent
|
|
42
|
+
const result = await exec('nowpayments --json currencies list --available');
|
|
43
|
+
const data = JSON.parse(result.stdout);
|
|
44
|
+
const currencies = data.currencies || [];
|
|
45
|
+
|
|
46
|
+
if (!currencies.includes(requestedCurrency.toLowerCase())) {
|
|
47
|
+
return "Currency not supported. Available: " + currencies.join(', ');
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Pattern 3: Price Estimation
|
|
52
|
+
|
|
53
|
+
Always estimate before creating payments:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
nowpayments --json estimate convert \
|
|
57
|
+
--from USD \
|
|
58
|
+
--to BTC \
|
|
59
|
+
--amount 100
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Agent Flow:**
|
|
63
|
+
1. Get user's desired amount and currencies
|
|
64
|
+
2. Call estimate to get conversion
|
|
65
|
+
3. Present estimate to user
|
|
66
|
+
4. Wait for confirmation before creating payment
|
|
67
|
+
|
|
68
|
+
### Pattern 4: Payment Creation
|
|
69
|
+
|
|
70
|
+
Create payments with all required parameters:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
nowpayments --json payment create \
|
|
74
|
+
--price 99.99 \
|
|
75
|
+
--currency USD \
|
|
76
|
+
--pay-currency BTC \
|
|
77
|
+
--order-id "ORDER-${timestamp}" \
|
|
78
|
+
--order-description "User's description"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Agent Best Practices:**
|
|
82
|
+
- Generate unique `order-id` (timestamp, UUID, etc.)
|
|
83
|
+
- Include descriptive `order-description`
|
|
84
|
+
- Store `payment_id` for tracking
|
|
85
|
+
- Present `pay_address` and `pay_amount` clearly to user
|
|
86
|
+
|
|
87
|
+
### Pattern 5: Payment Monitoring
|
|
88
|
+
|
|
89
|
+
Poll payment status at reasonable intervals:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
nowpayments --json payment get <payment_id>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Agent Polling Logic:**
|
|
96
|
+
```javascript
|
|
97
|
+
async function monitorPayment(paymentId, maxMinutes = 30) {
|
|
98
|
+
const startTime = Date.now();
|
|
99
|
+
const maxTime = maxMinutes * 60 * 1000;
|
|
100
|
+
|
|
101
|
+
while (Date.now() - startTime < maxTime) {
|
|
102
|
+
const result = await exec(`nowpayments --json payment get ${paymentId}`);
|
|
103
|
+
const payment = JSON.parse(result.stdout);
|
|
104
|
+
|
|
105
|
+
switch (payment.payment_status) {
|
|
106
|
+
case 'finished':
|
|
107
|
+
return { status: 'completed', payment };
|
|
108
|
+
case 'failed':
|
|
109
|
+
case 'expired':
|
|
110
|
+
return { status: 'failed', payment };
|
|
111
|
+
case 'partially_paid':
|
|
112
|
+
return { status: 'underpaid', payment };
|
|
113
|
+
default:
|
|
114
|
+
// Still processing, wait before next check
|
|
115
|
+
await sleep(30000); // 30 seconds
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return { status: 'timeout' };
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Pattern 6: Error Handling
|
|
124
|
+
|
|
125
|
+
Parse errors and provide helpful responses:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
nowpayments --json payment get invalid_id 2>&1
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Agent Error Response:**
|
|
132
|
+
```javascript
|
|
133
|
+
try {
|
|
134
|
+
const result = await exec('nowpayments --json payment get invalid_id');
|
|
135
|
+
const data = JSON.parse(result.stdout);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
// Parse error output
|
|
138
|
+
const errorMsg = error.stderr || error.message;
|
|
139
|
+
|
|
140
|
+
if (errorMsg.includes('API Error (401)')) {
|
|
141
|
+
return "Authentication failed. Please check your API key.";
|
|
142
|
+
} else if (errorMsg.includes('API Error (404)')) {
|
|
143
|
+
return "Payment not found. Please verify the payment ID.";
|
|
144
|
+
} else if (errorMsg.includes('Network error')) {
|
|
145
|
+
return "Cannot reach NOWPayments API. Check internet connection.";
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return "An error occurred: " + errorMsg;
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Common Agent Workflows
|
|
153
|
+
|
|
154
|
+
### Workflow 1: Create Payment
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Step 1: Validate currency
|
|
158
|
+
nowpayments currencies info BTC
|
|
159
|
+
|
|
160
|
+
# Step 2: Get estimate
|
|
161
|
+
nowpayments --json estimate convert \
|
|
162
|
+
--from USD \
|
|
163
|
+
--to BTC \
|
|
164
|
+
--amount 100
|
|
165
|
+
|
|
166
|
+
# Step 3: Create payment
|
|
167
|
+
nowpayments --json payment create \
|
|
168
|
+
--price 100 \
|
|
169
|
+
--currency USD \
|
|
170
|
+
--pay-currency BTC \
|
|
171
|
+
--order-id "ORDER-123"
|
|
172
|
+
|
|
173
|
+
# Step 4: Monitor status
|
|
174
|
+
nowpayments --json payment get <payment_id>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Agent Narrative:**
|
|
178
|
+
```
|
|
179
|
+
I'll help you create a Bitcoin payment for $100.
|
|
180
|
+
|
|
181
|
+
1. Validating BTC support... ✓
|
|
182
|
+
2. Getting current exchange rate...
|
|
183
|
+
- Rate: 0.00234 BTC = $100 USD
|
|
184
|
+
3. Creating payment...
|
|
185
|
+
- Payment ID: abc123
|
|
186
|
+
- Send exactly 0.00234 BTC to: bc1qxy2kg...
|
|
187
|
+
- Expires in: 1 hour
|
|
188
|
+
4. I'll monitor this payment for you.
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Workflow 2: List and Filter Payments
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Get recent payments
|
|
195
|
+
nowpayments --json payment list --limit 10 --order desc
|
|
196
|
+
|
|
197
|
+
# Filter by date range
|
|
198
|
+
nowpayments --json payment list \
|
|
199
|
+
--date-from 2024-01-01 \
|
|
200
|
+
--date-to 2024-01-31
|
|
201
|
+
|
|
202
|
+
# Find specific payment
|
|
203
|
+
nowpayments --json payment get abc123
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Agent Context Awareness:**
|
|
207
|
+
```javascript
|
|
208
|
+
// Agent keeps track of recent payments
|
|
209
|
+
const recentPayments = await getRecentPayments();
|
|
210
|
+
|
|
211
|
+
// When user says "check my last payment"
|
|
212
|
+
const lastPayment = recentPayments[0];
|
|
213
|
+
const status = await exec(`nowpayments --json payment get ${lastPayment.id}`);
|
|
214
|
+
|
|
215
|
+
// Present status in natural language
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Workflow 3: Invoice Management
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# Create invoice
|
|
222
|
+
nowpayments --json invoice create \
|
|
223
|
+
--price 49.99 \
|
|
224
|
+
--currency USD \
|
|
225
|
+
--order-id "INV-456" \
|
|
226
|
+
--success-url "https://example.com/success"
|
|
227
|
+
|
|
228
|
+
# Share invoice URL with user
|
|
229
|
+
# Returns: { "invoice_url": "https://nowpayments.io/payment/?iid=..." }
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Agent Response:**
|
|
233
|
+
```
|
|
234
|
+
I've created an invoice for $49.99:
|
|
235
|
+
|
|
236
|
+
Invoice ID: 1234567
|
|
237
|
+
Payment URL: https://nowpayments.io/payment/?iid=abc123
|
|
238
|
+
|
|
239
|
+
Share this link with your customer. They can pay with any supported cryptocurrency.
|
|
240
|
+
When payment is complete, they'll be redirected to your success page.
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Advanced Agent Techniques
|
|
244
|
+
|
|
245
|
+
### Technique 1: Batch Operations
|
|
246
|
+
|
|
247
|
+
Process multiple payments efficiently:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# List all waiting payments
|
|
251
|
+
payments=$(nowpayments --json payment list --limit 100)
|
|
252
|
+
|
|
253
|
+
# Check each one
|
|
254
|
+
echo "$payments" | jq -r '.data[] | select(.payment_status == "waiting") | .payment_id' | \
|
|
255
|
+
while read payment_id; do
|
|
256
|
+
nowpayments --json payment get "$payment_id"
|
|
257
|
+
done
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Technique 2: Smart Retries
|
|
261
|
+
|
|
262
|
+
Implement exponential backoff for API calls:
|
|
263
|
+
|
|
264
|
+
```javascript
|
|
265
|
+
async function withRetry(command, maxRetries = 3) {
|
|
266
|
+
for (let i = 0; i < maxRetries; i++) {
|
|
267
|
+
try {
|
|
268
|
+
return await exec(command);
|
|
269
|
+
} catch (error) {
|
|
270
|
+
if (i === maxRetries - 1) throw error;
|
|
271
|
+
|
|
272
|
+
const delay = Math.pow(2, i) * 1000; // Exponential backoff
|
|
273
|
+
await sleep(delay);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Technique 3: Caching Currency Lists
|
|
280
|
+
|
|
281
|
+
Cache currency list to reduce API calls:
|
|
282
|
+
|
|
283
|
+
```javascript
|
|
284
|
+
let currencyCache = null;
|
|
285
|
+
let cacheTime = null;
|
|
286
|
+
const CACHE_TTL = 3600000; // 1 hour
|
|
287
|
+
|
|
288
|
+
async function getAvailableCurrencies() {
|
|
289
|
+
const now = Date.now();
|
|
290
|
+
|
|
291
|
+
if (currencyCache && (now - cacheTime) < CACHE_TTL) {
|
|
292
|
+
return currencyCache;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const result = await exec('nowpayments --json currencies list --available');
|
|
296
|
+
currencyCache = JSON.parse(result.stdout);
|
|
297
|
+
cacheTime = now;
|
|
298
|
+
|
|
299
|
+
return currencyCache;
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Technique 4: Context Preservation
|
|
304
|
+
|
|
305
|
+
Maintain payment context across conversation:
|
|
306
|
+
|
|
307
|
+
```javascript
|
|
308
|
+
// Agent maintains session state
|
|
309
|
+
const session = {
|
|
310
|
+
currentPayment: null,
|
|
311
|
+
recentPayments: [],
|
|
312
|
+
preferences: {
|
|
313
|
+
defaultCurrency: 'USD',
|
|
314
|
+
defaultPayCurrency: 'BTC'
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// When user says "check the status"
|
|
319
|
+
if (session.currentPayment) {
|
|
320
|
+
const status = await checkPayment(session.currentPayment.id);
|
|
321
|
+
return formatStatus(status);
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Output Formatting for Users
|
|
326
|
+
|
|
327
|
+
### Format Payment Details
|
|
328
|
+
|
|
329
|
+
```javascript
|
|
330
|
+
function formatPayment(payment) {
|
|
331
|
+
return `
|
|
332
|
+
Payment Details:
|
|
333
|
+
- Status: ${payment.payment_status}
|
|
334
|
+
- Amount: ${payment.pay_amount} ${payment.pay_currency}
|
|
335
|
+
- Price: ${payment.price_amount} ${payment.price_currency}
|
|
336
|
+
- Address: ${payment.pay_address}
|
|
337
|
+
- Created: ${new Date(payment.created_at).toLocaleString()}
|
|
338
|
+
${payment.order_id ? `- Order: ${payment.order_id}` : ''}
|
|
339
|
+
`.trim();
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Format Currency List
|
|
344
|
+
|
|
345
|
+
```javascript
|
|
346
|
+
function formatCurrencies(currencies) {
|
|
347
|
+
const popular = ['BTC', 'ETH', 'USDT', 'USDC', 'LTC'];
|
|
348
|
+
const others = currencies.filter(c => !popular.includes(c.toUpperCase()));
|
|
349
|
+
|
|
350
|
+
return `
|
|
351
|
+
Popular Cryptocurrencies:
|
|
352
|
+
${popular.map(c => ` • ${c}`).join('\n')}
|
|
353
|
+
|
|
354
|
+
Other Available (${others.length}):
|
|
355
|
+
${others.slice(0, 10).map(c => ` • ${c.toUpperCase()}`).join('\n')}
|
|
356
|
+
${others.length > 10 ? ` ... and ${others.length - 10} more` : ''}
|
|
357
|
+
`.trim();
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
## Security Considerations
|
|
362
|
+
|
|
363
|
+
### 1. API Key Management
|
|
364
|
+
|
|
365
|
+
Never expose API keys in logs or responses:
|
|
366
|
+
|
|
367
|
+
```javascript
|
|
368
|
+
// ✗ Bad
|
|
369
|
+
console.log(`Using API key: ${apiKey}`);
|
|
370
|
+
|
|
371
|
+
// ✓ Good
|
|
372
|
+
console.log(`API key configured: ${apiKey.substring(0, 4)}...`);
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### 2. Input Validation
|
|
376
|
+
|
|
377
|
+
Validate user inputs before passing to CLI:
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
function validateAmount(amount) {
|
|
381
|
+
const num = parseFloat(amount);
|
|
382
|
+
if (isNaN(num) || num <= 0) {
|
|
383
|
+
throw new Error('Amount must be a positive number');
|
|
384
|
+
}
|
|
385
|
+
return num;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function validateCurrency(currency) {
|
|
389
|
+
if (!/^[A-Z]{3,5}$/.test(currency.toUpperCase())) {
|
|
390
|
+
throw new Error('Invalid currency format');
|
|
391
|
+
}
|
|
392
|
+
return currency.toUpperCase();
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### 3. Address Validation
|
|
397
|
+
|
|
398
|
+
Validate cryptocurrency addresses before payouts:
|
|
399
|
+
|
|
400
|
+
```javascript
|
|
401
|
+
// Basic validation (use proper library in production)
|
|
402
|
+
function validateBtcAddress(address) {
|
|
403
|
+
if (address.startsWith('bc1') && address.length >= 42) {
|
|
404
|
+
return true; // Bech32
|
|
405
|
+
}
|
|
406
|
+
if (/^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/.test(address)) {
|
|
407
|
+
return true; // Legacy
|
|
408
|
+
}
|
|
409
|
+
throw new Error('Invalid Bitcoin address');
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## Testing Agent Integration
|
|
414
|
+
|
|
415
|
+
### Unit Test Example
|
|
416
|
+
|
|
417
|
+
```javascript
|
|
418
|
+
describe('Payment Creation', () => {
|
|
419
|
+
it('should create payment with valid parameters', async () => {
|
|
420
|
+
const result = await exec(`nowpayments --json payment create \
|
|
421
|
+
--price 100 \
|
|
422
|
+
--currency USD \
|
|
423
|
+
--pay-currency BTC`);
|
|
424
|
+
|
|
425
|
+
const payment = JSON.parse(result.stdout);
|
|
426
|
+
expect(payment.payment_id).toBeDefined();
|
|
427
|
+
expect(payment.pay_address).toBeDefined();
|
|
428
|
+
expect(payment.payment_status).toBe('waiting');
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('should fail with invalid amount', async () => {
|
|
432
|
+
await expect(
|
|
433
|
+
exec(`nowpayments payment create --price -10 --currency USD --pay-currency BTC`)
|
|
434
|
+
).rejects.toThrow();
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Integration Test Example
|
|
440
|
+
|
|
441
|
+
```javascript
|
|
442
|
+
describe('Full Payment Flow', () => {
|
|
443
|
+
it('should handle complete payment lifecycle', async () => {
|
|
444
|
+
// Create payment
|
|
445
|
+
const createResult = await exec(`nowpayments --json payment create \
|
|
446
|
+
--price 100 --currency USD --pay-currency BTC`);
|
|
447
|
+
const payment = JSON.parse(createResult.stdout);
|
|
448
|
+
|
|
449
|
+
// Verify payment exists
|
|
450
|
+
const getResult = await exec(`nowpayments --json payment get ${payment.payment_id}`);
|
|
451
|
+
const retrieved = JSON.parse(getResult.stdout);
|
|
452
|
+
|
|
453
|
+
expect(retrieved.payment_id).toBe(payment.payment_id);
|
|
454
|
+
expect(retrieved.payment_status).toBe('waiting');
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
## Performance Tips
|
|
460
|
+
|
|
461
|
+
1. **Use JSON mode**: Faster parsing than formatted output
|
|
462
|
+
2. **Batch requests**: Combine operations where possible
|
|
463
|
+
3. **Cache static data**: Currency lists don't change often
|
|
464
|
+
4. **Reasonable polling**: Don't check payment status more than once per 30 seconds
|
|
465
|
+
5. **Parallel requests**: Independent operations can run concurrently
|
|
466
|
+
|
|
467
|
+
## Troubleshooting
|
|
468
|
+
|
|
469
|
+
### Issue: "No API key found"
|
|
470
|
+
|
|
471
|
+
```javascript
|
|
472
|
+
// Check multiple sources
|
|
473
|
+
const apiKey = process.env.NOWPAYMENTS_API_KEY ||
|
|
474
|
+
await getFromConfig() ||
|
|
475
|
+
await promptUser();
|
|
476
|
+
|
|
477
|
+
if (!apiKey) {
|
|
478
|
+
return "Please set your API key: nowpayments auth set YOUR_KEY";
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### Issue: Rate limiting
|
|
483
|
+
|
|
484
|
+
```javascript
|
|
485
|
+
if (error.includes('429') || error.includes('rate limit')) {
|
|
486
|
+
return "API rate limit reached. Please wait a moment and try again.";
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Issue: Network errors
|
|
491
|
+
|
|
492
|
+
```javascript
|
|
493
|
+
if (error.includes('ENOTFOUND') || error.includes('Network error')) {
|
|
494
|
+
return "Cannot connect to NOWPayments. Check your internet connection.";
|
|
495
|
+
}
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
## Best Practices Summary
|
|
499
|
+
|
|
500
|
+
1. Always use `--json` for programmatic access
|
|
501
|
+
2. Validate inputs before calling CLI
|
|
502
|
+
3. Handle all error cases gracefully
|
|
503
|
+
4. Provide clear, natural language responses
|
|
504
|
+
5. Cache where appropriate
|
|
505
|
+
6. Monitor but don't spam (reasonable polling intervals)
|
|
506
|
+
7. Keep context between commands
|
|
507
|
+
8. Test error paths thoroughly
|
|
508
|
+
9. Never expose sensitive data in logs
|
|
509
|
+
10. Use proper exit code checking
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
This CLI is designed to be a reliable tool for AI agents to integrate cryptocurrency payments into their workflows. The combination of structured JSON output, clear error handling, and comprehensive commands makes it ideal for autonomous operation.
|