openclaw-overlay-plugin 0.7.51 → 0.7.53
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/index.js +47 -42
- package/index.ts +47 -45
- package/openclaw.plugin.json +8 -1
- package/package.json +1 -2
- package/HOOK.md +0 -9
- package/src/core/wallet.js +0 -225
package/dist/index.js
CHANGED
|
@@ -7,17 +7,6 @@ import fs from 'node:fs';
|
|
|
7
7
|
import { initializeServiceSystem, serviceManager } from './src/services/index.js';
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
|
-
/**
|
|
11
|
-
* Helper to correctly locate the CLI script.
|
|
12
|
-
* If running from dist/index.js, CLI is in ./src/cli.js
|
|
13
|
-
* If running from index.ts, CLI is in ./dist/src/cli.js
|
|
14
|
-
*/
|
|
15
|
-
function getCliPath() {
|
|
16
|
-
const localCli = path.join(__dirname, 'src', 'cli.js');
|
|
17
|
-
if (fs.existsSync(localCli))
|
|
18
|
-
return localCli;
|
|
19
|
-
return path.join(__dirname, 'dist', 'src', 'cli.js');
|
|
20
|
-
}
|
|
21
10
|
const execFileAsync = promisify(execFile);
|
|
22
11
|
// Track background process for proper lifecycle management
|
|
23
12
|
let backgroundProcess = null;
|
|
@@ -173,7 +162,7 @@ async function autoAdvertiseServices(env, cliPath, logger) {
|
|
|
173
162
|
continue;
|
|
174
163
|
try {
|
|
175
164
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
176
|
-
const pluginConfig = config?.plugins?.entries?.['openclaw-overlay']?.config;
|
|
165
|
+
const pluginConfig = config?.plugins?.entries?.['openclaw-overlay-plugin']?.config || config?.plugins?.entries?.['openclaw-overlay-plugin'];
|
|
177
166
|
if (pluginConfig?.services && Array.isArray(pluginConfig.services)) {
|
|
178
167
|
servicesToAdvertise = pluginConfig.services;
|
|
179
168
|
break;
|
|
@@ -419,18 +408,16 @@ export async function activate(api) {
|
|
|
419
408
|
return register(api);
|
|
420
409
|
}
|
|
421
410
|
let isInitialized = false;
|
|
411
|
+
function getCliPath() {
|
|
412
|
+
return path.join(__dirname, 'dist', 'src', 'cli.js');
|
|
413
|
+
}
|
|
422
414
|
export default function register(api) {
|
|
423
415
|
if (isInitialized)
|
|
424
416
|
return;
|
|
425
417
|
isInitialized = true;
|
|
426
418
|
// Capture config at registration time
|
|
427
|
-
// Check all possible IDs for backward compatibility and various installation methods
|
|
428
419
|
const entries = api.getConfig?.()?.plugins?.entries || {};
|
|
429
|
-
const entry = entries['openclaw-overlay']
|
|
430
|
-
|| entries['openclaw-overlay-plugin']
|
|
431
|
-
|| entries['bsv-overlay']
|
|
432
|
-
|| {};
|
|
433
|
-
// Merge: gateway-level api.config > nested entry.config > flat entry properties
|
|
420
|
+
const entry = entries['openclaw-overlay-plugin'] || entries['openclaw-overlay'] || entries['bsv-overlay-skill'] || {};
|
|
434
421
|
const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
|
|
435
422
|
// Register the overlay agent tool
|
|
436
423
|
api.registerTool({
|
|
@@ -563,6 +550,44 @@ export default function register(api) {
|
|
|
563
550
|
}
|
|
564
551
|
}
|
|
565
552
|
});
|
|
553
|
+
// Register the /overlay slash command for direct chat interaction (Autoreply)
|
|
554
|
+
api.registerCommand({
|
|
555
|
+
name: "overlay",
|
|
556
|
+
description: "BSV Overlay Marketplace commands",
|
|
557
|
+
acceptsArgs: true,
|
|
558
|
+
requireAuth: true,
|
|
559
|
+
handler: async (ctx) => {
|
|
560
|
+
try {
|
|
561
|
+
const args = ctx.args || [];
|
|
562
|
+
const action = args[0] || 'status';
|
|
563
|
+
// Map slash command args to tool params
|
|
564
|
+
const params = { action };
|
|
565
|
+
if (action === 'request' && args[1])
|
|
566
|
+
params.service = args[1];
|
|
567
|
+
if (action === 'discover' && args[1])
|
|
568
|
+
params.service = args[1];
|
|
569
|
+
if (action === 'pay' && args[1])
|
|
570
|
+
params.identityKey = args[1];
|
|
571
|
+
if (action === 'pay' && args[2])
|
|
572
|
+
params.sats = parseInt(args[2], 10);
|
|
573
|
+
const result = await executeOverlayAction(params, pluginConfig, api);
|
|
574
|
+
let text = `**Overlay: ${action.toUpperCase()}**\n\n`;
|
|
575
|
+
if (typeof result === 'string') {
|
|
576
|
+
text += result;
|
|
577
|
+
}
|
|
578
|
+
else if (result.message) {
|
|
579
|
+
text += result.message;
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
text += JSON.stringify(result, null, 2);
|
|
583
|
+
}
|
|
584
|
+
return { text };
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
return { text: `❌ Overlay Error: ${error.message}` };
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
});
|
|
566
591
|
// Register background relay service
|
|
567
592
|
api.registerService({
|
|
568
593
|
id: "openclaw-overlay-relay",
|
|
@@ -571,13 +596,11 @@ export default function register(api) {
|
|
|
571
596
|
api.logger.info("Starting BSV overlay WebSocket relay...");
|
|
572
597
|
const env = buildEnvironment(pluginConfig);
|
|
573
598
|
const cliPath = getCliPath();
|
|
574
|
-
// Initialize the service system if available
|
|
575
599
|
try {
|
|
576
600
|
await initializeServiceSystem();
|
|
577
601
|
}
|
|
578
602
|
catch { }
|
|
579
603
|
startBackgroundService(env, cliPath, api.logger);
|
|
580
|
-
// Start auto-import
|
|
581
604
|
startAutoImport(env, cliPath, api.logger);
|
|
582
605
|
// Auto-check for registration on startup
|
|
583
606
|
(async () => {
|
|
@@ -587,11 +610,9 @@ export default function register(api) {
|
|
|
587
610
|
if (!fs.existsSync(regPath) && !fs.existsSync(onboardSentFile)) {
|
|
588
611
|
const walletPath = path.join(pluginConfig.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet'), 'wallet-identity.json');
|
|
589
612
|
if (fs.existsSync(walletPath)) {
|
|
590
|
-
// Wallet exists but not registered.
|
|
591
613
|
const balResult = await execFileAsync('node', [cliPath, 'balance'], { env });
|
|
592
614
|
const balance = parseCliOutput(balResult.stdout);
|
|
593
615
|
if ((balance.data?.walletBalance || 0) >= 1000) {
|
|
594
|
-
// Funded but not registered. Auto-register.
|
|
595
616
|
const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
|
|
596
617
|
if (parseCliOutput(regResult.stdout).success) {
|
|
597
618
|
api.logger.info('[openclaw-overlay] Agent auto-registered on startup');
|
|
@@ -734,7 +755,7 @@ export default function register(api) {
|
|
|
734
755
|
console.error("Error:", error.message);
|
|
735
756
|
}
|
|
736
757
|
});
|
|
737
|
-
});
|
|
758
|
+
}, { commands: ["overlay"] });
|
|
738
759
|
}
|
|
739
760
|
async function executeOverlayAction(params, config, api) {
|
|
740
761
|
const { action } = params;
|
|
@@ -801,7 +822,6 @@ async function handleServiceRequest(params, env, cliPath, config, api) {
|
|
|
801
822
|
if (!discoverOutput.success) {
|
|
802
823
|
throw new Error(`Discovery failed: ${discoverOutput.error}`);
|
|
803
824
|
}
|
|
804
|
-
// FIX: Use discoverOutput.data.services instead of treating data as flat array
|
|
805
825
|
const providers = discoverOutput.data.services;
|
|
806
826
|
if (!providers || providers.length === 0) {
|
|
807
827
|
throw new Error(`No providers found for service: ${service}`);
|
|
@@ -822,7 +842,7 @@ async function handleServiceRequest(params, env, cliPath, config, api) {
|
|
|
822
842
|
}
|
|
823
843
|
externalProviders = targeted;
|
|
824
844
|
}
|
|
825
|
-
// 3. Sort by price
|
|
845
|
+
// 3. Sort by price
|
|
826
846
|
externalProviders.sort((a, b) => (a.pricing?.amountSats || 0) - (b.pricing?.amountSats || 0));
|
|
827
847
|
const bestProvider = externalProviders[0];
|
|
828
848
|
const price = bestProvider.pricing?.amountSats || 0;
|
|
@@ -849,10 +869,6 @@ async function handleServiceRequest(params, env, cliPath, config, api) {
|
|
|
849
869
|
if (!requestOutput.success) {
|
|
850
870
|
throw new Error(`Service request failed: ${requestOutput.error}`);
|
|
851
871
|
}
|
|
852
|
-
// 7. Return immediately — no polling.
|
|
853
|
-
// The WebSocket background service handles incoming responses
|
|
854
|
-
// asynchronously and wakes the agent via /hooks/agent when a
|
|
855
|
-
// response arrives. This avoids blocking for up to 120s.
|
|
856
872
|
recordSpend(walletDir, price, service, bestProvider.name);
|
|
857
873
|
writeActivityEvent({ type: 'outgoing_payment', emoji: '💸', sats: price, service, provider: bestProvider.name, message: `Paid ${price} sats to ${bestProvider.name} for ${service}` });
|
|
858
874
|
return {
|
|
@@ -1149,7 +1165,7 @@ async function handleImport(params, env, cliPath) {
|
|
|
1149
1165
|
// Check if we should auto-register after successful import
|
|
1150
1166
|
const regPath = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'registration.json');
|
|
1151
1167
|
const isRegistered = fs.existsSync(regPath);
|
|
1152
|
-
if (!isRegistered && output.data?.balance >= 1000) {
|
|
1168
|
+
if (!isRegistered && (output.data?.balance || 0) >= 1000) {
|
|
1153
1169
|
// Auto-register immediately after funding
|
|
1154
1170
|
try {
|
|
1155
1171
|
const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
|
|
@@ -1281,13 +1297,11 @@ async function handleRefund(params, env, cliPath) {
|
|
|
1281
1297
|
async function handleOnboard(params, env, cliPath) {
|
|
1282
1298
|
const { agentName, agentDescription } = params;
|
|
1283
1299
|
const steps = [];
|
|
1284
|
-
// Apply agent name/description to env if provided
|
|
1285
1300
|
const onboardEnv = { ...env };
|
|
1286
1301
|
if (agentName)
|
|
1287
1302
|
onboardEnv.AGENT_NAME = agentName;
|
|
1288
1303
|
if (agentDescription)
|
|
1289
1304
|
onboardEnv.AGENT_DESCRIPTION = agentDescription;
|
|
1290
|
-
// Step 1: Setup wallet
|
|
1291
1305
|
try {
|
|
1292
1306
|
const setup = await execFileAsync('node', [cliPath, 'setup'], { env: onboardEnv });
|
|
1293
1307
|
const setupOutput = parseCliOutput(setup.stdout);
|
|
@@ -1297,7 +1311,6 @@ async function handleOnboard(params, env, cliPath) {
|
|
|
1297
1311
|
steps.push({ step: 'setup', success: false, error: err.message });
|
|
1298
1312
|
return { steps, nextStep: 'Fix wallet setup error and try again' };
|
|
1299
1313
|
}
|
|
1300
|
-
// Step 2: Get address
|
|
1301
1314
|
try {
|
|
1302
1315
|
const addr = await execFileAsync('node', [cliPath, 'address'], { env: onboardEnv });
|
|
1303
1316
|
const addrOutput = parseCliOutput(addr.stdout);
|
|
@@ -1306,7 +1319,6 @@ async function handleOnboard(params, env, cliPath) {
|
|
|
1306
1319
|
catch (err) {
|
|
1307
1320
|
steps.push({ step: 'address', success: false, error: err.message });
|
|
1308
1321
|
}
|
|
1309
|
-
// Step 3: Check balance
|
|
1310
1322
|
try {
|
|
1311
1323
|
const bal = await execFileAsync('node', [cliPath, 'balance'], { env: onboardEnv });
|
|
1312
1324
|
const balOutput = parseCliOutput(bal.stdout);
|
|
@@ -1323,7 +1335,6 @@ async function handleOnboard(params, env, cliPath) {
|
|
|
1323
1335
|
catch (err) {
|
|
1324
1336
|
steps.push({ step: 'balance', success: false, error: err.message });
|
|
1325
1337
|
}
|
|
1326
|
-
// Step 4: Register
|
|
1327
1338
|
try {
|
|
1328
1339
|
const reg = await execFileAsync('node', [cliPath, 'register'], { env: onboardEnv, timeout: 60000 });
|
|
1329
1340
|
const regOutput = parseCliOutput(reg.stdout);
|
|
@@ -1350,7 +1361,6 @@ async function handleOnboard(params, env, cliPath) {
|
|
|
1350
1361
|
};
|
|
1351
1362
|
}
|
|
1352
1363
|
async function handlePendingRequests(env, cliPath) {
|
|
1353
|
-
// Clean up old queue entries before checking pending requests
|
|
1354
1364
|
try {
|
|
1355
1365
|
const { cleanupServiceQueue } = await import('./src/scripts/utils/storage.js');
|
|
1356
1366
|
cleanupServiceQueue();
|
|
@@ -1362,7 +1372,6 @@ async function handlePendingRequests(env, cliPath) {
|
|
|
1362
1372
|
const output = parseCliOutput(result.stdout);
|
|
1363
1373
|
if (!output.success)
|
|
1364
1374
|
throw new Error(`Queue check failed: ${output.error}`);
|
|
1365
|
-
// Clear the alert file since we're checking now
|
|
1366
1375
|
const alertPath = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'pending-alert.jsonl');
|
|
1367
1376
|
try {
|
|
1368
1377
|
if (fs.existsSync(alertPath))
|
|
@@ -1382,7 +1391,6 @@ function handleActivity() {
|
|
|
1382
1391
|
catch {
|
|
1383
1392
|
return null;
|
|
1384
1393
|
} }).filter(Boolean);
|
|
1385
|
-
// Clear the feed after reading
|
|
1386
1394
|
fs.writeFileSync(feedPath, '');
|
|
1387
1395
|
return { events, count: events.length };
|
|
1388
1396
|
}
|
|
@@ -1397,7 +1405,6 @@ async function handleFulfill(params, env, cliPath) {
|
|
|
1397
1405
|
const output = parseCliOutput(cliResult.stdout);
|
|
1398
1406
|
if (!output.success)
|
|
1399
1407
|
throw new Error(`Fulfill failed: ${output.error}`);
|
|
1400
|
-
// Clean up the request ID from tracking since it's now fulfilled
|
|
1401
1408
|
wokenRequests.delete(requestId);
|
|
1402
1409
|
writeActivityEvent({ type: 'service_fulfilled', emoji: '✅', serviceId, recipientKey: recipientKey?.slice(0, 16), message: `Fulfilled ${serviceId} request — response sent` });
|
|
1403
1410
|
return output.data;
|
|
@@ -1419,7 +1426,6 @@ function buildEnvironment(config) {
|
|
|
1419
1426
|
if (config.arcUrl) {
|
|
1420
1427
|
env.BSV_ARC_URL = config.arcUrl;
|
|
1421
1428
|
}
|
|
1422
|
-
// Set defaults
|
|
1423
1429
|
env.BSV_NETWORK = env.BSV_NETWORK || 'mainnet';
|
|
1424
1430
|
if (!env.BSV_ARC_URL) {
|
|
1425
1431
|
env.BSV_ARC_URL = env.BSV_NETWORK === 'testnet'
|
|
@@ -1438,7 +1444,7 @@ function buildEnvironment(config) {
|
|
|
1438
1444
|
else if (!env.AGENT_DESCRIPTION) {
|
|
1439
1445
|
env.AGENT_DESCRIPTION = 'AI agent on the OpenClaw Overlay Network. Offers services for BSV micropayments.';
|
|
1440
1446
|
}
|
|
1441
|
-
env.AGENT_ROUTED = 'true';
|
|
1447
|
+
env.AGENT_ROUTED = 'true';
|
|
1442
1448
|
return env;
|
|
1443
1449
|
}
|
|
1444
1450
|
function parseCliOutput(stdout) {
|
|
@@ -1450,4 +1456,3 @@ function parseCliOutput(stdout) {
|
|
|
1450
1456
|
throw new Error(`Failed to parse CLI output: ${error.message}`);
|
|
1451
1457
|
}
|
|
1452
1458
|
}
|
|
1453
|
-
// sleep() removed — no longer needed since polling loop was removed
|
package/index.ts
CHANGED
|
@@ -8,17 +8,6 @@ import { initializeServiceSystem, serviceManager } from './src/services/index.js
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
|
|
11
|
-
/**
|
|
12
|
-
* Helper to correctly locate the CLI script.
|
|
13
|
-
* If running from dist/index.js, CLI is in ./src/cli.js
|
|
14
|
-
* If running from index.ts, CLI is in ./dist/src/cli.js
|
|
15
|
-
*/
|
|
16
|
-
function getCliPath(): string {
|
|
17
|
-
const localCli = path.join(__dirname, 'src', 'cli.js');
|
|
18
|
-
if (fs.existsSync(localCli)) return localCli;
|
|
19
|
-
return path.join(__dirname, 'dist', 'src', 'cli.js');
|
|
20
|
-
}
|
|
21
|
-
|
|
22
11
|
const execFileAsync = promisify(execFile);
|
|
23
12
|
|
|
24
13
|
// Track background process for proper lifecycle management
|
|
@@ -190,7 +179,7 @@ async function autoAdvertiseServices(env: any, cliPath: string, logger: any) {
|
|
|
190
179
|
if (!fs.existsSync(configPath)) continue;
|
|
191
180
|
try {
|
|
192
181
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
193
|
-
const pluginConfig = config?.plugins?.entries?.['openclaw-overlay']?.config;
|
|
182
|
+
const pluginConfig = config?.plugins?.entries?.['openclaw-overlay-plugin']?.config || config?.plugins?.entries?.['openclaw-overlay-plugin'];
|
|
194
183
|
if (pluginConfig?.services && Array.isArray(pluginConfig.services)) {
|
|
195
184
|
servicesToAdvertise = pluginConfig.services;
|
|
196
185
|
break;
|
|
@@ -464,19 +453,17 @@ export async function activate(api: any) {
|
|
|
464
453
|
|
|
465
454
|
let isInitialized = false;
|
|
466
455
|
|
|
456
|
+
function getCliPath() {
|
|
457
|
+
return path.join(__dirname, 'dist', 'src', 'cli.js');
|
|
458
|
+
}
|
|
459
|
+
|
|
467
460
|
export default function register(api: any) {
|
|
468
461
|
if (isInitialized) return;
|
|
469
462
|
isInitialized = true;
|
|
470
463
|
|
|
471
464
|
// Capture config at registration time
|
|
472
|
-
// Check all possible IDs for backward compatibility and various installation methods
|
|
473
465
|
const entries = api.getConfig?.()?.plugins?.entries || {};
|
|
474
|
-
const entry = entries['openclaw-overlay']
|
|
475
|
-
|| entries['openclaw-overlay-plugin']
|
|
476
|
-
|| entries['bsv-overlay']
|
|
477
|
-
|| {};
|
|
478
|
-
|
|
479
|
-
// Merge: gateway-level api.config > nested entry.config > flat entry properties
|
|
466
|
+
const entry = entries['openclaw-overlay-plugin'] || entries['openclaw-overlay'] || entries['bsv-overlay-skill'] || {};
|
|
480
467
|
const pluginConfig = { ...entry, ...(entry.config || {}), ...(api.config || {}) };
|
|
481
468
|
|
|
482
469
|
// Register the overlay agent tool
|
|
@@ -610,6 +597,43 @@ export default function register(api: any) {
|
|
|
610
597
|
}
|
|
611
598
|
});
|
|
612
599
|
|
|
600
|
+
// Register the /overlay slash command for direct chat interaction (Autoreply)
|
|
601
|
+
api.registerCommand({
|
|
602
|
+
name: "overlay",
|
|
603
|
+
description: "BSV Overlay Marketplace commands",
|
|
604
|
+
acceptsArgs: true,
|
|
605
|
+
requireAuth: true,
|
|
606
|
+
handler: async (ctx: any) => {
|
|
607
|
+
try {
|
|
608
|
+
const args = ctx.args || [];
|
|
609
|
+
const action = args[0] || 'status';
|
|
610
|
+
|
|
611
|
+
// Map slash command args to tool params
|
|
612
|
+
const params: any = { action };
|
|
613
|
+
|
|
614
|
+
if (action === 'request' && args[1]) params.service = args[1];
|
|
615
|
+
if (action === 'discover' && args[1]) params.service = args[1];
|
|
616
|
+
if (action === 'pay' && args[1]) params.identityKey = args[1];
|
|
617
|
+
if (action === 'pay' && args[2]) params.sats = parseInt(args[2], 10);
|
|
618
|
+
|
|
619
|
+
const result = await executeOverlayAction(params, pluginConfig, api);
|
|
620
|
+
|
|
621
|
+
let text = `**Overlay: ${action.toUpperCase()}**\n\n`;
|
|
622
|
+
if (typeof result === 'string') {
|
|
623
|
+
text += result;
|
|
624
|
+
} else if (result.message) {
|
|
625
|
+
text += result.message;
|
|
626
|
+
} else {
|
|
627
|
+
text += JSON.stringify(result, null, 2);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return { text };
|
|
631
|
+
} catch (error: any) {
|
|
632
|
+
return { text: `❌ Overlay Error: ${error.message}` };
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
|
|
613
637
|
// Register background relay service
|
|
614
638
|
api.registerService({
|
|
615
639
|
id: "openclaw-overlay-relay",
|
|
@@ -619,14 +643,11 @@ export default function register(api: any) {
|
|
|
619
643
|
const env = buildEnvironment(pluginConfig);
|
|
620
644
|
const cliPath = getCliPath();
|
|
621
645
|
|
|
622
|
-
// Initialize the service system if available
|
|
623
646
|
try {
|
|
624
647
|
await initializeServiceSystem();
|
|
625
648
|
} catch {}
|
|
626
649
|
|
|
627
650
|
startBackgroundService(env, cliPath, api.logger);
|
|
628
|
-
|
|
629
|
-
// Start auto-import
|
|
630
651
|
startAutoImport(env, cliPath, api.logger);
|
|
631
652
|
|
|
632
653
|
// Auto-check for registration on startup
|
|
@@ -639,12 +660,10 @@ export default function register(api: any) {
|
|
|
639
660
|
const walletPath = path.join(pluginConfig.walletDir || path.join(os.homedir(), '.openclaw', 'bsv-wallet'), 'wallet-identity.json');
|
|
640
661
|
|
|
641
662
|
if (fs.existsSync(walletPath)) {
|
|
642
|
-
// Wallet exists but not registered.
|
|
643
663
|
const balResult = await execFileAsync('node', [cliPath, 'balance'], { env });
|
|
644
664
|
const balance = parseCliOutput(balResult.stdout);
|
|
645
665
|
|
|
646
666
|
if ((balance.data?.walletBalance || 0) >= 1000) {
|
|
647
|
-
// Funded but not registered. Auto-register.
|
|
648
667
|
const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
|
|
649
668
|
if (parseCliOutput(regResult.stdout).success) {
|
|
650
669
|
api.logger.info('[openclaw-overlay] Agent auto-registered on startup');
|
|
@@ -789,7 +808,7 @@ export default function register(api: any) {
|
|
|
789
808
|
console.error("Error:", error.message);
|
|
790
809
|
}
|
|
791
810
|
});
|
|
792
|
-
});
|
|
811
|
+
}, { commands: ["overlay"] });
|
|
793
812
|
}
|
|
794
813
|
|
|
795
814
|
async function executeOverlayAction(params: any, config: any, api: any) {
|
|
@@ -885,7 +904,6 @@ async function handleServiceRequest(params: any, env: any, cliPath: string, conf
|
|
|
885
904
|
throw new Error(`Discovery failed: ${discoverOutput.error}`);
|
|
886
905
|
}
|
|
887
906
|
|
|
888
|
-
// FIX: Use discoverOutput.data.services instead of treating data as flat array
|
|
889
907
|
const providers = discoverOutput.data.services;
|
|
890
908
|
if (!providers || providers.length === 0) {
|
|
891
909
|
throw new Error(`No providers found for service: ${service}`);
|
|
@@ -910,7 +928,7 @@ async function handleServiceRequest(params: any, env: any, cliPath: string, conf
|
|
|
910
928
|
externalProviders = targeted;
|
|
911
929
|
}
|
|
912
930
|
|
|
913
|
-
// 3. Sort by price
|
|
931
|
+
// 3. Sort by price
|
|
914
932
|
externalProviders.sort((a: any, b: any) => (a.pricing?.amountSats || 0) - (b.pricing?.amountSats || 0));
|
|
915
933
|
|
|
916
934
|
const bestProvider = externalProviders[0];
|
|
@@ -946,10 +964,6 @@ async function handleServiceRequest(params: any, env: any, cliPath: string, conf
|
|
|
946
964
|
throw new Error(`Service request failed: ${requestOutput.error}`);
|
|
947
965
|
}
|
|
948
966
|
|
|
949
|
-
// 7. Return immediately — no polling.
|
|
950
|
-
// The WebSocket background service handles incoming responses
|
|
951
|
-
// asynchronously and wakes the agent via /hooks/agent when a
|
|
952
|
-
// response arrives. This avoids blocking for up to 120s.
|
|
953
967
|
recordSpend(walletDir, price, service, bestProvider.name);
|
|
954
968
|
writeActivityEvent({ type: 'outgoing_payment', emoji: '💸', sats: price, service, provider: bestProvider.name, message: `Paid ${price} sats to ${bestProvider.name} for ${service}` });
|
|
955
969
|
|
|
@@ -1294,7 +1308,7 @@ async function handleImport(params: any, env: any, cliPath: string) {
|
|
|
1294
1308
|
const regPath = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'registration.json');
|
|
1295
1309
|
const isRegistered = fs.existsSync(regPath);
|
|
1296
1310
|
|
|
1297
|
-
if (!isRegistered && output.data?.balance >= 1000) {
|
|
1311
|
+
if (!isRegistered && (output.data?.balance || 0) >= 1000) {
|
|
1298
1312
|
// Auto-register immediately after funding
|
|
1299
1313
|
try {
|
|
1300
1314
|
const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
|
|
@@ -1464,12 +1478,10 @@ async function handleOnboard(params: any, env: any, cliPath: string) {
|
|
|
1464
1478
|
const { agentName, agentDescription } = params;
|
|
1465
1479
|
const steps = [];
|
|
1466
1480
|
|
|
1467
|
-
// Apply agent name/description to env if provided
|
|
1468
1481
|
const onboardEnv = { ...env };
|
|
1469
1482
|
if (agentName) onboardEnv.AGENT_NAME = agentName;
|
|
1470
1483
|
if (agentDescription) onboardEnv.AGENT_DESCRIPTION = agentDescription;
|
|
1471
1484
|
|
|
1472
|
-
// Step 1: Setup wallet
|
|
1473
1485
|
try {
|
|
1474
1486
|
const setup = await execFileAsync('node', [cliPath, 'setup'], { env: onboardEnv });
|
|
1475
1487
|
const setupOutput = parseCliOutput(setup.stdout);
|
|
@@ -1479,7 +1491,6 @@ async function handleOnboard(params: any, env: any, cliPath: string) {
|
|
|
1479
1491
|
return { steps, nextStep: 'Fix wallet setup error and try again' };
|
|
1480
1492
|
}
|
|
1481
1493
|
|
|
1482
|
-
// Step 2: Get address
|
|
1483
1494
|
try {
|
|
1484
1495
|
const addr = await execFileAsync('node', [cliPath, 'address'], { env: onboardEnv });
|
|
1485
1496
|
const addrOutput = parseCliOutput(addr.stdout);
|
|
@@ -1488,7 +1499,6 @@ async function handleOnboard(params: any, env: any, cliPath: string) {
|
|
|
1488
1499
|
steps.push({ step: 'address', success: false, error: err.message });
|
|
1489
1500
|
}
|
|
1490
1501
|
|
|
1491
|
-
// Step 3: Check balance
|
|
1492
1502
|
try {
|
|
1493
1503
|
const bal = await execFileAsync('node', [cliPath, 'balance'], { env: onboardEnv });
|
|
1494
1504
|
const balOutput = parseCliOutput(bal.stdout);
|
|
@@ -1506,7 +1516,6 @@ async function handleOnboard(params: any, env: any, cliPath: string) {
|
|
|
1506
1516
|
steps.push({ step: 'balance', success: false, error: err.message });
|
|
1507
1517
|
}
|
|
1508
1518
|
|
|
1509
|
-
// Step 4: Register
|
|
1510
1519
|
try {
|
|
1511
1520
|
const reg = await execFileAsync('node', [cliPath, 'register'], { env: onboardEnv, timeout: 60000 });
|
|
1512
1521
|
const regOutput = parseCliOutput(reg.stdout);
|
|
@@ -1534,7 +1543,6 @@ async function handleOnboard(params: any, env: any, cliPath: string) {
|
|
|
1534
1543
|
}
|
|
1535
1544
|
|
|
1536
1545
|
async function handlePendingRequests(env: any, cliPath: string) {
|
|
1537
|
-
// Clean up old queue entries before checking pending requests
|
|
1538
1546
|
try {
|
|
1539
1547
|
const { cleanupServiceQueue } = await import('./src/scripts/utils/storage.js');
|
|
1540
1548
|
cleanupServiceQueue();
|
|
@@ -1546,7 +1554,6 @@ async function handlePendingRequests(env: any, cliPath: string) {
|
|
|
1546
1554
|
const output = parseCliOutput(result.stdout);
|
|
1547
1555
|
if (!output.success) throw new Error(`Queue check failed: ${output.error}`);
|
|
1548
1556
|
|
|
1549
|
-
// Clear the alert file since we're checking now
|
|
1550
1557
|
const alertPath = path.join(process.env.HOME || '', '.openclaw', 'openclaw-overlay', 'pending-alert.jsonl');
|
|
1551
1558
|
try { if (fs.existsSync(alertPath)) fs.unlinkSync(alertPath); } catch {}
|
|
1552
1559
|
|
|
@@ -1560,7 +1567,6 @@ function handleActivity() {
|
|
|
1560
1567
|
const lines = fs.readFileSync(feedPath, 'utf-8')?.trim().split('\n').filter(Boolean);
|
|
1561
1568
|
const events = lines.map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean);
|
|
1562
1569
|
|
|
1563
|
-
// Clear the feed after reading
|
|
1564
1570
|
fs.writeFileSync(feedPath, '');
|
|
1565
1571
|
|
|
1566
1572
|
return { events, count: events.length };
|
|
@@ -1578,7 +1584,6 @@ async function handleFulfill(params: any, env: any, cliPath: string) {
|
|
|
1578
1584
|
const output = parseCliOutput(cliResult.stdout);
|
|
1579
1585
|
if (!output.success) throw new Error(`Fulfill failed: ${output.error}`);
|
|
1580
1586
|
|
|
1581
|
-
// Clean up the request ID from tracking since it's now fulfilled
|
|
1582
1587
|
wokenRequests.delete(requestId);
|
|
1583
1588
|
|
|
1584
1589
|
writeActivityEvent({ type: 'service_fulfilled', emoji: '✅', serviceId, recipientKey: recipientKey?.slice(0, 16), message: `Fulfilled ${serviceId} request — response sent` });
|
|
@@ -1604,7 +1609,6 @@ function buildEnvironment(config: any) {
|
|
|
1604
1609
|
env.BSV_ARC_URL = config.arcUrl;
|
|
1605
1610
|
}
|
|
1606
1611
|
|
|
1607
|
-
// Set defaults
|
|
1608
1612
|
env.BSV_NETWORK = env.BSV_NETWORK || 'mainnet';
|
|
1609
1613
|
|
|
1610
1614
|
if (!env.BSV_ARC_URL) {
|
|
@@ -1622,7 +1626,7 @@ function buildEnvironment(config: any) {
|
|
|
1622
1626
|
} else if (!env.AGENT_DESCRIPTION) {
|
|
1623
1627
|
env.AGENT_DESCRIPTION = 'AI agent on the OpenClaw Overlay Network. Offers services for BSV micropayments.';
|
|
1624
1628
|
}
|
|
1625
|
-
env.AGENT_ROUTED = 'true';
|
|
1629
|
+
env.AGENT_ROUTED = 'true';
|
|
1626
1630
|
|
|
1627
1631
|
return env;
|
|
1628
1632
|
}
|
|
@@ -1635,5 +1639,3 @@ function parseCliOutput(stdout: any) {
|
|
|
1635
1639
|
throw new Error(`Failed to parse CLI output: ${error.message}`);
|
|
1636
1640
|
}
|
|
1637
1641
|
}
|
|
1638
|
-
|
|
1639
|
-
// sleep() removed — no longer needed since polling loop was removed
|
package/openclaw.plugin.json
CHANGED
|
@@ -6,9 +6,16 @@
|
|
|
6
6
|
"skills": [
|
|
7
7
|
"./SKILL.md"
|
|
8
8
|
],
|
|
9
|
+
"commands": [
|
|
10
|
+
{
|
|
11
|
+
"name": "overlay",
|
|
12
|
+
"description": "BSV Overlay Network management",
|
|
13
|
+
"isAutoreply": true
|
|
14
|
+
}
|
|
15
|
+
],
|
|
9
16
|
"configSchema": {
|
|
10
17
|
"type": "object",
|
|
11
|
-
"additionalProperties":
|
|
18
|
+
"additionalProperties": true,
|
|
12
19
|
"properties": {
|
|
13
20
|
"overlayUrl": {
|
|
14
21
|
"type": "string",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-overlay-plugin",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.53",
|
|
4
4
|
"description": "Openclaw BSV Overlay — agent discovery, service marketplace, and micropayments on the BSV blockchain",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"src/",
|
|
13
13
|
"dist/",
|
|
14
14
|
"SKILL.md",
|
|
15
|
-
"HOOK.md",
|
|
16
15
|
"README.md"
|
|
17
16
|
],
|
|
18
17
|
"bin": {
|
package/HOOK.md
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: openclaw-overlay-hooks
|
|
3
|
-
description: Background automation for the OpenClaw Overlay Network.
|
|
4
|
-
metadata: '{"openclaw": {"events": ["gateway:start"]}}'
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Overlay Hooks
|
|
8
|
-
This file ensures compatibility with the OpenClaw hook pack installer.
|
|
9
|
-
Background tasks are handled programmatically in index.ts.
|
package/src/core/wallet.js
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @a2a-bsv/core — BSVAgentWallet
|
|
3
|
-
*
|
|
4
|
-
* High-level wallet class for AI agent-to-agent BSV payments.
|
|
5
|
-
* Wraps @bsv/wallet-toolbox's Wallet + StorageKnex with a clean,
|
|
6
|
-
* minimal API surface designed for automated agent use.
|
|
7
|
-
*/
|
|
8
|
-
import { PrivateKey, CachedKeyDeriver } from '@bsv/sdk';
|
|
9
|
-
import { Wallet, WalletStorageManager, Services, Monitor, StorageKnex, randomBytesHex, ChaintracksServiceClient, } from '@bsv/wallet-toolbox';
|
|
10
|
-
import knexLib from 'knex';
|
|
11
|
-
import * as path from 'node:path';
|
|
12
|
-
import * as fs from 'node:fs';
|
|
13
|
-
import { toChain, DEFAULT_TAAL_API_KEYS, DEFAULT_DB_NAME } from './config.js';
|
|
14
|
-
import { buildPayment } from './payment.js';
|
|
15
|
-
import { verifyPayment, acceptPayment } from './verify.js';
|
|
16
|
-
/** Filename for the persisted wallet identity JSON. */
|
|
17
|
-
const IDENTITY_FILE = 'wallet-identity.json';
|
|
18
|
-
/**
|
|
19
|
-
* BSVAgentWallet — the primary class for agent-to-agent BSV payments.
|
|
20
|
-
*
|
|
21
|
-
* Usage:
|
|
22
|
-
* ```ts
|
|
23
|
-
* // Create a new wallet (generates keys)
|
|
24
|
-
* const wallet = await BSVAgentWallet.load({ network: 'testnet', storageDir: './agent-wallet' });
|
|
25
|
-
*
|
|
26
|
-
* // Load an existing wallet
|
|
27
|
-
* const wallet = await BSVAgentWallet.load({ network: 'testnet', storageDir: './agent-wallet' });
|
|
28
|
-
*
|
|
29
|
-
* // Make a payment
|
|
30
|
-
* const payment = await wallet.createPayment({ to: recipientPubKey, satoshis: 500 });
|
|
31
|
-
*
|
|
32
|
-
* // Verify and accept a payment
|
|
33
|
-
* const verification = wallet.verifyPayment({ beef: payment.beef });
|
|
34
|
-
* if (verification.valid) {
|
|
35
|
-
* await wallet.acceptPayment({ beef: payment.beef, ...derivationInfo });
|
|
36
|
-
* }
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
|
-
export class BSVAgentWallet {
|
|
40
|
-
/** @internal — exposed for advanced operations (e.g. direct internalizeAction) */
|
|
41
|
-
_setup;
|
|
42
|
-
constructor(setup) {
|
|
43
|
-
this._setup = setup;
|
|
44
|
-
}
|
|
45
|
-
// ---------------------------------------------------------------------------
|
|
46
|
-
// Factory methods
|
|
47
|
-
// ---------------------------------------------------------------------------
|
|
48
|
-
/**
|
|
49
|
-
* Create a new agent wallet. Generates a fresh root key and persists it.
|
|
50
|
-
* The SQLite database and identity file are written to `config.storageDir`.
|
|
51
|
-
*/
|
|
52
|
-
static async create(config) {
|
|
53
|
-
// Generate a new root key (or use one provided in config)
|
|
54
|
-
const rootKeyHex = config.rootKeyHex ?? PrivateKey.fromRandom().toHex();
|
|
55
|
-
const rootKey = PrivateKey.fromHex(rootKeyHex);
|
|
56
|
-
const identityKey = rootKey.toPublicKey().toString();
|
|
57
|
-
// Ensure the storage directory exists
|
|
58
|
-
fs.mkdirSync(config.storageDir, { recursive: true });
|
|
59
|
-
// Persist identity for later loading
|
|
60
|
-
const identity = {
|
|
61
|
-
rootKeyHex,
|
|
62
|
-
identityKey,
|
|
63
|
-
network: config.network,
|
|
64
|
-
};
|
|
65
|
-
const identityPath = path.join(config.storageDir, IDENTITY_FILE);
|
|
66
|
-
fs.writeFileSync(identityPath, JSON.stringify(identity, null, 2), 'utf-8');
|
|
67
|
-
// Build the wallet
|
|
68
|
-
const setup = await BSVAgentWallet.buildSetup(config, rootKeyHex);
|
|
69
|
-
return new BSVAgentWallet(setup);
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Load an existing agent wallet from its storage directory.
|
|
73
|
-
* Reads the persisted identity file and re-initializes the wallet.
|
|
74
|
-
*/
|
|
75
|
-
static async load(config) {
|
|
76
|
-
const identityPath = path.join(config.storageDir, IDENTITY_FILE);
|
|
77
|
-
if (!fs.existsSync(identityPath)) {
|
|
78
|
-
return this.create(config);
|
|
79
|
-
}
|
|
80
|
-
const identity = JSON.parse(fs.readFileSync(identityPath, 'utf-8'));
|
|
81
|
-
const rootKeyHex = config.rootKeyHex ?? identity.rootKeyHex;
|
|
82
|
-
const setup = await BSVAgentWallet.buildSetup(config, rootKeyHex);
|
|
83
|
-
return new BSVAgentWallet(setup);
|
|
84
|
-
}
|
|
85
|
-
// ---------------------------------------------------------------------------
|
|
86
|
-
// Wallet lifecycle
|
|
87
|
-
// ---------------------------------------------------------------------------
|
|
88
|
-
/**
|
|
89
|
-
* Get this wallet's public identity key (compressed hex, 33 bytes).
|
|
90
|
-
* This is the key other agents use to send payments to you.
|
|
91
|
-
*/
|
|
92
|
-
async getIdentityKey() {
|
|
93
|
-
return this._setup.identityKey;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Get the wallet's current balance in satoshis.
|
|
97
|
-
*
|
|
98
|
-
* Uses the BRC-100 wallet's balance method which sums spendable outputs
|
|
99
|
-
* in the default basket.
|
|
100
|
-
*/
|
|
101
|
-
async getBalance() {
|
|
102
|
-
return await this._setup.wallet.balance();
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Cleanly shut down the wallet, releasing database connections and
|
|
106
|
-
* stopping the background monitor.
|
|
107
|
-
*/
|
|
108
|
-
async destroy() {
|
|
109
|
-
await this._setup.wallet.destroy();
|
|
110
|
-
}
|
|
111
|
-
// ---------------------------------------------------------------------------
|
|
112
|
-
// Payment creation (sender/payer side)
|
|
113
|
-
// ---------------------------------------------------------------------------
|
|
114
|
-
/**
|
|
115
|
-
* Build a BRC-29 payment to another agent.
|
|
116
|
-
*
|
|
117
|
-
* The transaction is created with `noSend: true` — the sender does NOT
|
|
118
|
-
* broadcast it. Instead, the Atomic BEEF and derivation metadata are
|
|
119
|
-
* returned so they can be transmitted to the recipient, who will
|
|
120
|
-
* verify and internalize (broadcast) the payment.
|
|
121
|
-
*
|
|
122
|
-
* @param params.to — Recipient's compressed public key (hex).
|
|
123
|
-
* @param params.satoshis — Amount in satoshis.
|
|
124
|
-
* @param params.description — Optional human-readable note.
|
|
125
|
-
*/
|
|
126
|
-
async createPayment(params) {
|
|
127
|
-
return buildPayment(this._setup, params);
|
|
128
|
-
}
|
|
129
|
-
// ---------------------------------------------------------------------------
|
|
130
|
-
// Payment verification & acceptance (receiver/merchant side)
|
|
131
|
-
// ---------------------------------------------------------------------------
|
|
132
|
-
/**
|
|
133
|
-
* Verify an incoming Atomic BEEF payment.
|
|
134
|
-
*
|
|
135
|
-
* This performs structural validation and SPV verification via tx.verify().
|
|
136
|
-
*/
|
|
137
|
-
async verifyPayment(params) {
|
|
138
|
-
return await verifyPayment(params);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Accept (internalize) a verified payment into this wallet.
|
|
142
|
-
*
|
|
143
|
-
* Uses the BRC-29 wallet payment protocol to derive the correct key
|
|
144
|
-
* and claim the output. This triggers SPV verification and, if the
|
|
145
|
-
* transaction hasn't been broadcast yet, broadcasts it.
|
|
146
|
-
*/
|
|
147
|
-
async acceptPayment(params) {
|
|
148
|
-
return acceptPayment(this._setup, params);
|
|
149
|
-
}
|
|
150
|
-
// ---------------------------------------------------------------------------
|
|
151
|
-
// Access to underlying toolbox objects (for advanced use)
|
|
152
|
-
// ---------------------------------------------------------------------------
|
|
153
|
-
/** Get the underlying wallet-toolbox SetupWallet for advanced operations. */
|
|
154
|
-
getSetup() {
|
|
155
|
-
return this._setup;
|
|
156
|
-
}
|
|
157
|
-
// ---------------------------------------------------------------------------
|
|
158
|
-
// Private helpers
|
|
159
|
-
// ---------------------------------------------------------------------------
|
|
160
|
-
/**
|
|
161
|
-
* Internal: manually construct a BRC-100 wallet backed by SQLite.
|
|
162
|
-
*
|
|
163
|
-
* We build this by hand instead of using Setup.createWalletSQLite because
|
|
164
|
-
* the toolbox has a bug where its internal randomBytesHex is a stub.
|
|
165
|
-
* We use the same components but wire them up correctly.
|
|
166
|
-
*/
|
|
167
|
-
static async buildSetup(config, rootKeyHex) {
|
|
168
|
-
const chain = toChain(config.network);
|
|
169
|
-
const taalApiKey = config.taalApiKey ?? DEFAULT_TAAL_API_KEYS[chain];
|
|
170
|
-
const rootKey = PrivateKey.fromHex(rootKeyHex);
|
|
171
|
-
const identityKey = rootKey.toPublicKey().toString();
|
|
172
|
-
// 1. Key derivation
|
|
173
|
-
const keyDeriver = new CachedKeyDeriver(rootKey);
|
|
174
|
-
// 2. Storage manager (empty initially)
|
|
175
|
-
const storage = new WalletStorageManager(identityKey);
|
|
176
|
-
// 3. Network services (ARC broadcasting, chain tracking, etc.)
|
|
177
|
-
const serviceOptions = Services.createDefaultOptions(chain);
|
|
178
|
-
const chaintracksUrl = process.env.BSV_CHAINTRACKS_URL || 'https://chaintracks-us-1.bsvb.tech';
|
|
179
|
-
const arcUrl = process.env.BSV_ARC_URL;
|
|
180
|
-
serviceOptions.chaintracks = new ChaintracksServiceClient(chain, chaintracksUrl);
|
|
181
|
-
if (arcUrl) {
|
|
182
|
-
serviceOptions.arcUrl = arcUrl;
|
|
183
|
-
}
|
|
184
|
-
serviceOptions.taalApiKey = taalApiKey;
|
|
185
|
-
const services = new Services(serviceOptions);
|
|
186
|
-
// 4. Background monitor
|
|
187
|
-
const monopts = Monitor.createDefaultWalletMonitorOptions(chain, storage, services);
|
|
188
|
-
const monitor = new Monitor(monopts);
|
|
189
|
-
monitor.addDefaultTasks();
|
|
190
|
-
// 5. The BRC-100 Wallet
|
|
191
|
-
const wallet = new Wallet({ chain, keyDeriver, storage, services, monitor });
|
|
192
|
-
// 6. SQLite storage via knex
|
|
193
|
-
const filePath = path.join(config.storageDir, `${DEFAULT_DB_NAME}.sqlite`);
|
|
194
|
-
const knex = knexLib({
|
|
195
|
-
client: 'sqlite3',
|
|
196
|
-
connection: { filename: filePath },
|
|
197
|
-
useNullAsDefault: true,
|
|
198
|
-
});
|
|
199
|
-
// Fee model: configurable via BSV_FEE_MODEL env var (default: 100 sat/KB)
|
|
200
|
-
const feeModelValue = config.feeModel ??
|
|
201
|
-
(process.env.BSV_FEE_MODEL ? parseInt(process.env.BSV_FEE_MODEL, 10) : 100);
|
|
202
|
-
const activeStorage = new StorageKnex({
|
|
203
|
-
chain,
|
|
204
|
-
knex,
|
|
205
|
-
commissionSatoshis: 0,
|
|
206
|
-
commissionPubKeyHex: undefined,
|
|
207
|
-
feeModel: { model: 'sat/kb', value: feeModelValue },
|
|
208
|
-
});
|
|
209
|
-
await activeStorage.migrate(DEFAULT_DB_NAME, randomBytesHex(33));
|
|
210
|
-
await activeStorage.makeAvailable();
|
|
211
|
-
await storage.addWalletStorageProvider(activeStorage);
|
|
212
|
-
await activeStorage.findOrInsertUser(identityKey);
|
|
213
|
-
return {
|
|
214
|
-
rootKey,
|
|
215
|
-
identityKey,
|
|
216
|
-
keyDeriver,
|
|
217
|
-
chain,
|
|
218
|
-
storage,
|
|
219
|
-
services,
|
|
220
|
-
monitor,
|
|
221
|
-
wallet,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
//# sourceMappingURL=wallet.js.map
|