openclaw-overlay-plugin 0.7.47 → 0.7.49

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 CHANGED
@@ -418,7 +418,11 @@ function stopBackgroundService() {
418
418
  export async function activate(api) {
419
419
  return register(api);
420
420
  }
421
+ let isInitialized = false;
421
422
  export default function register(api) {
423
+ if (isInitialized)
424
+ return;
425
+ isInitialized = true;
422
426
  // Capture config at registration time
423
427
  // Check all possible IDs for backward compatibility and various installation methods
424
428
  const entries = api.getConfig?.()?.plugins?.entries || {};
@@ -589,7 +593,7 @@ export default function register(api) {
589
593
  // Register a skill-style wake handler
590
594
  api.registerHook({
591
595
  id: "openclaw-overlay-wake",
592
- event: "gateway:start",
596
+ events: ["gateway:start"],
593
597
  handler: async (ctx) => {
594
598
  // Auto-check for registration on startup
595
599
  (async () => {
@@ -1459,7 +1463,7 @@ function buildEnvironment(config) {
1459
1463
  function parseCliOutput(stdout) {
1460
1464
  try {
1461
1465
  const str = typeof stdout === 'string' ? stdout : String(stdout || '');
1462
- return JSON.parse(str?.trim());
1466
+ return JSON.parse(str.trim());
1463
1467
  }
1464
1468
  catch (error) {
1465
1469
  throw new Error(`Failed to parse CLI output: ${error.message}`);
@@ -186,18 +186,27 @@ export class BSVAgentWallet {
186
186
  const serviceOptions = Services.createDefaultOptions(chain);
187
187
  const chaintracksUrl = process.env.BSV_CHAINTRACKS_URL || 'https://chaintracks-us-1.bsvb.tech';
188
188
  const arcUrl = process.env.BSV_ARC_URL;
189
- serviceOptions.chaintracks = new ChaintracksServiceClient(chain, chaintracksUrl);
190
- if (arcUrl) {
191
- serviceOptions.arcUrl = arcUrl;
189
+ const isTestMode = config.enableMonitor === false;
190
+ if (!isTestMode) {
191
+ serviceOptions.chaintracks = new ChaintracksServiceClient(chain, chaintracksUrl);
192
+ if (arcUrl) {
193
+ serviceOptions.arcUrl = arcUrl;
194
+ }
192
195
  }
193
196
  serviceOptions.taalApiKey = taalApiKey;
194
197
  const services = new Services(serviceOptions);
195
198
  // 4. Background monitor
196
199
  const monopts = Monitor.createDefaultWalletMonitorOptions(chain, storage, services);
197
200
  const monitor = new Monitor(monopts);
198
- monitor.addDefaultTasks();
201
+ if (!isTestMode) {
202
+ monitor.addDefaultTasks();
203
+ }
204
+ else {
205
+ // In test mode, we clear all tasks to ensure no background activity
206
+ monitor.tasks = [];
207
+ }
199
208
  // 5. The BRC-100 Wallet
200
- const wallet = new Wallet({ chain, keyDeriver, storage, services, monitor });
209
+ const wallet = isTestMode ? undefined : new Wallet({ chain, keyDeriver, storage, services, monitor });
201
210
  // 6. SQLite storage via knex
202
211
  const filePath = path.join(config.storageDir, `${DEFAULT_DB_NAME}.sqlite`);
203
212
  const knex = knexLib({
@@ -225,8 +234,8 @@ export class BSVAgentWallet {
225
234
  keyDeriver,
226
235
  chain,
227
236
  storage,
228
- services,
229
- monitor,
237
+ services: isTestMode ? undefined : services,
238
+ monitor: isTestMode ? undefined : monitor,
230
239
  wallet,
231
240
  };
232
241
  }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Identity Consistency tests
3
+ *
4
+ * Verifies that all plugins produce the exact same identityKey from the same root secret.
5
+ */
6
+ export {};
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Identity Consistency tests
3
+ *
4
+ * Verifies that all plugins produce the exact same identityKey from the same root secret.
5
+ */
6
+ import { BSVAgentWallet } from '../core/wallet.js';
7
+ import * as fs from 'node:fs';
8
+ import * as path from 'node:path';
9
+ import * as os from 'node:os';
10
+ // Simple test runner
11
+ let passed = 0;
12
+ let failed = 0;
13
+ async function test(name, fn) {
14
+ try {
15
+ await fn();
16
+ console.log(` ✓ ${name}`);
17
+ passed++;
18
+ }
19
+ catch (err) {
20
+ console.log(` ✗ ${name}`);
21
+ console.log(err);
22
+ failed++;
23
+ }
24
+ }
25
+ function assert(condition, message) {
26
+ if (!condition)
27
+ throw new Error(`Assertion failed: ${message}`);
28
+ }
29
+ async function run() {
30
+ console.log('Identity Consistency tests\n');
31
+ const SHARED_ROOT_KEY = '0000000000000000000000000000000000000000000000000000000000000001';
32
+ const EXPECTED_IDENTITY = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798';
33
+ await test('Overlay plugin derives correct compressed pubkey', async () => {
34
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'identity-test-'));
35
+ try {
36
+ const wallet = await BSVAgentWallet.load({
37
+ network: 'mainnet',
38
+ storageDir: tmpDir,
39
+ rootKeyHex: SHARED_ROOT_KEY,
40
+ enableMonitor: false
41
+ });
42
+ const identity = await wallet.getIdentityKey();
43
+ assert(identity === EXPECTED_IDENTITY, `Should match expected identity. Got: ${identity}`);
44
+ assert(identity.length === 66, `Should be 66 chars (compressed hex). Got: ${identity.length}`);
45
+ await wallet.destroy();
46
+ }
47
+ finally {
48
+ fs.rmSync(tmpDir, { recursive: true, force: true });
49
+ }
50
+ });
51
+ // Since both use the same core logic (copied or shared), we verify the logic here
52
+ // against the known secp256k1 base point G (compressed).
53
+ console.log(`\n${passed} passed, ${failed} failed`);
54
+ if (failed > 0)
55
+ process.exit(1);
56
+ }
57
+ run().catch(err => {
58
+ console.error(err);
59
+ process.exit(1);
60
+ });
package/index.ts CHANGED
@@ -462,7 +462,12 @@ export async function activate(api: any) {
462
462
  return register(api);
463
463
  }
464
464
 
465
+ let isInitialized = false;
466
+
465
467
  export default function register(api: any) {
468
+ if (isInitialized) return;
469
+ isInitialized = true;
470
+
466
471
  // Capture config at registration time
467
472
  // Check all possible IDs for backward compatibility and various installation methods
468
473
  const entries = api.getConfig?.()?.plugins?.entries || {};
@@ -638,7 +643,7 @@ export default function register(api: any) {
638
643
  // Register a skill-style wake handler
639
644
  api.registerHook({
640
645
  id: "openclaw-overlay-wake",
641
- event: "gateway:start",
646
+ events: ["gateway:start"],
642
647
  handler: async (ctx: any) => {
643
648
  // Auto-check for registration on startup
644
649
  (async () => {
@@ -1644,7 +1649,7 @@ function buildEnvironment(config: any) {
1644
1649
  function parseCliOutput(stdout: any) {
1645
1650
  try {
1646
1651
  const str = typeof stdout === 'string' ? stdout : String(stdout || '');
1647
- return JSON.parse(str?.trim());
1652
+ return JSON.parse(str.trim());
1648
1653
  } catch (error: any) {
1649
1654
  throw new Error(`Failed to parse CLI output: ${error.message}`);
1650
1655
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-overlay-plugin",
3
- "version": "0.7.47",
3
+ "version": "0.7.49",
4
4
  "description": "Openclaw BSV Overlay — agent discovery, service marketplace, and micropayments on the BSV blockchain",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -243,9 +243,13 @@ export class BSVAgentWallet {
243
243
  const chaintracksUrl = process.env.BSV_CHAINTRACKS_URL || 'https://chaintracks-us-1.bsvb.tech';
244
244
  const arcUrl = process.env.BSV_ARC_URL;
245
245
 
246
- serviceOptions.chaintracks = new ChaintracksServiceClient(chain, chaintracksUrl);
247
- if (arcUrl) {
248
- serviceOptions.arcUrl = arcUrl;
246
+ const isTestMode = (config as any).enableMonitor === false;
247
+
248
+ if (!isTestMode) {
249
+ serviceOptions.chaintracks = new ChaintracksServiceClient(chain, chaintracksUrl);
250
+ if (arcUrl) {
251
+ serviceOptions.arcUrl = arcUrl;
252
+ }
249
253
  }
250
254
 
251
255
  serviceOptions.taalApiKey = taalApiKey;
@@ -254,10 +258,15 @@ export class BSVAgentWallet {
254
258
  // 4. Background monitor
255
259
  const monopts = Monitor.createDefaultWalletMonitorOptions(chain, storage, services);
256
260
  const monitor = new Monitor(monopts);
257
- monitor.addDefaultTasks();
261
+ if (!isTestMode) {
262
+ monitor.addDefaultTasks();
263
+ } else {
264
+ // In test mode, we clear all tasks to ensure no background activity
265
+ (monitor as any).tasks = [];
266
+ }
258
267
 
259
268
  // 5. The BRC-100 Wallet
260
- const wallet = new Wallet({ chain, keyDeriver, storage, services, monitor });
269
+ const wallet = isTestMode ? undefined : new Wallet({ chain, keyDeriver, storage, services, monitor });
261
270
 
262
271
  // 6. SQLite storage via knex
263
272
  const filePath = path.join(config.storageDir, `${DEFAULT_DB_NAME}.sqlite`);
@@ -290,9 +299,9 @@ export class BSVAgentWallet {
290
299
  keyDeriver,
291
300
  chain,
292
301
  storage,
293
- services,
294
- monitor,
302
+ services: isTestMode ? undefined : services,
303
+ monitor: isTestMode ? undefined : monitor,
295
304
  wallet,
296
- };
305
+ } as any;
297
306
  }
298
307
  }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Identity Consistency tests
3
+ *
4
+ * Verifies that all plugins produce the exact same identityKey from the same root secret.
5
+ */
6
+
7
+ import { BSVAgentWallet } from '../core/wallet.js';
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import * as os from 'node:os';
11
+
12
+ // Simple test runner
13
+ let passed = 0;
14
+ let failed = 0;
15
+
16
+ async function test(name: string, fn: () => void | Promise<void>) {
17
+ try {
18
+ await fn();
19
+ console.log(` ✓ ${name}`);
20
+ passed++;
21
+ } catch (err: unknown) {
22
+ console.log(` ✗ ${name}`);
23
+ console.log(err);
24
+ failed++;
25
+ }
26
+ }
27
+
28
+ function assert(condition: boolean, message: string) {
29
+ if (!condition) throw new Error(`Assertion failed: ${message}`);
30
+ }
31
+
32
+ async function run() {
33
+ console.log('Identity Consistency tests\n');
34
+
35
+ const SHARED_ROOT_KEY = '0000000000000000000000000000000000000000000000000000000000000001';
36
+ const EXPECTED_IDENTITY = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798';
37
+
38
+ await test('Overlay plugin derives correct compressed pubkey', async () => {
39
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'identity-test-'));
40
+ try {
41
+ const wallet = await BSVAgentWallet.load({
42
+ network: 'mainnet',
43
+ storageDir: tmpDir,
44
+ rootKeyHex: SHARED_ROOT_KEY,
45
+ enableMonitor: false
46
+ } as any);
47
+
48
+ const identity = await wallet.getIdentityKey();
49
+ assert(identity === EXPECTED_IDENTITY, `Should match expected identity. Got: ${identity}`);
50
+ assert(identity.length === 66, `Should be 66 chars (compressed hex). Got: ${identity.length}`);
51
+
52
+ await wallet.destroy();
53
+ } finally {
54
+ fs.rmSync(tmpDir, { recursive: true, force: true });
55
+ }
56
+ });
57
+
58
+ // Since both use the same core logic (copied or shared), we verify the logic here
59
+ // against the known secp256k1 base point G (compressed).
60
+
61
+ console.log(`\n${passed} passed, ${failed} failed`);
62
+ if (failed > 0) process.exit(1);
63
+ }
64
+
65
+ run().catch(err => {
66
+ console.error(err);
67
+ process.exit(1);
68
+ });