@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/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ktmcp-cli/nowpayments",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Production-ready CLI for NOWPayments cryptocurrency payment processing API",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"nowpayments": "./bin/nowpayments.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/nowpayments.js",
|
|
11
|
+
"test": "node --test",
|
|
12
|
+
"lint": "eslint ."
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"nowpayments",
|
|
16
|
+
"cryptocurrency",
|
|
17
|
+
"payment",
|
|
18
|
+
"cli",
|
|
19
|
+
"crypto",
|
|
20
|
+
"bitcoin",
|
|
21
|
+
"ethereum",
|
|
22
|
+
"commander"
|
|
23
|
+
],
|
|
24
|
+
"author": "KTMCP",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=16.0.0"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"commander": "^12.0.0",
|
|
31
|
+
"chalk": "^4.1.2",
|
|
32
|
+
"ora": "^5.4.1",
|
|
33
|
+
"dotenv": "^16.4.1",
|
|
34
|
+
"node-fetch": "^2.7.0",
|
|
35
|
+
"cli-table3": "^0.6.3"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"eslint": "^8.56.0"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication command
|
|
3
|
+
*
|
|
4
|
+
* Manage API keys and authentication configuration.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Command } = require('commander');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const { setConfig, getConfig, CONFIG_FILE } = require('../lib/config');
|
|
10
|
+
const { validateApiKeyFormat } = require('../lib/auth');
|
|
11
|
+
|
|
12
|
+
const command = new Command('auth');
|
|
13
|
+
|
|
14
|
+
command
|
|
15
|
+
.description('Manage API authentication')
|
|
16
|
+
.summary('Configure and manage API keys');
|
|
17
|
+
|
|
18
|
+
// Set API key
|
|
19
|
+
command
|
|
20
|
+
.command('set <api-key>')
|
|
21
|
+
.description('Save API key to config file')
|
|
22
|
+
.action((apiKey) => {
|
|
23
|
+
if (!validateApiKeyFormat(apiKey)) {
|
|
24
|
+
console.error(chalk.red('Error: Invalid API key format'));
|
|
25
|
+
console.error(chalk.yellow('API keys should be 20-100 alphanumeric characters'));
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setConfig('apiKey', apiKey);
|
|
30
|
+
console.log(chalk.green('✓ API key saved successfully'));
|
|
31
|
+
console.log(chalk.gray(`Config file: ${CONFIG_FILE}`));
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Show current API key (masked)
|
|
35
|
+
command
|
|
36
|
+
.command('show')
|
|
37
|
+
.description('Display current API key configuration (masked)')
|
|
38
|
+
.action(() => {
|
|
39
|
+
const apiKey = getConfig('apiKey');
|
|
40
|
+
|
|
41
|
+
if (!apiKey) {
|
|
42
|
+
console.log(chalk.yellow('No API key configured'));
|
|
43
|
+
console.log(chalk.gray('\nSet an API key with: nowpayments auth set YOUR_KEY'));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Mask the API key (show first 4 and last 4 characters)
|
|
48
|
+
const masked = apiKey.length > 8
|
|
49
|
+
? `${apiKey.substring(0, 4)}${'*'.repeat(apiKey.length - 8)}${apiKey.substring(apiKey.length - 4)}`
|
|
50
|
+
: '*'.repeat(apiKey.length);
|
|
51
|
+
|
|
52
|
+
console.log(chalk.cyan('API Key:'), masked);
|
|
53
|
+
console.log(chalk.gray(`Config file: ${CONFIG_FILE}`));
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Clear API key
|
|
57
|
+
command
|
|
58
|
+
.command('clear')
|
|
59
|
+
.description('Remove API key from config')
|
|
60
|
+
.action(() => {
|
|
61
|
+
setConfig('apiKey', null);
|
|
62
|
+
console.log(chalk.green('✓ API key cleared'));
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
module.exports = command;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Currencies command
|
|
3
|
+
*
|
|
4
|
+
* List and query available cryptocurrencies.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Command } = require('commander');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const Table = require('cli-table3');
|
|
10
|
+
const { makeRequest, handleApiError, displayResponse } = require('../lib/api');
|
|
11
|
+
|
|
12
|
+
const command = new Command('currencies');
|
|
13
|
+
|
|
14
|
+
command
|
|
15
|
+
.description('List available currencies')
|
|
16
|
+
.summary('Query supported cryptocurrencies');
|
|
17
|
+
|
|
18
|
+
// List all available currencies
|
|
19
|
+
command
|
|
20
|
+
.command('list')
|
|
21
|
+
.description('List all available cryptocurrencies')
|
|
22
|
+
.option('-a, --available', 'Show only available currencies for payments')
|
|
23
|
+
.option('-s, --selected', 'Show only selected currencies')
|
|
24
|
+
.action(async (options) => {
|
|
25
|
+
try {
|
|
26
|
+
let endpoint = '/currencies';
|
|
27
|
+
|
|
28
|
+
if (options.available) {
|
|
29
|
+
endpoint = '/merchant/coins';
|
|
30
|
+
} else if (options.selected) {
|
|
31
|
+
endpoint = '/currencies?fixed_rate=true';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const data = await makeRequest(command.parent.parent, endpoint);
|
|
35
|
+
|
|
36
|
+
displayResponse(command.parent.parent, data, (response) => {
|
|
37
|
+
const currencies = response.selectedCurrencies || response.currencies || [];
|
|
38
|
+
|
|
39
|
+
if (!currencies || currencies.length === 0) {
|
|
40
|
+
console.log(chalk.yellow('No currencies found'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log(chalk.cyan(`\nAvailable Currencies: ${currencies.length}`));
|
|
45
|
+
|
|
46
|
+
// Display as formatted list
|
|
47
|
+
const columns = 4;
|
|
48
|
+
for (let i = 0; i < currencies.length; i += columns) {
|
|
49
|
+
const row = currencies.slice(i, i + columns);
|
|
50
|
+
console.log(' ' + row.map(c => chalk.bold(c.toUpperCase())).join(' '));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
} catch (error) {
|
|
54
|
+
handleApiError(error);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Get currency details
|
|
59
|
+
command
|
|
60
|
+
.command('info <currency>')
|
|
61
|
+
.description('Get information about a specific currency')
|
|
62
|
+
.action(async (currency) => {
|
|
63
|
+
try {
|
|
64
|
+
// First get all currencies
|
|
65
|
+
const data = await makeRequest(command.parent.parent, '/currencies');
|
|
66
|
+
|
|
67
|
+
const currencies = data.currencies || [];
|
|
68
|
+
const currencyUpper = currency.toUpperCase();
|
|
69
|
+
|
|
70
|
+
if (currencies.includes(currencyUpper.toLowerCase())) {
|
|
71
|
+
console.log(chalk.cyan('\nCurrency:'), chalk.bold(currencyUpper));
|
|
72
|
+
console.log(chalk.green('✓ Supported by NOWPayments'));
|
|
73
|
+
|
|
74
|
+
// Get minimum amount
|
|
75
|
+
try {
|
|
76
|
+
const minData = await makeRequest(command.parent.parent, '/min-amount', {
|
|
77
|
+
queryParams: { currency_from: 'USD', currency_to: currencyUpper }
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
if (minData.min_amount) {
|
|
81
|
+
console.log(chalk.cyan('Minimum amount:'), minData.min_amount, currencyUpper);
|
|
82
|
+
}
|
|
83
|
+
} catch (e) {
|
|
84
|
+
// Minimum amount not available
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
console.log(chalk.red(`\n✗ Currency ${currencyUpper} is not supported`));
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
handleApiError(error);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
module.exports = command;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Estimate command
|
|
3
|
+
*
|
|
4
|
+
* Calculate cryptocurrency price estimates and conversions.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Command } = require('commander');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const { makeRequest, handleApiError, displayResponse } = require('../lib/api');
|
|
10
|
+
|
|
11
|
+
const command = new Command('estimate');
|
|
12
|
+
|
|
13
|
+
command
|
|
14
|
+
.description('Estimate cryptocurrency amounts')
|
|
15
|
+
.summary('Calculate price conversions and estimates');
|
|
16
|
+
|
|
17
|
+
// Estimate conversion
|
|
18
|
+
command
|
|
19
|
+
.command('convert')
|
|
20
|
+
.description('Estimate cryptocurrency amount for a given price')
|
|
21
|
+
.requiredOption('-f, --from <currency>', 'Currency to convert from (e.g., USD, EUR)')
|
|
22
|
+
.requiredOption('-t, --to <currency>', 'Cryptocurrency to convert to (e.g., BTC, ETH)')
|
|
23
|
+
.requiredOption('-a, --amount <amount>', 'Amount to convert')
|
|
24
|
+
.action(async (options) => {
|
|
25
|
+
try {
|
|
26
|
+
const amount = parseFloat(options.amount);
|
|
27
|
+
|
|
28
|
+
if (isNaN(amount) || amount <= 0) {
|
|
29
|
+
console.error(chalk.red('Error: Amount must be a positive number'));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const data = await makeRequest(command.parent.parent, '/estimate', {
|
|
34
|
+
queryParams: {
|
|
35
|
+
amount,
|
|
36
|
+
currency_from: options.from.toUpperCase(),
|
|
37
|
+
currency_to: options.to.toUpperCase()
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
displayResponse(command.parent.parent, data, (response) => {
|
|
42
|
+
console.log(chalk.cyan('\nEstimate:'));
|
|
43
|
+
console.log(chalk.bold(` ${amount} ${options.from.toUpperCase()}`), '→',
|
|
44
|
+
chalk.green(`${response.estimated_amount || response.amount_to} ${options.to.toUpperCase()}`));
|
|
45
|
+
|
|
46
|
+
if (response.fee_amount) {
|
|
47
|
+
console.log(chalk.gray(` Network fee: ${response.fee_amount} ${options.to.toUpperCase()}`));
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
} catch (error) {
|
|
51
|
+
handleApiError(error);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Get minimum amount
|
|
56
|
+
command
|
|
57
|
+
.command('min')
|
|
58
|
+
.description('Get minimum payment amount for a currency pair')
|
|
59
|
+
.requiredOption('-f, --from <currency>', 'Currency from (e.g., USD)')
|
|
60
|
+
.requiredOption('-t, --to <currency>', 'Cryptocurrency to (e.g., BTC)')
|
|
61
|
+
.option('--fiat', 'Get fiat equivalent of minimum')
|
|
62
|
+
.action(async (options) => {
|
|
63
|
+
try {
|
|
64
|
+
const data = await makeRequest(command.parent.parent, '/min-amount', {
|
|
65
|
+
queryParams: {
|
|
66
|
+
currency_from: options.from.toUpperCase(),
|
|
67
|
+
currency_to: options.to.toUpperCase(),
|
|
68
|
+
fiat_equivalent: options.fiat ? 'true' : undefined
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
displayResponse(command.parent.parent, data, (response) => {
|
|
73
|
+
console.log(chalk.cyan('\nMinimum Payment Amount:'));
|
|
74
|
+
console.log(chalk.bold(` ${response.min_amount} ${options.to.toUpperCase()}`));
|
|
75
|
+
|
|
76
|
+
if (response.fiat_equivalent) {
|
|
77
|
+
console.log(chalk.gray(` ≈ ${response.fiat_equivalent} ${options.from.toUpperCase()}`));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
handleApiError(error);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
module.exports = command;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Invoice command
|
|
3
|
+
*
|
|
4
|
+
* Create and manage payment invoices.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Command } = require('commander');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const Table = require('cli-table3');
|
|
10
|
+
const { makeRequest, handleApiError, displayResponse } = require('../lib/api');
|
|
11
|
+
|
|
12
|
+
const command = new Command('invoice');
|
|
13
|
+
|
|
14
|
+
command
|
|
15
|
+
.description('Manage invoices')
|
|
16
|
+
.summary('Create and query payment invoices');
|
|
17
|
+
|
|
18
|
+
// Create a new invoice
|
|
19
|
+
command
|
|
20
|
+
.command('create')
|
|
21
|
+
.description('Create a new invoice')
|
|
22
|
+
.requiredOption('-p, --price <amount>', 'Invoice amount')
|
|
23
|
+
.requiredOption('-c, --currency <currency>', 'Price currency (e.g., USD)')
|
|
24
|
+
.option('--order-id <id>', 'Your order ID')
|
|
25
|
+
.option('--order-description <desc>', 'Order description')
|
|
26
|
+
.option('--ipn-url <url>', 'IPN callback URL')
|
|
27
|
+
.option('--success-url <url>', 'Success redirect URL')
|
|
28
|
+
.option('--cancel-url <url>', 'Cancel redirect URL')
|
|
29
|
+
.option('--partially-paid-url <url>', 'Partially paid redirect URL')
|
|
30
|
+
.option('--payout-currency <currency>', 'Payout currency')
|
|
31
|
+
.option('--payout-address <address>', 'Payout address')
|
|
32
|
+
.action(async (options) => {
|
|
33
|
+
try {
|
|
34
|
+
const price = parseFloat(options.price);
|
|
35
|
+
|
|
36
|
+
if (isNaN(price) || price <= 0) {
|
|
37
|
+
console.error(chalk.red('Error: Price must be a positive number'));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const invoiceData = {
|
|
42
|
+
price_amount: price,
|
|
43
|
+
price_currency: options.currency.toUpperCase(),
|
|
44
|
+
order_id: options.orderId,
|
|
45
|
+
order_description: options.orderDescription,
|
|
46
|
+
ipn_callback_url: options.ipnUrl,
|
|
47
|
+
success_url: options.successUrl,
|
|
48
|
+
cancel_url: options.cancelUrl,
|
|
49
|
+
partially_paid_url: options.partiallyPaidUrl,
|
|
50
|
+
payout_currency: options.payoutCurrency?.toUpperCase(),
|
|
51
|
+
payout_address: options.payoutAddress
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Remove undefined values
|
|
55
|
+
Object.keys(invoiceData).forEach(key => {
|
|
56
|
+
if (invoiceData[key] === undefined) {
|
|
57
|
+
delete invoiceData[key];
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const data = await makeRequest(command.parent.parent, '/invoice', {
|
|
62
|
+
method: 'POST',
|
|
63
|
+
body: invoiceData
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
displayResponse(command.parent.parent, data, (response) => {
|
|
67
|
+
console.log(chalk.green('\n✓ Invoice created successfully'));
|
|
68
|
+
console.log(chalk.cyan('\nInvoice Details:'));
|
|
69
|
+
console.log(chalk.bold(' Invoice ID:'), response.id);
|
|
70
|
+
console.log(chalk.bold(' Status:'), response.invoice_status);
|
|
71
|
+
console.log(chalk.bold(' Price:'), `${response.price_amount} ${response.price_currency}`);
|
|
72
|
+
console.log(chalk.bold(' Invoice URL:'), chalk.yellow(response.invoice_url));
|
|
73
|
+
|
|
74
|
+
if (response.order_id) {
|
|
75
|
+
console.log(chalk.bold(' Order ID:'), response.order_id);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log(chalk.gray('\n Created:'), new Date(response.created_at).toLocaleString());
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
handleApiError(error);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Get invoice details
|
|
86
|
+
command
|
|
87
|
+
.command('get <invoice-id>')
|
|
88
|
+
.description('Get invoice details by ID')
|
|
89
|
+
.action(async (invoiceId) => {
|
|
90
|
+
try {
|
|
91
|
+
const data = await makeRequest(command.parent.parent, `/invoice/${invoiceId}`);
|
|
92
|
+
|
|
93
|
+
displayResponse(command.parent.parent, data, (response) => {
|
|
94
|
+
console.log(chalk.cyan('\nInvoice Details:'));
|
|
95
|
+
|
|
96
|
+
const table = new Table({
|
|
97
|
+
chars: { 'mid': '', 'left-mid': '', 'mid-mid': '', 'right-mid': '' }
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
table.push(
|
|
101
|
+
['Invoice ID', response.id],
|
|
102
|
+
['Status', response.invoice_status],
|
|
103
|
+
['Price', `${response.price_amount} ${response.price_currency}`],
|
|
104
|
+
['Invoice URL', response.invoice_url]
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
if (response.order_id) {
|
|
108
|
+
table.push(['Order ID', response.order_id]);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (response.order_description) {
|
|
112
|
+
table.push(['Description', response.order_description]);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (response.payment_id) {
|
|
116
|
+
table.push(['Payment ID', response.payment_id]);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
table.push(
|
|
120
|
+
['Created', new Date(response.created_at).toLocaleString()],
|
|
121
|
+
['Updated', new Date(response.updated_at).toLocaleString()]
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
console.log(table.toString());
|
|
125
|
+
});
|
|
126
|
+
} catch (error) {
|
|
127
|
+
handleApiError(error);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// List invoices
|
|
132
|
+
command
|
|
133
|
+
.command('list')
|
|
134
|
+
.description('List all invoices')
|
|
135
|
+
.option('-l, --limit <number>', 'Number of invoices to return', '10')
|
|
136
|
+
.option('-p, --page <number>', 'Page number', '0')
|
|
137
|
+
.option('--sort-by <field>', 'Sort by field (created_at, updated_at)')
|
|
138
|
+
.option('--order <order>', 'Sort order (asc, desc)', 'desc')
|
|
139
|
+
.option('--date-from <date>', 'Filter by start date (YYYY-MM-DD)')
|
|
140
|
+
.option('--date-to <date>', 'Filter by end date (YYYY-MM-DD)')
|
|
141
|
+
.action(async (options) => {
|
|
142
|
+
try {
|
|
143
|
+
const queryParams = {
|
|
144
|
+
limit: parseInt(options.limit),
|
|
145
|
+
page: parseInt(options.page),
|
|
146
|
+
sortBy: options.sortBy,
|
|
147
|
+
orderBy: options.order,
|
|
148
|
+
dateFrom: options.dateFrom,
|
|
149
|
+
dateTo: options.dateTo
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const data = await makeRequest(command.parent.parent, '/invoice', {
|
|
153
|
+
queryParams
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
displayResponse(command.parent.parent, data, (response) => {
|
|
157
|
+
const invoices = response.data || [];
|
|
158
|
+
|
|
159
|
+
if (invoices.length === 0) {
|
|
160
|
+
console.log(chalk.yellow('\nNo invoices found'));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.log(chalk.cyan(`\nInvoices (${invoices.length}):`));
|
|
165
|
+
|
|
166
|
+
const table = new Table({
|
|
167
|
+
head: ['ID', 'Status', 'Amount', 'Currency', 'Created'],
|
|
168
|
+
colWidths: [20, 15, 12, 10, 25]
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
invoices.forEach(invoice => {
|
|
172
|
+
table.push([
|
|
173
|
+
invoice.id?.toString().substring(0, 18) || 'N/A',
|
|
174
|
+
invoice.invoice_status || 'N/A',
|
|
175
|
+
invoice.price_amount || 'N/A',
|
|
176
|
+
invoice.price_currency || 'N/A',
|
|
177
|
+
new Date(invoice.created_at).toLocaleString()
|
|
178
|
+
]);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
console.log(table.toString());
|
|
182
|
+
});
|
|
183
|
+
} catch (error) {
|
|
184
|
+
handleApiError(error);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
module.exports = command;
|