@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.
@@ -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=0x00
12
+ PARTICIPANT_ADDRESS=0x0000000000000000000000000000000000000000
13
13
 
14
14
  PARTICIPANT_REQUIRE_EXPLICIT_SUBMIT=true
15
15
  PARTICIPANT_AUTO_SUBMIT=false
@@ -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=0x00
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`.
@@ -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
- BOT_ADDRESS: wallet.address
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
- PARTICIPANT_BOT_ADDRESS: wallet.address,
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wiimdy/openfunderse",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "Install OpenFunderse skill packs into Codex",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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
- - BOT_ADDRESS
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.