payment-skill 1.1.18 → 1.1.19

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.
@@ -14,8 +14,45 @@ export const configCommands = new Command('config')
14
14
  configCommands
15
15
  .command('get')
16
16
  .description('Get configuration value')
17
- .argument('<key>', 'Configuration key')
17
+ .argument('<key>', 'Configuration key (e.g., providers.wise.environment)')
18
18
  .action((key) => {
19
+ // Handle provider-specific keys
20
+ if (key.startsWith('providers.')) {
21
+ const parts = key.split('.');
22
+ const providerName = parts[1];
23
+ const providerKey = parts[2];
24
+
25
+ const provider = configManager.getProvider(providerName);
26
+ if (provider && providerKey) {
27
+ const value = (provider as any)[providerKey];
28
+ if (value !== undefined) {
29
+ console.log(JSON.stringify(value, null, 2));
30
+ return;
31
+ }
32
+ }
33
+ console.log(chalk.yellow(`Key '${key}' not found`));
34
+ return;
35
+ }
36
+
37
+ // Handle nested keys
38
+ if (key.includes('.')) {
39
+ const parts = key.split('.');
40
+ const config = configManager.getConfig();
41
+ let current = config;
42
+
43
+ for (const part of parts) {
44
+ if (current && typeof current === 'object' && part in current) {
45
+ current = current[part];
46
+ } else {
47
+ console.log(chalk.yellow(`Key '${key}' not found`));
48
+ return;
49
+ }
50
+ }
51
+ console.log(JSON.stringify(current, null, 2));
52
+ return;
53
+ }
54
+
55
+ // Simple key
19
56
  const config = configManager.getConfig();
20
57
  const value = config[key];
21
58
  if (value !== undefined) {
@@ -31,39 +68,47 @@ configCommands
31
68
  .argument('<key>', 'Configuration key (e.g., providers.wise.environment)')
32
69
  .argument('<value>', 'Configuration value')
33
70
  .action((key, value) => {
34
- const setNestedValue = (obj: any, keys: string[], val: any) => {
35
- let current = obj;
36
- for (let i = 0; i < keys.length - 1; i++) {
37
- if (!current[keys[i]]) current[keys[i]] = {};
38
- current = current[keys[i]];
39
- }
40
- current[keys[keys.length - 1]] = val;
41
- };
42
-
71
+ // Parse the value (try JSON first, then use as string)
72
+ let parsedValue: any;
43
73
  try {
44
- const parsedValue = JSON.parse(value);
45
- const config = configManager.getConfig();
74
+ parsedValue = JSON.parse(value);
75
+ } catch {
76
+ parsedValue = value;
77
+ }
78
+
79
+ // Handle nested keys like providers.wise.environment
80
+ if (key.startsWith('providers.')) {
81
+ const parts = key.split('.');
82
+ const providerName = parts[1];
83
+ const providerKey = parts[2];
46
84
 
47
- if (key.includes('.')) {
48
- const parts = key.split('.');
49
- setNestedValue(config, parts, parsedValue);
50
- configManager.setConfig(parts[0], config[parts[0]]);
51
- } else {
52
- configManager.setConfig(key, parsedValue);
53
- }
85
+ const provider = configManager.getProvider(providerName) || { name: providerName };
86
+ (provider as any)[providerKey] = parsedValue;
87
+ configManager.setProvider(providerName, provider as any);
54
88
  console.log(chalk.green(`✓ Set ${key} = ${value}`));
55
- } catch {
89
+ return;
90
+ }
91
+
92
+ // Handle other nested keys
93
+ if (key.includes('.')) {
94
+ const parts = key.split('.');
56
95
  const config = configManager.getConfig();
96
+ let current = config;
57
97
 
58
- if (key.includes('.')) {
59
- const parts = key.split('.');
60
- setNestedValue(config, parts, value);
61
- configManager.setConfig(parts[0], config[parts[0]]);
62
- } else {
63
- configManager.setConfig(key, value);
98
+ for (let i = 0; i < parts.length - 1; i++) {
99
+ if (!current[parts[i]]) current[parts[i]] = {};
100
+ current = current[parts[i]];
64
101
  }
102
+ current[parts[parts.length - 1]] = parsedValue;
103
+
104
+ configManager.setConfig(parts[0], config[parts[0]]);
65
105
  console.log(chalk.green(`✓ Set ${key} = ${value}`));
106
+ return;
66
107
  }
108
+
109
+ // Simple key
110
+ configManager.setConfig(key, parsedValue);
111
+ console.log(chalk.green(`✓ Set ${key} = ${value}`));
67
112
  });
68
113
 
69
114
  configCommands
@@ -175,6 +175,43 @@ wiseCommands
175
175
  }
176
176
  });
177
177
 
178
+ // Create recipient
179
+ wiseCommands
180
+ .command('create-recipient')
181
+ .description('Create a recipient account')
182
+ .requiredOption('-n, --name <name>', 'Account holder name')
183
+ .requiredOption('-c, --currency <currency>', 'Currency (EUR, USD, etc)')
184
+ .requiredOption('--iban <iban>', 'IBAN number')
185
+ .option('-p, --profile <id>', 'Profile ID')
186
+ .action(async (options) => {
187
+ const spinner = ora('Creating recipient...').start();
188
+ try {
189
+ const config = configManager.getProvider('wise');
190
+ if (!config) {
191
+ throw new Error('Wise not configured');
192
+ }
193
+
194
+ const client = new WiseClient(config as any);
195
+ const profileId = options.profile || config.profileId;
196
+
197
+ const recipient = await client.createRecipient(
198
+ profileId,
199
+ options.currency,
200
+ options.name,
201
+ { iban: options.iban }
202
+ );
203
+
204
+ spinner.stop();
205
+ console.log(chalk.green('✓ Recipient created'));
206
+ console.log(` ID: ${recipient.id}`);
207
+ console.log(` Name: ${recipient.accountHolderName}`);
208
+ console.log(` IBAN: ${recipient.details.iban}`);
209
+ } catch (error: any) {
210
+ spinner.fail(error.message);
211
+ process.exit(1);
212
+ }
213
+ });
214
+
178
215
  // List transfers
179
216
  wiseCommands
180
217
  .command('list')
@@ -15,7 +15,15 @@ import {
15
15
  BunqConfig
16
16
  } from '../types';
17
17
 
18
- const CONFIG_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.payment-skill');
18
+ // Support both old location (~/.payment-skill) and new location (./data)
19
+ const OLD_CONFIG_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.payment-skill');
20
+ const NEW_CONFIG_DIR = path.join(__dirname, '..', '..', 'data');
21
+
22
+ // Use new location if it exists and has config, otherwise fall back to old location
23
+ const CONFIG_DIR = fs.existsSync(path.join(NEW_CONFIG_DIR, 'config.json'))
24
+ ? NEW_CONFIG_DIR
25
+ : (fs.existsSync(OLD_CONFIG_DIR) ? OLD_CONFIG_DIR : NEW_CONFIG_DIR);
26
+
19
27
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
20
28
  const EMERGENCY_FILE = path.join(CONFIG_DIR, 'emergency.json');
21
29
 
@@ -9,7 +9,15 @@ import * as path from 'path';
9
9
  import { Transaction, TransactionStatus } from '../types';
10
10
  import { configManager } from './config';
11
11
 
12
- const DATA_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.payment-skill');
12
+ // Support both old location (~/.payment-skill) and new location (./data)
13
+ const OLD_DATA_DIR = path.join(process.env.HOME || process.env.USERPROFILE || '.', '.payment-skill');
14
+ const NEW_DATA_DIR = path.join(__dirname, '..', '..', 'data');
15
+
16
+ // Use new location if it exists and has config, otherwise fall back to old location
17
+ const DATA_DIR = fs.existsSync(path.join(NEW_DATA_DIR, 'config.json'))
18
+ ? NEW_DATA_DIR
19
+ : (fs.existsSync(OLD_DATA_DIR) ? OLD_DATA_DIR : NEW_DATA_DIR);
20
+
13
21
  const TRANSACTIONS_FILE = path.join(DATA_DIR, 'transactions.json');
14
22
 
15
23
  export class TransactionManager {
@@ -8,6 +8,7 @@ import express from 'express';
8
8
  import cors from 'cors';
9
9
  import helmet from 'helmet';
10
10
  import path from 'path';
11
+ import * as fs from 'fs-extra';
11
12
  import { configManager } from '../core/config';
12
13
  import { transactionManager } from '../core/transaction';
13
14
  import { fetchAndSaveWiseProfile } from '../api/wise-profile';
@@ -16,7 +17,7 @@ export class PaymentSkillServer {
16
17
  private app: express.Application;
17
18
  private port: number;
18
19
 
19
- constructor(port: number = 8080) {
20
+ constructor(port: number = 18790) {
20
21
  this.app = express();
21
22
  this.port = port;
22
23
  this.setupMiddleware();
@@ -250,6 +251,24 @@ export class PaymentSkillServer {
250
251
  res.status(200).send('OK');
251
252
  });
252
253
 
254
+ // Verified Merchants
255
+ this.app.get('/api/verified-merchants', (req, res) => {
256
+ try {
257
+ const merchantsPath = path.join(__dirname, '../../verified-merchants.json');
258
+ console.log('Looking for verified merchants at:', merchantsPath);
259
+ if (fs.existsSync(merchantsPath)) {
260
+ const data = fs.readJsonSync(merchantsPath);
261
+ res.json(data);
262
+ } else {
263
+ console.log('File not found, returning empty list');
264
+ res.json({ merchants: [], version: '1.0.0' });
265
+ }
266
+ } catch (error: any) {
267
+ console.error('Error loading verified merchants:', error.message);
268
+ res.status(500).json({ error: 'Failed to load verified merchants', details: error.message });
269
+ }
270
+ });
271
+
253
272
  // Dashboard route - serve dashboard.html
254
273
  this.app.get('/', (req, res) => {
255
274
  res.sendFile(path.join(__dirname, '../../dashboard.html'));
@@ -270,7 +289,7 @@ export class PaymentSkillServer {
270
289
 
271
290
  // Start server if run directly
272
291
  if (require.main === module) {
273
- const port = parseInt(process.env.PORT || '8080');
292
+ const port = parseInt(process.env.PORT || '18790');
274
293
  const server = new PaymentSkillServer(port);
275
294
  server.start();
276
295
  }
@@ -38,8 +38,8 @@
38
38
  },
39
39
  {
40
40
  "id": "clickclack-market",
41
- "name": "ClickClack Market",
42
- "domains": ["clickclack.market"],
41
+ "name": "ManyClaws",
42
+ "domains": ["manyclaws.store"],
43
43
  "categories": ["marketplace", "shopping"],
44
44
  "verified": true,
45
45
  "riskLevel": "low",