@hasna/wallets 0.1.2 → 0.1.4
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/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +1122 -0
- package/dist/db/agents.d.ts +8 -0
- package/dist/db/agents.d.ts.map +1 -0
- package/dist/db/cards.d.ts +25 -0
- package/dist/db/cards.d.ts.map +1 -0
- package/dist/db/database.d.ts +9 -0
- package/dist/db/database.d.ts.map +1 -0
- package/dist/db/providers.d.ts +13 -0
- package/dist/db/providers.d.ts.map +1 -0
- package/dist/db/transactions.d.ts +18 -0
- package/dist/db/transactions.d.ts.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +869 -0
- package/dist/lib/config.d.ts +13 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/doctor.d.ts +3 -0
- package/dist/lib/doctor.d.ts.map +1 -0
- package/dist/lib/format.d.ts +7 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +5073 -0
- package/dist/providers/agentcard.d.ts +25 -0
- package/dist/providers/agentcard.d.ts.map +1 -0
- package/dist/providers/index.d.ts +11 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/registry.d.ts +6 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/types/index.d.ts +215 -0
- package/dist/types/index.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.js
ADDED
|
@@ -0,0 +1,869 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/db/database.ts
|
|
3
|
+
import { Database } from "bun:sqlite";
|
|
4
|
+
import { homedir } from "os";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import { existsSync, mkdirSync } from "fs";
|
|
7
|
+
var _db = null;
|
|
8
|
+
var MIGRATIONS = [
|
|
9
|
+
{
|
|
10
|
+
id: 1,
|
|
11
|
+
sql: `
|
|
12
|
+
CREATE TABLE IF NOT EXISTS providers (
|
|
13
|
+
id TEXT PRIMARY KEY,
|
|
14
|
+
name TEXT NOT NULL UNIQUE,
|
|
15
|
+
type TEXT NOT NULL,
|
|
16
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'inactive', 'error')),
|
|
17
|
+
config TEXT DEFAULT '{}',
|
|
18
|
+
metadata TEXT DEFAULT '{}',
|
|
19
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
20
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
CREATE TABLE IF NOT EXISTS cards (
|
|
24
|
+
id TEXT PRIMARY KEY,
|
|
25
|
+
provider_id TEXT NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
|
|
26
|
+
external_id TEXT NOT NULL,
|
|
27
|
+
name TEXT NOT NULL,
|
|
28
|
+
last_four TEXT NOT NULL DEFAULT '',
|
|
29
|
+
brand TEXT NOT NULL DEFAULT 'visa',
|
|
30
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('active', 'frozen', 'closed', 'pending')),
|
|
31
|
+
currency TEXT NOT NULL DEFAULT 'USD',
|
|
32
|
+
balance REAL NOT NULL DEFAULT 0,
|
|
33
|
+
funded_amount REAL NOT NULL DEFAULT 0,
|
|
34
|
+
spending_limit REAL,
|
|
35
|
+
agent_id TEXT,
|
|
36
|
+
metadata TEXT DEFAULT '{}',
|
|
37
|
+
expires_at TEXT,
|
|
38
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
39
|
+
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
CREATE TABLE IF NOT EXISTS transactions (
|
|
43
|
+
id TEXT PRIMARY KEY,
|
|
44
|
+
card_id TEXT NOT NULL REFERENCES cards(id) ON DELETE CASCADE,
|
|
45
|
+
provider_id TEXT NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
|
|
46
|
+
external_id TEXT,
|
|
47
|
+
type TEXT NOT NULL CHECK(type IN ('purchase', 'refund', 'load', 'withdrawal', 'fee')),
|
|
48
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'completed', 'failed', 'reversed')),
|
|
49
|
+
amount REAL NOT NULL,
|
|
50
|
+
currency TEXT NOT NULL DEFAULT 'USD',
|
|
51
|
+
merchant TEXT,
|
|
52
|
+
description TEXT,
|
|
53
|
+
metadata TEXT DEFAULT '{}',
|
|
54
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
CREATE TABLE IF NOT EXISTS agents (
|
|
58
|
+
id TEXT PRIMARY KEY,
|
|
59
|
+
name TEXT NOT NULL UNIQUE,
|
|
60
|
+
description TEXT,
|
|
61
|
+
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
|
|
62
|
+
last_seen_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_cards_provider ON cards(provider_id);
|
|
66
|
+
CREATE INDEX IF NOT EXISTS idx_cards_agent ON cards(agent_id);
|
|
67
|
+
CREATE INDEX IF NOT EXISTS idx_cards_status ON cards(status);
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_transactions_card ON transactions(card_id);
|
|
69
|
+
CREATE INDEX IF NOT EXISTS idx_transactions_provider ON transactions(provider_id);
|
|
70
|
+
CREATE INDEX IF NOT EXISTS idx_transactions_type ON transactions(type);
|
|
71
|
+
|
|
72
|
+
CREATE TABLE IF NOT EXISTS _migrations (
|
|
73
|
+
id INTEGER PRIMARY KEY,
|
|
74
|
+
applied_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
75
|
+
);
|
|
76
|
+
`
|
|
77
|
+
}
|
|
78
|
+
];
|
|
79
|
+
function runMigrations(db) {
|
|
80
|
+
db.run(`CREATE TABLE IF NOT EXISTS _migrations (
|
|
81
|
+
id INTEGER PRIMARY KEY,
|
|
82
|
+
applied_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
83
|
+
)`);
|
|
84
|
+
for (const migration of MIGRATIONS) {
|
|
85
|
+
const applied = db.query("SELECT id FROM _migrations WHERE id = ?").get(migration.id);
|
|
86
|
+
if (!applied) {
|
|
87
|
+
db.run("BEGIN");
|
|
88
|
+
try {
|
|
89
|
+
db.run(migration.sql);
|
|
90
|
+
db.run("INSERT INTO _migrations (id) VALUES (?)", [migration.id]);
|
|
91
|
+
db.run("COMMIT");
|
|
92
|
+
} catch (e) {
|
|
93
|
+
db.run("ROLLBACK");
|
|
94
|
+
throw e;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function resolveDbPath() {
|
|
100
|
+
const envPath = process.env["WALLETS_DB_PATH"];
|
|
101
|
+
if (envPath)
|
|
102
|
+
return envPath;
|
|
103
|
+
const dir = join(homedir(), ".wallets");
|
|
104
|
+
if (!existsSync(dir)) {
|
|
105
|
+
mkdirSync(dir, { recursive: true });
|
|
106
|
+
}
|
|
107
|
+
return join(dir, "wallets.db");
|
|
108
|
+
}
|
|
109
|
+
function getDatabase(dbPath) {
|
|
110
|
+
if (_db)
|
|
111
|
+
return _db;
|
|
112
|
+
const path = dbPath || resolveDbPath();
|
|
113
|
+
_db = new Database(path);
|
|
114
|
+
_db.run("PRAGMA journal_mode = WAL");
|
|
115
|
+
_db.run("PRAGMA foreign_keys = ON");
|
|
116
|
+
_db.run("PRAGMA busy_timeout = 5000");
|
|
117
|
+
runMigrations(_db);
|
|
118
|
+
return _db;
|
|
119
|
+
}
|
|
120
|
+
function closeDatabase() {
|
|
121
|
+
if (_db) {
|
|
122
|
+
_db.close();
|
|
123
|
+
_db = null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function resetDatabase() {
|
|
127
|
+
closeDatabase();
|
|
128
|
+
_db = null;
|
|
129
|
+
}
|
|
130
|
+
function now() {
|
|
131
|
+
return new Date().toISOString();
|
|
132
|
+
}
|
|
133
|
+
function uuid() {
|
|
134
|
+
return crypto.randomUUID();
|
|
135
|
+
}
|
|
136
|
+
function shortId() {
|
|
137
|
+
return crypto.randomUUID().slice(0, 8);
|
|
138
|
+
}
|
|
139
|
+
// src/db/providers.ts
|
|
140
|
+
function rowToProvider(row) {
|
|
141
|
+
return {
|
|
142
|
+
...row,
|
|
143
|
+
status: row.status,
|
|
144
|
+
config: JSON.parse(row.config || "{}"),
|
|
145
|
+
metadata: JSON.parse(row.metadata || "{}")
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function createProvider(input, db) {
|
|
149
|
+
const d = db || getDatabase();
|
|
150
|
+
const id = shortId();
|
|
151
|
+
d.run(`INSERT INTO providers (id, name, type, config, metadata) VALUES (?, ?, ?, ?, ?)`, [
|
|
152
|
+
id,
|
|
153
|
+
input.name,
|
|
154
|
+
input.type,
|
|
155
|
+
JSON.stringify(input.config || {}),
|
|
156
|
+
JSON.stringify(input.metadata || {})
|
|
157
|
+
]);
|
|
158
|
+
return getProvider(id, d);
|
|
159
|
+
}
|
|
160
|
+
function getProvider(id, db) {
|
|
161
|
+
const d = db || getDatabase();
|
|
162
|
+
const row = d.query("SELECT * FROM providers WHERE id = ?").get(id);
|
|
163
|
+
return row ? rowToProvider(row) : null;
|
|
164
|
+
}
|
|
165
|
+
function getProviderByName(name, db) {
|
|
166
|
+
const d = db || getDatabase();
|
|
167
|
+
const row = d.query("SELECT * FROM providers WHERE name = ?").get(name);
|
|
168
|
+
return row ? rowToProvider(row) : null;
|
|
169
|
+
}
|
|
170
|
+
function listProviders(db) {
|
|
171
|
+
const d = db || getDatabase();
|
|
172
|
+
const rows = d.query("SELECT * FROM providers ORDER BY created_at DESC").all();
|
|
173
|
+
return rows.map(rowToProvider);
|
|
174
|
+
}
|
|
175
|
+
function updateProvider(id, input, db) {
|
|
176
|
+
const d = db || getDatabase();
|
|
177
|
+
const provider = getProvider(id, d);
|
|
178
|
+
if (!provider)
|
|
179
|
+
throw new Error(`Provider not found: ${id}`);
|
|
180
|
+
const sets = [];
|
|
181
|
+
const params = [];
|
|
182
|
+
if (input.name !== undefined) {
|
|
183
|
+
sets.push("name = ?");
|
|
184
|
+
params.push(input.name);
|
|
185
|
+
}
|
|
186
|
+
if (input.config !== undefined) {
|
|
187
|
+
sets.push("config = ?");
|
|
188
|
+
params.push(JSON.stringify(input.config));
|
|
189
|
+
}
|
|
190
|
+
if (input.metadata !== undefined) {
|
|
191
|
+
sets.push("metadata = ?");
|
|
192
|
+
params.push(JSON.stringify(input.metadata));
|
|
193
|
+
}
|
|
194
|
+
if (input.status !== undefined) {
|
|
195
|
+
sets.push("status = ?");
|
|
196
|
+
params.push(input.status);
|
|
197
|
+
}
|
|
198
|
+
if (sets.length > 0) {
|
|
199
|
+
sets.push("updated_at = ?");
|
|
200
|
+
params.push(now());
|
|
201
|
+
params.push(id);
|
|
202
|
+
d.run(`UPDATE providers SET ${sets.join(", ")} WHERE id = ?`, params);
|
|
203
|
+
}
|
|
204
|
+
return getProvider(id, d);
|
|
205
|
+
}
|
|
206
|
+
function deleteProvider(id, db) {
|
|
207
|
+
const d = db || getDatabase();
|
|
208
|
+
return d.run("DELETE FROM providers WHERE id = ?", [id]).changes > 0;
|
|
209
|
+
}
|
|
210
|
+
function ensureProvider(name, type, config, db) {
|
|
211
|
+
const d = db || getDatabase();
|
|
212
|
+
const existing = getProviderByName(name, d);
|
|
213
|
+
if (existing) {
|
|
214
|
+
if (config) {
|
|
215
|
+
return updateProvider(existing.id, { config }, d);
|
|
216
|
+
}
|
|
217
|
+
d.run("UPDATE providers SET updated_at = ? WHERE id = ?", [now(), existing.id]);
|
|
218
|
+
return getProvider(existing.id, d);
|
|
219
|
+
}
|
|
220
|
+
return createProvider({ name, type, config }, d);
|
|
221
|
+
}
|
|
222
|
+
// src/db/cards.ts
|
|
223
|
+
function rowToCard(row) {
|
|
224
|
+
return {
|
|
225
|
+
...row,
|
|
226
|
+
status: row.status,
|
|
227
|
+
currency: row.currency,
|
|
228
|
+
metadata: JSON.parse(row.metadata || "{}")
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function createCardRecord(input, db) {
|
|
232
|
+
const d = db || getDatabase();
|
|
233
|
+
const id = uuid();
|
|
234
|
+
d.run(`INSERT INTO cards (id, provider_id, external_id, name, last_four, brand, status, currency, balance, funded_amount, spending_limit, agent_id, metadata, expires_at)
|
|
235
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
236
|
+
id,
|
|
237
|
+
input.provider_id,
|
|
238
|
+
input.external_id,
|
|
239
|
+
input.name,
|
|
240
|
+
input.last_four || "",
|
|
241
|
+
input.brand || "visa",
|
|
242
|
+
input.status || "pending",
|
|
243
|
+
input.currency || "USD",
|
|
244
|
+
input.balance ?? 0,
|
|
245
|
+
input.funded_amount ?? 0,
|
|
246
|
+
input.spending_limit ?? null,
|
|
247
|
+
input.agent_id ?? null,
|
|
248
|
+
JSON.stringify(input.metadata || {}),
|
|
249
|
+
input.expires_at ?? null
|
|
250
|
+
]);
|
|
251
|
+
return getCard(id, d);
|
|
252
|
+
}
|
|
253
|
+
function getCard(id, db) {
|
|
254
|
+
const d = db || getDatabase();
|
|
255
|
+
const row = d.query("SELECT * FROM cards WHERE id = ?").get(id);
|
|
256
|
+
return row ? rowToCard(row) : null;
|
|
257
|
+
}
|
|
258
|
+
function getCardByExternalId(externalId, providerId, db) {
|
|
259
|
+
const d = db || getDatabase();
|
|
260
|
+
const row = d.query("SELECT * FROM cards WHERE external_id = ? AND provider_id = ?").get(externalId, providerId);
|
|
261
|
+
return row ? rowToCard(row) : null;
|
|
262
|
+
}
|
|
263
|
+
function listCards(filter = {}, db) {
|
|
264
|
+
const d = db || getDatabase();
|
|
265
|
+
const conditions = [];
|
|
266
|
+
const params = [];
|
|
267
|
+
if (filter.provider_id) {
|
|
268
|
+
conditions.push("provider_id = ?");
|
|
269
|
+
params.push(filter.provider_id);
|
|
270
|
+
}
|
|
271
|
+
if (filter.status) {
|
|
272
|
+
conditions.push("status = ?");
|
|
273
|
+
params.push(filter.status);
|
|
274
|
+
}
|
|
275
|
+
if (filter.agent_id) {
|
|
276
|
+
conditions.push("agent_id = ?");
|
|
277
|
+
params.push(filter.agent_id);
|
|
278
|
+
}
|
|
279
|
+
if (filter.currency) {
|
|
280
|
+
conditions.push("currency = ?");
|
|
281
|
+
params.push(filter.currency);
|
|
282
|
+
}
|
|
283
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
284
|
+
const limit = filter.limit ? `LIMIT ${filter.limit}` : "";
|
|
285
|
+
const offset = filter.offset ? `OFFSET ${filter.offset}` : "";
|
|
286
|
+
const rows = d.query(`SELECT * FROM cards ${where} ORDER BY created_at DESC ${limit} ${offset}`).all(...params);
|
|
287
|
+
return rows.map(rowToCard);
|
|
288
|
+
}
|
|
289
|
+
function updateCard(id, input, db) {
|
|
290
|
+
const d = db || getDatabase();
|
|
291
|
+
const card = getCard(id, d);
|
|
292
|
+
if (!card)
|
|
293
|
+
throw new Error(`Card not found: ${id}`);
|
|
294
|
+
const sets = [];
|
|
295
|
+
const params = [];
|
|
296
|
+
if (input.name !== undefined) {
|
|
297
|
+
sets.push("name = ?");
|
|
298
|
+
params.push(input.name);
|
|
299
|
+
}
|
|
300
|
+
if (input.status !== undefined) {
|
|
301
|
+
sets.push("status = ?");
|
|
302
|
+
params.push(input.status);
|
|
303
|
+
}
|
|
304
|
+
if (input.spending_limit !== undefined) {
|
|
305
|
+
sets.push("spending_limit = ?");
|
|
306
|
+
params.push(input.spending_limit);
|
|
307
|
+
}
|
|
308
|
+
if (input.metadata !== undefined) {
|
|
309
|
+
sets.push("metadata = ?");
|
|
310
|
+
params.push(JSON.stringify(input.metadata));
|
|
311
|
+
}
|
|
312
|
+
if (sets.length > 0) {
|
|
313
|
+
sets.push("updated_at = ?");
|
|
314
|
+
params.push(now());
|
|
315
|
+
params.push(id);
|
|
316
|
+
d.run(`UPDATE cards SET ${sets.join(", ")} WHERE id = ?`, params);
|
|
317
|
+
}
|
|
318
|
+
return getCard(id, d);
|
|
319
|
+
}
|
|
320
|
+
function updateCardBalance(id, balance, db) {
|
|
321
|
+
const d = db || getDatabase();
|
|
322
|
+
d.run("UPDATE cards SET balance = ?, updated_at = ? WHERE id = ?", [balance, now(), id]);
|
|
323
|
+
return getCard(id, d);
|
|
324
|
+
}
|
|
325
|
+
function deleteCard(id, db) {
|
|
326
|
+
const d = db || getDatabase();
|
|
327
|
+
return d.run("DELETE FROM cards WHERE id = ?", [id]).changes > 0;
|
|
328
|
+
}
|
|
329
|
+
// src/db/transactions.ts
|
|
330
|
+
function rowToTransaction(row) {
|
|
331
|
+
return {
|
|
332
|
+
...row,
|
|
333
|
+
type: row.type,
|
|
334
|
+
status: row.status,
|
|
335
|
+
currency: row.currency,
|
|
336
|
+
metadata: JSON.parse(row.metadata || "{}")
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
function createTransaction(input, db) {
|
|
340
|
+
const d = db || getDatabase();
|
|
341
|
+
const id = uuid();
|
|
342
|
+
d.run(`INSERT INTO transactions (id, card_id, provider_id, external_id, type, status, amount, currency, merchant, description, metadata)
|
|
343
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
344
|
+
id,
|
|
345
|
+
input.card_id,
|
|
346
|
+
input.provider_id,
|
|
347
|
+
input.external_id ?? null,
|
|
348
|
+
input.type,
|
|
349
|
+
input.status || "completed",
|
|
350
|
+
input.amount,
|
|
351
|
+
input.currency || "USD",
|
|
352
|
+
input.merchant ?? null,
|
|
353
|
+
input.description ?? null,
|
|
354
|
+
JSON.stringify(input.metadata || {})
|
|
355
|
+
]);
|
|
356
|
+
return getTransaction(id, d);
|
|
357
|
+
}
|
|
358
|
+
function getTransaction(id, db) {
|
|
359
|
+
const d = db || getDatabase();
|
|
360
|
+
const row = d.query("SELECT * FROM transactions WHERE id = ?").get(id);
|
|
361
|
+
return row ? rowToTransaction(row) : null;
|
|
362
|
+
}
|
|
363
|
+
function listTransactions(filter = {}, db) {
|
|
364
|
+
const d = db || getDatabase();
|
|
365
|
+
const conditions = [];
|
|
366
|
+
const params = [];
|
|
367
|
+
if (filter.card_id) {
|
|
368
|
+
conditions.push("card_id = ?");
|
|
369
|
+
params.push(filter.card_id);
|
|
370
|
+
}
|
|
371
|
+
if (filter.provider_id) {
|
|
372
|
+
conditions.push("provider_id = ?");
|
|
373
|
+
params.push(filter.provider_id);
|
|
374
|
+
}
|
|
375
|
+
if (filter.type) {
|
|
376
|
+
conditions.push("type = ?");
|
|
377
|
+
params.push(filter.type);
|
|
378
|
+
}
|
|
379
|
+
if (filter.status) {
|
|
380
|
+
conditions.push("status = ?");
|
|
381
|
+
params.push(filter.status);
|
|
382
|
+
}
|
|
383
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
384
|
+
const limit = filter.limit ? `LIMIT ${filter.limit}` : "";
|
|
385
|
+
const offset = filter.offset ? `OFFSET ${filter.offset}` : "";
|
|
386
|
+
const rows = d.query(`SELECT * FROM transactions ${where} ORDER BY created_at DESC ${limit} ${offset}`).all(...params);
|
|
387
|
+
return rows.map(rowToTransaction);
|
|
388
|
+
}
|
|
389
|
+
// src/db/agents.ts
|
|
390
|
+
function rowToAgent(row) {
|
|
391
|
+
return { ...row };
|
|
392
|
+
}
|
|
393
|
+
function registerAgent(input, db) {
|
|
394
|
+
const d = db || getDatabase();
|
|
395
|
+
const normalizedName = input.name.trim().toLowerCase();
|
|
396
|
+
const existing = getAgentByName(normalizedName, d);
|
|
397
|
+
if (existing) {
|
|
398
|
+
d.run("UPDATE agents SET last_seen_at = ? WHERE id = ?", [now(), existing.id]);
|
|
399
|
+
return getAgent(existing.id, d);
|
|
400
|
+
}
|
|
401
|
+
const id = shortId();
|
|
402
|
+
d.run("INSERT INTO agents (id, name, description) VALUES (?, ?, ?)", [id, normalizedName, input.description ?? null]);
|
|
403
|
+
return getAgent(id, d);
|
|
404
|
+
}
|
|
405
|
+
function getAgent(id, db) {
|
|
406
|
+
const d = db || getDatabase();
|
|
407
|
+
const row = d.query("SELECT * FROM agents WHERE id = ?").get(id);
|
|
408
|
+
return row ? rowToAgent(row) : null;
|
|
409
|
+
}
|
|
410
|
+
function getAgentByName(name, db) {
|
|
411
|
+
const d = db || getDatabase();
|
|
412
|
+
const normalizedName = name.trim().toLowerCase();
|
|
413
|
+
const row = d.query("SELECT * FROM agents WHERE name = ?").get(normalizedName);
|
|
414
|
+
return row ? rowToAgent(row) : null;
|
|
415
|
+
}
|
|
416
|
+
function listAgents(db) {
|
|
417
|
+
const d = db || getDatabase();
|
|
418
|
+
const rows = d.query("SELECT * FROM agents ORDER BY last_seen_at DESC").all();
|
|
419
|
+
return rows.map(rowToAgent);
|
|
420
|
+
}
|
|
421
|
+
function deleteAgent(id, db) {
|
|
422
|
+
const d = db || getDatabase();
|
|
423
|
+
return d.run("DELETE FROM agents WHERE id = ?", [id]).changes > 0;
|
|
424
|
+
}
|
|
425
|
+
// src/types/index.ts
|
|
426
|
+
class WalletError extends Error {
|
|
427
|
+
static code = "WALLET_ERROR";
|
|
428
|
+
static suggestion = "Check the wallet configuration and try again.";
|
|
429
|
+
constructor(message) {
|
|
430
|
+
super(message);
|
|
431
|
+
this.name = "WalletError";
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
class ProviderNotFoundError extends Error {
|
|
436
|
+
static code = "PROVIDER_NOT_FOUND";
|
|
437
|
+
static suggestion = "Use 'wallets provider list' to see available providers, or 'wallets provider add' to register one.";
|
|
438
|
+
constructor(id) {
|
|
439
|
+
super(`Provider not found: ${id}`);
|
|
440
|
+
this.name = "ProviderNotFoundError";
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
class CardNotFoundError extends Error {
|
|
445
|
+
static code = "CARD_NOT_FOUND";
|
|
446
|
+
static suggestion = "Use 'wallets card list' to see available cards.";
|
|
447
|
+
constructor(id) {
|
|
448
|
+
super(`Card not found: ${id}`);
|
|
449
|
+
this.name = "CardNotFoundError";
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
class ProviderError extends Error {
|
|
454
|
+
static code = "PROVIDER_ERROR";
|
|
455
|
+
static suggestion = "Check the provider configuration and API credentials. Run 'wallets doctor' for diagnostics.";
|
|
456
|
+
constructor(provider, message) {
|
|
457
|
+
super(`Provider '${provider}' error: ${message}`);
|
|
458
|
+
this.name = "ProviderError";
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
class InsufficientFundsError extends Error {
|
|
463
|
+
static code = "INSUFFICIENT_FUNDS";
|
|
464
|
+
static suggestion = "Fund the card with more money before making this transaction.";
|
|
465
|
+
constructor(cardId, required, available) {
|
|
466
|
+
super(`Insufficient funds on card ${cardId}: need ${required}, have ${available}`);
|
|
467
|
+
this.name = "InsufficientFundsError";
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
class ConfigError extends Error {
|
|
472
|
+
static code = "CONFIG_ERROR";
|
|
473
|
+
static suggestion = "Check ~/.wallets/config.json and ensure all required fields are set.";
|
|
474
|
+
constructor(message) {
|
|
475
|
+
super(message);
|
|
476
|
+
this.name = "ConfigError";
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
class AgentNotFoundError extends Error {
|
|
481
|
+
static code = "AGENT_NOT_FOUND";
|
|
482
|
+
static suggestion = "Use 'wallets agent list' to see registered agents.";
|
|
483
|
+
constructor(id) {
|
|
484
|
+
super(`Agent not found: ${id}`);
|
|
485
|
+
this.name = "AgentNotFoundError";
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// src/providers/agentcard.ts
|
|
490
|
+
class AgentCardProvider {
|
|
491
|
+
name = "agentcard";
|
|
492
|
+
type = "agentcard";
|
|
493
|
+
jwt;
|
|
494
|
+
baseUrl;
|
|
495
|
+
constructor(config) {
|
|
496
|
+
this.jwt = config.jwt;
|
|
497
|
+
this.baseUrl = config.baseUrl || "https://api.agentcard.sh";
|
|
498
|
+
}
|
|
499
|
+
async request(path, options = {}) {
|
|
500
|
+
const url = `${this.baseUrl}${path}`;
|
|
501
|
+
const res = await fetch(url, {
|
|
502
|
+
...options,
|
|
503
|
+
headers: {
|
|
504
|
+
"Content-Type": "application/json",
|
|
505
|
+
Authorization: `Bearer ${this.jwt}`,
|
|
506
|
+
...options.headers || {}
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
if (!res.ok) {
|
|
510
|
+
const body = await res.text();
|
|
511
|
+
throw new ProviderError("agentcard", `HTTP ${res.status}: ${body}`);
|
|
512
|
+
}
|
|
513
|
+
return res.json();
|
|
514
|
+
}
|
|
515
|
+
async createCard(input) {
|
|
516
|
+
const data = await this.request("/cards", {
|
|
517
|
+
method: "POST",
|
|
518
|
+
body: JSON.stringify({ amount: input.amount })
|
|
519
|
+
});
|
|
520
|
+
return {
|
|
521
|
+
id: data.id,
|
|
522
|
+
provider_id: "",
|
|
523
|
+
external_id: data.id,
|
|
524
|
+
name: input.name || `AgentCard $${input.amount}`,
|
|
525
|
+
last_four: "",
|
|
526
|
+
brand: "visa",
|
|
527
|
+
status: data.status || "pending",
|
|
528
|
+
currency: input.currency || "USD",
|
|
529
|
+
balance: 0,
|
|
530
|
+
funded_amount: data.amount || input.amount,
|
|
531
|
+
spending_limit: input.spending_limit ?? null,
|
|
532
|
+
agent_id: input.agent_id ?? null,
|
|
533
|
+
metadata: input.metadata || {},
|
|
534
|
+
expires_at: null,
|
|
535
|
+
created_at: new Date().toISOString(),
|
|
536
|
+
updated_at: new Date().toISOString(),
|
|
537
|
+
funding_url: data.funding_url
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
async listCards() {
|
|
541
|
+
const data = await this.request("/cards");
|
|
542
|
+
return data.map((c) => ({
|
|
543
|
+
id: c.id,
|
|
544
|
+
provider_id: "",
|
|
545
|
+
external_id: c.id,
|
|
546
|
+
name: `AgentCard ${c.last_four ? `*${c.last_four}` : c.id.slice(0, 8)}`,
|
|
547
|
+
last_four: c.last_four || "",
|
|
548
|
+
brand: "visa",
|
|
549
|
+
status: c.status || "active",
|
|
550
|
+
currency: "USD",
|
|
551
|
+
balance: c.balance ?? 0,
|
|
552
|
+
funded_amount: c.amount ?? 0,
|
|
553
|
+
spending_limit: null,
|
|
554
|
+
agent_id: null,
|
|
555
|
+
metadata: {},
|
|
556
|
+
expires_at: null,
|
|
557
|
+
created_at: c.created_at || new Date().toISOString(),
|
|
558
|
+
updated_at: new Date().toISOString()
|
|
559
|
+
}));
|
|
560
|
+
}
|
|
561
|
+
async getCardDetails(externalId) {
|
|
562
|
+
const data = await this.request(`/cards/${externalId}/details`);
|
|
563
|
+
return {
|
|
564
|
+
id: data.id,
|
|
565
|
+
provider_id: "",
|
|
566
|
+
external_id: data.id,
|
|
567
|
+
name: `AgentCard *${data.last_four || data.pan.slice(-4)}`,
|
|
568
|
+
last_four: data.last_four || data.pan.slice(-4),
|
|
569
|
+
brand: "visa",
|
|
570
|
+
status: data.status || "active",
|
|
571
|
+
currency: "USD",
|
|
572
|
+
balance: data.balance ?? 0,
|
|
573
|
+
funded_amount: data.amount ?? 0,
|
|
574
|
+
spending_limit: null,
|
|
575
|
+
agent_id: null,
|
|
576
|
+
metadata: {},
|
|
577
|
+
expires_at: null,
|
|
578
|
+
created_at: new Date().toISOString(),
|
|
579
|
+
updated_at: new Date().toISOString(),
|
|
580
|
+
pan: data.pan,
|
|
581
|
+
cvv: data.cvv,
|
|
582
|
+
exp_month: data.exp_month,
|
|
583
|
+
exp_year: data.exp_year
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
async getBalance(externalId) {
|
|
587
|
+
const data = await this.request(`/cards/${externalId}/balance`);
|
|
588
|
+
return {
|
|
589
|
+
balance: data.balance,
|
|
590
|
+
currency: data.currency || "USD"
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
async closeCard(externalId) {
|
|
594
|
+
await this.request(`/cards/${externalId}/close`, { method: "POST" });
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// src/providers/registry.ts
|
|
599
|
+
var providers = new Map;
|
|
600
|
+
function registerProviderFactory(type, factory) {
|
|
601
|
+
providers.set(type, factory);
|
|
602
|
+
}
|
|
603
|
+
function listProviderTypes() {
|
|
604
|
+
return Array.from(providers.keys());
|
|
605
|
+
}
|
|
606
|
+
function createProviderInstance(type) {
|
|
607
|
+
const factory = providers.get(type);
|
|
608
|
+
if (!factory) {
|
|
609
|
+
throw new Error(`Unknown provider type: ${type}. Available: ${listProviderTypes().join(", ")}`);
|
|
610
|
+
}
|
|
611
|
+
return factory();
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// src/providers/index.ts
|
|
615
|
+
registerProviderFactory("agentcard", () => {
|
|
616
|
+
throw new Error("AgentCard requires config. Use createAgentCardProvider() instead.");
|
|
617
|
+
});
|
|
618
|
+
function createAgentCardProvider(config) {
|
|
619
|
+
return new AgentCardProvider(config);
|
|
620
|
+
}
|
|
621
|
+
function getProviderInstance(type, config) {
|
|
622
|
+
switch (type) {
|
|
623
|
+
case "agentcard":
|
|
624
|
+
return new AgentCardProvider({ jwt: config["jwt"], baseUrl: config["baseUrl"] });
|
|
625
|
+
default:
|
|
626
|
+
return createProviderInstance(type);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
// src/lib/config.ts
|
|
630
|
+
import { homedir as homedir2 } from "os";
|
|
631
|
+
import { join as join2 } from "path";
|
|
632
|
+
import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
|
|
633
|
+
function getConfigDir() {
|
|
634
|
+
return process.env["WALLETS_CONFIG_DIR"] || join2(homedir2(), ".wallets");
|
|
635
|
+
}
|
|
636
|
+
function getConfigPath() {
|
|
637
|
+
return join2(getConfigDir(), "config.json");
|
|
638
|
+
}
|
|
639
|
+
function loadConfig() {
|
|
640
|
+
const configPath = getConfigPath();
|
|
641
|
+
if (!existsSync2(configPath)) {
|
|
642
|
+
return {};
|
|
643
|
+
}
|
|
644
|
+
try {
|
|
645
|
+
return JSON.parse(readFileSync(configPath, "utf-8"));
|
|
646
|
+
} catch {
|
|
647
|
+
return {};
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
function saveConfig(config) {
|
|
651
|
+
const configDir = getConfigDir();
|
|
652
|
+
if (!existsSync2(configDir)) {
|
|
653
|
+
mkdirSync2(configDir, { recursive: true });
|
|
654
|
+
}
|
|
655
|
+
writeFileSync(join2(configDir, "config.json"), JSON.stringify(config, null, 2) + `
|
|
656
|
+
`);
|
|
657
|
+
}
|
|
658
|
+
function getProviderConfig(providerName) {
|
|
659
|
+
const config = loadConfig();
|
|
660
|
+
return config.providers?.[providerName];
|
|
661
|
+
}
|
|
662
|
+
function setProviderConfig(providerName, providerConfig) {
|
|
663
|
+
const config = loadConfig();
|
|
664
|
+
if (!config.providers)
|
|
665
|
+
config.providers = {};
|
|
666
|
+
config.providers[providerName] = providerConfig;
|
|
667
|
+
saveConfig(config);
|
|
668
|
+
}
|
|
669
|
+
// src/lib/doctor.ts
|
|
670
|
+
import { existsSync as existsSync3 } from "fs";
|
|
671
|
+
import { join as join3 } from "path";
|
|
672
|
+
function runDoctor() {
|
|
673
|
+
const checks = [];
|
|
674
|
+
const configDir = getConfigDir();
|
|
675
|
+
checks.push({
|
|
676
|
+
name: "Config directory",
|
|
677
|
+
status: existsSync3(configDir) ? "ok" : "warn",
|
|
678
|
+
message: existsSync3(configDir) ? `Found at ${configDir}` : `Not found at ${configDir}. Run 'wallets provider add' to create it.`
|
|
679
|
+
});
|
|
680
|
+
const configPath = getConfigPath();
|
|
681
|
+
if (existsSync3(configPath)) {
|
|
682
|
+
try {
|
|
683
|
+
const config = loadConfig();
|
|
684
|
+
checks.push({
|
|
685
|
+
name: "Config file",
|
|
686
|
+
status: "ok",
|
|
687
|
+
message: `Valid config at ${configPath}`
|
|
688
|
+
});
|
|
689
|
+
if (config.default_provider) {
|
|
690
|
+
checks.push({
|
|
691
|
+
name: "Default provider",
|
|
692
|
+
status: "ok",
|
|
693
|
+
message: `Set to '${config.default_provider}'`
|
|
694
|
+
});
|
|
695
|
+
} else {
|
|
696
|
+
checks.push({
|
|
697
|
+
name: "Default provider",
|
|
698
|
+
status: "warn",
|
|
699
|
+
message: "No default provider set. Use 'wallets provider add' to register one."
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
} catch {
|
|
703
|
+
checks.push({
|
|
704
|
+
name: "Config file",
|
|
705
|
+
status: "error",
|
|
706
|
+
message: `Invalid JSON at ${configPath}`
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
} else {
|
|
710
|
+
checks.push({
|
|
711
|
+
name: "Config file",
|
|
712
|
+
status: "warn",
|
|
713
|
+
message: `Not found at ${configPath}. Run 'wallets provider add' to create it.`
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
try {
|
|
717
|
+
const db = getDatabase();
|
|
718
|
+
const providers2 = listProviders(db);
|
|
719
|
+
checks.push({
|
|
720
|
+
name: "Database",
|
|
721
|
+
status: "ok",
|
|
722
|
+
message: `Connected. ${providers2.length} provider(s) registered.`
|
|
723
|
+
});
|
|
724
|
+
for (const provider of providers2) {
|
|
725
|
+
const hasConfig = provider.config && Object.keys(provider.config).length > 0;
|
|
726
|
+
if (provider.type === "agentcard") {
|
|
727
|
+
const hasJwt = provider.config && "jwt" in provider.config;
|
|
728
|
+
checks.push({
|
|
729
|
+
name: `Provider: ${provider.name}`,
|
|
730
|
+
status: hasJwt ? "ok" : "error",
|
|
731
|
+
message: hasJwt ? `AgentCard configured (status: ${provider.status})` : "Missing JWT token. Run 'wallets provider add agentcard' to configure."
|
|
732
|
+
});
|
|
733
|
+
} else {
|
|
734
|
+
checks.push({
|
|
735
|
+
name: `Provider: ${provider.name}`,
|
|
736
|
+
status: hasConfig ? "ok" : "warn",
|
|
737
|
+
message: `Type: ${provider.type}, Status: ${provider.status}${hasConfig ? "" : " (no config)"}`
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
if (providers2.length === 0) {
|
|
742
|
+
checks.push({
|
|
743
|
+
name: "Providers",
|
|
744
|
+
status: "warn",
|
|
745
|
+
message: "No providers registered. Use 'wallets provider add' to add one."
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
} catch (e) {
|
|
749
|
+
checks.push({
|
|
750
|
+
name: "Database",
|
|
751
|
+
status: "error",
|
|
752
|
+
message: `Failed to connect: ${e instanceof Error ? e.message : String(e)}`
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
try {
|
|
756
|
+
const binPath = join3(import.meta.dir, "../../dist/mcp/index.js");
|
|
757
|
+
const srcPath = join3(import.meta.dir, "../mcp/index.ts");
|
|
758
|
+
const mcpAvailable = existsSync3(binPath) || existsSync3(srcPath);
|
|
759
|
+
checks.push({
|
|
760
|
+
name: "MCP server",
|
|
761
|
+
status: mcpAvailable ? "ok" : "warn",
|
|
762
|
+
message: mcpAvailable ? "MCP server binary available" : "MCP server not found. Run 'bun run build' to compile."
|
|
763
|
+
});
|
|
764
|
+
} catch {
|
|
765
|
+
checks.push({
|
|
766
|
+
name: "MCP server",
|
|
767
|
+
status: "warn",
|
|
768
|
+
message: "Could not check MCP server status."
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
return {
|
|
772
|
+
checks,
|
|
773
|
+
healthy: checks.every((c) => c.status !== "error")
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
// src/lib/format.ts
|
|
777
|
+
function formatCard(card) {
|
|
778
|
+
const id = card.id.slice(0, 8);
|
|
779
|
+
const last4 = card.last_four ? `*${card.last_four}` : "----";
|
|
780
|
+
return `${id} ${card.status.padEnd(8)} ${last4.padEnd(6)} $${card.balance.toFixed(2).padStart(10)} ${card.name}`;
|
|
781
|
+
}
|
|
782
|
+
function formatProvider(provider) {
|
|
783
|
+
return `${provider.id.slice(0, 8)} ${provider.status.padEnd(8)} ${provider.type.padEnd(12)} ${provider.name}`;
|
|
784
|
+
}
|
|
785
|
+
function formatTransaction(tx) {
|
|
786
|
+
const id = tx.id.slice(0, 8);
|
|
787
|
+
const sign = tx.type === "refund" || tx.type === "load" ? "+" : "-";
|
|
788
|
+
return `${id} ${tx.type.padEnd(10)} ${tx.status.padEnd(10)} ${sign}$${tx.amount.toFixed(2).padStart(9)} ${tx.merchant || tx.description || ""}`;
|
|
789
|
+
}
|
|
790
|
+
function formatDoctorCheck(check) {
|
|
791
|
+
const icon = check.status === "ok" ? "[ok]" : check.status === "warn" ? "[!!]" : "[ERR]";
|
|
792
|
+
return `${icon} ${check.name}: ${check.message}`;
|
|
793
|
+
}
|
|
794
|
+
function formatError(error) {
|
|
795
|
+
if (error instanceof ProviderNotFoundError) {
|
|
796
|
+
return JSON.stringify({ code: ProviderNotFoundError.code, message: error.message, suggestion: ProviderNotFoundError.suggestion });
|
|
797
|
+
}
|
|
798
|
+
if (error instanceof CardNotFoundError) {
|
|
799
|
+
return JSON.stringify({ code: CardNotFoundError.code, message: error.message, suggestion: CardNotFoundError.suggestion });
|
|
800
|
+
}
|
|
801
|
+
if (error instanceof ProviderError) {
|
|
802
|
+
return JSON.stringify({ code: ProviderError.code, message: error.message, suggestion: ProviderError.suggestion });
|
|
803
|
+
}
|
|
804
|
+
if (error instanceof InsufficientFundsError) {
|
|
805
|
+
return JSON.stringify({ code: InsufficientFundsError.code, message: error.message, suggestion: InsufficientFundsError.suggestion });
|
|
806
|
+
}
|
|
807
|
+
if (error instanceof ConfigError) {
|
|
808
|
+
return JSON.stringify({ code: ConfigError.code, message: error.message, suggestion: ConfigError.suggestion });
|
|
809
|
+
}
|
|
810
|
+
if (error instanceof AgentNotFoundError) {
|
|
811
|
+
return JSON.stringify({ code: AgentNotFoundError.code, message: error.message, suggestion: AgentNotFoundError.suggestion });
|
|
812
|
+
}
|
|
813
|
+
if (error instanceof WalletError) {
|
|
814
|
+
return JSON.stringify({ code: WalletError.code, message: error.message, suggestion: WalletError.suggestion });
|
|
815
|
+
}
|
|
816
|
+
if (error instanceof Error) {
|
|
817
|
+
return JSON.stringify({ code: "UNKNOWN_ERROR", message: error.message });
|
|
818
|
+
}
|
|
819
|
+
return JSON.stringify({ code: "UNKNOWN_ERROR", message: String(error) });
|
|
820
|
+
}
|
|
821
|
+
export {
|
|
822
|
+
updateProvider,
|
|
823
|
+
updateCardBalance,
|
|
824
|
+
updateCard,
|
|
825
|
+
setProviderConfig,
|
|
826
|
+
saveConfig,
|
|
827
|
+
runDoctor,
|
|
828
|
+
resetDatabase,
|
|
829
|
+
registerProviderFactory,
|
|
830
|
+
registerAgent,
|
|
831
|
+
loadConfig,
|
|
832
|
+
listTransactions,
|
|
833
|
+
listProviders,
|
|
834
|
+
listProviderTypes,
|
|
835
|
+
listCards,
|
|
836
|
+
listAgents,
|
|
837
|
+
getTransaction,
|
|
838
|
+
getProviderInstance,
|
|
839
|
+
getProviderConfig,
|
|
840
|
+
getProviderByName,
|
|
841
|
+
getProvider,
|
|
842
|
+
getDatabase,
|
|
843
|
+
getCardByExternalId,
|
|
844
|
+
getCard,
|
|
845
|
+
getAgentByName,
|
|
846
|
+
getAgent,
|
|
847
|
+
formatTransaction,
|
|
848
|
+
formatProvider,
|
|
849
|
+
formatError,
|
|
850
|
+
formatDoctorCheck,
|
|
851
|
+
formatCard,
|
|
852
|
+
ensureProvider,
|
|
853
|
+
deleteProvider,
|
|
854
|
+
deleteCard,
|
|
855
|
+
deleteAgent,
|
|
856
|
+
createTransaction,
|
|
857
|
+
createProvider,
|
|
858
|
+
createCardRecord,
|
|
859
|
+
createAgentCardProvider,
|
|
860
|
+
closeDatabase,
|
|
861
|
+
WalletError,
|
|
862
|
+
ProviderNotFoundError,
|
|
863
|
+
ProviderError,
|
|
864
|
+
InsufficientFundsError,
|
|
865
|
+
ConfigError,
|
|
866
|
+
CardNotFoundError,
|
|
867
|
+
AgentNotFoundError,
|
|
868
|
+
AgentCardProvider
|
|
869
|
+
};
|