@moltbankhq/openclaw 0.1.13 → 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 +4 -29
- package/index.ts +50 -291
- package/package.json +37 -8
- 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,25 +22,19 @@ 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:
|
|
34
28
|
|
|
35
|
-
- Downloads and configures the MoltBank skill (`
|
|
29
|
+
- Downloads and configures the MoltBank skill (`SKILL.md` + scripts)
|
|
36
30
|
- Installs and registers [mcporter](https://www.npmjs.com/package/mcporter) for MCP server connectivity
|
|
37
31
|
- Handles OAuth device-code authentication to link your agent to your MoltBank account
|
|
38
32
|
- Configures sandbox (Docker) or host mode automatically based on your OpenClaw setup
|
|
39
|
-
- Injects
|
|
33
|
+
- Injects the sandbox auth path (`MOLTBANK_CREDENTIALS_PATH`) plus `ACTIVE_ORG_OVERRIDE`, while keeping tokens and signer keys in a skill-local credentials file
|
|
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
|
|
|
@@ -1974,6 +1903,42 @@ export function ensureMcporterConfig(skillDir: string, appBaseUrl: string, api:
|
|
|
1974
1903
|
api.logger.info('[moltbank] ✓ MoltBank will use skill-local mcporter config only');
|
|
1975
1904
|
}
|
|
1976
1905
|
|
|
1906
|
+
function runHostReadinessCheck(skillDir: string, api: LoggerApi): boolean {
|
|
1907
|
+
const active = parseActiveTokenFromCredentials();
|
|
1908
|
+
if (!active.ok || !active.activeOrg) {
|
|
1909
|
+
api.logger.warn('[moltbank] host setup incomplete: active organization could not be resolved for readiness verification');
|
|
1910
|
+
return false;
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
const wrapperPath = IS_WIN ? join(skillDir, 'scripts', 'moltbank.ps1') : join(skillDir, 'scripts', 'moltbank.sh');
|
|
1914
|
+
const readinessArgs = ['call', 'MoltBank.get_balance', `organizationName=${active.activeOrg}`, 'date=today'];
|
|
1915
|
+
const readinessTimeoutMs = IS_WIN ? 30000 : 25000;
|
|
1916
|
+
|
|
1917
|
+
api.logger.info(`[moltbank] verifying readiness with authenticated balance read (org: ${active.activeOrg})...`);
|
|
1918
|
+
|
|
1919
|
+
const readiness = runCommand(wrapperPath, readinessArgs, {
|
|
1920
|
+
cwd: skillDir,
|
|
1921
|
+
silent: true,
|
|
1922
|
+
timeoutMs: readinessTimeoutMs,
|
|
1923
|
+
env: {
|
|
1924
|
+
ACTIVE_ORG_OVERRIDE: active.activeOrg
|
|
1925
|
+
}
|
|
1926
|
+
});
|
|
1927
|
+
|
|
1928
|
+
if (!readiness.ok) {
|
|
1929
|
+
const combined = `${readiness.stderr}\n${readiness.stdout}`.trim();
|
|
1930
|
+
const detail = lastNonEmptyLine(combined);
|
|
1931
|
+
if (detail) {
|
|
1932
|
+
api.logger.warn(`[moltbank] readiness detail: ${detail}`);
|
|
1933
|
+
}
|
|
1934
|
+
api.logger.warn('[moltbank] host setup incomplete: authenticated balance-read verification failed');
|
|
1935
|
+
return false;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
api.logger.info('[moltbank] host readiness verified (`MoltBank.get_balance`)');
|
|
1939
|
+
return true;
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1977
1942
|
// ─── sandbox env vars ────────────────────────────────────────────────────────
|
|
1978
1943
|
|
|
1979
1944
|
export function injectSandboxEnv(skillDir: string, api: LoggerApi): boolean {
|
|
@@ -2213,7 +2178,7 @@ function restartGatewayAfterHostSetup(api: LoggerApi): boolean {
|
|
|
2213
2178
|
// ─── main setup ───────────────────────────────────────────────────────────────
|
|
2214
2179
|
|
|
2215
2180
|
export async function runSetup(
|
|
2216
|
-
cfg:
|
|
2181
|
+
cfg: MoltbankConfig,
|
|
2217
2182
|
api: LoggerApi,
|
|
2218
2183
|
options: { authWaitMode?: AuthWaitMode; restartGatewayOnSuccess?: boolean } = {}
|
|
2219
2184
|
) {
|
|
@@ -2232,9 +2197,6 @@ export async function runSetup(
|
|
|
2232
2197
|
api.logger.info(`[moltbank] skill dir: ${skillDir}`);
|
|
2233
2198
|
api.logger.info(`[moltbank] base url: ${appBaseUrl}`);
|
|
2234
2199
|
api.logger.info(`[moltbank] ══════════════════════════════════════`);
|
|
2235
|
-
api.logger.info('[moltbank] preflight: cleaning stale MoltBank plugin load paths...');
|
|
2236
|
-
cleanupStaleMoltbankPluginLoadPaths(api);
|
|
2237
|
-
|
|
2238
2200
|
if (sandbox) {
|
|
2239
2201
|
api.logger.info('[moltbank] configuring sandbox mode...');
|
|
2240
2202
|
|
|
@@ -2262,10 +2224,10 @@ export async function runSetup(
|
|
|
2262
2224
|
if (pending) {
|
|
2263
2225
|
api.logger.warn('[moltbank] sandbox auth pending — startup continues without blocking channel startup');
|
|
2264
2226
|
api.logger.info('[moltbank] setup will finalize automatically after browser approval');
|
|
2265
|
-
api.logger.info('[moltbank] optional immediate check: `
|
|
2227
|
+
api.logger.info('[moltbank] optional immediate check: `moltbank status`');
|
|
2266
2228
|
} else {
|
|
2267
2229
|
api.logger.warn('[moltbank] sandbox auth setup failed before issuing a valid device code');
|
|
2268
|
-
api.logger.warn('[moltbank] review the previous error and rerun `
|
|
2230
|
+
api.logger.warn('[moltbank] review the previous error and rerun `moltbank setup`');
|
|
2269
2231
|
}
|
|
2270
2232
|
return;
|
|
2271
2233
|
}
|
|
@@ -2321,10 +2283,10 @@ export async function runSetup(
|
|
|
2321
2283
|
if (pending) {
|
|
2322
2284
|
api.logger.warn('[moltbank] host auth pending — startup continues without blocking channel startup');
|
|
2323
2285
|
api.logger.info('[moltbank] setup will finalize automatically after browser approval');
|
|
2324
|
-
api.logger.info('[moltbank] optional immediate check: `
|
|
2286
|
+
api.logger.info('[moltbank] optional immediate check: `moltbank status`');
|
|
2325
2287
|
} else {
|
|
2326
2288
|
api.logger.warn('[moltbank] host auth setup failed before issuing a valid device code');
|
|
2327
|
-
api.logger.warn('[moltbank] review the previous error and rerun `
|
|
2289
|
+
api.logger.warn('[moltbank] review the previous error and rerun `moltbank setup`');
|
|
2328
2290
|
}
|
|
2329
2291
|
return;
|
|
2330
2292
|
}
|
|
@@ -2338,98 +2300,8 @@ export async function runSetup(
|
|
|
2338
2300
|
api.logger.info('[moltbank] [host 7/8] writing/registering mcporter config...');
|
|
2339
2301
|
ensureMcporterConfig(skillDir, appBaseUrl, api);
|
|
2340
2302
|
|
|
2341
|
-
api.logger.info('[moltbank] [host 8/8] running
|
|
2342
|
-
|
|
2343
|
-
let smokeOk = false;
|
|
2344
|
-
|
|
2345
|
-
if (IS_WIN) {
|
|
2346
|
-
const mcporterConfigPath = join(skillDir, 'assets', 'mcporter.json');
|
|
2347
|
-
const active = parseActiveTokenFromCredentials();
|
|
2348
|
-
const mcpSmoke = runCommand('mcporter', ['--config', mcporterConfigPath, 'list', 'MoltBank'], {
|
|
2349
|
-
cwd: skillDir,
|
|
2350
|
-
silent: true,
|
|
2351
|
-
timeoutMs: smokeTimeoutMs,
|
|
2352
|
-
env: {
|
|
2353
|
-
MOLTBANK: active.token ?? '__MOLTBANK_PLACEHOLDER__'
|
|
2354
|
-
}
|
|
2355
|
-
});
|
|
2356
|
-
|
|
2357
|
-
if (mcpSmoke.ok) {
|
|
2358
|
-
api.logger.info('[moltbank] host smoke test passed (`mcporter list MoltBank`)');
|
|
2359
|
-
smokeOk = true;
|
|
2360
|
-
} else {
|
|
2361
|
-
const mcpCombined = `${mcpSmoke.stderr}\n${mcpSmoke.stdout}`.trim();
|
|
2362
|
-
const mcpCombinedLower = mcpCombined.toLowerCase();
|
|
2363
|
-
const mcpDetail = lastNonEmptyLine(mcpCombined);
|
|
2364
|
-
if (mcpDetail) {
|
|
2365
|
-
api.logger.warn(`[moltbank] smoke detail: ${mcpDetail}`);
|
|
2366
|
-
}
|
|
2367
|
-
|
|
2368
|
-
const timedOut = mcpSmoke.stderr.includes('ETIMEDOUT') || mcpCombinedLower.includes('timed out');
|
|
2369
|
-
if (timedOut) {
|
|
2370
|
-
api.logger.warn(
|
|
2371
|
-
`[moltbank] host MCP smoke timed out after ${Math.floor(smokeTimeoutMs / 1000)}s; running local fallback checks`
|
|
2372
|
-
);
|
|
2373
|
-
|
|
2374
|
-
const ps1Path = join(skillDir, 'scripts', 'moltbank.ps1');
|
|
2375
|
-
const fallback = runCommand(
|
|
2376
|
-
'powershell',
|
|
2377
|
-
[
|
|
2378
|
-
'-NoProfile',
|
|
2379
|
-
'-NonInteractive',
|
|
2380
|
-
'-ExecutionPolicy',
|
|
2381
|
-
'Bypass',
|
|
2382
|
-
'-Command',
|
|
2383
|
-
"$ErrorActionPreference = 'Stop'; if (-not (Test-Path -LiteralPath $env:MOLTBANK_WRAPPER_PATH)) { throw 'moltbank.ps1 not found' }; if (-not (Get-Command bash -ErrorAction SilentlyContinue)) { throw 'bash is not installed or not on PATH' }; if (-not (Get-Command mcporter -ErrorAction SilentlyContinue)) { throw 'mcporter is not installed or not on PATH' }; Write-Output 'ok'"
|
|
2384
|
-
],
|
|
2385
|
-
{
|
|
2386
|
-
cwd: skillDir,
|
|
2387
|
-
silent: true,
|
|
2388
|
-
timeoutMs: 10000,
|
|
2389
|
-
env: { MOLTBANK_WRAPPER_PATH: ps1Path }
|
|
2390
|
-
}
|
|
2391
|
-
);
|
|
2392
|
-
|
|
2393
|
-
if (fallback.ok) {
|
|
2394
|
-
api.logger.warn('[moltbank] host smoke fallback passed (wrapper prerequisites available), but MCP endpoint was not verified');
|
|
2395
|
-
smokeOk = true;
|
|
2396
|
-
} else {
|
|
2397
|
-
const fallbackCombined = `${fallback.stderr}\n${fallback.stdout}`.trim();
|
|
2398
|
-
const fallbackDetail = lastNonEmptyLine(fallbackCombined);
|
|
2399
|
-
if (fallbackDetail) {
|
|
2400
|
-
api.logger.warn(`[moltbank] fallback detail: ${fallbackDetail}`);
|
|
2401
|
-
}
|
|
2402
|
-
api.logger.warn('[moltbank] host setup incomplete: MCP smoke timed out and fallback checks failed');
|
|
2403
|
-
}
|
|
2404
|
-
} else if (
|
|
2405
|
-
mcpCombinedLower.includes('mcporter') &&
|
|
2406
|
-
(mcpCombinedLower.includes('not recognized') || mcpCombinedLower.includes('not found'))
|
|
2407
|
-
) {
|
|
2408
|
-
api.logger.warn('[moltbank] mcporter binary not found in PATH during smoke test');
|
|
2409
|
-
} else {
|
|
2410
|
-
api.logger.warn('[moltbank] host setup incomplete: smoke test failed (`mcporter list MoltBank`)');
|
|
2411
|
-
}
|
|
2412
|
-
}
|
|
2413
|
-
} else {
|
|
2414
|
-
const smoke = runCommand(join(skillDir, 'scripts', 'moltbank.sh'), ['list', 'MoltBank'], {
|
|
2415
|
-
cwd: skillDir,
|
|
2416
|
-
silent: true,
|
|
2417
|
-
timeoutMs: smokeTimeoutMs
|
|
2418
|
-
});
|
|
2419
|
-
if (!smoke.ok) {
|
|
2420
|
-
const smokeCombined = `${smoke.stderr}\n${smoke.stdout}`.trim();
|
|
2421
|
-
const smokeDetail = lastNonEmptyLine(smokeCombined);
|
|
2422
|
-
if (smokeDetail) {
|
|
2423
|
-
api.logger.warn(`[moltbank] smoke detail: ${smokeDetail}`);
|
|
2424
|
-
}
|
|
2425
|
-
api.logger.warn('[moltbank] host setup incomplete: smoke test failed (`moltbank list MoltBank` via platform script)');
|
|
2426
|
-
} else {
|
|
2427
|
-
api.logger.info('[moltbank] host smoke test passed (`moltbank list MoltBank`)');
|
|
2428
|
-
smokeOk = true;
|
|
2429
|
-
}
|
|
2430
|
-
}
|
|
2431
|
-
|
|
2432
|
-
hostReady = smokeOk;
|
|
2303
|
+
api.logger.info('[moltbank] [host 8/8] running readiness balance check...');
|
|
2304
|
+
hostReady = runHostReadinessCheck(skillDir, api);
|
|
2433
2305
|
|
|
2434
2306
|
api.logger.info('[moltbank] host mode — setup completed with onboarding flow');
|
|
2435
2307
|
|
|
@@ -2489,116 +2361,3 @@ export async function runSetup(
|
|
|
2489
2361
|
api.logger.info(`[moltbank] ══════════════════════════════════════`);
|
|
2490
2362
|
}
|
|
2491
2363
|
|
|
2492
|
-
// ─── plugin register ──────────────────────────────────────────────────────────
|
|
2493
|
-
|
|
2494
|
-
export default function register(api: PluginApi) {
|
|
2495
|
-
const cfg: MoltbankPluginConfig = api.config?.plugins?.entries?.moltbank?.config ?? {};
|
|
2496
|
-
|
|
2497
|
-
api.registerService({
|
|
2498
|
-
id: 'moltbank-setup',
|
|
2499
|
-
start: async () => {
|
|
2500
|
-
await runSetup(cfg, api, { authWaitMode: 'nonblocking' });
|
|
2501
|
-
},
|
|
2502
|
-
stop: async () => {
|
|
2503
|
-
stopBackgroundOauthPoll(getSkillDir(cfg));
|
|
2504
|
-
stopBackgroundFinalize(getSkillDir(cfg));
|
|
2505
|
-
api.logger.info('[moltbank] plugin stopped');
|
|
2506
|
-
}
|
|
2507
|
-
});
|
|
2508
|
-
|
|
2509
|
-
api.registerCli(
|
|
2510
|
-
({ program }: { program: CliCommandLike }) => {
|
|
2511
|
-
program
|
|
2512
|
-
.command('moltbank')
|
|
2513
|
-
.description('MoltBank plugin commands')
|
|
2514
|
-
.addCommand(
|
|
2515
|
-
program
|
|
2516
|
-
.createCommand('setup')
|
|
2517
|
-
.description('Re-run MoltBank setup')
|
|
2518
|
-
.action(async () => {
|
|
2519
|
-
const verbose = process.argv.includes('--verbose');
|
|
2520
|
-
const restartGatewayOnSuccess = getSetupGatewayRestartEnabled(IS_WIN);
|
|
2521
|
-
const logger = createSetupCommandLogger({ verbose, statusCommand: 'openclaw moltbank status' });
|
|
2522
|
-
try {
|
|
2523
|
-
await runSetup(cfg, logger, { authWaitMode: 'blocking', restartGatewayOnSuccess });
|
|
2524
|
-
} finally {
|
|
2525
|
-
logger.finish();
|
|
2526
|
-
}
|
|
2527
|
-
})
|
|
2528
|
-
)
|
|
2529
|
-
.addCommand(
|
|
2530
|
-
program
|
|
2531
|
-
.createCommand('setup-blocking')
|
|
2532
|
-
.description('Re-run full MoltBank setup and wait for OAuth approval')
|
|
2533
|
-
.action(async () => {
|
|
2534
|
-
const verbose = process.argv.includes('--verbose');
|
|
2535
|
-
const restartGatewayOnSuccess = getSetupGatewayRestartEnabled(IS_WIN);
|
|
2536
|
-
const logger = createSetupCommandLogger({ verbose, statusCommand: 'openclaw moltbank status' });
|
|
2537
|
-
try {
|
|
2538
|
-
await runSetup(cfg, logger, { authWaitMode: 'blocking', restartGatewayOnSuccess });
|
|
2539
|
-
} finally {
|
|
2540
|
-
logger.finish();
|
|
2541
|
-
}
|
|
2542
|
-
})
|
|
2543
|
-
)
|
|
2544
|
-
.addCommand(
|
|
2545
|
-
program
|
|
2546
|
-
.createCommand('sandbox-setup')
|
|
2547
|
-
.description('Reconfigure sandbox docker in openclaw.json')
|
|
2548
|
-
.action(() => {
|
|
2549
|
-
const changed = configureSandbox({ logger: console });
|
|
2550
|
-
if (changed) {
|
|
2551
|
-
recreateSandboxAndRestart({ logger: console });
|
|
2552
|
-
} else {
|
|
2553
|
-
console.log('[moltbank] No sandbox docker changes — not scheduling teardown');
|
|
2554
|
-
}
|
|
2555
|
-
})
|
|
2556
|
-
)
|
|
2557
|
-
.addCommand(
|
|
2558
|
-
program
|
|
2559
|
-
.createCommand('inject-key')
|
|
2560
|
-
.description('Re-inject sandbox env vars from credentials.json')
|
|
2561
|
-
.action(() => {
|
|
2562
|
-
const skillDir = getSkillDir(cfg);
|
|
2563
|
-
const changed = injectSandboxEnv(skillDir, { logger: console });
|
|
2564
|
-
if (changed) {
|
|
2565
|
-
recreateSandboxAndRestart({ logger: console });
|
|
2566
|
-
} else {
|
|
2567
|
-
console.log('[moltbank] No env changes — not scheduling teardown');
|
|
2568
|
-
}
|
|
2569
|
-
})
|
|
2570
|
-
)
|
|
2571
|
-
.addCommand(
|
|
2572
|
-
program
|
|
2573
|
-
.createCommand('status')
|
|
2574
|
-
.description('Show current MoltBank auth state')
|
|
2575
|
-
.action(() => {
|
|
2576
|
-
const appBaseUrl = getAppBaseUrl(cfg);
|
|
2577
|
-
const skillDir = getSkillDir(cfg);
|
|
2578
|
-
printAuthStatus(skillDir, appBaseUrl, { logger: console });
|
|
2579
|
-
})
|
|
2580
|
-
)
|
|
2581
|
-
.addCommand(
|
|
2582
|
-
program
|
|
2583
|
-
.createCommand('auth-status')
|
|
2584
|
-
.description('Show current MoltBank auth state (credentials, pending code, background poll)')
|
|
2585
|
-
.action(() => {
|
|
2586
|
-
const appBaseUrl = getAppBaseUrl(cfg);
|
|
2587
|
-
const skillDir = getSkillDir(cfg);
|
|
2588
|
-
printAuthStatus(skillDir, appBaseUrl, { logger: console });
|
|
2589
|
-
})
|
|
2590
|
-
)
|
|
2591
|
-
.addCommand(
|
|
2592
|
-
program
|
|
2593
|
-
.createCommand('register')
|
|
2594
|
-
.description('Re-register mcporter server')
|
|
2595
|
-
.action(() => {
|
|
2596
|
-
const appBaseUrl = getAppBaseUrl(cfg);
|
|
2597
|
-
const skillDir = getSkillDir(cfg);
|
|
2598
|
-
ensureMcporterConfig(skillDir, appBaseUrl, { logger: console });
|
|
2599
|
-
})
|
|
2600
|
-
);
|
|
2601
|
-
},
|
|
2602
|
-
{ commands: ['moltbank'] }
|
|
2603
|
-
);
|
|
2604
|
-
}
|
package/package.json
CHANGED
|
@@ -1,20 +1,49 @@
|
|
|
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
|
+
"homepage": "https://github.com/moltbankhq/openclaw-plugin#readme",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/moltbankhq/openclaw-plugin.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/moltbankhq/openclaw-plugin/issues"
|
|
12
|
+
},
|
|
5
13
|
"main": "index.ts",
|
|
14
|
+
"types": "index.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": "./index.ts",
|
|
17
|
+
"./cli": "./cli.ts",
|
|
18
|
+
"./package.json": "./package.json"
|
|
19
|
+
},
|
|
6
20
|
"bin": {
|
|
7
21
|
"moltbank": "./bin/moltbank.mjs"
|
|
8
22
|
},
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
23
|
+
"files": [
|
|
24
|
+
"README.md",
|
|
25
|
+
"bin/",
|
|
26
|
+
"cli.ts",
|
|
27
|
+
"index.ts"
|
|
28
|
+
],
|
|
29
|
+
"keywords": [
|
|
30
|
+
"moltbank",
|
|
31
|
+
"openclaw",
|
|
32
|
+
"treasury",
|
|
33
|
+
"mcp",
|
|
34
|
+
"cli",
|
|
35
|
+
"stablecoin",
|
|
36
|
+
"x402"
|
|
37
|
+
],
|
|
15
38
|
"author": "",
|
|
16
39
|
"license": "ISC",
|
|
17
40
|
"type": "module",
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=22"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
18
47
|
"dependencies": {
|
|
19
48
|
"tsx": "^4.20.6"
|
|
20
49
|
},
|
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
|
-
}
|