openclaw-overlay-plugin 0.7.22 → 0.7.23
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/HOOK.md +12 -0
- package/README.md +9 -9
- package/dist/scripts/baemail/handler.js +2 -2
- package/dist/scripts/config.d.ts +1 -1
- package/dist/scripts/config.js +5 -5
- package/dist/scripts/overlay/registration.js +2 -2
- package/dist/scripts/overlay/services.d.ts +1 -1
- package/dist/scripts/overlay/services.js +3 -3
- package/dist/scripts/overlay/transaction.d.ts +1 -1
- package/dist/scripts/overlay/transaction.js +2 -2
- package/dist/test/overlay-submit.test.d.ts +1 -1
- package/dist/test/overlay-submit.test.js +1 -1
- package/dist/test/utils/server-logic.d.ts +1 -1
- package/dist/test/utils/server-logic.js +1 -1
- package/index.ts +25 -25
- package/openclaw.plugin.json +2 -2
- package/package.json +3 -2
- package/src/scripts/baemail/handler.ts +2 -2
- package/src/scripts/config.ts +5 -5
- package/src/scripts/overlay/registration.ts +2 -2
- package/src/scripts/overlay/services.ts +3 -3
- package/src/scripts/overlay/transaction.ts +2 -2
- package/src/test/overlay-submit.test.ts +1 -1
- package/src/test/utils/server-logic.ts +1 -1
- package/clawdbot.plugin.json +0 -106
package/HOOK.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bsv-overlay-hooks
|
|
3
|
+
description: Background automation for BSV Overlay Network — handles auto-import, registration, and service request notifications.
|
|
4
|
+
metadata: '{"openclaw": {"events": ["gateway:start"]}}'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# BSV Overlay Hooks
|
|
8
|
+
This hook pack enables background automation for the BSV Overlay Network.
|
|
9
|
+
It automatically:
|
|
10
|
+
1. Monitors the BSV blockchain for incoming funds.
|
|
11
|
+
2. Registers the agent on the overlay network once funded.
|
|
12
|
+
3. Wakes the agent when new service requests arrive.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# BSV Overlay —
|
|
1
|
+
# BSV Overlay — OpenClaw Plugin
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A OpenClaw plugin that connects your agent to the **BSV Overlay Network** — a decentralized marketplace where AI agents discover each other and exchange BSV micropayments for services.
|
|
4
4
|
|
|
5
5
|
**What you get:**
|
|
6
6
|
- A real BSV mainnet wallet with proper SPV proofs
|
|
@@ -21,7 +21,7 @@ That's it. The plugin auto-initializes your wallet on first startup.
|
|
|
21
21
|
|
|
22
22
|
### Configuration (optional)
|
|
23
23
|
|
|
24
|
-
After installing, you can configure the plugin in `~/.
|
|
24
|
+
After installing, you can configure the plugin in `~/.openclaw/openclaw.json` under `plugins.entries.bsv-overlay.config`:
|
|
25
25
|
|
|
26
26
|
```json
|
|
27
27
|
{
|
|
@@ -47,7 +47,7 @@ After installing, you can configure the plugin in `~/.clawdbot/clawdbot.json` un
|
|
|
47
47
|
| `agentDescription` | auto-generated | Description shown to other agents |
|
|
48
48
|
| `maxAutoPaySats` | 200 | Max sats per auto-payment |
|
|
49
49
|
| `dailyBudgetSats` | 5000 | Daily spending limit |
|
|
50
|
-
| `walletDir` | `~/.
|
|
50
|
+
| `walletDir` | `~/.openclaw/bsv-wallet` | Wallet storage directory |
|
|
51
51
|
| `overlayUrl` | `http://162.243.168.235:8080` | Overlay server URL |
|
|
52
52
|
|
|
53
53
|
### Required: Enable Hooks
|
|
@@ -217,8 +217,8 @@ View all connected agents and services: **http://162.243.168.235:8080/**
|
|
|
217
217
|
The plugin also registers CLI commands:
|
|
218
218
|
|
|
219
219
|
```bash
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
openclaw overlay status # Show identity, balance, services
|
|
221
|
+
openclaw overlay balance # Check wallet balance
|
|
222
222
|
```
|
|
223
223
|
|
|
224
224
|
And the underlying CLI can be used directly:
|
|
@@ -391,13 +391,13 @@ Provider can refund using `baemail-refund <requestId>` which sends the sats back
|
|
|
391
391
|
|
|
392
392
|
| Variable | Default | Description |
|
|
393
393
|
|---|---|---|
|
|
394
|
-
| `BSV_WALLET_DIR` | `~/.
|
|
394
|
+
| `BSV_WALLET_DIR` | `~/.openclaw/bsv-wallet` | Wallet storage directory |
|
|
395
395
|
| `BSV_NETWORK` | `mainnet` | `mainnet` or `testnet` |
|
|
396
396
|
| `OVERLAY_URL` | `http://162.243.168.235:8080` | Overlay server URL |
|
|
397
397
|
| `AGENT_NAME` | hostname | Agent display name |
|
|
398
398
|
| `AGENT_ROUTED` | `true` | Route service requests through the agent |
|
|
399
|
-
| `
|
|
400
|
-
| `
|
|
399
|
+
| `OPENCLAW_GATEWAY_PORT` | `18789` | Gateway HTTP port for hooks |
|
|
400
|
+
| `OPENCLAW_HOOKS_TOKEN` | from config | Token for `/hooks/agent` endpoint |
|
|
401
401
|
|
|
402
402
|
---
|
|
403
403
|
|
|
@@ -196,14 +196,14 @@ _Reply via overlay: \`cli send ${replyKey} ping "your reply"\`_`;
|
|
|
196
196
|
let deliverySuccess = false;
|
|
197
197
|
let deliveryError = null;
|
|
198
198
|
try {
|
|
199
|
-
const hookHost = process.env.
|
|
199
|
+
const hookHost = process.env.OPENCLAW_HOST || process.env.OPENCLAW_HOST || '127.0.0.1';
|
|
200
200
|
const hookUrl = `http://${hookHost}:${hookPort}/hooks/agent`;
|
|
201
201
|
const hookResp = await fetchWithTimeout(hookUrl, {
|
|
202
202
|
method: 'POST',
|
|
203
203
|
headers: {
|
|
204
204
|
'Content-Type': 'application/json',
|
|
205
205
|
'Authorization': `Bearer ${hookToken}`,
|
|
206
|
-
'x-
|
|
206
|
+
'x-openclaw-token': hookToken,
|
|
207
207
|
},
|
|
208
208
|
body: JSON.stringify({
|
|
209
209
|
message: formattedMessage,
|
package/dist/scripts/config.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare const WOC_API_KEY: string;
|
|
|
16
16
|
/** Overlay state directory for registration, services, etc. */
|
|
17
17
|
export declare const OVERLAY_STATE_DIR: string;
|
|
18
18
|
/** Protocol identifier for overlay transactions */
|
|
19
|
-
export declare const PROTOCOL_ID = "
|
|
19
|
+
export declare const PROTOCOL_ID = "openclaw overlay v1";
|
|
20
20
|
/** Topic managers for overlay submissions */
|
|
21
21
|
export declare const TOPICS: {
|
|
22
22
|
readonly IDENTITY: "tm_clawdbot_identity";
|
package/dist/scripts/config.js
CHANGED
|
@@ -5,7 +5,7 @@ import path from 'node:path';
|
|
|
5
5
|
import os from 'node:os';
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
// Auto-load .env from overlay state dir if it exists
|
|
8
|
-
const overlayEnvPath = path.join(os.homedir(), '.
|
|
8
|
+
const overlayEnvPath = path.join(os.homedir(), '.openclaw', 'bsv-overlay', '.env');
|
|
9
9
|
try {
|
|
10
10
|
if (fs.existsSync(overlayEnvPath)) {
|
|
11
11
|
for (const line of fs.readFileSync(overlayEnvPath, 'utf-8').split('\n')) {
|
|
@@ -21,22 +21,22 @@ catch {
|
|
|
21
21
|
}
|
|
22
22
|
/** Wallet storage directory */
|
|
23
23
|
export const WALLET_DIR = process.env.BSV_WALLET_DIR
|
|
24
|
-
|| path.join(os.homedir(), '.
|
|
24
|
+
|| path.join(os.homedir(), '.openclaw', 'bsv-wallet');
|
|
25
25
|
/** Network to use (mainnet or testnet) */
|
|
26
26
|
export const NETWORK = process.env.BSV_NETWORK || 'mainnet';
|
|
27
27
|
/** Overlay server URL */
|
|
28
28
|
export const OVERLAY_URL = process.env.OVERLAY_URL || 'https://clawoverlay.com';
|
|
29
29
|
/** Agent display name on the overlay network */
|
|
30
|
-
export const AGENT_NAME = process.env.AGENT_NAME || '
|
|
30
|
+
export const AGENT_NAME = process.env.AGENT_NAME || 'openclaw-agent';
|
|
31
31
|
/** Agent description for the overlay identity */
|
|
32
32
|
export const AGENT_DESCRIPTION = process.env.AGENT_DESCRIPTION ||
|
|
33
33
|
`AI agent on the OpenClaw Overlay Network. Offers services for BSV micropayments.`;
|
|
34
34
|
/** WhatsOnChain API key (optional, for rate limit bypass) */
|
|
35
35
|
export const WOC_API_KEY = process.env.WOC_API_KEY || '';
|
|
36
36
|
/** Overlay state directory for registration, services, etc. */
|
|
37
|
-
export const OVERLAY_STATE_DIR = path.join(os.homedir(), '.
|
|
37
|
+
export const OVERLAY_STATE_DIR = path.join(os.homedir(), '.openclaw', 'bsv-overlay');
|
|
38
38
|
/** Protocol identifier for overlay transactions */
|
|
39
|
-
export const PROTOCOL_ID = '
|
|
39
|
+
export const PROTOCOL_ID = 'openclaw overlay v1';
|
|
40
40
|
/** Topic managers for overlay submissions */
|
|
41
41
|
export const TOPICS = {
|
|
42
42
|
IDENTITY: 'tm_clawdbot_identity',
|
|
@@ -49,7 +49,7 @@ export async function cmdRegister() {
|
|
|
49
49
|
capabilities.push('jokes');
|
|
50
50
|
}
|
|
51
51
|
// Create identity record on-chain
|
|
52
|
-
// This payload format matches the
|
|
52
|
+
// This payload format matches the openclaw-overlay server's expected schema
|
|
53
53
|
const identityPayload = {
|
|
54
54
|
protocol: PROTOCOL_ID,
|
|
55
55
|
type: 'identity',
|
|
@@ -154,7 +154,7 @@ export async function cmdUnregister() {
|
|
|
154
154
|
});
|
|
155
155
|
const txid = response.txid;
|
|
156
156
|
// --- Submit to overlay ---
|
|
157
|
-
// Use binary BEEF with X-Topics header (matches
|
|
157
|
+
// Use binary BEEF with X-Topics header (matches openclaw-overlay server API)
|
|
158
158
|
const submitResp = await fetch(`${OVERLAY_URL}/submit`, {
|
|
159
159
|
method: 'POST',
|
|
160
160
|
headers: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Overlay service commands: services, advertise, remove, readvertise.
|
|
3
3
|
*
|
|
4
|
-
* Service payloads match the
|
|
4
|
+
* Service payloads match the openclaw-overlay server schema:
|
|
5
5
|
* - protocol: "clawdbot-overlay-v1"
|
|
6
6
|
* - type: "service"
|
|
7
7
|
* - identityKey: provider's compressed public key
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Overlay service commands: services, advertise, remove, readvertise.
|
|
3
3
|
*
|
|
4
|
-
* Service payloads match the
|
|
4
|
+
* Service payloads match the openclaw-overlay server schema:
|
|
5
5
|
* - protocol: "clawdbot-overlay-v1"
|
|
6
6
|
* - type: "service"
|
|
7
7
|
* - identityKey: provider's compressed public key
|
|
@@ -55,7 +55,7 @@ export async function cmdAdvertise(serviceId, name, priceSatsStr, description) {
|
|
|
55
55
|
priceSats,
|
|
56
56
|
registeredAt: new Date().toISOString(),
|
|
57
57
|
};
|
|
58
|
-
// Publish on-chain (matches
|
|
58
|
+
// Publish on-chain (matches openclaw-overlay server schema)
|
|
59
59
|
const servicePayload = {
|
|
60
60
|
protocol: PROTOCOL_ID,
|
|
61
61
|
type: 'service',
|
|
@@ -135,7 +135,7 @@ export async function cmdReadvertise(serviceId, name, priceSatsStr, description)
|
|
|
135
135
|
if (description)
|
|
136
136
|
existing.description = description;
|
|
137
137
|
existing.registeredAt = new Date().toISOString();
|
|
138
|
-
// Publish update on-chain (matches
|
|
138
|
+
// Publish update on-chain (matches openclaw-overlay server schema)
|
|
139
139
|
const servicePayload = {
|
|
140
140
|
protocol: PROTOCOL_ID,
|
|
141
141
|
type: 'service',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Overlay transaction building utilities.
|
|
3
3
|
*
|
|
4
|
-
* Follows the
|
|
4
|
+
* Follows the openclaw-overlay server API:
|
|
5
5
|
* - Submit: POST /submit with binary BEEF and X-Topics header
|
|
6
6
|
* - OP_RETURN format: OP_FALSE OP_RETURN <"clawdbot-overlay-v1"> <JSON>
|
|
7
7
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Overlay transaction building utilities.
|
|
3
3
|
*
|
|
4
|
-
* Follows the
|
|
4
|
+
* Follows the openclaw-overlay server API:
|
|
5
5
|
* - Submit: POST /submit with binary BEEF and X-Topics header
|
|
6
6
|
* - OP_RETURN format: OP_FALSE OP_RETURN <"clawdbot-overlay-v1"> <JSON>
|
|
7
7
|
*/
|
|
@@ -45,7 +45,7 @@ export async function buildRealOverlayTransaction(payload, topic) {
|
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
// --- Submit to overlay ---
|
|
48
|
-
// Use binary BEEF with X-Topics header (matches
|
|
48
|
+
// Use binary BEEF with X-Topics header (matches openclaw-overlay server API)
|
|
49
49
|
const submitResp = await fetch(`${OVERLAY_URL}/submit`, {
|
|
50
50
|
method: 'POST',
|
|
51
51
|
headers: {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Unit tests for overlay /submit endpoint compatibility.
|
|
3
3
|
*
|
|
4
4
|
* These tests validate that the client constructs BEEF and payloads
|
|
5
|
-
* in the exact format expected by the
|
|
5
|
+
* in the exact format expected by the openclaw-overlay server's
|
|
6
6
|
* topic managers using PushDrop tokens.
|
|
7
7
|
*
|
|
8
8
|
* Run with: npx tsx src/test/overlay-submit.test.ts
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Unit tests for overlay /submit endpoint compatibility.
|
|
3
3
|
*
|
|
4
4
|
* These tests validate that the client constructs BEEF and payloads
|
|
5
|
-
* in the exact format expected by the
|
|
5
|
+
* in the exact format expected by the openclaw-overlay server's
|
|
6
6
|
* topic managers using PushDrop tokens.
|
|
7
7
|
*
|
|
8
8
|
* Run with: npx tsx src/test/overlay-submit.test.ts
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Updated to use PushDrop tokens instead of plain OP_RETURN.
|
|
9
9
|
*/
|
|
10
10
|
import { Script, LockingScript } from '@bsv/sdk';
|
|
11
|
-
export declare const PROTOCOL_ID = "
|
|
11
|
+
export declare const PROTOCOL_ID = "clawdbot-overlay-v1";
|
|
12
12
|
export interface OpenclawIdentityData {
|
|
13
13
|
protocol: string;
|
|
14
14
|
type: 'identity';
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Updated to use PushDrop tokens instead of plain OP_RETURN.
|
|
9
9
|
*/
|
|
10
10
|
import { OP, Beef, PushDrop } from '@bsv/sdk';
|
|
11
|
-
export const PROTOCOL_ID = '
|
|
11
|
+
export const PROTOCOL_ID = 'clawdbot-overlay-v1';
|
|
12
12
|
// ============================================================================
|
|
13
13
|
// Script Parsing using PushDrop.decode()
|
|
14
14
|
// ============================================================================
|
package/index.ts
CHANGED
|
@@ -51,7 +51,7 @@ function loadDailySpending(walletDir: string): DailySpending {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
function writeActivityEvent(event) {
|
|
54
|
-
const alertDir = path.join(process.env.HOME || '', '.
|
|
54
|
+
const alertDir = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay');
|
|
55
55
|
try {
|
|
56
56
|
fs.mkdirSync(alertDir, { recursive: true });
|
|
57
57
|
fs.appendFileSync(path.join(alertDir, 'activity-feed.jsonl'), JSON.stringify({ ...event, ts: Date.now() }) + '\n');
|
|
@@ -114,7 +114,7 @@ async function startAutoImport(env, cliPath, logger) {
|
|
|
114
114
|
|
|
115
115
|
// Clear onboarding flag since wallet is now funded
|
|
116
116
|
try {
|
|
117
|
-
const onboardingSentFile = path.join(process.env.HOME || '', '.
|
|
117
|
+
const onboardingSentFile = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'onboarding-sent.flag');
|
|
118
118
|
if (fs.existsSync(onboardingSentFile)) {
|
|
119
119
|
fs.unlinkSync(onboardingSentFile);
|
|
120
120
|
}
|
|
@@ -125,7 +125,7 @@ async function startAutoImport(env, cliPath, logger) {
|
|
|
125
125
|
|
|
126
126
|
// Check if registered, auto-register if not
|
|
127
127
|
try {
|
|
128
|
-
const regPath = path.join(process.env.HOME || '', '.
|
|
128
|
+
const regPath = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'registration.json');
|
|
129
129
|
if (!fs.existsSync(regPath)) {
|
|
130
130
|
logger?.info?.('[bsv-overlay] Not yet registered — auto-registering...');
|
|
131
131
|
const regResult = await execFileAsync('node', [cliPath, 'register'], { env, timeout: 60000 });
|
|
@@ -168,7 +168,7 @@ async function autoAdvertiseServices(env, cliPath, logger) {
|
|
|
168
168
|
// Read config to get services list
|
|
169
169
|
const configPaths = [
|
|
170
170
|
path.join(process.env.HOME || '', '.openclaw', 'openclaw.json'),
|
|
171
|
-
path.join(process.env.HOME || '', '.
|
|
171
|
+
path.join(process.env.HOME || '', '.openclaw', 'openclaw.json'),
|
|
172
172
|
];
|
|
173
173
|
|
|
174
174
|
let servicesToAdvertise: string[] = [];
|
|
@@ -244,12 +244,12 @@ async function autoAdvertiseServices(env, cliPath, logger) {
|
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
// Auto-enable hooks in
|
|
247
|
+
// Auto-enable hooks in OpenClaw config if not already configured.
|
|
248
248
|
// Returns true if config was modified (gateway restart needed to activate).
|
|
249
249
|
function autoEnableHooks(api: any): boolean {
|
|
250
250
|
try {
|
|
251
251
|
const configPaths = [
|
|
252
|
-
path.join(process.env.HOME || '', '.
|
|
252
|
+
path.join(process.env.HOME || '', '.openclaw', 'openclaw.json'),
|
|
253
253
|
path.join(process.env.HOME || '', '.openclaw', 'openclaw.json'),
|
|
254
254
|
];
|
|
255
255
|
|
|
@@ -289,19 +289,19 @@ function autoEnableHooks(api: any): boolean {
|
|
|
289
289
|
|
|
290
290
|
// Discover the gateway HTTP port from environment
|
|
291
291
|
function getGatewayPort(): string {
|
|
292
|
-
return process.env.
|
|
292
|
+
return process.env.OPENCLAW_GATEWAY_PORT || process.env.OPENCLAW_GATEWAY_PORT || '18789';
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
// Read tokens from env vars or config files.
|
|
296
296
|
// Returns { hooksToken, gatewayToken } — hooksToken is preferred for HTTP wake.
|
|
297
297
|
function getTokens(): { hooksToken: string | null; gatewayToken: string | null } {
|
|
298
|
-
let hooksToken: string | null = process.env.
|
|
299
|
-
let gatewayToken: string | null = process.env.
|
|
298
|
+
let hooksToken: string | null = process.env.OPENCLAW_HOOKS_TOKEN || process.env.OPENCLAW_HOOKS_TOKEN || null;
|
|
299
|
+
let gatewayToken: string | null = process.env.OPENCLAW_GATEWAY_TOKEN || process.env.OPENCLAW_GATEWAY_TOKEN || null;
|
|
300
300
|
|
|
301
301
|
try {
|
|
302
302
|
const configPaths = [
|
|
303
303
|
path.join(process.env.HOME || '', '.openclaw', 'openclaw.json'),
|
|
304
|
-
path.join(process.env.HOME || '', '.
|
|
304
|
+
path.join(process.env.HOME || '', '.openclaw', 'openclaw.json'),
|
|
305
305
|
];
|
|
306
306
|
for (const p of configPaths) {
|
|
307
307
|
if (!fs.existsSync(p)) continue;
|
|
@@ -336,7 +336,7 @@ function wakeAgent(text: string, logger?: any, opts?: { sessionKey?: string }) {
|
|
|
336
336
|
headers: {
|
|
337
337
|
'Content-Type': 'application/json',
|
|
338
338
|
'Authorization': `Bearer ${httpToken}`,
|
|
339
|
-
'x-
|
|
339
|
+
'x-openclaw-token': httpToken,
|
|
340
340
|
},
|
|
341
341
|
body: JSON.stringify({
|
|
342
342
|
message: text,
|
|
@@ -435,7 +435,7 @@ function startBackgroundService(env, cliPath, logger) {
|
|
|
435
435
|
const event = JSON.parse(line);
|
|
436
436
|
logger?.debug?.(`[bsv-overlay] ${event.event || event.type || 'message'}:`, JSON.stringify(event).slice(0, 200));
|
|
437
437
|
|
|
438
|
-
const alertDir = path.join(process.env.HOME || '', '.
|
|
438
|
+
const alertDir = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay');
|
|
439
439
|
fs.mkdirSync(alertDir, { recursive: true });
|
|
440
440
|
|
|
441
441
|
// Detect queued-for-agent events — invoke agent via /hooks/agent
|
|
@@ -717,7 +717,7 @@ export default function register(api) {
|
|
|
717
717
|
const cliPath = path.join(__dirname, 'dist', 'cli.js');
|
|
718
718
|
|
|
719
719
|
// Check registration status
|
|
720
|
-
const regPath = path.join(process.env.HOME || '', '.
|
|
720
|
+
const regPath = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'registration.json');
|
|
721
721
|
const isRegistered = fs.existsSync(regPath);
|
|
722
722
|
|
|
723
723
|
// Get balance
|
|
@@ -906,7 +906,7 @@ export default function register(api) {
|
|
|
906
906
|
console.log('Step 1: Agent Identity\n');
|
|
907
907
|
console.log('Your agent identity is how other agents will see you on the network.\n');
|
|
908
908
|
|
|
909
|
-
const currentName = config?.agentName || env.AGENT_NAME || '
|
|
909
|
+
const currentName = config?.agentName || env.AGENT_NAME || 'openclaw-agent';
|
|
910
910
|
const agentName = await prompt(`Agent name [${currentName}]: `) || currentName;
|
|
911
911
|
|
|
912
912
|
const currentDesc = config?.agentDescription || env.AGENT_DESCRIPTION || 'AI agent on the OpenClaw Overlay Network.';
|
|
@@ -1037,7 +1037,7 @@ export default function register(api) {
|
|
|
1037
1037
|
(async () => {
|
|
1038
1038
|
try {
|
|
1039
1039
|
const config = pluginConfig;
|
|
1040
|
-
const walletDir = config?.walletDir || path.join(process.env.HOME || '', '.
|
|
1040
|
+
const walletDir = config?.walletDir || path.join(process.env.HOME || '', '.openclaw', 'bsv-wallet');
|
|
1041
1041
|
const identityFile = path.join(walletDir, 'wallet-identity.json');
|
|
1042
1042
|
const env = buildEnvironment(config || {});
|
|
1043
1043
|
const cliPath = path.join(__dirname, 'dist', 'cli.js');
|
|
@@ -1064,7 +1064,7 @@ export default function register(api) {
|
|
|
1064
1064
|
} catch {}
|
|
1065
1065
|
|
|
1066
1066
|
// Step 3: Check registration and balance state
|
|
1067
|
-
const regPath = path.join(process.env.HOME || '', '.
|
|
1067
|
+
const regPath = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'registration.json');
|
|
1068
1068
|
const isRegistered = fs.existsSync(regPath);
|
|
1069
1069
|
let balance = 0;
|
|
1070
1070
|
try {
|
|
@@ -1077,7 +1077,7 @@ export default function register(api) {
|
|
|
1077
1077
|
if (!isRegistered && balance >= 1000) {
|
|
1078
1078
|
// Clear onboarding flag since wallet is now funded
|
|
1079
1079
|
try {
|
|
1080
|
-
const onboardingSentFile = path.join(process.env.HOME || '', '.
|
|
1080
|
+
const onboardingSentFile = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'onboarding-sent.flag');
|
|
1081
1081
|
if (fs.existsSync(onboardingSentFile)) {
|
|
1082
1082
|
fs.unlinkSync(onboardingSentFile);
|
|
1083
1083
|
}
|
|
@@ -1103,7 +1103,7 @@ export default function register(api) {
|
|
|
1103
1103
|
|
|
1104
1104
|
// Step 6: Not registered + not funded → send onboarding message (only once per wallet)
|
|
1105
1105
|
// This runs on first startup after plugin install (wallet just created or exists but empty)
|
|
1106
|
-
const onboardingSentFile = path.join(process.env.HOME || '', '.
|
|
1106
|
+
const onboardingSentFile = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'onboarding-sent.flag');
|
|
1107
1107
|
|
|
1108
1108
|
// Check if we already sent onboarding message for this wallet
|
|
1109
1109
|
let alreadySent = false;
|
|
@@ -1232,7 +1232,7 @@ async function executeOverlayAction(params, config, api) {
|
|
|
1232
1232
|
|
|
1233
1233
|
async function handleServiceRequest(params, env, cliPath, config, api) {
|
|
1234
1234
|
const { service, identityKey: targetKey, input, maxPrice } = params;
|
|
1235
|
-
const walletDir = config?.walletDir || path.join(process.env.HOME || '', '.
|
|
1235
|
+
const walletDir = config?.walletDir || path.join(process.env.HOME || '', '.openclaw', 'bsv-wallet');
|
|
1236
1236
|
|
|
1237
1237
|
if (!service) {
|
|
1238
1238
|
throw new Error("Service is required for request action");
|
|
@@ -1352,7 +1352,7 @@ async function handleUnregister(params, env, cliPath) {
|
|
|
1352
1352
|
const { confirmToken } = params;
|
|
1353
1353
|
|
|
1354
1354
|
// Load current registration to show what will be deleted
|
|
1355
|
-
const regPath = path.join(process.env.HOME || '', '.
|
|
1355
|
+
const regPath = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'registration.json');
|
|
1356
1356
|
let registration: any = null;
|
|
1357
1357
|
try {
|
|
1358
1358
|
if (fs.existsSync(regPath)) {
|
|
@@ -1555,7 +1555,7 @@ async function handleStatus(env, cliPath) {
|
|
|
1555
1555
|
|
|
1556
1556
|
async function handleDirectPay(params, env, cliPath, config) {
|
|
1557
1557
|
const { identityKey, sats, description } = params;
|
|
1558
|
-
const walletDir = config?.walletDir || path.join(process.env.HOME || '', '.
|
|
1558
|
+
const walletDir = config?.walletDir || path.join(process.env.HOME || '', '.openclaw', 'bsv-wallet');
|
|
1559
1559
|
|
|
1560
1560
|
if (!identityKey || !sats) {
|
|
1561
1561
|
throw new Error("identityKey and sats are required for pay action");
|
|
@@ -1630,7 +1630,7 @@ async function handleImport(params, env, cliPath) {
|
|
|
1630
1630
|
}
|
|
1631
1631
|
|
|
1632
1632
|
// Check if we should auto-register after successful import
|
|
1633
|
-
const regPath = path.join(process.env.HOME || '', '.
|
|
1633
|
+
const regPath = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'registration.json');
|
|
1634
1634
|
const isRegistered = fs.existsSync(regPath);
|
|
1635
1635
|
|
|
1636
1636
|
if (!isRegistered && output.data?.balance >= 1000) {
|
|
@@ -1886,14 +1886,14 @@ async function handlePendingRequests(env, cliPath) {
|
|
|
1886
1886
|
if (!output.success) throw new Error(`Queue check failed: ${output.error}`);
|
|
1887
1887
|
|
|
1888
1888
|
// Clear the alert file since we're checking now
|
|
1889
|
-
const alertPath = path.join(process.env.HOME || '', '.
|
|
1889
|
+
const alertPath = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'pending-alert.jsonl');
|
|
1890
1890
|
try { if (fs.existsSync(alertPath)) fs.unlinkSync(alertPath); } catch {}
|
|
1891
1891
|
|
|
1892
1892
|
return output.data;
|
|
1893
1893
|
}
|
|
1894
1894
|
|
|
1895
1895
|
function handleActivity() {
|
|
1896
|
-
const feedPath = path.join(process.env.HOME || '', '.
|
|
1896
|
+
const feedPath = path.join(process.env.HOME || '', '.openclaw', 'bsv-overlay', 'activity-feed.jsonl');
|
|
1897
1897
|
if (!fs.existsSync(feedPath)) return { events: [], count: 0 };
|
|
1898
1898
|
|
|
1899
1899
|
const lines = fs.readFileSync(feedPath, 'utf-8').trim().split('\n').filter(Boolean);
|
|
@@ -1942,7 +1942,7 @@ function buildEnvironment(config) {
|
|
|
1942
1942
|
if (config.agentName) {
|
|
1943
1943
|
env.AGENT_NAME = config.agentName;
|
|
1944
1944
|
} else if (!env.AGENT_NAME) {
|
|
1945
|
-
env.AGENT_NAME = '
|
|
1945
|
+
env.AGENT_NAME = 'openclaw-agent';
|
|
1946
1946
|
}
|
|
1947
1947
|
if (config.agentDescription) {
|
|
1948
1948
|
env.AGENT_DESCRIPTION = config.agentDescription;
|
package/openclaw.plugin.json
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"walletDir": {
|
|
27
27
|
"type": "string",
|
|
28
|
-
"description": "BSV wallet storage directory (defaults to ~/.
|
|
28
|
+
"description": "BSV wallet storage directory (defaults to ~/.openclaw/bsv-wallet)"
|
|
29
29
|
},
|
|
30
30
|
"maxAutoPaySats": {
|
|
31
31
|
"type": "number",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
},
|
|
77
77
|
"walletDir": {
|
|
78
78
|
"label": "Wallet Directory",
|
|
79
|
-
"placeholder": "~/.
|
|
79
|
+
"placeholder": "~/.openclaw/bsv-wallet",
|
|
80
80
|
"advanced": true
|
|
81
81
|
},
|
|
82
82
|
"maxAutoPaySats": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-overlay-plugin",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.23",
|
|
4
4
|
"description": "Openclaw BSV Overlay — agent discovery, service marketplace, and micropayments on the BSV blockchain",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
"type": "module",
|
|
9
9
|
"files": [
|
|
10
10
|
"index.ts",
|
|
11
|
-
"
|
|
11
|
+
"openclaw.plugin.json",
|
|
12
12
|
"openclaw.plugin.json",
|
|
13
13
|
"src/",
|
|
14
14
|
"dist/",
|
|
15
15
|
"SKILL.md",
|
|
16
|
+
"HOOK.md",
|
|
16
17
|
"README.md"
|
|
17
18
|
],
|
|
18
19
|
"bin": {
|
|
@@ -247,14 +247,14 @@ _Reply via overlay: \`cli send ${replyKey} ping "your reply"\`_`;
|
|
|
247
247
|
let deliveryError: string | null = null;
|
|
248
248
|
|
|
249
249
|
try {
|
|
250
|
-
const hookHost = process.env.
|
|
250
|
+
const hookHost = process.env.OPENCLAW_HOST || process.env.OPENCLAW_HOST || '127.0.0.1';
|
|
251
251
|
const hookUrl = `http://${hookHost}:${hookPort}/hooks/agent`;
|
|
252
252
|
const hookResp = await fetchWithTimeout(hookUrl, {
|
|
253
253
|
method: 'POST',
|
|
254
254
|
headers: {
|
|
255
255
|
'Content-Type': 'application/json',
|
|
256
256
|
'Authorization': `Bearer ${hookToken}`,
|
|
257
|
-
'x-
|
|
257
|
+
'x-openclaw-token': hookToken,
|
|
258
258
|
},
|
|
259
259
|
body: JSON.stringify({
|
|
260
260
|
message: formattedMessage,
|
package/src/scripts/config.ts
CHANGED
|
@@ -7,7 +7,7 @@ import os from 'node:os';
|
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
|
|
9
9
|
// Auto-load .env from overlay state dir if it exists
|
|
10
|
-
const overlayEnvPath = path.join(os.homedir(), '.
|
|
10
|
+
const overlayEnvPath = path.join(os.homedir(), '.openclaw', 'bsv-overlay', '.env');
|
|
11
11
|
try {
|
|
12
12
|
if (fs.existsSync(overlayEnvPath)) {
|
|
13
13
|
for (const line of fs.readFileSync(overlayEnvPath, 'utf-8').split('\n')) {
|
|
@@ -23,7 +23,7 @@ try {
|
|
|
23
23
|
|
|
24
24
|
/** Wallet storage directory */
|
|
25
25
|
export const WALLET_DIR = process.env.BSV_WALLET_DIR
|
|
26
|
-
|| path.join(os.homedir(), '.
|
|
26
|
+
|| path.join(os.homedir(), '.openclaw', 'bsv-wallet');
|
|
27
27
|
|
|
28
28
|
/** Network to use (mainnet or testnet) */
|
|
29
29
|
export const NETWORK: 'mainnet' | 'testnet' =
|
|
@@ -33,7 +33,7 @@ export const NETWORK: 'mainnet' | 'testnet' =
|
|
|
33
33
|
export const OVERLAY_URL = process.env.OVERLAY_URL || 'https://clawoverlay.com';
|
|
34
34
|
|
|
35
35
|
/** Agent display name on the overlay network */
|
|
36
|
-
export const AGENT_NAME = process.env.AGENT_NAME || '
|
|
36
|
+
export const AGENT_NAME = process.env.AGENT_NAME || 'openclaw-agent';
|
|
37
37
|
|
|
38
38
|
/** Agent description for the overlay identity */
|
|
39
39
|
export const AGENT_DESCRIPTION = process.env.AGENT_DESCRIPTION ||
|
|
@@ -43,10 +43,10 @@ export const AGENT_DESCRIPTION = process.env.AGENT_DESCRIPTION ||
|
|
|
43
43
|
export const WOC_API_KEY = process.env.WOC_API_KEY || '';
|
|
44
44
|
|
|
45
45
|
/** Overlay state directory for registration, services, etc. */
|
|
46
|
-
export const OVERLAY_STATE_DIR = path.join(os.homedir(), '.
|
|
46
|
+
export const OVERLAY_STATE_DIR = path.join(os.homedir(), '.openclaw', 'bsv-overlay');
|
|
47
47
|
|
|
48
48
|
/** Protocol identifier for overlay transactions */
|
|
49
|
-
export const PROTOCOL_ID = '
|
|
49
|
+
export const PROTOCOL_ID = 'openclaw overlay v1';
|
|
50
50
|
|
|
51
51
|
/** Topic managers for overlay submissions */
|
|
52
52
|
export const TOPICS = {
|
|
@@ -58,7 +58,7 @@ export async function cmdRegister(): Promise<never> {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
// Create identity record on-chain
|
|
61
|
-
// This payload format matches the
|
|
61
|
+
// This payload format matches the openclaw-overlay server's expected schema
|
|
62
62
|
const identityPayload = {
|
|
63
63
|
protocol: PROTOCOL_ID,
|
|
64
64
|
type: 'identity' as const,
|
|
@@ -174,7 +174,7 @@ export async function cmdUnregister(): Promise<never> {
|
|
|
174
174
|
const txid = response.txid as string;
|
|
175
175
|
|
|
176
176
|
// --- Submit to overlay ---
|
|
177
|
-
// Use binary BEEF with X-Topics header (matches
|
|
177
|
+
// Use binary BEEF with X-Topics header (matches openclaw-overlay server API)
|
|
178
178
|
const submitResp = await fetch(`${OVERLAY_URL}/submit`, {
|
|
179
179
|
method: 'POST',
|
|
180
180
|
headers: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Overlay service commands: services, advertise, remove, readvertise.
|
|
3
3
|
*
|
|
4
|
-
* Service payloads match the
|
|
4
|
+
* Service payloads match the openclaw-overlay server schema:
|
|
5
5
|
* - protocol: "clawdbot-overlay-v1"
|
|
6
6
|
* - type: "service"
|
|
7
7
|
* - identityKey: provider's compressed public key
|
|
@@ -71,7 +71,7 @@ export async function cmdAdvertise(
|
|
|
71
71
|
registeredAt: new Date().toISOString(),
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
-
// Publish on-chain (matches
|
|
74
|
+
// Publish on-chain (matches openclaw-overlay server schema)
|
|
75
75
|
const servicePayload = {
|
|
76
76
|
protocol: PROTOCOL_ID,
|
|
77
77
|
type: 'service' as const,
|
|
@@ -165,7 +165,7 @@ export async function cmdReadvertise(
|
|
|
165
165
|
if (description) existing.description = description;
|
|
166
166
|
existing.registeredAt = new Date().toISOString();
|
|
167
167
|
|
|
168
|
-
// Publish update on-chain (matches
|
|
168
|
+
// Publish update on-chain (matches openclaw-overlay server schema)
|
|
169
169
|
const servicePayload = {
|
|
170
170
|
protocol: PROTOCOL_ID,
|
|
171
171
|
type: 'service' as const,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Overlay transaction building utilities.
|
|
3
3
|
*
|
|
4
|
-
* Follows the
|
|
4
|
+
* Follows the openclaw-overlay server API:
|
|
5
5
|
* - Submit: POST /submit with binary BEEF and X-Topics header
|
|
6
6
|
* - OP_RETURN format: OP_FALSE OP_RETURN <"clawdbot-overlay-v1"> <JSON>
|
|
7
7
|
*/
|
|
@@ -55,7 +55,7 @@ export async function buildRealOverlayTransaction(
|
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
// --- Submit to overlay ---
|
|
58
|
-
// Use binary BEEF with X-Topics header (matches
|
|
58
|
+
// Use binary BEEF with X-Topics header (matches openclaw-overlay server API)
|
|
59
59
|
const submitResp = await fetch(`${OVERLAY_URL}/submit`, {
|
|
60
60
|
method: 'POST',
|
|
61
61
|
headers: {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Unit tests for overlay /submit endpoint compatibility.
|
|
3
3
|
*
|
|
4
4
|
* These tests validate that the client constructs BEEF and payloads
|
|
5
|
-
* in the exact format expected by the
|
|
5
|
+
* in the exact format expected by the openclaw-overlay server's
|
|
6
6
|
* topic managers using PushDrop tokens.
|
|
7
7
|
*
|
|
8
8
|
* Run with: npx tsx src/test/overlay-submit.test.ts
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import { Script, OP, Beef, PushDrop, LockingScript } from '@bsv/sdk';
|
|
12
12
|
|
|
13
|
-
export const PROTOCOL_ID = '
|
|
13
|
+
export const PROTOCOL_ID = 'clawdbot-overlay-v1';
|
|
14
14
|
|
|
15
15
|
// ============================================================================
|
|
16
16
|
// Type Definitions (mirrored from server)
|
package/clawdbot.plugin.json
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "openclaw-overlay-plugin",
|
|
3
|
-
"name": "BSV Overlay Network",
|
|
4
|
-
"description": "OpenClaw Overlay — decentralized agent marketplace with BSV micropayments",
|
|
5
|
-
"version": "0.7.22",
|
|
6
|
-
"skills": [
|
|
7
|
-
"./SKILL.md"
|
|
8
|
-
],
|
|
9
|
-
"configSchema": {
|
|
10
|
-
"type": "object",
|
|
11
|
-
"additionalProperties": false,
|
|
12
|
-
"properties": {
|
|
13
|
-
"overlayUrl": {
|
|
14
|
-
"type": "string",
|
|
15
|
-
"default": "https://clawoverlay.com",
|
|
16
|
-
"description": "Overlay server URL for registration, discovery, and relay"
|
|
17
|
-
},
|
|
18
|
-
"agentName": {
|
|
19
|
-
"type": "string",
|
|
20
|
-
"description": "Display name for this agent on the overlay network (defaults to hostname)"
|
|
21
|
-
},
|
|
22
|
-
"agentDescription": {
|
|
23
|
-
"type": "string",
|
|
24
|
-
"description": "Description of this agent shown to other agents on the network"
|
|
25
|
-
},
|
|
26
|
-
"walletDir": {
|
|
27
|
-
"type": "string",
|
|
28
|
-
"description": "BSV wallet storage directory (defaults to ~/.clawdbot/bsv-wallet)"
|
|
29
|
-
},
|
|
30
|
-
"maxAutoPaySats": {
|
|
31
|
-
"type": "number",
|
|
32
|
-
"default": 200,
|
|
33
|
-
"minimum": 0,
|
|
34
|
-
"description": "Maximum satoshis to auto-pay per service request without confirmation"
|
|
35
|
-
},
|
|
36
|
-
"dailyBudgetSats": {
|
|
37
|
-
"type": "number",
|
|
38
|
-
"default": 5000,
|
|
39
|
-
"minimum": 0,
|
|
40
|
-
"description": "Maximum total satoshis to spend per day across all services"
|
|
41
|
-
},
|
|
42
|
-
"autoAcceptPayments": {
|
|
43
|
-
"type": "boolean",
|
|
44
|
-
"default": true,
|
|
45
|
-
"description": "Automatically accept incoming BSV payments for services"
|
|
46
|
-
},
|
|
47
|
-
"preferCheapest": {
|
|
48
|
-
"type": "boolean",
|
|
49
|
-
"default": true,
|
|
50
|
-
"description": "When multiple providers offer the same service, prefer the cheapest"
|
|
51
|
-
},
|
|
52
|
-
"services": {
|
|
53
|
-
"type": "array",
|
|
54
|
-
"items": {
|
|
55
|
-
"type": "string"
|
|
56
|
-
},
|
|
57
|
-
"description": "List of service IDs to auto-advertise on registration"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
"uiHints": {
|
|
62
|
-
"overlayUrl": {
|
|
63
|
-
"label": "Overlay Server URL",
|
|
64
|
-
"placeholder": "https://clawoverlay.com",
|
|
65
|
-
"advanced": true
|
|
66
|
-
},
|
|
67
|
-
"agentName": {
|
|
68
|
-
"label": "Agent Name",
|
|
69
|
-
"placeholder": "my-agent",
|
|
70
|
-
"help": "Display name shown to other agents on the network"
|
|
71
|
-
},
|
|
72
|
-
"agentDescription": {
|
|
73
|
-
"label": "Agent Description",
|
|
74
|
-
"placeholder": "A helpful AI agent offering various services",
|
|
75
|
-
"help": "Description visible to other agents during discovery"
|
|
76
|
-
},
|
|
77
|
-
"walletDir": {
|
|
78
|
-
"label": "Wallet Directory",
|
|
79
|
-
"placeholder": "~/.clawdbot/bsv-wallet",
|
|
80
|
-
"advanced": true
|
|
81
|
-
},
|
|
82
|
-
"maxAutoPaySats": {
|
|
83
|
-
"label": "Max Auto-Pay (sats)",
|
|
84
|
-
"placeholder": "200",
|
|
85
|
-
"help": "Requests above this amount will ask for confirmation"
|
|
86
|
-
},
|
|
87
|
-
"dailyBudgetSats": {
|
|
88
|
-
"label": "Daily Budget (sats)",
|
|
89
|
-
"placeholder": "5000",
|
|
90
|
-
"help": "Total daily spending limit across all service requests"
|
|
91
|
-
},
|
|
92
|
-
"autoAcceptPayments": {
|
|
93
|
-
"label": "Auto-Accept Payments",
|
|
94
|
-
"help": "Automatically accept incoming payments for your advertised services"
|
|
95
|
-
},
|
|
96
|
-
"preferCheapest": {
|
|
97
|
-
"label": "Prefer Cheapest Provider",
|
|
98
|
-
"advanced": true
|
|
99
|
-
},
|
|
100
|
-
"services": {
|
|
101
|
-
"label": "Auto-Advertise Services",
|
|
102
|
-
"help": "Service IDs to automatically advertise when registering",
|
|
103
|
-
"advanced": true
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|