openclaw-overlay-plugin 0.7.47 → 0.7.48

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 || {};
@@ -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 || {};
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.48",
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
+ });