@darksol/terminal 0.5.6 → 0.5.7
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/package.json +1 -1
- package/src/cli.js +5 -5
- package/src/services/cards.js +56 -26
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -273,13 +273,13 @@ export function cli(argv) {
|
|
|
273
273
|
|
|
274
274
|
cards
|
|
275
275
|
.command('order')
|
|
276
|
-
.description('Order a prepaid card')
|
|
277
|
-
.
|
|
278
|
-
.
|
|
279
|
-
.
|
|
276
|
+
.description('Order a prepaid card (interactive if flags omitted)')
|
|
277
|
+
.option('-p, --provider <name>', 'Card provider (swype/mpc/reward)')
|
|
278
|
+
.option('-a, --amount <usd>', 'Card amount in USD')
|
|
279
|
+
.option('-e, --email <address>', 'Delivery email for card activation link')
|
|
280
280
|
.option('-t, --ticker <coin>', 'Payment crypto (default: usdc)')
|
|
281
281
|
.option('-n, --network <net>', 'Payment network (default: base)')
|
|
282
|
-
.action((opts) => cardsOrder(opts.provider, parseFloat(opts.amount), {
|
|
282
|
+
.action((opts) => cardsOrder(opts.provider, opts.amount ? parseFloat(opts.amount) : null, {
|
|
283
283
|
email: opts.email,
|
|
284
284
|
ticker: opts.ticker,
|
|
285
285
|
network: opts.network,
|
package/src/services/cards.js
CHANGED
|
@@ -121,24 +121,65 @@ export async function cardsCatalog() {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
export async function cardsOrder(provider, amount, opts = {}) {
|
|
124
|
+
const inquirer = (await import('inquirer')).default;
|
|
125
|
+
const validProviders = ['swype', 'mpc', 'reward'];
|
|
126
|
+
|
|
127
|
+
// ── Email: ask if missing ──
|
|
124
128
|
if (!opts.email) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
const { email } = await inquirer.prompt([{
|
|
130
|
+
type: 'input',
|
|
131
|
+
name: 'email',
|
|
132
|
+
message: theme.gold('Delivery email (card activation link):'),
|
|
133
|
+
validate: v => v.includes('@') ? true : 'Enter a valid email address',
|
|
134
|
+
}]);
|
|
135
|
+
opts.email = email;
|
|
128
136
|
}
|
|
129
137
|
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
138
|
+
// ── Amount: re-prompt if invalid ──
|
|
139
|
+
let numAmount = Number(amount);
|
|
140
|
+
while (!VALID_AMOUNTS.includes(numAmount)) {
|
|
141
|
+
if (amount) warn(`$${amount} is not a valid denomination.`);
|
|
142
|
+
const { picked } = await inquirer.prompt([{
|
|
143
|
+
type: 'list',
|
|
144
|
+
name: 'picked',
|
|
145
|
+
message: theme.gold('Card amount:'),
|
|
146
|
+
choices: VALID_AMOUNTS.map(a => ({ name: `$${a}`, value: a })),
|
|
147
|
+
}]);
|
|
148
|
+
numAmount = picked;
|
|
135
149
|
}
|
|
136
150
|
|
|
137
|
-
//
|
|
138
|
-
const validProviders = ['swype', 'mpc', 'reward'];
|
|
151
|
+
// ── Provider: re-prompt if invalid ──
|
|
139
152
|
if (!validProviders.includes((provider || '').toLowerCase())) {
|
|
140
|
-
|
|
141
|
-
|
|
153
|
+
if (provider) warn(`"${provider}" is not a valid provider.`);
|
|
154
|
+
const { picked } = await inquirer.prompt([{
|
|
155
|
+
type: 'list',
|
|
156
|
+
name: 'picked',
|
|
157
|
+
message: theme.gold('Card provider:'),
|
|
158
|
+
choices: [
|
|
159
|
+
{ name: 'Swype — Mastercard (Global)', value: 'swype' },
|
|
160
|
+
{ name: 'MPC — Mastercard (US only)', value: 'mpc' },
|
|
161
|
+
{ name: 'Reward — Visa (US only)', value: 'reward' },
|
|
162
|
+
],
|
|
163
|
+
}]);
|
|
164
|
+
provider = picked;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ── Crypto: resolve or re-prompt if invalid ──
|
|
168
|
+
let resolvedCrypto = null;
|
|
169
|
+
if (opts.ticker) {
|
|
170
|
+
resolvedCrypto = resolveTickerNetwork(opts.ticker, opts.network);
|
|
171
|
+
if (!resolvedCrypto) {
|
|
172
|
+
warn(`"${opts.ticker}${opts.network ? '/' + opts.network : ''}" is not supported.`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (!resolvedCrypto) {
|
|
176
|
+
const { picked } = await inquirer.prompt([{
|
|
177
|
+
type: 'list',
|
|
178
|
+
name: 'picked',
|
|
179
|
+
message: theme.gold('Pay with:'),
|
|
180
|
+
choices: VERIFIED_COMBOS.map(c => ({ name: c.display, value: c })),
|
|
181
|
+
}]);
|
|
182
|
+
resolvedCrypto = picked;
|
|
142
183
|
}
|
|
143
184
|
|
|
144
185
|
const spin = spinner('Processing card order...').start();
|
|
@@ -147,21 +188,10 @@ export async function cardsOrder(provider, amount, opts = {}) {
|
|
|
147
188
|
provider: provider.toLowerCase(),
|
|
148
189
|
amount: numAmount,
|
|
149
190
|
email: opts.email,
|
|
191
|
+
tickerFrom: resolvedCrypto.ticker,
|
|
192
|
+
networkFrom: resolvedCrypto.network,
|
|
150
193
|
};
|
|
151
|
-
|
|
152
|
-
// Resolve and validate crypto
|
|
153
|
-
if (opts.ticker) {
|
|
154
|
-
const resolved = resolveTickerNetwork(opts.ticker, opts.network);
|
|
155
|
-
if (!resolved) {
|
|
156
|
-
spin.fail('Invalid payment method');
|
|
157
|
-
error(`"${opts.ticker}${opts.network ? '/' + opts.network : ''}" is not a supported payment option.`);
|
|
158
|
-
info('Supported: ' + VERIFIED_COMBOS.map(c => c.display).join(', '));
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
body.tickerFrom = resolved.ticker;
|
|
162
|
-
body.networkFrom = resolved.network;
|
|
163
|
-
info(`Payment: ${resolved.display}`);
|
|
164
|
-
}
|
|
194
|
+
info(`Payment: ${resolvedCrypto.display}`);
|
|
165
195
|
|
|
166
196
|
const data = await fetchJSON(`${BASE()}/api/cards/order`, {
|
|
167
197
|
method: 'POST',
|