@moltbankhq/openclaw 0.1.14 → 0.1.15
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/README.md +2 -27
- package/index.ts +12 -199
- package/package.json +3 -9
- package/openclaw.plugin.json +0 -29
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @moltbankhq/openclaw
|
|
2
2
|
|
|
3
|
-
Standalone CLI
|
|
3
|
+
Standalone CLI for [MoltBank](https://moltbank.bot) — stablecoin treasury controls, approvals, and audit trails for agent fleets.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -22,12 +22,6 @@ Or from a local install:
|
|
|
22
22
|
npm exec --package @moltbankhq/openclaw -- moltbank setup
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
OpenClaw plugin mode still exists in this pass for compatibility:
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
openclaw plugins install @moltbankhq/openclaw
|
|
29
|
-
```
|
|
30
|
-
|
|
31
25
|
## What it does
|
|
32
26
|
|
|
33
27
|
This package connects your OpenClaw agent to MoltBank's stablecoin treasury infrastructure. During setup, it:
|
|
@@ -40,7 +34,7 @@ This package connects your OpenClaw agent to MoltBank's stablecoin treasury infr
|
|
|
40
34
|
|
|
41
35
|
Once set up, your agent can manage treasury operations, set per-agent spending limits, handle x402 payments, and interact with MoltBank's MCP server — all within OpenClaw.
|
|
42
36
|
|
|
43
|
-
The standalone `moltbank` CLI is for install, setup, auth status, and repair flows. Actual treasury operations should run through the installed skill wrapper scripts inside the skill directory.
|
|
37
|
+
The standalone `moltbank` CLI is the supported path for install, setup, auth status, and repair flows. Actual treasury operations should run through the installed skill wrapper scripts inside the skill directory.
|
|
44
38
|
|
|
45
39
|
## Setup
|
|
46
40
|
|
|
@@ -73,25 +67,6 @@ CLI flags:
|
|
|
73
67
|
moltbank setup --app-base-url https://app.moltbank.bot --skill-name MoltBank
|
|
74
68
|
```
|
|
75
69
|
|
|
76
|
-
Plugin mode can still read optional config from your `openclaw.json`:
|
|
77
|
-
|
|
78
|
-
Optional config in your `openclaw.json`:
|
|
79
|
-
|
|
80
|
-
```json
|
|
81
|
-
{
|
|
82
|
-
"plugins": {
|
|
83
|
-
"entries": {
|
|
84
|
-
"moltbank": {
|
|
85
|
-
"config": {
|
|
86
|
-
"appBaseUrl": "https://app.moltbank.bot",
|
|
87
|
-
"skillName": "MoltBank"
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
```
|
|
94
|
-
|
|
95
70
|
## Environment Variables
|
|
96
71
|
|
|
97
72
|
| Variable | Description |
|
package/index.ts
CHANGED
|
@@ -7,7 +7,7 @@ const IS_WIN = process.platform === 'win32';
|
|
|
7
7
|
type OpenclawConfig = Record<string, unknown>;
|
|
8
8
|
type ParsedJsonObject = Record<string, unknown>;
|
|
9
9
|
|
|
10
|
-
export interface
|
|
10
|
+
export interface MoltbankConfig {
|
|
11
11
|
skillName?: string;
|
|
12
12
|
appBaseUrl?: string;
|
|
13
13
|
}
|
|
@@ -53,36 +53,6 @@ export interface SetupCommandLoggerOptions {
|
|
|
53
53
|
statusCommand?: string;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
interface ServiceDefinition {
|
|
57
|
-
id: string;
|
|
58
|
-
start: () => void | Promise<void>;
|
|
59
|
-
stop: () => void | Promise<void>;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
interface CliCommandLike {
|
|
63
|
-
command(name: string): CliCommandLike;
|
|
64
|
-
createCommand(name: string): CliCommandLike;
|
|
65
|
-
description(text: string): CliCommandLike;
|
|
66
|
-
addCommand(command: CliCommandLike): CliCommandLike;
|
|
67
|
-
action(handler: () => void | Promise<void>): CliCommandLike;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
interface PluginApiConfig {
|
|
71
|
-
plugins?: {
|
|
72
|
-
entries?: {
|
|
73
|
-
moltbank?: {
|
|
74
|
-
config?: MoltbankPluginConfig;
|
|
75
|
-
};
|
|
76
|
-
};
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
interface PluginApi extends LoggerApi {
|
|
81
|
-
config?: PluginApiConfig;
|
|
82
|
-
registerService(service: ServiceDefinition): void;
|
|
83
|
-
registerCli(handler: (args: { program: CliCommandLike }) => void, options: { commands: string[] }): void;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
56
|
export type AuthWaitMode = 'blocking' | 'nonblocking';
|
|
87
57
|
const oauthPollers = new Map<string, ReturnType<typeof spawn>>();
|
|
88
58
|
const backgroundFinalizers = new Map<string, ReturnType<typeof spawn>>();
|
|
@@ -920,15 +890,15 @@ function getWorkspace(): string {
|
|
|
920
890
|
return process.env.OPENCLAW_WORKSPACE || join(homedir(), '.openclaw', 'workspace');
|
|
921
891
|
}
|
|
922
892
|
|
|
923
|
-
export function getSkillName(cfg:
|
|
893
|
+
export function getSkillName(cfg: MoltbankConfig): string {
|
|
924
894
|
return cfg?.skillName || process.env.MOLTBANK_SKILL_NAME || 'MoltBank';
|
|
925
895
|
}
|
|
926
896
|
|
|
927
|
-
export function getAppBaseUrl(cfg:
|
|
897
|
+
export function getAppBaseUrl(cfg: MoltbankConfig): string {
|
|
928
898
|
return (cfg?.appBaseUrl || process.env.APP_BASE_URL || 'https://app.moltbank.bot').trim();
|
|
929
899
|
}
|
|
930
900
|
|
|
931
|
-
export function getSkillBundleBaseUrl(cfg:
|
|
901
|
+
export function getSkillBundleBaseUrl(cfg: MoltbankConfig): string {
|
|
932
902
|
const base = getAppBaseUrl(cfg).replace(/\/$/, '');
|
|
933
903
|
return base.endsWith('/skill') ? base : `${base}/skill`;
|
|
934
904
|
}
|
|
@@ -944,7 +914,7 @@ function isSandboxEnabled(): boolean {
|
|
|
944
914
|
}
|
|
945
915
|
}
|
|
946
916
|
|
|
947
|
-
export function getSkillDir(cfg:
|
|
917
|
+
export function getSkillDir(cfg: MoltbankConfig): string {
|
|
948
918
|
const skillName = getSkillName(cfg);
|
|
949
919
|
return join(getWorkspace(), 'skills', skillName);
|
|
950
920
|
}
|
|
@@ -1065,47 +1035,6 @@ function setNestedValue(obj: Record<string, unknown>, path: string[], value: unk
|
|
|
1065
1035
|
current[path[path.length - 1]] = value;
|
|
1066
1036
|
}
|
|
1067
1037
|
|
|
1068
|
-
function cleanupStaleMoltbankPluginLoadPaths(api: LoggerApi): boolean {
|
|
1069
|
-
try {
|
|
1070
|
-
const config = readOpenclawConfig();
|
|
1071
|
-
const loadPathsPath = ['plugins', 'load', 'paths'];
|
|
1072
|
-
const current = getNestedValue(config, loadPathsPath);
|
|
1073
|
-
if (!Array.isArray(current)) return false;
|
|
1074
|
-
|
|
1075
|
-
const removed: string[] = [];
|
|
1076
|
-
const next: unknown[] = [];
|
|
1077
|
-
|
|
1078
|
-
for (const entry of current) {
|
|
1079
|
-
if (typeof entry !== 'string') {
|
|
1080
|
-
next.push(entry);
|
|
1081
|
-
continue;
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
const normalized = entry.replace(/\\/g, '/').toLowerCase();
|
|
1085
|
-
const looksLikeMoltbankPath = normalized.includes('moltbank');
|
|
1086
|
-
if (looksLikeMoltbankPath && !existsSync(entry)) {
|
|
1087
|
-
removed.push(entry);
|
|
1088
|
-
continue;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
next.push(entry);
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
if (removed.length === 0) {
|
|
1095
|
-
api.logger.info('[moltbank] ✓ no stale MoltBank plugin load paths found');
|
|
1096
|
-
return false;
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
setNestedValue(config, loadPathsPath, next);
|
|
1100
|
-
writeOpenclawConfig(config);
|
|
1101
|
-
api.logger.info(`[moltbank] ✓ removed stale MoltBank plugin load path(s): ${removed.join(', ')}`);
|
|
1102
|
-
return true;
|
|
1103
|
-
} catch (e) {
|
|
1104
|
-
api.logger.warn('[moltbank] could not clean stale MoltBank plugin load paths: ' + String(e));
|
|
1105
|
-
return false;
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
1038
|
// ─── mcporter ────────────────────────────────────────────────────────────────
|
|
1110
1039
|
|
|
1111
1040
|
function ensureMcporter(api: LoggerApi) {
|
|
@@ -1692,7 +1621,7 @@ function startBackgroundFinalizeAfterAuth(skillDir: string, appBaseUrl: string,
|
|
|
1692
1621
|
}
|
|
1693
1622
|
if (existing) backgroundFinalizers.delete(skillDir);
|
|
1694
1623
|
|
|
1695
|
-
const child = spawn('
|
|
1624
|
+
const child = spawn('moltbank', ['setup-blocking'], {
|
|
1696
1625
|
cwd: skillDir,
|
|
1697
1626
|
env: {
|
|
1698
1627
|
...process.env,
|
|
@@ -1849,7 +1778,7 @@ function ensureMoltbankAuth(skillDir: string, appBaseUrl: string, api: LoggerApi
|
|
|
1849
1778
|
const backgroundTimeoutSeconds = Math.max(30, expiresAt - now - 5);
|
|
1850
1779
|
startBackgroundOauthPoll(skillDir, appBaseUrl, credsPath, deviceCode, backgroundTimeoutSeconds, api);
|
|
1851
1780
|
api.logger.info('[moltbank] once approved in browser, setup finalization will continue automatically');
|
|
1852
|
-
api.logger.info('[moltbank] optional immediate check: `
|
|
1781
|
+
api.logger.info('[moltbank] optional immediate check: `moltbank status`');
|
|
1853
1782
|
return false;
|
|
1854
1783
|
}
|
|
1855
1784
|
|
|
@@ -2249,7 +2178,7 @@ function restartGatewayAfterHostSetup(api: LoggerApi): boolean {
|
|
|
2249
2178
|
// ─── main setup ───────────────────────────────────────────────────────────────
|
|
2250
2179
|
|
|
2251
2180
|
export async function runSetup(
|
|
2252
|
-
cfg:
|
|
2181
|
+
cfg: MoltbankConfig,
|
|
2253
2182
|
api: LoggerApi,
|
|
2254
2183
|
options: { authWaitMode?: AuthWaitMode; restartGatewayOnSuccess?: boolean } = {}
|
|
2255
2184
|
) {
|
|
@@ -2268,9 +2197,6 @@ export async function runSetup(
|
|
|
2268
2197
|
api.logger.info(`[moltbank] skill dir: ${skillDir}`);
|
|
2269
2198
|
api.logger.info(`[moltbank] base url: ${appBaseUrl}`);
|
|
2270
2199
|
api.logger.info(`[moltbank] ══════════════════════════════════════`);
|
|
2271
|
-
api.logger.info('[moltbank] preflight: cleaning stale MoltBank plugin load paths...');
|
|
2272
|
-
cleanupStaleMoltbankPluginLoadPaths(api);
|
|
2273
|
-
|
|
2274
2200
|
if (sandbox) {
|
|
2275
2201
|
api.logger.info('[moltbank] configuring sandbox mode...');
|
|
2276
2202
|
|
|
@@ -2298,10 +2224,10 @@ export async function runSetup(
|
|
|
2298
2224
|
if (pending) {
|
|
2299
2225
|
api.logger.warn('[moltbank] sandbox auth pending — startup continues without blocking channel startup');
|
|
2300
2226
|
api.logger.info('[moltbank] setup will finalize automatically after browser approval');
|
|
2301
|
-
api.logger.info('[moltbank] optional immediate check: `
|
|
2227
|
+
api.logger.info('[moltbank] optional immediate check: `moltbank status`');
|
|
2302
2228
|
} else {
|
|
2303
2229
|
api.logger.warn('[moltbank] sandbox auth setup failed before issuing a valid device code');
|
|
2304
|
-
api.logger.warn('[moltbank] review the previous error and rerun `
|
|
2230
|
+
api.logger.warn('[moltbank] review the previous error and rerun `moltbank setup`');
|
|
2305
2231
|
}
|
|
2306
2232
|
return;
|
|
2307
2233
|
}
|
|
@@ -2357,10 +2283,10 @@ export async function runSetup(
|
|
|
2357
2283
|
if (pending) {
|
|
2358
2284
|
api.logger.warn('[moltbank] host auth pending — startup continues without blocking channel startup');
|
|
2359
2285
|
api.logger.info('[moltbank] setup will finalize automatically after browser approval');
|
|
2360
|
-
api.logger.info('[moltbank] optional immediate check: `
|
|
2286
|
+
api.logger.info('[moltbank] optional immediate check: `moltbank status`');
|
|
2361
2287
|
} else {
|
|
2362
2288
|
api.logger.warn('[moltbank] host auth setup failed before issuing a valid device code');
|
|
2363
|
-
api.logger.warn('[moltbank] review the previous error and rerun `
|
|
2289
|
+
api.logger.warn('[moltbank] review the previous error and rerun `moltbank setup`');
|
|
2364
2290
|
}
|
|
2365
2291
|
return;
|
|
2366
2292
|
}
|
|
@@ -2435,116 +2361,3 @@ export async function runSetup(
|
|
|
2435
2361
|
api.logger.info(`[moltbank] ══════════════════════════════════════`);
|
|
2436
2362
|
}
|
|
2437
2363
|
|
|
2438
|
-
// ─── plugin register ──────────────────────────────────────────────────────────
|
|
2439
|
-
|
|
2440
|
-
export default function register(api: PluginApi) {
|
|
2441
|
-
const cfg: MoltbankPluginConfig = api.config?.plugins?.entries?.moltbank?.config ?? {};
|
|
2442
|
-
|
|
2443
|
-
api.registerService({
|
|
2444
|
-
id: 'moltbank-setup',
|
|
2445
|
-
start: async () => {
|
|
2446
|
-
await runSetup(cfg, api, { authWaitMode: 'nonblocking' });
|
|
2447
|
-
},
|
|
2448
|
-
stop: async () => {
|
|
2449
|
-
stopBackgroundOauthPoll(getSkillDir(cfg));
|
|
2450
|
-
stopBackgroundFinalize(getSkillDir(cfg));
|
|
2451
|
-
api.logger.info('[moltbank] plugin stopped');
|
|
2452
|
-
}
|
|
2453
|
-
});
|
|
2454
|
-
|
|
2455
|
-
api.registerCli(
|
|
2456
|
-
({ program }: { program: CliCommandLike }) => {
|
|
2457
|
-
program
|
|
2458
|
-
.command('moltbank')
|
|
2459
|
-
.description('MoltBank plugin commands')
|
|
2460
|
-
.addCommand(
|
|
2461
|
-
program
|
|
2462
|
-
.createCommand('setup')
|
|
2463
|
-
.description('Re-run MoltBank setup')
|
|
2464
|
-
.action(async () => {
|
|
2465
|
-
const verbose = process.argv.includes('--verbose');
|
|
2466
|
-
const restartGatewayOnSuccess = getSetupGatewayRestartEnabled(IS_WIN);
|
|
2467
|
-
const logger = createSetupCommandLogger({ verbose, statusCommand: 'openclaw moltbank status' });
|
|
2468
|
-
try {
|
|
2469
|
-
await runSetup(cfg, logger, { authWaitMode: 'blocking', restartGatewayOnSuccess });
|
|
2470
|
-
} finally {
|
|
2471
|
-
logger.finish();
|
|
2472
|
-
}
|
|
2473
|
-
})
|
|
2474
|
-
)
|
|
2475
|
-
.addCommand(
|
|
2476
|
-
program
|
|
2477
|
-
.createCommand('setup-blocking')
|
|
2478
|
-
.description('Re-run full MoltBank setup and wait for OAuth approval')
|
|
2479
|
-
.action(async () => {
|
|
2480
|
-
const verbose = process.argv.includes('--verbose');
|
|
2481
|
-
const restartGatewayOnSuccess = getSetupGatewayRestartEnabled(IS_WIN);
|
|
2482
|
-
const logger = createSetupCommandLogger({ verbose, statusCommand: 'openclaw moltbank status' });
|
|
2483
|
-
try {
|
|
2484
|
-
await runSetup(cfg, logger, { authWaitMode: 'blocking', restartGatewayOnSuccess });
|
|
2485
|
-
} finally {
|
|
2486
|
-
logger.finish();
|
|
2487
|
-
}
|
|
2488
|
-
})
|
|
2489
|
-
)
|
|
2490
|
-
.addCommand(
|
|
2491
|
-
program
|
|
2492
|
-
.createCommand('sandbox-setup')
|
|
2493
|
-
.description('Reconfigure sandbox docker in openclaw.json')
|
|
2494
|
-
.action(() => {
|
|
2495
|
-
const changed = configureSandbox({ logger: console });
|
|
2496
|
-
if (changed) {
|
|
2497
|
-
recreateSandboxAndRestart({ logger: console });
|
|
2498
|
-
} else {
|
|
2499
|
-
console.log('[moltbank] No sandbox docker changes — not scheduling teardown');
|
|
2500
|
-
}
|
|
2501
|
-
})
|
|
2502
|
-
)
|
|
2503
|
-
.addCommand(
|
|
2504
|
-
program
|
|
2505
|
-
.createCommand('inject-key')
|
|
2506
|
-
.description('Re-inject sandbox env vars from credentials.json')
|
|
2507
|
-
.action(() => {
|
|
2508
|
-
const skillDir = getSkillDir(cfg);
|
|
2509
|
-
const changed = injectSandboxEnv(skillDir, { logger: console });
|
|
2510
|
-
if (changed) {
|
|
2511
|
-
recreateSandboxAndRestart({ logger: console });
|
|
2512
|
-
} else {
|
|
2513
|
-
console.log('[moltbank] No env changes — not scheduling teardown');
|
|
2514
|
-
}
|
|
2515
|
-
})
|
|
2516
|
-
)
|
|
2517
|
-
.addCommand(
|
|
2518
|
-
program
|
|
2519
|
-
.createCommand('status')
|
|
2520
|
-
.description('Show current MoltBank auth state')
|
|
2521
|
-
.action(() => {
|
|
2522
|
-
const appBaseUrl = getAppBaseUrl(cfg);
|
|
2523
|
-
const skillDir = getSkillDir(cfg);
|
|
2524
|
-
printAuthStatus(skillDir, appBaseUrl, { logger: console });
|
|
2525
|
-
})
|
|
2526
|
-
)
|
|
2527
|
-
.addCommand(
|
|
2528
|
-
program
|
|
2529
|
-
.createCommand('auth-status')
|
|
2530
|
-
.description('Show current MoltBank auth state (credentials, pending code, background poll)')
|
|
2531
|
-
.action(() => {
|
|
2532
|
-
const appBaseUrl = getAppBaseUrl(cfg);
|
|
2533
|
-
const skillDir = getSkillDir(cfg);
|
|
2534
|
-
printAuthStatus(skillDir, appBaseUrl, { logger: console });
|
|
2535
|
-
})
|
|
2536
|
-
)
|
|
2537
|
-
.addCommand(
|
|
2538
|
-
program
|
|
2539
|
-
.createCommand('register')
|
|
2540
|
-
.description('Re-register mcporter server')
|
|
2541
|
-
.action(() => {
|
|
2542
|
-
const appBaseUrl = getAppBaseUrl(cfg);
|
|
2543
|
-
const skillDir = getSkillDir(cfg);
|
|
2544
|
-
ensureMcporterConfig(skillDir, appBaseUrl, { logger: console });
|
|
2545
|
-
})
|
|
2546
|
-
);
|
|
2547
|
-
},
|
|
2548
|
-
{ commands: ['moltbank'] }
|
|
2549
|
-
);
|
|
2550
|
-
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moltbankhq/openclaw",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "MoltBank stablecoin treasury CLI and OpenClaw
|
|
3
|
+
"version": "0.1.15",
|
|
4
|
+
"description": "MoltBank stablecoin treasury CLI and OpenClaw skill installer",
|
|
5
5
|
"homepage": "https://github.com/moltbankhq/openclaw-plugin#readme",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -24,14 +24,8 @@
|
|
|
24
24
|
"README.md",
|
|
25
25
|
"bin/",
|
|
26
26
|
"cli.ts",
|
|
27
|
-
"index.ts"
|
|
28
|
-
"openclaw.plugin.json"
|
|
27
|
+
"index.ts"
|
|
29
28
|
],
|
|
30
|
-
"openclaw": {
|
|
31
|
-
"extensions": [
|
|
32
|
-
"./index.ts"
|
|
33
|
-
]
|
|
34
|
-
},
|
|
35
29
|
"keywords": [
|
|
36
30
|
"moltbank",
|
|
37
31
|
"openclaw",
|
package/openclaw.plugin.json
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "moltbank",
|
|
3
|
-
"name": "MoltBank",
|
|
4
|
-
"description": "MoltBank stablecoin treasury plugin for OpenClaw — installs mcporter, npm dependencies, sandbox setup, and the MoltBank skill",
|
|
5
|
-
"configSchema": {
|
|
6
|
-
"type": "object",
|
|
7
|
-
"additionalProperties": false,
|
|
8
|
-
"properties": {
|
|
9
|
-
"appBaseUrl": {
|
|
10
|
-
"type": "string",
|
|
11
|
-
"description": "MoltBank deployment URL"
|
|
12
|
-
},
|
|
13
|
-
"skillName": {
|
|
14
|
-
"type": "string",
|
|
15
|
-
"description": "Override skill folder name (default: MoltBank)"
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"uiHints": {
|
|
20
|
-
"appBaseUrl": {
|
|
21
|
-
"label": "App Base URL",
|
|
22
|
-
"placeholder": "https://app.moltbank.bot"
|
|
23
|
-
},
|
|
24
|
-
"skillName": {
|
|
25
|
-
"label": "Skill Name",
|
|
26
|
-
"placeholder": "MoltBank"
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|