@wiimdy/openfunderse 1.1.4 → 1.1.6
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/.env.participant.example +1 -1
- package/.env.strategy.example +1 -1
- package/README.md +3 -0
- package/bin/openfunderse.mjs +131 -5
- package/package.json +1 -1
- package/packs/openfunderse-participant/openfunderse-participant/SKILL.md +5 -0
- package/packs/openfunderse-strategy/openfunderse-strategy/SKILL.md +5 -1
package/.env.participant.example
CHANGED
|
@@ -9,7 +9,7 @@ CHAIN_ID=10143
|
|
|
9
9
|
CLAIM_ATTESTATION_VERIFIER_ADDRESS=0x76AB8571cED9F4A81b733969216F53C1e13BC835
|
|
10
10
|
# Temporary bootstrap key (public and unsafe). Replace via bot-init before real usage.
|
|
11
11
|
PARTICIPANT_PRIVATE_KEY=__TEMP_PRIVATE_KEY__
|
|
12
|
-
PARTICIPANT_ADDRESS=
|
|
12
|
+
PARTICIPANT_ADDRESS=0x0000000000000000000000000000000000000000
|
|
13
13
|
|
|
14
14
|
PARTICIPANT_REQUIRE_EXPLICIT_SUBMIT=true
|
|
15
15
|
PARTICIPANT_AUTO_SUBMIT=false
|
package/.env.strategy.example
CHANGED
|
@@ -20,7 +20,7 @@ NADFUN_WMON_ADDRESS=0xFb8bE43D65FBC1290D6178C6DbA6E58c6D18fA60
|
|
|
20
20
|
# Strategy signer (EOA)
|
|
21
21
|
# Temporary bootstrap key (public and unsafe). Replace via bot-init before real usage.
|
|
22
22
|
STRATEGY_PRIVATE_KEY=__TEMP_PRIVATE_KEY__
|
|
23
|
-
STRATEGY_ADDRESS=
|
|
23
|
+
STRATEGY_ADDRESS=0x0000000000000000000000000000000000000000
|
|
24
24
|
|
|
25
25
|
# STRATEGY_CREATE_MIN_SIGNER_BALANCE_WEI=10000000000000000
|
|
26
26
|
|
package/README.md
CHANGED
|
@@ -22,6 +22,9 @@ set -a; source .env.strategy; set +a
|
|
|
22
22
|
set -a; source .env.participant; set +a
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
By default, `install` and `bot-init` also sync env keys into OpenClaw config (`~/.openclaw/openclaw.json > env.vars`).
|
|
26
|
+
Disable this with `--no-sync-openclaw-env`.
|
|
27
|
+
|
|
25
28
|
## Where Files Are Stored
|
|
26
29
|
|
|
27
30
|
- In OpenClaw, skills are installed under `~/.openclaw/workspace/skills`.
|
package/bin/openfunderse.mjs
CHANGED
|
@@ -26,7 +26,6 @@ const STRATEGY_ENV_TEMPLATE = `# OpenFunderse strategy env scaffold
|
|
|
26
26
|
RELAYER_URL=https://your-relayer.example.com
|
|
27
27
|
BOT_ID=bot-strategy-1
|
|
28
28
|
BOT_API_KEY=replace_me
|
|
29
|
-
BOT_ADDRESS=0x0000000000000000000000000000000000000000
|
|
30
29
|
CHAIN_ID=10143
|
|
31
30
|
RPC_URL=https://testnet-rpc.monad.xyz
|
|
32
31
|
|
|
@@ -42,6 +41,7 @@ NADFUN_WMON_ADDRESS=0x0000000000000000000000000000000000000000
|
|
|
42
41
|
# Strategy signer (EOA)
|
|
43
42
|
# Temporary bootstrap key (public and unsafe). Replace via bot-init before real usage.
|
|
44
43
|
STRATEGY_PRIVATE_KEY=${TEMP_PRIVATE_KEY}
|
|
44
|
+
STRATEGY_ADDRESS=0x0000000000000000000000000000000000000000
|
|
45
45
|
# STRATEGY_CREATE_MIN_SIGNER_BALANCE_WEI=10000000000000000
|
|
46
46
|
|
|
47
47
|
# Safety defaults
|
|
@@ -55,10 +55,10 @@ const PARTICIPANT_ENV_TEMPLATE = `# OpenFunderse participant env scaffold
|
|
|
55
55
|
RELAYER_URL=https://your-relayer.example.com
|
|
56
56
|
BOT_ID=bot-participant-1
|
|
57
57
|
BOT_API_KEY=replace_me
|
|
58
|
-
BOT_ADDRESS=0x0000000000000000000000000000000000000000
|
|
59
58
|
CHAIN_ID=10143
|
|
60
59
|
# Temporary bootstrap key (public and unsafe). Replace via bot-init before real usage.
|
|
61
60
|
PARTICIPANT_PRIVATE_KEY=${TEMP_PRIVATE_KEY}
|
|
61
|
+
PARTICIPANT_ADDRESS=0x0000000000000000000000000000000000000000
|
|
62
62
|
PARTICIPANT_REQUIRE_EXPLICIT_SUBMIT=true
|
|
63
63
|
PARTICIPANT_AUTO_SUBMIT=false
|
|
64
64
|
# PARTICIPANT_TRUSTED_RELAYER_HOSTS=openfunderse-relayer.example.com
|
|
@@ -71,8 +71,10 @@ function printUsage() {
|
|
|
71
71
|
Usage:
|
|
72
72
|
openfunderse list
|
|
73
73
|
openfunderse bot-init [--role <strategy|participant>] [--skill-name <name>] [--env-path <path>] [--wallet-dir <dir>] [--wallet-name <name>] [--force] [--yes]
|
|
74
|
+
[--no-sync-openclaw-env]
|
|
74
75
|
openfunderse install <pack-name> [--dest <skills-dir>] [--codex-home <dir>] [--force] [--with-runtime]
|
|
75
76
|
[--no-init-env] [--env-path <path>] [--env-profile <strategy|participant|all>]
|
|
77
|
+
[--no-sync-openclaw-env]
|
|
76
78
|
[--runtime-package <name>] [--runtime-dir <dir>] [--runtime-manager <npm|pnpm|yarn|bun>]
|
|
77
79
|
|
|
78
80
|
Examples:
|
|
@@ -105,6 +107,7 @@ function parseArgs(argv) {
|
|
|
105
107
|
skillName: "",
|
|
106
108
|
walletDir: "",
|
|
107
109
|
walletName: "",
|
|
110
|
+
syncOpenclawEnv: true,
|
|
108
111
|
yes: false
|
|
109
112
|
};
|
|
110
113
|
const positionals = [];
|
|
@@ -137,6 +140,14 @@ function parseArgs(argv) {
|
|
|
137
140
|
options.withRuntime = true;
|
|
138
141
|
continue;
|
|
139
142
|
}
|
|
143
|
+
if (token === "--sync-openclaw-env") {
|
|
144
|
+
options.syncOpenclawEnv = true;
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (token === "--no-sync-openclaw-env") {
|
|
148
|
+
options.syncOpenclawEnv = false;
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
140
151
|
if (token === "--init-env") {
|
|
141
152
|
options.initEnv = true;
|
|
142
153
|
options.initEnvExplicit = true;
|
|
@@ -317,6 +328,11 @@ function runtimeEnvExamplePath(runtimeDir, runtimePackage) {
|
|
|
317
328
|
return path.join(runtimeDir, "node_modules", ...runtimePackage.split("/"), ".env.example");
|
|
318
329
|
}
|
|
319
330
|
|
|
331
|
+
function openclawConfigPath(codexHome) {
|
|
332
|
+
const resolvedCodexHome = path.resolve(codexHome);
|
|
333
|
+
return path.join(path.dirname(resolvedCodexHome), "openclaw.json");
|
|
334
|
+
}
|
|
335
|
+
|
|
320
336
|
function defaultEnvFileNameForProfile(profile) {
|
|
321
337
|
if (profile === "strategy") {
|
|
322
338
|
return ".env.strategy";
|
|
@@ -411,6 +427,86 @@ function readAssignedEnvValue(content, key) {
|
|
|
411
427
|
return "";
|
|
412
428
|
}
|
|
413
429
|
|
|
430
|
+
function parseEnvAssignments(content) {
|
|
431
|
+
const result = {};
|
|
432
|
+
const lines = String(content || "").replace(/^\uFEFF/, "").split(/\r?\n/);
|
|
433
|
+
for (const rawLine of lines) {
|
|
434
|
+
const line = rawLine.trim();
|
|
435
|
+
if (!line || line.startsWith("#")) continue;
|
|
436
|
+
const match = line.match(/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
|
|
437
|
+
if (!match) continue;
|
|
438
|
+
const key = match[1];
|
|
439
|
+
let value = (match[2] || "").trim();
|
|
440
|
+
if (
|
|
441
|
+
((value.startsWith("\"") && value.endsWith("\"")) ||
|
|
442
|
+
(value.startsWith("'") && value.endsWith("'"))) &&
|
|
443
|
+
value.length >= 2
|
|
444
|
+
) {
|
|
445
|
+
value = value.slice(1, -1);
|
|
446
|
+
}
|
|
447
|
+
result[key] = value;
|
|
448
|
+
}
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
async function syncOpenclawEnvVarsFromFile(envFile, codexHome) {
|
|
453
|
+
const configPath = openclawConfigPath(codexHome);
|
|
454
|
+
if (!existsSync(configPath)) {
|
|
455
|
+
return {
|
|
456
|
+
synced: false,
|
|
457
|
+
reason: "openclaw-config-not-found",
|
|
458
|
+
configPath,
|
|
459
|
+
envFile,
|
|
460
|
+
writtenKeys: []
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const envContent = await readFile(envFile, "utf8");
|
|
465
|
+
const assignments = parseEnvAssignments(envContent);
|
|
466
|
+
const keys = Object.keys(assignments);
|
|
467
|
+
if (keys.length === 0) {
|
|
468
|
+
return {
|
|
469
|
+
synced: false,
|
|
470
|
+
reason: "empty-env-file",
|
|
471
|
+
configPath,
|
|
472
|
+
envFile,
|
|
473
|
+
writtenKeys: []
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const rawConfig = await readFile(configPath, "utf8");
|
|
478
|
+
const parsedConfig = JSON.parse(rawConfig);
|
|
479
|
+
if (!parsedConfig || typeof parsedConfig !== "object" || Array.isArray(parsedConfig)) {
|
|
480
|
+
throw new Error(`invalid openclaw config json object: ${configPath}`);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const nextConfig = { ...parsedConfig };
|
|
484
|
+
const envSection =
|
|
485
|
+
nextConfig.env && typeof nextConfig.env === "object" && !Array.isArray(nextConfig.env)
|
|
486
|
+
? { ...nextConfig.env }
|
|
487
|
+
: {};
|
|
488
|
+
const varsSection =
|
|
489
|
+
envSection.vars && typeof envSection.vars === "object" && !Array.isArray(envSection.vars)
|
|
490
|
+
? { ...envSection.vars }
|
|
491
|
+
: {};
|
|
492
|
+
|
|
493
|
+
for (const [key, value] of Object.entries(assignments)) {
|
|
494
|
+
varsSection[key] = value;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
envSection.vars = varsSection;
|
|
498
|
+
nextConfig.env = envSection;
|
|
499
|
+
await writeFile(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`);
|
|
500
|
+
|
|
501
|
+
return {
|
|
502
|
+
synced: true,
|
|
503
|
+
reason: "ok",
|
|
504
|
+
configPath,
|
|
505
|
+
envFile,
|
|
506
|
+
writtenKeys: keys
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
414
510
|
function isPlaceholderEnvValue(value) {
|
|
415
511
|
const normalized = (value || "").trim();
|
|
416
512
|
if (!normalized) return true;
|
|
@@ -493,14 +589,13 @@ function roleEnvUpdates(role, wallet) {
|
|
|
493
589
|
return {
|
|
494
590
|
CHAIN_ID: DEFAULT_MONAD_CHAIN_ID,
|
|
495
591
|
STRATEGY_PRIVATE_KEY: wallet.privateKey,
|
|
496
|
-
|
|
592
|
+
STRATEGY_ADDRESS: wallet.address
|
|
497
593
|
};
|
|
498
594
|
}
|
|
499
595
|
return {
|
|
500
596
|
CHAIN_ID: DEFAULT_MONAD_CHAIN_ID,
|
|
501
597
|
PARTICIPANT_PRIVATE_KEY: wallet.privateKey,
|
|
502
|
-
|
|
503
|
-
BOT_ADDRESS: wallet.address
|
|
598
|
+
PARTICIPANT_ADDRESS: wallet.address
|
|
504
599
|
};
|
|
505
600
|
}
|
|
506
601
|
|
|
@@ -596,11 +691,27 @@ async function runBotInit(options) {
|
|
|
596
691
|
await mkdir(path.dirname(envFile), { recursive: true });
|
|
597
692
|
await writeFile(envFile, nextEnvContent);
|
|
598
693
|
await chmod(envFile, 0o600);
|
|
694
|
+
let syncMeta = null;
|
|
695
|
+
if (options.syncOpenclawEnv) {
|
|
696
|
+
const codexHome = options.codexHome ? path.resolve(options.codexHome) : defaultCodexHome();
|
|
697
|
+
syncMeta = await syncOpenclawEnvVarsFromFile(envFile, codexHome);
|
|
698
|
+
}
|
|
599
699
|
const sourceCommand = `set -a; source ${shellQuote(envFile)}; set +a`;
|
|
600
700
|
|
|
601
701
|
console.log(`Initialized ${role} bot wallet for Monad testnet (${DEFAULT_MONAD_CHAIN_ID}).`);
|
|
602
702
|
console.log(`Address: ${wallet.address}`);
|
|
603
703
|
console.log(`Env file updated: ${envFile}`);
|
|
704
|
+
if (syncMeta) {
|
|
705
|
+
if (syncMeta.synced) {
|
|
706
|
+
console.log(
|
|
707
|
+
`Synced env vars to OpenClaw config: ${syncMeta.configPath} (${syncMeta.writtenKeys.length} keys)`
|
|
708
|
+
);
|
|
709
|
+
} else {
|
|
710
|
+
console.log(
|
|
711
|
+
`Skipped OpenClaw env sync (${syncMeta.reason}): ${syncMeta.configPath}`
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
604
715
|
console.log(`Wallet backup (keep secret): ${walletFiles.walletPath}`);
|
|
605
716
|
console.log(`Private key backup (keep secret): ${walletFiles.privateKeyPath}`);
|
|
606
717
|
console.log(`Load env now: ${sourceCommand}`);
|
|
@@ -776,6 +887,10 @@ async function installPack(packName, options) {
|
|
|
776
887
|
};
|
|
777
888
|
envScaffoldMeta = await writeEnvScaffold(envOptions);
|
|
778
889
|
}
|
|
890
|
+
let openclawSyncMeta = null;
|
|
891
|
+
if (envScaffoldMeta && options.syncOpenclawEnv) {
|
|
892
|
+
openclawSyncMeta = await syncOpenclawEnvVarsFromFile(envScaffoldMeta.envFile, codexHome);
|
|
893
|
+
}
|
|
779
894
|
|
|
780
895
|
console.log(`Installed pack: ${packName}`);
|
|
781
896
|
console.log(`Skills root: ${skillsRoot}`);
|
|
@@ -796,6 +911,17 @@ async function installPack(packName, options) {
|
|
|
796
911
|
);
|
|
797
912
|
}
|
|
798
913
|
}
|
|
914
|
+
if (openclawSyncMeta) {
|
|
915
|
+
if (openclawSyncMeta.synced) {
|
|
916
|
+
console.log(
|
|
917
|
+
`Synced env vars to OpenClaw config: ${openclawSyncMeta.configPath} (${openclawSyncMeta.writtenKeys.length} keys)`
|
|
918
|
+
);
|
|
919
|
+
} else {
|
|
920
|
+
console.log(
|
|
921
|
+
`Skipped OpenClaw env sync (${openclawSyncMeta.reason}): ${openclawSyncMeta.configPath}`
|
|
922
|
+
);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
799
925
|
console.log("Restart Codex to pick up new skills.");
|
|
800
926
|
}
|
|
801
927
|
|
package/package.json
CHANGED
|
@@ -12,6 +12,7 @@ metadata:
|
|
|
12
12
|
- BOT_API_KEY
|
|
13
13
|
- CHAIN_ID
|
|
14
14
|
- CLAIM_ATTESTATION_VERIFIER_ADDRESS
|
|
15
|
+
- PARTICIPANT_ADDRESS
|
|
15
16
|
bins:
|
|
16
17
|
- node
|
|
17
18
|
- npm
|
|
@@ -51,6 +52,10 @@ npx @wiimdy/openfunderse@latest bot-init \
|
|
|
51
52
|
set -a; source .env.participant; set +a
|
|
52
53
|
```
|
|
53
54
|
|
|
55
|
+
OpenClaw note:
|
|
56
|
+
- `install` / `bot-init` sync env keys into `~/.openclaw/openclaw.json` (`env.vars`) by default.
|
|
57
|
+
- Use `--no-sync-openclaw-env` if you want file-only behavior.
|
|
58
|
+
|
|
54
59
|
Note:
|
|
55
60
|
- The scaffold includes a temporary public key placeholder by default.
|
|
56
61
|
- Always run `bot-init` before funding or running production actions.
|
|
@@ -11,7 +11,7 @@ metadata:
|
|
|
11
11
|
- RELAYER_URL
|
|
12
12
|
- BOT_ID
|
|
13
13
|
- BOT_API_KEY
|
|
14
|
-
-
|
|
14
|
+
- STRATEGY_ADDRESS
|
|
15
15
|
- CHAIN_ID
|
|
16
16
|
- RPC_URL
|
|
17
17
|
- STRATEGY_PRIVATE_KEY
|
|
@@ -73,6 +73,10 @@ npx @wiimdy/openfunderse@latest bot-init \
|
|
|
73
73
|
set -a; source .env.strategy; set +a
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
+
OpenClaw note:
|
|
77
|
+
- `install` / `bot-init` sync env keys into `~/.openclaw/openclaw.json` (`env.vars`) by default.
|
|
78
|
+
- Use `--no-sync-openclaw-env` if you want file-only behavior.
|
|
79
|
+
|
|
76
80
|
Note:
|
|
77
81
|
- The scaffold includes a temporary public key placeholder by default.
|
|
78
82
|
- Always run `bot-init` before funding or running production actions.
|