@darksol/terminal 0.4.11 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/cli.js +11 -4
- package/src/services/cards.js +63 -16
- package/src/web/commands.js +206 -0
- package/src/web/server.js +2 -0
- package/src/web/terminal.js +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ A unified CLI for market intel, trading, AI-powered analysis, on-chain oracle, c
|
|
|
15
15
|
[](https://opensource.org/licenses/MIT)
|
|
16
16
|
[](https://nodejs.org/)
|
|
17
17
|
|
|
18
|
+
- Current release: **0.5.0**
|
|
18
19
|
- Changelog: `CHANGELOG.md`
|
|
19
20
|
|
|
20
21
|
## Install
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -274,13 +274,20 @@ export function cli(argv) {
|
|
|
274
274
|
cards
|
|
275
275
|
.command('order')
|
|
276
276
|
.description('Order a prepaid card')
|
|
277
|
-
.requiredOption('-p, --provider <name>', 'Card provider')
|
|
277
|
+
.requiredOption('-p, --provider <name>', 'Card provider (swype/mpc/reward)')
|
|
278
278
|
.requiredOption('-a, --amount <usd>', 'Card amount in USD')
|
|
279
|
-
.
|
|
279
|
+
.requiredOption('-e, --email <address>', 'Delivery email for card activation link')
|
|
280
|
+
.option('-t, --ticker <coin>', 'Payment crypto (default: usdc)')
|
|
281
|
+
.option('-n, --network <net>', 'Payment network (default: base)')
|
|
282
|
+
.action((opts) => cardsOrder(opts.provider, parseFloat(opts.amount), {
|
|
283
|
+
email: opts.email,
|
|
284
|
+
ticker: opts.ticker,
|
|
285
|
+
network: opts.network,
|
|
286
|
+
}));
|
|
280
287
|
|
|
281
288
|
cards
|
|
282
|
-
.command('status <
|
|
283
|
-
.description('Check order status')
|
|
289
|
+
.command('status <tradeId>')
|
|
290
|
+
.description('Check order status by trade ID')
|
|
284
291
|
.action((id) => cardsStatus(id));
|
|
285
292
|
|
|
286
293
|
// ═══════════════════════════════════════
|
package/src/services/cards.js
CHANGED
|
@@ -4,27 +4,39 @@ import { theme } from '../ui/theme.js';
|
|
|
4
4
|
import { spinner, kvDisplay, error, info, table } from '../ui/components.js';
|
|
5
5
|
import { showSection } from '../ui/banner.js';
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const BASE = () => getServiceURL('cards') || 'https://acp.darksol.net';
|
|
8
8
|
|
|
9
9
|
export async function cardsCatalog() {
|
|
10
10
|
const spin = spinner('Loading card catalog...').start();
|
|
11
11
|
try {
|
|
12
|
-
const data = await fetchJSON(`${
|
|
12
|
+
const data = await fetchJSON(`${BASE()}/api/cards/catalog`);
|
|
13
13
|
spin.succeed('Catalog loaded');
|
|
14
14
|
|
|
15
15
|
showSection('PREPAID CARDS');
|
|
16
16
|
const cards = data.providers || data;
|
|
17
17
|
if (Array.isArray(cards)) {
|
|
18
18
|
const rows = cards.map(c => [
|
|
19
|
-
theme.gold(c.name),
|
|
20
|
-
c.network || 'Visa/MC',
|
|
21
|
-
c.
|
|
19
|
+
theme.gold(c.name || c.id),
|
|
20
|
+
c.brand || c.network || 'Visa/MC',
|
|
21
|
+
c.currency || 'USD',
|
|
22
22
|
c.region || 'Global',
|
|
23
23
|
]);
|
|
24
|
-
table(['Provider', '
|
|
24
|
+
table(['Provider', 'Brand', 'Currency', 'Region'], rows);
|
|
25
25
|
} else {
|
|
26
26
|
kvDisplay(Object.entries(cards).map(([k, v]) => [k, String(v)]));
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
// Show pricing tiers if available
|
|
30
|
+
if (data.pricing?.tiers) {
|
|
31
|
+
console.log('');
|
|
32
|
+
showSection('PRICING');
|
|
33
|
+
const tRows = data.pricing.tiers.map(t => [
|
|
34
|
+
`$${t.denomination}`,
|
|
35
|
+
`$${t.youPay}`,
|
|
36
|
+
]);
|
|
37
|
+
table(['Card Value', 'You Pay'], tRows);
|
|
38
|
+
console.log(theme.dim(` ${data.pricing.markup || '3% service fee'} + ${data.pricing.issuanceFee || '~3% provider fee'}`));
|
|
39
|
+
}
|
|
28
40
|
} catch (err) {
|
|
29
41
|
spin.fail('Catalog failed');
|
|
30
42
|
error(err.message);
|
|
@@ -32,33 +44,68 @@ export async function cardsCatalog() {
|
|
|
32
44
|
}
|
|
33
45
|
}
|
|
34
46
|
|
|
35
|
-
export async function cardsOrder(provider, amount) {
|
|
47
|
+
export async function cardsOrder(provider, amount, opts = {}) {
|
|
48
|
+
if (!opts.email) {
|
|
49
|
+
error('Email is required for card delivery. Use --email <address>');
|
|
50
|
+
info('Example: darksol cards order -p swype -a 100 --email you@example.com');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
36
54
|
const spin = spinner('Processing card order...').start();
|
|
37
55
|
try {
|
|
38
|
-
const
|
|
56
|
+
const body = {
|
|
57
|
+
provider,
|
|
58
|
+
amount: Number(amount),
|
|
59
|
+
email: opts.email,
|
|
60
|
+
};
|
|
61
|
+
// Optional: custom crypto + network
|
|
62
|
+
if (opts.ticker) body.tickerFrom = opts.ticker;
|
|
63
|
+
if (opts.network) body.networkFrom = opts.network;
|
|
64
|
+
|
|
65
|
+
const data = await fetchJSON(`${BASE()}/api/cards/order`, {
|
|
39
66
|
method: 'POST',
|
|
40
67
|
headers: { 'Content-Type': 'application/json' },
|
|
41
|
-
body: JSON.stringify(
|
|
68
|
+
body: JSON.stringify(body),
|
|
42
69
|
});
|
|
43
70
|
spin.succeed('Order placed');
|
|
44
71
|
|
|
45
|
-
|
|
46
|
-
|
|
72
|
+
if (data.order) {
|
|
73
|
+
showSection('CARD ORDER');
|
|
74
|
+
kvDisplay([
|
|
75
|
+
['Trade ID', theme.gold(data.order.tradeId)],
|
|
76
|
+
['Status', data.order.status],
|
|
77
|
+
['Card', `$${data.order.cardAmount} ${data.order.currency} ${data.order.brand}`],
|
|
78
|
+
['Provider', data.order.provider],
|
|
79
|
+
['Pay', `${data.order.amountCrypto} ${data.order.ticker?.toUpperCase()} (${data.order.network})`],
|
|
80
|
+
['To Address', data.order.paymentAddress],
|
|
81
|
+
...(data.order.paymentMemo ? [['Memo', data.order.paymentMemo]] : []),
|
|
82
|
+
['Delivery', opts.email],
|
|
83
|
+
]);
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log(theme.accent(` ${data.order.message}`));
|
|
86
|
+
console.log('');
|
|
87
|
+
info(`Check status: darksol cards status ${data.order.tradeId}`);
|
|
88
|
+
} else {
|
|
89
|
+
kvDisplay(Object.entries(data).map(([k, v]) => [k, String(v)]));
|
|
90
|
+
}
|
|
47
91
|
} catch (err) {
|
|
48
92
|
spin.fail('Order failed');
|
|
49
93
|
error(err.message);
|
|
50
|
-
info('The cards order API may not be live yet. Check: https://acp.darksol.net/cards');
|
|
51
94
|
}
|
|
52
95
|
}
|
|
53
96
|
|
|
54
|
-
export async function cardsStatus(
|
|
97
|
+
export async function cardsStatus(tradeId) {
|
|
55
98
|
const spin = spinner('Checking order...').start();
|
|
56
99
|
try {
|
|
57
|
-
const data = await fetchJSON(`${
|
|
100
|
+
const data = await fetchJSON(`${BASE()}/api/cards/status?tradeId=${tradeId}`);
|
|
58
101
|
spin.succeed('Status loaded');
|
|
59
102
|
|
|
60
|
-
showSection(`CARD ORDER — ${
|
|
61
|
-
|
|
103
|
+
showSection(`CARD ORDER — ${tradeId}`);
|
|
104
|
+
if (data.order) {
|
|
105
|
+
kvDisplay(Object.entries(data.order).map(([k, v]) => [k, String(v)]));
|
|
106
|
+
} else {
|
|
107
|
+
kvDisplay(Object.entries(data).map(([k, v]) => [k, String(v)]));
|
|
108
|
+
}
|
|
62
109
|
} catch (err) {
|
|
63
110
|
spin.fail('Status check failed');
|
|
64
111
|
error(err.message);
|
package/src/web/commands.js
CHANGED
|
@@ -173,6 +173,51 @@ export async function handleMenuSelect(id, value, item, ws) {
|
|
|
173
173
|
});
|
|
174
174
|
return {};
|
|
175
175
|
|
|
176
|
+
case 'cards_action':
|
|
177
|
+
if (value === 'order') {
|
|
178
|
+
ws.sendMenu('cards_provider', '◆ Select Provider', [
|
|
179
|
+
{ value: 'swype', label: 'Swype', desc: 'Mastercard · Global' },
|
|
180
|
+
{ value: 'mpc', label: 'MPC', desc: 'Mastercard · US Only' },
|
|
181
|
+
{ value: 'reward', label: 'Reward', desc: 'Visa · US Only' },
|
|
182
|
+
{ value: 'back', label: '← Back', desc: '' },
|
|
183
|
+
]);
|
|
184
|
+
return {};
|
|
185
|
+
}
|
|
186
|
+
if (value === 'status') {
|
|
187
|
+
ws.sendPrompt('cards_status_id', 'Trade ID:', {});
|
|
188
|
+
return {};
|
|
189
|
+
}
|
|
190
|
+
return {};
|
|
191
|
+
|
|
192
|
+
case 'cards_provider':
|
|
193
|
+
if (value === 'back') return {};
|
|
194
|
+
// Store provider, ask for amount
|
|
195
|
+
ws.sendMenu('cards_amount', `◆ Card Amount (${value})`, [
|
|
196
|
+
{ value: '10', label: '$10', desc: 'Pay ~$10.60' },
|
|
197
|
+
{ value: '25', label: '$25', desc: 'Pay ~$26.50' },
|
|
198
|
+
{ value: '50', label: '$50', desc: 'Pay ~$53' },
|
|
199
|
+
{ value: '100', label: '$100', desc: 'Pay ~$106' },
|
|
200
|
+
{ value: '250', label: '$250', desc: 'Pay ~$265' },
|
|
201
|
+
{ value: '500', label: '$500', desc: 'Pay ~$530' },
|
|
202
|
+
{ value: '1000', label: '$1,000', desc: 'Pay ~$1,060' },
|
|
203
|
+
{ value: 'back', label: '← Back', desc: '' },
|
|
204
|
+
].map(i => ({ ...i, meta: { provider: value } })));
|
|
205
|
+
return {};
|
|
206
|
+
|
|
207
|
+
case 'cards_amount':
|
|
208
|
+
if (value === 'back') return {};
|
|
209
|
+
// Store provider+amount, ask for email
|
|
210
|
+
ws.sendPrompt('cards_email', 'Delivery email (card activation link will be sent here):', {
|
|
211
|
+
provider: item?.meta?.provider || 'swype',
|
|
212
|
+
amount: value,
|
|
213
|
+
});
|
|
214
|
+
return {};
|
|
215
|
+
|
|
216
|
+
case 'cards_crypto':
|
|
217
|
+
if (value === 'back') return {};
|
|
218
|
+
// Execute the order
|
|
219
|
+
return await executeCardOrder(item?.meta || {}, ws);
|
|
220
|
+
|
|
176
221
|
case 'agent_action':
|
|
177
222
|
if (value === 'start') {
|
|
178
223
|
const { listWallets } = await import('../wallet/keystore.js');
|
|
@@ -275,6 +320,31 @@ export async function handlePromptResponse(id, value, meta, ws) {
|
|
|
275
320
|
return {};
|
|
276
321
|
}
|
|
277
322
|
|
|
323
|
+
if (id === 'cards_status_id') {
|
|
324
|
+
if (!value) { ws.sendLine(` ${ANSI.red}✗ Cancelled${ANSI.reset}`); ws.sendLine(''); return {}; }
|
|
325
|
+
return await showCardStatus(value.trim(), ws);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (id === 'cards_email') {
|
|
329
|
+
if (!value) { ws.sendLine(` ${ANSI.red}✗ Cancelled${ANSI.reset}`); ws.sendLine(''); return {}; }
|
|
330
|
+
const provider = meta.provider || 'swype';
|
|
331
|
+
const amount = meta.amount || '100';
|
|
332
|
+
const email = value.trim();
|
|
333
|
+
|
|
334
|
+
// Ask for crypto selection
|
|
335
|
+
ws.sendMenu('cards_crypto', `◆ Pay With (${provider} $${amount} → ${email})`, [
|
|
336
|
+
{ value: 'usdc_base', label: 'USDC on Base', desc: 'Default · fast & cheap', meta: { provider, amount, email, ticker: 'usdc', network: 'base' } },
|
|
337
|
+
{ value: 'usdc_eth', label: 'USDC on Ethereum', desc: 'Higher fees', meta: { provider, amount, email, ticker: 'usdc', network: 'eth' } },
|
|
338
|
+
{ value: 'usdt_trc20', label: 'USDT on Tron', desc: 'TRC-20', meta: { provider, amount, email, ticker: 'usdt', network: 'trc20' } },
|
|
339
|
+
{ value: 'btc', label: 'Bitcoin', desc: 'BTC mainnet', meta: { provider, amount, email, ticker: 'btc', network: 'mainnet' } },
|
|
340
|
+
{ value: 'eth', label: 'Ethereum', desc: 'ETH mainnet', meta: { provider, amount, email, ticker: 'eth', network: 'eth' } },
|
|
341
|
+
{ value: 'sol', label: 'Solana', desc: 'SOL', meta: { provider, amount, email, ticker: 'sol', network: 'sol' } },
|
|
342
|
+
{ value: 'xmr', label: 'Monero', desc: 'XMR', meta: { provider, amount, email, ticker: 'xmr', network: 'xmr' } },
|
|
343
|
+
{ value: 'default', label: 'Default (USDC/Base)', desc: 'Let API choose', meta: { provider, amount, email } },
|
|
344
|
+
]);
|
|
345
|
+
return {};
|
|
346
|
+
}
|
|
347
|
+
|
|
278
348
|
if (id === 'agent_signer_password') {
|
|
279
349
|
const wallet = meta.wallet;
|
|
280
350
|
if (!wallet || !value) {
|
|
@@ -359,6 +429,8 @@ export async function handleCommand(cmd, ws) {
|
|
|
359
429
|
return await cmdConfig(ws);
|
|
360
430
|
case 'oracle':
|
|
361
431
|
return await cmdOracle(args, ws);
|
|
432
|
+
case 'cards':
|
|
433
|
+
return await cmdCards(args, ws);
|
|
362
434
|
case 'casino':
|
|
363
435
|
return await cmdCasino(args, ws);
|
|
364
436
|
case 'facilitator':
|
|
@@ -911,6 +983,140 @@ async function cmdHistory(args, ws) {
|
|
|
911
983
|
// ══════════════════════════════════════════════════
|
|
912
984
|
// SERVICE COMMANDS (thin wrappers)
|
|
913
985
|
// ══════════════════════════════════════════════════
|
|
986
|
+
// ══════════════════════════════════════════════════
|
|
987
|
+
// CARDS (interactive ordering)
|
|
988
|
+
// ══════════════════════════════════════════════════
|
|
989
|
+
const CARDS_API = 'https://acp.darksol.net/api/cards';
|
|
990
|
+
|
|
991
|
+
async function cmdCards(args, ws) {
|
|
992
|
+
const sub = (args[0] || '').toLowerCase();
|
|
993
|
+
|
|
994
|
+
if (sub === 'status' && args[1]) {
|
|
995
|
+
return await showCardStatus(args[1], ws);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
// Show catalog + order menu
|
|
999
|
+
ws.sendLine(`${ANSI.gold} ◆ PREPAID CARDS${ANSI.reset}`);
|
|
1000
|
+
ws.sendLine(`${ANSI.dim} ${'─'.repeat(50)}${ANSI.reset}`);
|
|
1001
|
+
|
|
1002
|
+
try {
|
|
1003
|
+
const resp = await fetch(`${CARDS_API}/catalog`);
|
|
1004
|
+
const data = await resp.json();
|
|
1005
|
+
|
|
1006
|
+
if (data.providers) {
|
|
1007
|
+
for (const p of data.providers) {
|
|
1008
|
+
ws.sendLine(` ${ANSI.gold}${p.name}${ANSI.reset} ${ANSI.dim}${p.brand} · ${p.region}${ANSI.reset}`);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
if (data.pricing?.tiers) {
|
|
1012
|
+
ws.sendLine('');
|
|
1013
|
+
ws.sendLine(` ${ANSI.darkGold}Pricing${ANSI.reset} ${ANSI.dim}${data.pricing.markup} + ${data.pricing.issuanceFee}${ANSI.reset}`);
|
|
1014
|
+
const tierStr = data.pricing.tiers.map(t => `$${t.denomination}→$${t.youPay}`).join(' ');
|
|
1015
|
+
ws.sendLine(` ${ANSI.dim}${tierStr}${ANSI.reset}`);
|
|
1016
|
+
}
|
|
1017
|
+
ws.sendLine('');
|
|
1018
|
+
} catch {
|
|
1019
|
+
ws.sendLine(` ${ANSI.dim}Could not load catalog${ANSI.reset}`);
|
|
1020
|
+
ws.sendLine('');
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
ws.sendMenu('cards_action', '◆ Prepaid Cards', [
|
|
1024
|
+
{ value: 'order', label: '💳 Order Card', desc: 'Start a new order' },
|
|
1025
|
+
{ value: 'status', label: '🔍 Check Status', desc: 'Track existing order' },
|
|
1026
|
+
{ value: 'back', label: '← Back', desc: '' },
|
|
1027
|
+
]);
|
|
1028
|
+
return {};
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
async function showCardStatus(tradeId, ws) {
|
|
1032
|
+
try {
|
|
1033
|
+
const resp = await fetch(`${CARDS_API}/status?tradeId=${tradeId}`);
|
|
1034
|
+
const ct = resp.headers.get('content-type') || '';
|
|
1035
|
+
if (!ct.includes('json')) {
|
|
1036
|
+
ws.sendLine(` ${ANSI.red}✗ Invalid response from status endpoint${ANSI.reset}`);
|
|
1037
|
+
return {};
|
|
1038
|
+
}
|
|
1039
|
+
const data = await resp.json();
|
|
1040
|
+
ws.sendLine(`${ANSI.gold} ◆ ORDER STATUS — ${tradeId}${ANSI.reset}`);
|
|
1041
|
+
ws.sendLine(`${ANSI.dim} ${'─'.repeat(50)}${ANSI.reset}`);
|
|
1042
|
+
const order = data.order || data;
|
|
1043
|
+
for (const [k, v] of Object.entries(order)) {
|
|
1044
|
+
if (v !== null && v !== undefined) {
|
|
1045
|
+
ws.sendLine(` ${ANSI.darkGold}${k}${ANSI.reset} ${ANSI.white}${v}${ANSI.reset}`);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
ws.sendLine('');
|
|
1049
|
+
} catch (err) {
|
|
1050
|
+
ws.sendLine(` ${ANSI.red}✗ ${err.message}${ANSI.reset}`);
|
|
1051
|
+
ws.sendLine('');
|
|
1052
|
+
}
|
|
1053
|
+
return {};
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
async function executeCardOrder(orderMeta, ws) {
|
|
1057
|
+
const { provider, amount, email, ticker, network } = orderMeta;
|
|
1058
|
+
ws.sendLine(` ${ANSI.dim}Placing order...${ANSI.reset}`);
|
|
1059
|
+
|
|
1060
|
+
try {
|
|
1061
|
+
const body = { provider: provider || 'swype', amount: Number(amount), email };
|
|
1062
|
+
if (ticker) body.tickerFrom = ticker;
|
|
1063
|
+
if (network) body.networkFrom = network;
|
|
1064
|
+
|
|
1065
|
+
const resp = await fetch(`${CARDS_API}/order`, {
|
|
1066
|
+
method: 'POST',
|
|
1067
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1068
|
+
body: JSON.stringify(body),
|
|
1069
|
+
});
|
|
1070
|
+
const ct = resp.headers.get('content-type') || '';
|
|
1071
|
+
if (!ct.includes('json')) {
|
|
1072
|
+
const text = await resp.text();
|
|
1073
|
+
ws.sendLine(` ${ANSI.red}✗ API returned non-JSON: ${text.substring(0, 80)}${ANSI.reset}`);
|
|
1074
|
+
ws.sendLine('');
|
|
1075
|
+
return {};
|
|
1076
|
+
}
|
|
1077
|
+
const data = await resp.json();
|
|
1078
|
+
|
|
1079
|
+
if (!data.success || !data.order) {
|
|
1080
|
+
ws.sendLine(` ${ANSI.red}✗ Order failed: ${data.error || JSON.stringify(data)}${ANSI.reset}`);
|
|
1081
|
+
ws.sendLine('');
|
|
1082
|
+
return {};
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
const o = data.order;
|
|
1086
|
+
ws.sendLine('');
|
|
1087
|
+
ws.sendLine(`${ANSI.gold} ◆ ORDER PLACED${ANSI.reset}`);
|
|
1088
|
+
ws.sendLine(`${ANSI.dim} ${'─'.repeat(50)}${ANSI.reset}`);
|
|
1089
|
+
ws.sendLine(` ${ANSI.darkGold}Trade ID${ANSI.reset} ${ANSI.gold}${o.tradeId}${ANSI.reset}`);
|
|
1090
|
+
ws.sendLine(` ${ANSI.darkGold}Status${ANSI.reset} ${ANSI.white}${o.status}${ANSI.reset}`);
|
|
1091
|
+
ws.sendLine(` ${ANSI.darkGold}Card${ANSI.reset} ${ANSI.white}$${o.cardAmount} ${o.currency} ${o.brand}${ANSI.reset}`);
|
|
1092
|
+
ws.sendLine(` ${ANSI.darkGold}Provider${ANSI.reset} ${ANSI.white}${o.provider}${ANSI.reset}`);
|
|
1093
|
+
ws.sendLine(` ${ANSI.darkGold}Delivery${ANSI.reset} ${ANSI.white}${email}${ANSI.reset}`);
|
|
1094
|
+
ws.sendLine('');
|
|
1095
|
+
ws.sendLine(` ${ANSI.green}PAY EXACTLY:${ANSI.reset}`);
|
|
1096
|
+
ws.sendLine(` ${ANSI.gold}${o.amountCrypto} ${(o.ticker || '').toUpperCase()}${ANSI.reset} ${ANSI.dim}(${o.network})${ANSI.reset}`);
|
|
1097
|
+
ws.sendLine('');
|
|
1098
|
+
ws.sendLine(` ${ANSI.darkGold}To Address:${ANSI.reset}`);
|
|
1099
|
+
const addr = o.paymentAddress;
|
|
1100
|
+
ws.sendLine(` ${ANSI.dim}┌${'─'.repeat(addr.length + 4)}┐${ANSI.reset}`);
|
|
1101
|
+
ws.sendLine(` ${ANSI.dim}│ ${ANSI.gold}${addr}${ANSI.dim} │${ANSI.reset}`);
|
|
1102
|
+
ws.sendLine(` ${ANSI.dim}└${'─'.repeat(addr.length + 4)}┘${ANSI.reset}`);
|
|
1103
|
+
if (o.paymentMemo) {
|
|
1104
|
+
ws.sendLine(` ${ANSI.darkGold}Memo:${ANSI.reset} ${ANSI.white}${o.paymentMemo}${ANSI.reset}`);
|
|
1105
|
+
}
|
|
1106
|
+
ws.sendLine('');
|
|
1107
|
+
ws.sendLine(` ${ANSI.dim}${o.message}${ANSI.reset}`);
|
|
1108
|
+
ws.sendLine(` ${ANSI.dim}Check status: cards status ${o.tradeId}${ANSI.reset}`);
|
|
1109
|
+
ws.sendLine('');
|
|
1110
|
+
} catch (err) {
|
|
1111
|
+
ws.sendLine(` ${ANSI.red}✗ ${err.message}${ANSI.reset}`);
|
|
1112
|
+
ws.sendLine('');
|
|
1113
|
+
}
|
|
1114
|
+
return {};
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
// ══════════════════════════════════════════════════
|
|
1118
|
+
// ORACLE
|
|
1119
|
+
// ══════════════════════════════════════════════════
|
|
914
1120
|
async function cmdOracle(args, ws) {
|
|
915
1121
|
try {
|
|
916
1122
|
const resp = await fetch('https://acp.darksol.net/oracle');
|
package/src/web/server.js
CHANGED
|
@@ -169,6 +169,7 @@ export async function startWebShell(opts = {}) {
|
|
|
169
169
|
{ value: 'portfolio', label: '📊 Portfolio', desc: 'Multi-chain balances' },
|
|
170
170
|
{ value: 'market', label: '📈 Market', desc: 'Price + liquidity intel' },
|
|
171
171
|
{ value: 'mail', label: '📧 Mail', desc: 'AgentMail status/inbox' },
|
|
172
|
+
{ value: 'cards', label: '💳 Cards', desc: 'Order prepaid Visa/MC' },
|
|
172
173
|
{ value: 'oracle', label: '🎲 Oracle', desc: 'Randomness service' },
|
|
173
174
|
{ value: 'casino', label: '🎰 Casino', desc: 'Service status' },
|
|
174
175
|
{ value: 'facilitator', label: '💸 Facilitator', desc: 'x402 health' },
|
|
@@ -308,6 +309,7 @@ function getHelp() {
|
|
|
308
309
|
['', ''],
|
|
309
310
|
['', `${gold}SERVICES${reset}`],
|
|
310
311
|
['market <token>', 'Market intel & data'],
|
|
312
|
+
['cards', 'Order prepaid Visa/MC cards'],
|
|
311
313
|
['mail status', 'AgentMail status'],
|
|
312
314
|
['mail inbox', 'Check email inbox'],
|
|
313
315
|
['oracle roll', 'On-chain random oracle'],
|
package/src/web/terminal.js
CHANGED
|
@@ -16,7 +16,7 @@ const A = {
|
|
|
16
16
|
|
|
17
17
|
const COMMANDS = [
|
|
18
18
|
'ai', 'price', 'watch', 'gas', 'portfolio', 'history', 'market',
|
|
19
|
-
'wallet', 'send', 'receive', 'agent', 'mail', 'keys', 'oracle', 'casino',
|
|
19
|
+
'wallet', 'send', 'receive', 'agent', 'cards', 'mail', 'keys', 'oracle', 'casino',
|
|
20
20
|
'facilitator', 'config', 'logs', 'help', 'clear', 'banner', 'exit',
|
|
21
21
|
];
|
|
22
22
|
|