@wlfi-agent/cli 1.4.13 → 1.4.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.
Files changed (289) hide show
  1. package/Cargo.lock +3968 -0
  2. package/Cargo.toml +50 -0
  3. package/README.md +426 -6
  4. package/crates/vault-cli-admin/Cargo.toml +26 -0
  5. package/crates/vault-cli-admin/src/io_utils.rs +500 -0
  6. package/crates/vault-cli-admin/src/main.rs +3990 -0
  7. package/crates/vault-cli-admin/src/shared_config.rs +624 -0
  8. package/crates/vault-cli-admin/src/tui/amounts.rs +180 -0
  9. package/crates/vault-cli-admin/src/tui/token_rpc.rs +250 -0
  10. package/crates/vault-cli-admin/src/tui/utils.rs +82 -0
  11. package/crates/vault-cli-admin/src/tui.rs +3410 -0
  12. package/crates/vault-cli-agent/Cargo.toml +24 -0
  13. package/crates/vault-cli-agent/src/io_utils.rs +576 -0
  14. package/crates/vault-cli-agent/src/main.rs +833 -0
  15. package/crates/vault-cli-daemon/Cargo.toml +28 -0
  16. package/crates/vault-cli-daemon/src/bin/wlfi-agent-system-keychain.rs +216 -0
  17. package/crates/vault-cli-daemon/src/main.rs +644 -0
  18. package/crates/vault-cli-daemon/src/relay_sync.rs +894 -0
  19. package/crates/vault-cli-daemon/tests/system_keychain_helper_acl.rs +167 -0
  20. package/crates/vault-daemon/Cargo.toml +32 -0
  21. package/crates/vault-daemon/src/daemon_parts/api_impl_and_utils.rs +1041 -0
  22. package/crates/vault-daemon/src/daemon_parts/core_helpers.rs +1256 -0
  23. package/crates/vault-daemon/src/daemon_parts/types_api_rpc.rs +622 -0
  24. package/crates/vault-daemon/src/lib.rs +54 -0
  25. package/crates/vault-daemon/src/persistence.rs +441 -0
  26. package/crates/vault-daemon/src/tests.rs +237 -0
  27. package/crates/vault-daemon/src/tests_parts/part1.rs +1224 -0
  28. package/crates/vault-daemon/src/tests_parts/part2.rs +1021 -0
  29. package/crates/vault-daemon/src/tests_parts/part3.rs +835 -0
  30. package/crates/vault-daemon/src/tests_parts/part4.rs +604 -0
  31. package/crates/vault-domain/Cargo.toml +20 -0
  32. package/crates/vault-domain/src/action.rs +849 -0
  33. package/crates/vault-domain/src/address.rs +51 -0
  34. package/crates/vault-domain/src/approval.rs +90 -0
  35. package/crates/vault-domain/src/constants.rs +4 -0
  36. package/crates/vault-domain/src/error.rs +54 -0
  37. package/crates/vault-domain/src/keys.rs +71 -0
  38. package/crates/vault-domain/src/lib.rs +42 -0
  39. package/crates/vault-domain/src/nonce.rs +102 -0
  40. package/crates/vault-domain/src/policy.rs +172 -0
  41. package/crates/vault-domain/src/request.rs +53 -0
  42. package/crates/vault-domain/src/scope.rs +24 -0
  43. package/crates/vault-domain/src/session.rs +50 -0
  44. package/crates/vault-domain/src/signature.rs +34 -0
  45. package/crates/vault-domain/src/tests.rs +651 -0
  46. package/crates/vault-domain/src/u128_as_decimal_string.rs +44 -0
  47. package/crates/vault-policy/Cargo.toml +17 -0
  48. package/crates/vault-policy/src/engine.rs +301 -0
  49. package/crates/vault-policy/src/error.rs +81 -0
  50. package/crates/vault-policy/src/lib.rs +17 -0
  51. package/crates/vault-policy/src/report.rs +34 -0
  52. package/crates/vault-policy/src/tests.rs +891 -0
  53. package/crates/vault-policy/src/tests_explain.rs +78 -0
  54. package/crates/vault-sdk-agent/Cargo.toml +21 -0
  55. package/crates/vault-sdk-agent/src/lib.rs +711 -0
  56. package/crates/vault-signer/Cargo.toml +25 -0
  57. package/crates/vault-signer/src/lib.rs +731 -0
  58. package/crates/vault-signer/tests/secure_enclave_acl.rs +54 -0
  59. package/crates/vault-transport-unix/Cargo.toml +24 -0
  60. package/crates/vault-transport-unix/src/lib.rs +1640 -0
  61. package/crates/vault-transport-xpc/Cargo.toml +25 -0
  62. package/crates/vault-transport-xpc/src/client_codec_api.rs +635 -0
  63. package/crates/vault-transport-xpc/src/lib.rs +680 -0
  64. package/crates/vault-transport-xpc/src/tests.rs +818 -0
  65. package/crates/vault-transport-xpc/tests/e2e_flow.rs +773 -0
  66. package/dist/cli.cjs +35088 -0
  67. package/dist/cli.cjs.map +1 -0
  68. package/package.json +45 -41
  69. package/packages/cache/.turbo/turbo-build.log +52 -0
  70. package/packages/cache/dist/chunk-2QFWMUXT.cjs +43 -0
  71. package/packages/cache/dist/chunk-2QFWMUXT.cjs.map +1 -0
  72. package/packages/cache/dist/chunk-4U63TZTQ.js +43 -0
  73. package/packages/cache/dist/chunk-4U63TZTQ.js.map +1 -0
  74. package/packages/cache/dist/chunk-ALQ6H7KG.cjs +404 -0
  75. package/packages/cache/dist/chunk-ALQ6H7KG.cjs.map +1 -0
  76. package/packages/cache/dist/chunk-FGJEEF5N.js +404 -0
  77. package/packages/cache/dist/chunk-FGJEEF5N.js.map +1 -0
  78. package/packages/cache/dist/chunk-UYNEHZHB.cjs +45 -0
  79. package/packages/cache/dist/chunk-UYNEHZHB.cjs.map +1 -0
  80. package/packages/cache/dist/chunk-VXVMPG3W.js +45 -0
  81. package/packages/cache/dist/chunk-VXVMPG3W.js.map +1 -0
  82. package/packages/cache/dist/client/index.cjs +11 -0
  83. package/packages/cache/dist/client/index.cjs.map +1 -0
  84. package/packages/cache/dist/client/index.d.cts +15 -0
  85. package/packages/cache/dist/client/index.d.ts +15 -0
  86. package/packages/cache/dist/client/index.js +11 -0
  87. package/packages/cache/dist/client/index.js.map +1 -0
  88. package/packages/cache/dist/errors/index.cjs +11 -0
  89. package/packages/cache/dist/errors/index.cjs.map +1 -0
  90. package/packages/cache/dist/errors/index.d.cts +26 -0
  91. package/packages/cache/dist/errors/index.d.ts +26 -0
  92. package/packages/cache/dist/errors/index.js +11 -0
  93. package/packages/cache/dist/errors/index.js.map +1 -0
  94. package/packages/cache/dist/index.cjs +29 -0
  95. package/packages/cache/dist/index.cjs.map +1 -0
  96. package/packages/cache/dist/index.d.cts +4 -0
  97. package/packages/cache/dist/index.d.ts +4 -0
  98. package/packages/cache/dist/index.js +29 -0
  99. package/packages/cache/dist/index.js.map +1 -0
  100. package/packages/cache/dist/service/index.cjs +15 -0
  101. package/packages/cache/dist/service/index.cjs.map +1 -0
  102. package/packages/cache/dist/service/index.d.cts +184 -0
  103. package/packages/cache/dist/service/index.d.ts +184 -0
  104. package/packages/cache/dist/service/index.js +15 -0
  105. package/packages/cache/dist/service/index.js.map +1 -0
  106. package/packages/cache/node_modules/.bin/jiti +17 -0
  107. package/packages/cache/node_modules/.bin/tsc +17 -0
  108. package/packages/cache/node_modules/.bin/tsserver +17 -0
  109. package/packages/cache/node_modules/.bin/tsup +17 -0
  110. package/packages/cache/node_modules/.bin/tsup-node +17 -0
  111. package/packages/cache/node_modules/.bin/tsx +17 -0
  112. package/packages/cache/node_modules/.bin/vitest +17 -0
  113. package/packages/cache/package.json +48 -0
  114. package/packages/cache/src/client/index.ts +56 -0
  115. package/packages/cache/src/errors/index.ts +53 -0
  116. package/packages/cache/src/index.ts +3 -0
  117. package/packages/cache/src/service/index.test.ts +263 -0
  118. package/packages/cache/src/service/index.ts +678 -0
  119. package/packages/cache/tsconfig.json +13 -0
  120. package/packages/cache/tsup.config.ts +13 -0
  121. package/packages/cache/vitest.config.ts +16 -0
  122. package/packages/config/.turbo/turbo-build.log +18 -0
  123. package/packages/config/dist/index.cjs +1037 -0
  124. package/packages/config/dist/index.cjs.map +1 -0
  125. package/packages/config/dist/index.d.ts +131 -0
  126. package/packages/config/node_modules/.bin/jiti +17 -0
  127. package/packages/config/node_modules/.bin/tsc +17 -0
  128. package/packages/config/node_modules/.bin/tsserver +17 -0
  129. package/packages/config/node_modules/.bin/tsup +17 -0
  130. package/packages/config/node_modules/.bin/tsup-node +17 -0
  131. package/packages/config/node_modules/.bin/tsx +17 -0
  132. package/packages/config/package.json +21 -0
  133. package/packages/config/src/index.js +1 -0
  134. package/packages/config/src/index.ts +1282 -0
  135. package/packages/config/tsconfig.json +4 -0
  136. package/packages/rpc/.turbo/turbo-build.log +32 -0
  137. package/packages/rpc/dist/_esm-BCLXDO2R.cjs +3660 -0
  138. package/packages/rpc/dist/_esm-BCLXDO2R.cjs.map +1 -0
  139. package/packages/rpc/dist/ccip-OWJLAW55.cjs +16 -0
  140. package/packages/rpc/dist/ccip-OWJLAW55.cjs.map +1 -0
  141. package/packages/rpc/dist/chunk-APQIFZ3B.cjs +6247 -0
  142. package/packages/rpc/dist/chunk-APQIFZ3B.cjs.map +1 -0
  143. package/packages/rpc/dist/chunk-CDO2GWRD.cjs +410 -0
  144. package/packages/rpc/dist/chunk-CDO2GWRD.cjs.map +1 -0
  145. package/packages/rpc/dist/chunk-QGTNTFJ7.cjs +2249 -0
  146. package/packages/rpc/dist/chunk-QGTNTFJ7.cjs.map +1 -0
  147. package/packages/rpc/dist/chunk-TZDTAHWR.cjs +44 -0
  148. package/packages/rpc/dist/chunk-TZDTAHWR.cjs.map +1 -0
  149. package/packages/rpc/dist/index.cjs +7342 -0
  150. package/packages/rpc/dist/index.cjs.map +1 -0
  151. package/packages/rpc/dist/index.d.ts +3857 -0
  152. package/packages/rpc/dist/secp256k1-WCNM675D.cjs +18 -0
  153. package/packages/rpc/dist/secp256k1-WCNM675D.cjs.map +1 -0
  154. package/packages/rpc/node_modules/.bin/jiti +17 -0
  155. package/packages/rpc/node_modules/.bin/tsc +17 -0
  156. package/packages/rpc/node_modules/.bin/tsserver +17 -0
  157. package/packages/rpc/node_modules/.bin/tsup +17 -0
  158. package/packages/rpc/node_modules/.bin/tsup-node +17 -0
  159. package/packages/rpc/node_modules/.bin/tsx +17 -0
  160. package/packages/rpc/package.json +25 -0
  161. package/packages/rpc/src/index.ts +206 -0
  162. package/packages/rpc/tsconfig.json +4 -0
  163. package/packages/typescript/base.json +36 -0
  164. package/packages/typescript/nextjs.json +17 -0
  165. package/packages/typescript/package.json +10 -0
  166. package/packages/ui/.turbo/turbo-build.log +44 -0
  167. package/packages/ui/dist/chunk-MOAFBKSA.js +11 -0
  168. package/packages/ui/dist/chunk-MOAFBKSA.js.map +1 -0
  169. package/packages/ui/dist/components/badge.d.ts +12 -0
  170. package/packages/ui/dist/components/badge.js +31 -0
  171. package/packages/ui/dist/components/badge.js.map +1 -0
  172. package/packages/ui/dist/components/button.d.ts +13 -0
  173. package/packages/ui/dist/components/button.js +40 -0
  174. package/packages/ui/dist/components/button.js.map +1 -0
  175. package/packages/ui/dist/components/card.d.ts +10 -0
  176. package/packages/ui/dist/components/card.js +39 -0
  177. package/packages/ui/dist/components/card.js.map +1 -0
  178. package/packages/ui/dist/components/input.d.ts +5 -0
  179. package/packages/ui/dist/components/input.js +28 -0
  180. package/packages/ui/dist/components/input.js.map +1 -0
  181. package/packages/ui/dist/components/label.d.ts +5 -0
  182. package/packages/ui/dist/components/label.js +13 -0
  183. package/packages/ui/dist/components/label.js.map +1 -0
  184. package/packages/ui/dist/components/separator.d.ts +5 -0
  185. package/packages/ui/dist/components/separator.js +13 -0
  186. package/packages/ui/dist/components/separator.js.map +1 -0
  187. package/packages/ui/dist/components/textarea.d.ts +5 -0
  188. package/packages/ui/dist/components/textarea.js +27 -0
  189. package/packages/ui/dist/components/textarea.js.map +1 -0
  190. package/packages/ui/dist/tailwind.d.ts +56 -0
  191. package/packages/ui/dist/tailwind.js +60 -0
  192. package/packages/ui/dist/tailwind.js.map +1 -0
  193. package/packages/ui/dist/utils/cn.d.ts +5 -0
  194. package/packages/ui/dist/utils/cn.js +7 -0
  195. package/packages/ui/dist/utils/cn.js.map +1 -0
  196. package/packages/ui/node_modules/.bin/jiti +17 -0
  197. package/packages/ui/node_modules/.bin/tsc +17 -0
  198. package/packages/ui/node_modules/.bin/tsserver +17 -0
  199. package/packages/ui/node_modules/.bin/tsup +17 -0
  200. package/packages/ui/node_modules/.bin/tsup-node +17 -0
  201. package/packages/ui/node_modules/.bin/tsx +17 -0
  202. package/packages/ui/package.json +69 -0
  203. package/packages/ui/src/components/badge.tsx +27 -0
  204. package/packages/ui/src/components/button.tsx +40 -0
  205. package/packages/ui/src/components/card.tsx +31 -0
  206. package/packages/ui/src/components/input.tsx +21 -0
  207. package/packages/ui/src/components/label.tsx +6 -0
  208. package/packages/ui/src/components/separator.tsx +6 -0
  209. package/packages/ui/src/components/textarea.tsx +20 -0
  210. package/packages/ui/src/globals.css +70 -0
  211. package/packages/ui/src/tailwind.ts +56 -0
  212. package/packages/ui/src/utils/cn.ts +6 -0
  213. package/packages/ui/tsconfig.json +20 -0
  214. package/packages/ui/tsup.config.ts +20 -0
  215. package/pnpm-workspace.yaml +4 -0
  216. package/scripts/install-rust-binaries.mjs +84 -0
  217. package/scripts/launchd/install-user-daemon.sh +358 -0
  218. package/scripts/launchd/run-vault-daemon.sh +5 -0
  219. package/scripts/launchd/run-wlfi-agent-daemon.sh +73 -0
  220. package/scripts/launchd/uninstall-user-daemon.sh +103 -0
  221. package/src/cli.ts +2121 -0
  222. package/src/lib/admin-guard.js +1 -0
  223. package/src/lib/admin-guard.ts +185 -0
  224. package/src/lib/admin-passthrough.ts +33 -0
  225. package/src/lib/admin-reset.ts +751 -0
  226. package/src/lib/admin-setup.ts +1612 -0
  227. package/src/lib/agent-auth-clear.js +1 -0
  228. package/src/lib/agent-auth-clear.ts +58 -0
  229. package/src/lib/agent-auth-forwarding.js +1 -0
  230. package/src/lib/agent-auth-forwarding.ts +149 -0
  231. package/src/lib/agent-auth-migrate.js +1 -0
  232. package/src/lib/agent-auth-migrate.ts +150 -0
  233. package/src/lib/agent-auth-revoke.ts +103 -0
  234. package/src/lib/agent-auth-rotate.ts +107 -0
  235. package/src/lib/agent-auth-token.js +1 -0
  236. package/src/lib/agent-auth-token.ts +25 -0
  237. package/src/lib/agent-auth.ts +89 -0
  238. package/src/lib/asset-broadcast.js +1 -0
  239. package/src/lib/asset-broadcast.ts +285 -0
  240. package/src/lib/bootstrap-artifacts.js +1 -0
  241. package/src/lib/bootstrap-artifacts.ts +205 -0
  242. package/src/lib/bootstrap-credentials.js +1 -0
  243. package/src/lib/bootstrap-credentials.ts +832 -0
  244. package/src/lib/config-amounts.js +1 -0
  245. package/src/lib/config-amounts.ts +189 -0
  246. package/src/lib/config-mutation.ts +27 -0
  247. package/src/lib/fs-trust.js +1 -0
  248. package/src/lib/fs-trust.ts +537 -0
  249. package/src/lib/keychain.js +1 -0
  250. package/src/lib/keychain.ts +225 -0
  251. package/src/lib/local-admin-access.ts +106 -0
  252. package/src/lib/network-selection.js +1 -0
  253. package/src/lib/network-selection.ts +71 -0
  254. package/src/lib/passthrough-security.js +1 -0
  255. package/src/lib/passthrough-security.ts +114 -0
  256. package/src/lib/rpc-guard.js +1 -0
  257. package/src/lib/rpc-guard.ts +7 -0
  258. package/src/lib/rust-spawn-options.js +1 -0
  259. package/src/lib/rust-spawn-options.ts +98 -0
  260. package/src/lib/rust.js +1 -0
  261. package/src/lib/rust.ts +143 -0
  262. package/src/lib/signed-tx.js +1 -0
  263. package/src/lib/signed-tx.ts +116 -0
  264. package/src/lib/status-repair-cli.ts +116 -0
  265. package/src/lib/sudo.js +1 -0
  266. package/src/lib/sudo.ts +172 -0
  267. package/src/lib/vault-password-forwarding.js +1 -0
  268. package/src/lib/vault-password-forwarding.ts +155 -0
  269. package/src/lib/wallet-profile.js +1 -0
  270. package/src/lib/wallet-profile.ts +332 -0
  271. package/src/lib/wallet-repair.js +1 -0
  272. package/src/lib/wallet-repair.ts +304 -0
  273. package/src/lib/wallet-setup.js +1 -0
  274. package/src/lib/wallet-setup.ts +1466 -0
  275. package/src/lib/wallet-status.js +1 -0
  276. package/src/lib/wallet-status.ts +640 -0
  277. package/tsconfig.base.json +17 -0
  278. package/tsconfig.json +10 -0
  279. package/tsup.config.ts +25 -0
  280. package/turbo.json +41 -0
  281. package/LICENSE.md +0 -1
  282. package/dist/wlfa/index.cjs +0 -250
  283. package/dist/wlfa/index.d.cts +0 -1
  284. package/dist/wlfa/index.d.ts +0 -1
  285. package/dist/wlfa/index.js +0 -250
  286. package/dist/wlfc/index.cjs +0 -1839
  287. package/dist/wlfc/index.d.cts +0 -1
  288. package/dist/wlfc/index.d.ts +0 -1
  289. package/dist/wlfc/index.js +0 -1839
@@ -0,0 +1,1037 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import fs from "fs";
5
+ import os from "os";
6
+ import path from "path";
7
+ var WLFI_DIRNAME = ".wlfi_agent";
8
+ var CONFIG_FILENAME = "config.json";
9
+ var PRIVATE_DIR_MODE = 448;
10
+ var PRIVATE_FILE_MODE = 384;
11
+ var GROUP_OTHER_WRITE_MODE_MASK = 18;
12
+ var PRIVATE_FILE_MODE_MASK = 63;
13
+ var STICKY_BIT_MODE = 512;
14
+ var MAX_CONFIG_FILE_BYTES = 256 * 1024;
15
+ var DEFAULT_ETH_RPC_URL = "https://eth.llamarpc.com";
16
+ var DEFAULT_BSC_RPC_URL = "https://bsc.drpc.org";
17
+ var DEFAULT_USD1_ADDRESS = "0xc83DE66ebA6a91B6F3d167f2ee9F0C42aD70B611";
18
+ var BUILTIN_CHAINS = {
19
+ eth: { chainId: 1, name: "eth", rpcUrl: DEFAULT_ETH_RPC_URL },
20
+ ethereum: { chainId: 1, name: "ethereum", rpcUrl: DEFAULT_ETH_RPC_URL },
21
+ mainnet: { chainId: 1, name: "mainnet", rpcUrl: DEFAULT_ETH_RPC_URL },
22
+ sepolia: { chainId: 11155111, name: "sepolia" },
23
+ base: { chainId: 8453, name: "base" },
24
+ "base-sepolia": { chainId: 84532, name: "base-sepolia" },
25
+ optimism: { chainId: 10, name: "optimism" },
26
+ arbitrum: { chainId: 42161, name: "arbitrum" },
27
+ polygon: { chainId: 137, name: "polygon" },
28
+ bsc: { chainId: 56, name: "bsc", rpcUrl: DEFAULT_BSC_RPC_URL }
29
+ };
30
+ var BUILTIN_TOKENS = {
31
+ bnb: {
32
+ name: "BNB",
33
+ symbol: "BNB",
34
+ defaultPolicy: defaultTokenPolicy("0.01", "0.2", "1.4"),
35
+ chains: {
36
+ bsc: {
37
+ chainId: 56,
38
+ isNative: true,
39
+ decimals: 18,
40
+ defaultPolicy: defaultTokenPolicy("0.01", "0.2", "1.4")
41
+ }
42
+ }
43
+ },
44
+ eth: {
45
+ symbol: "ETH",
46
+ chains: {
47
+ ethereum: { chainId: 1, isNative: true, decimals: 18 },
48
+ sepolia: { chainId: 11155111, isNative: true, decimals: 18 },
49
+ base: { chainId: 8453, isNative: true, decimals: 18 },
50
+ "base-sepolia": { chainId: 84532, isNative: true, decimals: 18 },
51
+ optimism: { chainId: 10, isNative: true, decimals: 18 },
52
+ arbitrum: { chainId: 42161, isNative: true, decimals: 18 }
53
+ }
54
+ },
55
+ usdc: {
56
+ symbol: "USDC",
57
+ chains: {
58
+ ethereum: {
59
+ chainId: 1,
60
+ isNative: false,
61
+ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
62
+ decimals: 6
63
+ },
64
+ base: {
65
+ chainId: 8453,
66
+ isNative: false,
67
+ address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
68
+ decimals: 6
69
+ }
70
+ }
71
+ },
72
+ usd1: {
73
+ name: "USD1",
74
+ symbol: "USD1",
75
+ defaultPolicy: defaultTokenPolicy("10", "100", "700"),
76
+ chains: {
77
+ eth: {
78
+ chainId: 1,
79
+ isNative: false,
80
+ address: DEFAULT_USD1_ADDRESS,
81
+ decimals: 18,
82
+ defaultPolicy: defaultTokenPolicy("10", "100", "700")
83
+ },
84
+ bsc: {
85
+ chainId: 56,
86
+ isNative: false,
87
+ address: DEFAULT_USD1_ADDRESS,
88
+ decimals: 18,
89
+ defaultPolicy: defaultTokenPolicy("10", "100", "700")
90
+ }
91
+ }
92
+ }
93
+ };
94
+ function defaultTokenPolicy(perTxAmountDecimal, dailyAmountDecimal, weeklyAmountDecimal) {
95
+ return {
96
+ perTxAmountDecimal,
97
+ dailyAmountDecimal,
98
+ weeklyAmountDecimal
99
+ };
100
+ }
101
+ function defaultChainProfiles() {
102
+ return {
103
+ eth: {
104
+ chainId: 1,
105
+ name: "ETH",
106
+ rpcUrl: DEFAULT_ETH_RPC_URL
107
+ },
108
+ bsc: {
109
+ chainId: 56,
110
+ name: "BSC",
111
+ rpcUrl: DEFAULT_BSC_RPC_URL
112
+ }
113
+ };
114
+ }
115
+ function defaultTokenProfiles() {
116
+ return {
117
+ usd1: {
118
+ name: "USD1",
119
+ symbol: "USD1",
120
+ defaultPolicy: defaultTokenPolicy("10", "100", "700"),
121
+ destinationOverrides: [],
122
+ manualApprovalPolicies: [],
123
+ chains: {
124
+ eth: {
125
+ chainId: 1,
126
+ isNative: false,
127
+ address: DEFAULT_USD1_ADDRESS,
128
+ decimals: 18,
129
+ defaultPolicy: defaultTokenPolicy("10", "100", "700")
130
+ },
131
+ bsc: {
132
+ chainId: 56,
133
+ isNative: false,
134
+ address: DEFAULT_USD1_ADDRESS,
135
+ decimals: 18,
136
+ defaultPolicy: defaultTokenPolicy("10", "100", "700")
137
+ }
138
+ }
139
+ },
140
+ bnb: {
141
+ name: "BNB",
142
+ symbol: "BNB",
143
+ defaultPolicy: defaultTokenPolicy("0.01", "0.2", "1.4"),
144
+ destinationOverrides: [],
145
+ manualApprovalPolicies: [],
146
+ chains: {
147
+ bsc: {
148
+ chainId: 56,
149
+ isNative: true,
150
+ decimals: 18,
151
+ defaultPolicy: defaultTokenPolicy("0.01", "0.2", "1.4")
152
+ }
153
+ }
154
+ }
155
+ };
156
+ }
157
+ function normalizeLoopbackHostname(hostname) {
158
+ if (hostname.startsWith("[") && hostname.endsWith("]")) {
159
+ return hostname.slice(1, -1).toLowerCase();
160
+ }
161
+ return hostname.toLowerCase();
162
+ }
163
+ function isIpv4Loopback(hostname) {
164
+ const parts = hostname.split(".");
165
+ if (parts.length !== 4 || parts.some((part) => !/^\d+$/u.test(part))) {
166
+ return false;
167
+ }
168
+ const octets = parts.map((part) => Number(part));
169
+ if (octets.some((octet) => octet < 0 || octet > 255)) {
170
+ return false;
171
+ }
172
+ return octets[0] === 127;
173
+ }
174
+ function isLoopbackHostname(hostname) {
175
+ const normalized = normalizeLoopbackHostname(hostname);
176
+ return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "::1" || isIpv4Loopback(normalized);
177
+ }
178
+ function assertSafeRpcUrl(value, label = "rpcUrl") {
179
+ const normalized = value.trim();
180
+ if (!normalized) {
181
+ throw new Error(`${label} is required`);
182
+ }
183
+ let parsed;
184
+ try {
185
+ parsed = new URL(normalized);
186
+ } catch {
187
+ throw new Error(`${label} must be a valid http(s) URL`);
188
+ }
189
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
190
+ throw new Error(`${label} must use https or localhost http`);
191
+ }
192
+ if (parsed.username || parsed.password) {
193
+ throw new Error(`${label} must not include embedded credentials`);
194
+ }
195
+ if (!parsed.hostname) {
196
+ throw new Error(`${label} must include a hostname`);
197
+ }
198
+ if (parsed.protocol === "http:" && !isLoopbackHostname(parsed.hostname)) {
199
+ throw new Error(`${label} must use https unless it targets localhost or a loopback address`);
200
+ }
201
+ return normalized;
202
+ }
203
+ var ADDRESS_PATTERN = /^0x[a-f0-9]{40}$/iu;
204
+ function assertValidEvmAddress(value, label) {
205
+ const normalized = value.trim();
206
+ if (!ADDRESS_PATTERN.test(normalized)) {
207
+ throw new Error(`${label} must be a valid EVM address`);
208
+ }
209
+ return normalized;
210
+ }
211
+ function assertPositiveSafeInteger(value, label) {
212
+ if (!Number.isSafeInteger(value) || value <= 0) {
213
+ throw new Error(`${label} must be a positive safe integer`);
214
+ }
215
+ return value;
216
+ }
217
+ function assertTokenDecimals(value, label) {
218
+ if (!Number.isInteger(value) || value < 0 || value > 255) {
219
+ throw new Error(`${label} must be an integer between 0 and 255`);
220
+ }
221
+ return value;
222
+ }
223
+ function assertOptionalTokenAmount(value, label) {
224
+ if (value == null) {
225
+ return void 0;
226
+ }
227
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
228
+ throw new Error(`${label} must be a positive finite number`);
229
+ }
230
+ return value;
231
+ }
232
+ function assertOptionalTrimmedString(value, label) {
233
+ if (value == null) {
234
+ return void 0;
235
+ }
236
+ const normalized = value.trim();
237
+ if (!normalized) {
238
+ return void 0;
239
+ }
240
+ return normalized;
241
+ }
242
+ function assertRequiredTrimmedString(value, label) {
243
+ const normalized = assertOptionalTrimmedString(value, label);
244
+ if (!normalized) {
245
+ throw new Error(`${label} is required`);
246
+ }
247
+ return normalized;
248
+ }
249
+ function assertOptionalStringArray(value, label) {
250
+ if (value == null) {
251
+ return void 0;
252
+ }
253
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
254
+ throw new Error(`${label} must be an array of strings`);
255
+ }
256
+ const normalized = value.map((entry) => entry.trim()).filter((entry) => entry.length > 0);
257
+ return normalized.length > 0 ? normalized : void 0;
258
+ }
259
+ function normalizeWalletProfile(profile) {
260
+ if (profile == null) {
261
+ return void 0;
262
+ }
263
+ return {
264
+ vaultKeyId: assertOptionalTrimmedString(profile.vaultKeyId, "wallet.vaultKeyId"),
265
+ vaultPublicKey: assertRequiredTrimmedString(profile.vaultPublicKey, "wallet.vaultPublicKey"),
266
+ address: profile.address ? assertValidEvmAddress(profile.address, "wallet.address") : void 0,
267
+ agentKeyId: assertOptionalTrimmedString(profile.agentKeyId, "wallet.agentKeyId"),
268
+ policyAttachment: assertRequiredTrimmedString(profile.policyAttachment, "wallet.policyAttachment"),
269
+ attachedPolicyIds: assertOptionalStringArray(profile.attachedPolicyIds, "wallet.attachedPolicyIds"),
270
+ policyNote: assertOptionalTrimmedString(profile.policyNote, "wallet.policyNote"),
271
+ networkScope: assertOptionalTrimmedString(profile.networkScope, "wallet.networkScope"),
272
+ assetScope: assertOptionalTrimmedString(profile.assetScope, "wallet.assetScope"),
273
+ recipientScope: assertOptionalTrimmedString(profile.recipientScope, "wallet.recipientScope")
274
+ };
275
+ }
276
+ function normalizeTokenPolicyProfile(tokenKey, chainKey, policy) {
277
+ if (!policy) {
278
+ return void 0;
279
+ }
280
+ return {
281
+ perTxAmount: assertOptionalTokenAmount(policy.perTxAmount, `token '${tokenKey}' chain '${chainKey}' perTxAmount`),
282
+ dailyAmount: assertOptionalTokenAmount(policy.dailyAmount, `token '${tokenKey}' chain '${chainKey}' dailyAmount`),
283
+ weeklyAmount: assertOptionalTokenAmount(policy.weeklyAmount, `token '${tokenKey}' chain '${chainKey}' weeklyAmount`),
284
+ perTxAmountDecimal: assertOptionalTrimmedString(policy.perTxAmountDecimal, `token '${tokenKey}' chain '${chainKey}' perTxAmountDecimal`),
285
+ dailyAmountDecimal: assertOptionalTrimmedString(policy.dailyAmountDecimal, `token '${tokenKey}' chain '${chainKey}' dailyAmountDecimal`),
286
+ weeklyAmountDecimal: assertOptionalTrimmedString(policy.weeklyAmountDecimal, `token '${tokenKey}' chain '${chainKey}' weeklyAmountDecimal`),
287
+ perTxLimit: assertOptionalTrimmedString(policy.perTxLimit, `token '${tokenKey}' chain '${chainKey}' perTxLimit`),
288
+ dailyLimit: assertOptionalTrimmedString(policy.dailyLimit, `token '${tokenKey}' chain '${chainKey}' dailyLimit`),
289
+ weeklyLimit: assertOptionalTrimmedString(policy.weeklyLimit, `token '${tokenKey}' chain '${chainKey}' weeklyLimit`),
290
+ maxGasPerChainWei: assertOptionalTrimmedString(policy.maxGasPerChainWei, `token '${tokenKey}' chain '${chainKey}' maxGasPerChainWei`),
291
+ dailyMaxTxCount: assertOptionalTrimmedString(policy.dailyMaxTxCount, `token '${tokenKey}' chain '${chainKey}' dailyMaxTxCount`),
292
+ perTxMaxFeePerGasGwei: assertOptionalTrimmedString(policy.perTxMaxFeePerGasGwei, `token '${tokenKey}' chain '${chainKey}' perTxMaxFeePerGasGwei`),
293
+ perTxMaxFeePerGasWei: assertOptionalTrimmedString(policy.perTxMaxFeePerGasWei, `token '${tokenKey}' chain '${chainKey}' perTxMaxFeePerGasWei`),
294
+ perTxMaxPriorityFeePerGasWei: assertOptionalTrimmedString(policy.perTxMaxPriorityFeePerGasWei, `token '${tokenKey}' chain '${chainKey}' perTxMaxPriorityFeePerGasWei`),
295
+ perTxMaxCalldataBytes: assertOptionalTrimmedString(policy.perTxMaxCalldataBytes, `token '${tokenKey}' chain '${chainKey}' perTxMaxCalldataBytes`)
296
+ };
297
+ }
298
+ function normalizeTokenDestinationOverrideProfile(tokenKey, profile) {
299
+ const recipient = assertValidEvmAddress(profile.recipient, `token '${tokenKey}' destination override recipient`);
300
+ return {
301
+ recipient,
302
+ limits: normalizeTokenPolicyProfile(tokenKey, "override", profile.limits) ?? {}
303
+ };
304
+ }
305
+ function normalizeTokenManualApprovalProfile(tokenKey, profile) {
306
+ return {
307
+ priority: profile.priority === void 0 ? void 0 : assertPositiveSafeInteger(profile.priority, `token '${tokenKey}' manual approval priority`),
308
+ recipient: profile.recipient ? assertValidEvmAddress(profile.recipient, `token '${tokenKey}' manual approval recipient`) : void 0,
309
+ minAmount: assertOptionalTokenAmount(profile.minAmount, `token '${tokenKey}' manual approval minAmount`),
310
+ maxAmount: assertOptionalTokenAmount(profile.maxAmount, `token '${tokenKey}' manual approval maxAmount`),
311
+ minAmountDecimal: assertOptionalTrimmedString(profile.minAmountDecimal, `token '${tokenKey}' manual approval minAmountDecimal`),
312
+ maxAmountDecimal: assertOptionalTrimmedString(profile.maxAmountDecimal, `token '${tokenKey}' manual approval maxAmountDecimal`),
313
+ minAmountWei: assertOptionalTrimmedString(profile.minAmountWei, `token '${tokenKey}' manual approval minAmountWei`),
314
+ maxAmountWei: assertOptionalTrimmedString(profile.maxAmountWei, `token '${tokenKey}' manual approval maxAmountWei`)
315
+ };
316
+ }
317
+ function normalizeTokenChainProfile(tokenKey, chainKey, profile) {
318
+ const normalizedChainKey = chainKey.trim().toLowerCase();
319
+ if (!normalizedChainKey) {
320
+ throw new Error(`token '${tokenKey}' chain key is required`);
321
+ }
322
+ const normalized = {
323
+ chainId: assertPositiveSafeInteger(profile.chainId, `token '${tokenKey}' chain '${normalizedChainKey}' chainId`),
324
+ isNative: Boolean(profile.isNative),
325
+ decimals: assertTokenDecimals(profile.decimals, `token '${tokenKey}' chain '${normalizedChainKey}' decimals`),
326
+ defaultPolicy: normalizeTokenPolicyProfile(tokenKey, normalizedChainKey, profile.defaultPolicy)
327
+ };
328
+ if (normalized.isNative) {
329
+ if (profile.address?.trim()) {
330
+ throw new Error(`token '${tokenKey}' chain '${normalizedChainKey}' must not set address when isNative=true`);
331
+ }
332
+ } else {
333
+ normalized.address = assertValidEvmAddress(
334
+ profile.address ?? "",
335
+ `token '${tokenKey}' chain '${normalizedChainKey}' address`
336
+ );
337
+ }
338
+ return normalized;
339
+ }
340
+ function normalizeTokenProfile(key, profile) {
341
+ const normalizedKey = key.trim().toLowerCase();
342
+ if (!normalizedKey) {
343
+ throw new Error("token profile key is required");
344
+ }
345
+ const symbol = profile.symbol?.trim();
346
+ if (!symbol) {
347
+ throw new Error(`token profile '${normalizedKey}' symbol is required`);
348
+ }
349
+ const name = assertOptionalTrimmedString(profile.name, `token profile '${normalizedKey}' name`);
350
+ const normalizedChains = {};
351
+ for (const [chainKey, chainProfile] of Object.entries(profile.chains ?? {})) {
352
+ const normalizedChainKey = chainKey.trim().toLowerCase();
353
+ if (!normalizedChainKey) {
354
+ throw new Error(`token profile '${normalizedKey}' contains an empty chain key`);
355
+ }
356
+ normalizedChains[normalizedChainKey] = normalizeTokenChainProfile(normalizedKey, normalizedChainKey, chainProfile);
357
+ }
358
+ return {
359
+ name,
360
+ symbol,
361
+ defaultPolicy: normalizeTokenPolicyProfile(normalizedKey, "default", profile.defaultPolicy),
362
+ destinationOverrides: (profile.destinationOverrides ?? []).map(
363
+ (item) => normalizeTokenDestinationOverrideProfile(normalizedKey, item)
364
+ ),
365
+ manualApprovalPolicies: (profile.manualApprovalPolicies ?? []).map(
366
+ (item) => normalizeTokenManualApprovalProfile(normalizedKey, item)
367
+ ),
368
+ chains: normalizedChains
369
+ };
370
+ }
371
+ function normalizeChainProfileEntry(key, profile) {
372
+ const normalizedKey = key.trim().toLowerCase();
373
+ if (!normalizedKey) {
374
+ throw new Error("chain profile key is required");
375
+ }
376
+ const name = profile.name?.trim() || normalizedKey;
377
+ return {
378
+ chainId: assertPositiveSafeInteger(profile.chainId, `chain profile '${normalizedKey}' chainId`),
379
+ name,
380
+ rpcUrl: profile.rpcUrl ? assertSafeRpcUrl(profile.rpcUrl, `chain profile '${normalizedKey}' rpcUrl`) : void 0
381
+ };
382
+ }
383
+ function normalizeChainProfiles(profiles) {
384
+ const normalized = {};
385
+ for (const [key, profile] of Object.entries(profiles ?? {})) {
386
+ const normalizedKey = key.trim().toLowerCase();
387
+ if (!normalizedKey) {
388
+ throw new Error("chain profile key is required");
389
+ }
390
+ normalized[normalizedKey] = normalizeChainProfileEntry(normalizedKey, profile);
391
+ }
392
+ return normalized;
393
+ }
394
+ function normalizeTokenProfiles(profiles) {
395
+ const normalized = {};
396
+ for (const [key, profile] of Object.entries(profiles ?? {})) {
397
+ const normalizedKey = key.trim().toLowerCase();
398
+ if (!normalizedKey) {
399
+ throw new Error("token profile key is required");
400
+ }
401
+ normalized[normalizedKey] = normalizeTokenProfile(normalizedKey, profile);
402
+ }
403
+ return normalized;
404
+ }
405
+ function normalizePath(targetPath) {
406
+ return path.resolve(targetPath);
407
+ }
408
+ function requirePathValue(targetPath, label) {
409
+ const normalized = targetPath.trim();
410
+ if (!normalized) {
411
+ throw new Error(`${label} is required`);
412
+ }
413
+ return normalizePath(normalized);
414
+ }
415
+ function readLstat(targetPath) {
416
+ try {
417
+ return fs.lstatSync(targetPath);
418
+ } catch (error) {
419
+ if (error.code === "ENOENT") {
420
+ return null;
421
+ }
422
+ throw error;
423
+ }
424
+ }
425
+ function readLstatAllowInaccessible(targetPath) {
426
+ try {
427
+ return fs.lstatSync(targetPath);
428
+ } catch (error) {
429
+ const code = error.code;
430
+ if (code === "ENOENT") {
431
+ return null;
432
+ }
433
+ if (code === "EACCES" || code === "EPERM") {
434
+ return "inaccessible";
435
+ }
436
+ throw error;
437
+ }
438
+ }
439
+ function isStableRootOwnedSymlink(stats, targetPath) {
440
+ if (process.platform === "win32" || typeof stats.uid !== "number" || stats.uid !== 0) {
441
+ return false;
442
+ }
443
+ const parentPath = path.dirname(targetPath);
444
+ const parentStats = readLstat(parentPath);
445
+ return Boolean(
446
+ parentStats && parentStats.isDirectory() && typeof parentStats.uid === "number" && parentStats.uid === 0 && (parentStats.mode & GROUP_OTHER_WRITE_MODE_MASK) === 0
447
+ );
448
+ }
449
+ function assertNoSymlinkAncestorDirectories(targetPath, label) {
450
+ const normalized = normalizePath(targetPath);
451
+ const parent = path.dirname(normalized);
452
+ if (parent === normalized) {
453
+ return;
454
+ }
455
+ const { root } = path.parse(parent);
456
+ const relativeParent = parent.slice(root.length);
457
+ if (!relativeParent) {
458
+ return;
459
+ }
460
+ let currentPath = root;
461
+ for (const segment of relativeParent.split(path.sep).filter(Boolean)) {
462
+ currentPath = path.join(currentPath, segment);
463
+ const stats = readLstat(currentPath);
464
+ if (!stats) {
465
+ break;
466
+ }
467
+ if (stats.isSymbolicLink()) {
468
+ if (isStableRootOwnedSymlink(stats, currentPath)) {
469
+ continue;
470
+ }
471
+ throw new Error(`${label} '${normalized}' must not traverse symlinked ancestor directories`);
472
+ }
473
+ }
474
+ }
475
+ function findNearestExistingPath(targetPath) {
476
+ let currentPath = normalizePath(targetPath);
477
+ while (true) {
478
+ const stats = readLstat(currentPath);
479
+ if (stats) {
480
+ return {
481
+ path: currentPath,
482
+ stats
483
+ };
484
+ }
485
+ const parentPath = path.dirname(currentPath);
486
+ if (parentPath === currentPath) {
487
+ throw new Error(`No existing ancestor directory found for '${targetPath}'`);
488
+ }
489
+ currentPath = parentPath;
490
+ }
491
+ }
492
+ function allowedOwnerUids() {
493
+ const allowed = /* @__PURE__ */ new Set();
494
+ const effectiveUid = typeof process.geteuid === "function" ? process.geteuid() : null;
495
+ if (effectiveUid !== null) {
496
+ allowed.add(effectiveUid);
497
+ }
498
+ const sudoUid = process.env.SUDO_UID?.trim();
499
+ if (effectiveUid === 0 && sudoUid && /^\d+$/u.test(sudoUid)) {
500
+ allowed.add(Number(sudoUid));
501
+ }
502
+ return allowed;
503
+ }
504
+ function assertTrustedOwner(stats, targetPath, label) {
505
+ if (process.platform === "win32" || typeof stats.uid !== "number") {
506
+ return;
507
+ }
508
+ if (stats.uid === 0) {
509
+ return;
510
+ }
511
+ const allowed = allowedOwnerUids();
512
+ if (!allowed.has(stats.uid)) {
513
+ throw new Error(
514
+ `${label} '${targetPath}' must be owned by the current user, sudo caller, or root`
515
+ );
516
+ }
517
+ }
518
+ function assertSecureDirectory(stats, targetPath, label) {
519
+ assertTrustedOwner(stats, targetPath, label);
520
+ if (process.platform === "win32") {
521
+ return;
522
+ }
523
+ if ((stats.mode & GROUP_OTHER_WRITE_MODE_MASK) !== 0) {
524
+ throw new Error(`${label} '${targetPath}' must not be writable by group/other`);
525
+ }
526
+ }
527
+ function isStickyDirectory(stats) {
528
+ return process.platform !== "win32" && (stats.mode & STICKY_BIT_MODE) !== 0;
529
+ }
530
+ function assertSecureDirectoryPath(targetPath, label) {
531
+ const normalized = normalizePath(targetPath);
532
+ assertNoSymlinkAncestorDirectories(normalized, label);
533
+ const targetStats = fs.lstatSync(normalized);
534
+ if (targetStats.isSymbolicLink()) {
535
+ throw new Error(`${label} '${normalized}' must not be a symlink`);
536
+ }
537
+ if (!targetStats.isDirectory()) {
538
+ throw new Error(`${label} '${normalized}' must be a directory`);
539
+ }
540
+ assertSecureDirectory(targetStats, normalized, label);
541
+ const ancestors = [];
542
+ let currentPath = fs.realpathSync.native(normalized);
543
+ while (true) {
544
+ ancestors.push(currentPath);
545
+ const parentPath = path.dirname(currentPath);
546
+ if (parentPath === currentPath) {
547
+ break;
548
+ }
549
+ currentPath = parentPath;
550
+ }
551
+ for (const [index, currentDirectory] of ancestors.entries()) {
552
+ if (index === 0) {
553
+ continue;
554
+ }
555
+ const stats = fs.lstatSync(currentDirectory);
556
+ if (!stats.isDirectory()) {
557
+ throw new Error(`${label} '${currentDirectory}' must be a directory`);
558
+ }
559
+ assertTrustedOwner(stats, currentDirectory, label);
560
+ if (process.platform !== "win32" && (stats.mode & GROUP_OTHER_WRITE_MODE_MASK) !== 0) {
561
+ const allowStickyAncestor = index > 0 && isStickyDirectory(stats);
562
+ if (!allowStickyAncestor) {
563
+ throw new Error(`${label} '${currentDirectory}' must not be writable by group/other`);
564
+ }
565
+ }
566
+ }
567
+ }
568
+ function assertSecureFile(stats, targetPath, label) {
569
+ assertTrustedOwner(stats, targetPath, label);
570
+ if (process.platform === "win32") {
571
+ return;
572
+ }
573
+ if ((stats.mode & PRIVATE_FILE_MODE_MASK) !== 0) {
574
+ throw new Error(`${label} '${targetPath}' must not grant group/other permissions`);
575
+ }
576
+ }
577
+ function assertNotSymlink(targetPath, label) {
578
+ const stats = readLstat(targetPath);
579
+ if (stats?.isSymbolicLink()) {
580
+ throw new Error(`${label} '${targetPath}' must not be a symlink`);
581
+ }
582
+ return stats;
583
+ }
584
+ function tightenPermissions(targetPath, mode) {
585
+ try {
586
+ fs.chmodSync(targetPath, mode);
587
+ } catch {
588
+ }
589
+ }
590
+ function ensurePrivateDirectory(targetPath, label) {
591
+ const normalized = normalizePath(targetPath);
592
+ assertNoSymlinkAncestorDirectories(normalized, label);
593
+ const stats = assertNotSymlink(normalized, label);
594
+ if (stats && !stats.isDirectory()) {
595
+ throw new Error(`${label} '${normalized}' must be a directory`);
596
+ }
597
+ if (!stats) {
598
+ fs.mkdirSync(normalized, { recursive: true, mode: PRIVATE_DIR_MODE });
599
+ }
600
+ tightenPermissions(normalized, PRIVATE_DIR_MODE);
601
+ assertSecureDirectoryPath(normalized, label);
602
+ return normalized;
603
+ }
604
+ function readUtf8FileSecure(targetPath, label, maxBytes) {
605
+ const normalized = normalizePath(targetPath);
606
+ assertSecureDirectoryPath(path.dirname(normalized), `${label} parent directory`);
607
+ const openFlags = process.platform === "win32" ? fs.constants.O_RDONLY : fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW;
608
+ const fd = fs.openSync(normalized, openFlags);
609
+ try {
610
+ const stats = fs.fstatSync(fd);
611
+ if (!stats.isFile()) {
612
+ throw new Error(`${label} '${normalized}' must be a regular file`);
613
+ }
614
+ assertSecureFile(stats, normalized, label);
615
+ if (maxBytes !== void 0 && stats.size > maxBytes) {
616
+ throw new Error(`${label} '${normalized}' must not exceed ${maxBytes} bytes`);
617
+ }
618
+ return fs.readFileSync(fd, "utf8");
619
+ } finally {
620
+ fs.closeSync(fd);
621
+ }
622
+ }
623
+ function readPrivateJsonFile(targetPath, label) {
624
+ const normalized = normalizePath(targetPath);
625
+ const stats = assertNotSymlink(normalized, label);
626
+ if (!stats) {
627
+ return null;
628
+ }
629
+ if (!stats.isFile()) {
630
+ throw new Error(`${label} '${normalized}' must be a regular file`);
631
+ }
632
+ tightenPermissions(normalized, PRIVATE_FILE_MODE);
633
+ return JSON.parse(readUtf8FileSecure(normalized, label, MAX_CONFIG_FILE_BYTES));
634
+ }
635
+ function assertSecurePlannedDirectoryPath(targetPath, label) {
636
+ const normalized = requirePathValue(targetPath, label);
637
+ assertNoSymlinkAncestorDirectories(normalized, label);
638
+ const stats = readLstat(normalized);
639
+ if (stats) {
640
+ if (stats.isSymbolicLink()) {
641
+ throw new Error(`${label} '${normalized}' must not be a symlink`);
642
+ }
643
+ if (!stats.isDirectory()) {
644
+ throw new Error(`${label} '${normalized}' must be a directory`);
645
+ }
646
+ assertSecureDirectoryPath(normalized, label);
647
+ return normalized;
648
+ }
649
+ const nearestExistingPath = findNearestExistingPath(normalized);
650
+ if (nearestExistingPath.stats.isSymbolicLink()) {
651
+ throw new Error(`${label} '${nearestExistingPath.path}' must not be a symlink`);
652
+ }
653
+ if (!nearestExistingPath.stats.isDirectory()) {
654
+ throw new Error(`${label} '${nearestExistingPath.path}' must be a directory`);
655
+ }
656
+ assertSecureDirectoryPath(nearestExistingPath.path, label);
657
+ return normalized;
658
+ }
659
+ function assertSecurePlannedDaemonSocketPath(targetPath, label) {
660
+ const normalized = requirePathValue(targetPath, label);
661
+ assertSecurePlannedDirectoryPath(path.dirname(normalized), `${label} directory`);
662
+ const stats = readLstat(normalized);
663
+ if (!stats) {
664
+ return normalized;
665
+ }
666
+ if (stats.isSymbolicLink()) {
667
+ throw new Error(`${label} '${normalized}' must not be a symlink`);
668
+ }
669
+ if (process.platform !== "win32" && !stats.isSocket()) {
670
+ throw new Error(`${label} '${normalized}' must be a unix socket`);
671
+ }
672
+ assertTrustedOwner(stats, normalized, label);
673
+ return normalized;
674
+ }
675
+ function assertSecurePlannedPrivateFilePath(targetPath, label) {
676
+ const normalized = requirePathValue(targetPath, label);
677
+ assertSecurePlannedDirectoryPath(path.dirname(normalized), `${label} directory`);
678
+ const stats = readLstatAllowInaccessible(normalized);
679
+ if (!stats || stats === "inaccessible") {
680
+ return normalized;
681
+ }
682
+ if (stats.isSymbolicLink()) {
683
+ throw new Error(`${label} '${normalized}' must not be a symlink`);
684
+ }
685
+ if (!stats.isFile()) {
686
+ throw new Error(`${label} '${normalized}' must be a regular file`);
687
+ }
688
+ assertSecureFile(stats, normalized, label);
689
+ return normalized;
690
+ }
691
+ function writePrivateFile(targetPath, contents, label) {
692
+ const normalized = normalizePath(targetPath);
693
+ const parent = ensurePrivateDirectory(path.dirname(normalized), `${label} parent`);
694
+ assertNotSymlink(normalized, label);
695
+ const tempPath = path.join(
696
+ parent,
697
+ `.${path.basename(normalized)}.tmp-${process.pid}-${Date.now()}`
698
+ );
699
+ try {
700
+ fs.writeFileSync(tempPath, contents, {
701
+ encoding: "utf8",
702
+ mode: PRIVATE_FILE_MODE,
703
+ flag: "wx"
704
+ });
705
+ tightenPermissions(tempPath, PRIVATE_FILE_MODE);
706
+ fs.renameSync(tempPath, normalized);
707
+ tightenPermissions(normalized, PRIVATE_FILE_MODE);
708
+ } finally {
709
+ try {
710
+ if (fs.existsSync(tempPath)) {
711
+ fs.rmSync(tempPath);
712
+ }
713
+ } catch {
714
+ }
715
+ }
716
+ }
717
+ function normalizedDefaultConfig() {
718
+ return {
719
+ daemonSocket: defaultDaemonSocketPath(),
720
+ stateFile: defaultStateFilePath(),
721
+ rustBinDir: defaultRustBinDir(),
722
+ chains: defaultChainProfiles(),
723
+ tokens: defaultTokenProfiles()
724
+ };
725
+ }
726
+ function applySeedDefaultsIfLegacyEmpty(config) {
727
+ const chainCount = Object.keys(config.chains ?? {}).length;
728
+ const tokenCount = Object.keys(config.tokens ?? {}).length;
729
+ if (chainCount === 0 && tokenCount === 0) {
730
+ return {
731
+ ...config,
732
+ chains: defaultChainProfiles(),
733
+ tokens: defaultTokenProfiles()
734
+ };
735
+ }
736
+ return config;
737
+ }
738
+ function resolveWlfiHome() {
739
+ const explicit = process.env.WLFI_HOME?.trim();
740
+ if (explicit) {
741
+ return normalizePath(explicit);
742
+ }
743
+ return path.join(os.homedir(), WLFI_DIRNAME);
744
+ }
745
+ function resolveConfigPath() {
746
+ return path.join(resolveWlfiHome(), CONFIG_FILENAME);
747
+ }
748
+ function defaultDaemonSocketPath() {
749
+ return path.join(resolveWlfiHome(), "daemon.sock");
750
+ }
751
+ function defaultStateFilePath() {
752
+ return path.join(resolveWlfiHome(), "daemon-state.enc");
753
+ }
754
+ function defaultRustBinDir() {
755
+ return path.join(resolveWlfiHome(), "bin");
756
+ }
757
+ function defaultConfig() {
758
+ return normalizedDefaultConfig();
759
+ }
760
+ function ensureWlfiHome() {
761
+ return ensurePrivateDirectory(resolveWlfiHome(), "WLFI home");
762
+ }
763
+ function readConfig() {
764
+ ensureWlfiHome();
765
+ const parsed = readPrivateJsonFile(resolveConfigPath(), "config file");
766
+ const merged = applySeedDefaultsIfLegacyEmpty({
767
+ ...normalizedDefaultConfig(),
768
+ ...parsed ?? {}
769
+ });
770
+ return {
771
+ ...merged,
772
+ wallet: normalizeWalletProfile(merged.wallet),
773
+ chains: normalizeChainProfiles(merged.chains),
774
+ tokens: normalizeTokenProfiles(merged.tokens)
775
+ };
776
+ }
777
+ function writeConfig(nextConfig) {
778
+ ensureWlfiHome();
779
+ const merged = {
780
+ ...normalizedDefaultConfig(),
781
+ ...readConfig(),
782
+ ...nextConfig
783
+ };
784
+ if (Object.prototype.hasOwnProperty.call(nextConfig, "rpcUrl") && merged.rpcUrl !== void 0) {
785
+ merged.rpcUrl = assertSafeRpcUrl(merged.rpcUrl, "rpcUrl");
786
+ }
787
+ if (Object.prototype.hasOwnProperty.call(nextConfig, "daemonSocket") && merged.daemonSocket !== void 0) {
788
+ merged.daemonSocket = assertSecurePlannedDaemonSocketPath(merged.daemonSocket, "daemonSocket");
789
+ }
790
+ if (Object.prototype.hasOwnProperty.call(nextConfig, "stateFile") && merged.stateFile !== void 0) {
791
+ merged.stateFile = assertSecurePlannedPrivateFilePath(merged.stateFile, "stateFile");
792
+ }
793
+ if (Object.prototype.hasOwnProperty.call(nextConfig, "rustBinDir") && merged.rustBinDir !== void 0) {
794
+ merged.rustBinDir = assertSecurePlannedDirectoryPath(merged.rustBinDir, "rustBinDir");
795
+ }
796
+ merged.wallet = normalizeWalletProfile(merged.wallet);
797
+ merged.chains = normalizeChainProfiles(merged.chains);
798
+ merged.tokens = normalizeTokenProfiles(merged.tokens);
799
+ writePrivateFile(resolveConfigPath(), JSON.stringify(merged, null, 2) + "\n", "config file");
800
+ return merged;
801
+ }
802
+ function deleteConfigKey(key) {
803
+ ensureWlfiHome();
804
+ const current = {
805
+ ...normalizedDefaultConfig(),
806
+ ...readConfig()
807
+ };
808
+ delete current[key];
809
+ const normalized = {
810
+ ...normalizedDefaultConfig(),
811
+ ...current,
812
+ chains: current.chains ?? {},
813
+ tokens: current.tokens ?? {}
814
+ };
815
+ writePrivateFile(resolveConfigPath(), JSON.stringify(normalized, null, 2) + "\n", "config file");
816
+ return normalized;
817
+ }
818
+ function listBuiltinChains() {
819
+ return Object.entries(BUILTIN_CHAINS).map(([key, value]) => ({ ...value, name: key })).sort((left, right) => left.chainId - right.chainId || left.name.localeCompare(right.name));
820
+ }
821
+ function listBuiltinTokens() {
822
+ return Object.entries(BUILTIN_TOKENS).map(([key, value]) => ({
823
+ key,
824
+ name: value.name,
825
+ symbol: value.symbol,
826
+ chains: Object.entries(value.chains ?? {}).map(([chainKey, chainValue]) => ({ key: chainKey, ...chainValue })).sort((left, right) => left.chainId - right.chainId || left.key.localeCompare(right.key))
827
+ })).sort((left, right) => left.key.localeCompare(right.key));
828
+ }
829
+ function listConfiguredTokens(config = readConfig()) {
830
+ return Object.entries(config.tokens ?? {}).map(([key, value]) => ({
831
+ key,
832
+ name: value.name,
833
+ symbol: value.symbol,
834
+ chains: Object.entries(value.chains ?? {}).map(([chainKey, chainValue]) => ({ key: chainKey, ...chainValue })).sort((left, right) => left.chainId - right.chainId || left.key.localeCompare(right.key))
835
+ })).sort((left, right) => left.key.localeCompare(right.key));
836
+ }
837
+ function resolveTokenProfile(selector, config = readConfig()) {
838
+ const normalized = selector.trim().toLowerCase();
839
+ if (!normalized) {
840
+ return null;
841
+ }
842
+ for (const [key, value] of Object.entries(config.tokens ?? {})) {
843
+ if (key.toLowerCase() === normalized || value.symbol.toLowerCase() === normalized) {
844
+ return { key, source: "configured", ...value };
845
+ }
846
+ }
847
+ for (const [key, value] of Object.entries(BUILTIN_TOKENS)) {
848
+ if (key.toLowerCase() === normalized || value.symbol.toLowerCase() === normalized) {
849
+ return { key, source: "builtin", ...value };
850
+ }
851
+ }
852
+ return null;
853
+ }
854
+ function listConfiguredChains(config = readConfig()) {
855
+ return Object.entries(config.chains ?? {}).map(([key, value]) => ({ key, ...value })).sort((left, right) => left.chainId - right.chainId || left.key.localeCompare(right.key));
856
+ }
857
+ function resolveChainProfile(selector, config = readConfig()) {
858
+ const normalized = selector.trim().toLowerCase();
859
+ if (!normalized) {
860
+ return null;
861
+ }
862
+ for (const [key, value] of Object.entries(config.chains ?? {})) {
863
+ if (key.toLowerCase() === normalized || value.name.toLowerCase() === normalized || String(value.chainId) === selector) {
864
+ return { ...value, key, source: "configured" };
865
+ }
866
+ }
867
+ if (BUILTIN_CHAINS[normalized]) {
868
+ return { ...BUILTIN_CHAINS[normalized], key: normalized, source: "builtin" };
869
+ }
870
+ if (config.chainId !== void 0 && String(config.chainId) === selector) {
871
+ return {
872
+ chainId: config.chainId,
873
+ name: config.chainName ?? normalized,
874
+ rpcUrl: config.rpcUrl,
875
+ source: "active"
876
+ };
877
+ }
878
+ return null;
879
+ }
880
+ function saveChainProfile(key, profile) {
881
+ const normalizedKey = key.trim().toLowerCase();
882
+ if (!normalizedKey) {
883
+ throw new Error("chain profile key is required");
884
+ }
885
+ const normalizedProfile = normalizeChainProfileEntry(normalizedKey, profile);
886
+ return writeConfig({
887
+ chains: {
888
+ ...readConfig().chains ?? {},
889
+ [normalizedKey]: normalizedProfile
890
+ }
891
+ });
892
+ }
893
+ function removeChainProfile(key) {
894
+ const normalizedKey = key.trim().toLowerCase();
895
+ const nextChains = { ...readConfig().chains ?? {} };
896
+ delete nextChains[normalizedKey];
897
+ return writeConfig({ chains: nextChains });
898
+ }
899
+ function saveTokenProfile(key, profile) {
900
+ const normalizedKey = key.trim().toLowerCase();
901
+ return writeConfig({
902
+ tokens: {
903
+ ...readConfig().tokens ?? {},
904
+ [normalizedKey]: normalizeTokenProfile(normalizedKey, profile)
905
+ }
906
+ });
907
+ }
908
+ function saveTokenChainProfile(tokenKey, chainKey, profile, options = {}) {
909
+ const normalizedTokenKey = tokenKey.trim().toLowerCase();
910
+ const normalizedChainKey = chainKey.trim().toLowerCase();
911
+ const current = readConfig();
912
+ const existing = current.tokens?.[normalizedTokenKey];
913
+ const symbol = options.symbol?.trim() || existing?.symbol;
914
+ if (!symbol) {
915
+ throw new Error(`token '${normalizedTokenKey}' symbol is required`);
916
+ }
917
+ return writeConfig({
918
+ tokens: {
919
+ ...current.tokens ?? {},
920
+ [normalizedTokenKey]: normalizeTokenProfile(normalizedTokenKey, {
921
+ name: existing?.name,
922
+ symbol,
923
+ defaultPolicy: existing?.defaultPolicy,
924
+ destinationOverrides: existing?.destinationOverrides,
925
+ manualApprovalPolicies: existing?.manualApprovalPolicies,
926
+ chains: {
927
+ ...existing?.chains ?? {},
928
+ [normalizedChainKey]: normalizeTokenChainProfile(normalizedTokenKey, normalizedChainKey, profile)
929
+ }
930
+ })
931
+ }
932
+ });
933
+ }
934
+ function removeTokenProfile(key) {
935
+ const normalizedKey = key.trim().toLowerCase();
936
+ const nextTokens = { ...readConfig().tokens ?? {} };
937
+ delete nextTokens[normalizedKey];
938
+ return writeConfig({ tokens: nextTokens });
939
+ }
940
+ function removeTokenChainProfile(tokenKey, chainKey) {
941
+ const normalizedTokenKey = tokenKey.trim().toLowerCase();
942
+ const normalizedChainKey = chainKey.trim().toLowerCase();
943
+ const current = readConfig();
944
+ const token = current.tokens?.[normalizedTokenKey];
945
+ if (!token) {
946
+ return current;
947
+ }
948
+ const nextChains = { ...token.chains ?? {} };
949
+ delete nextChains[normalizedChainKey];
950
+ const nextTokens = { ...current.tokens ?? {} };
951
+ if (Object.keys(nextChains).length === 0) {
952
+ delete nextTokens[normalizedTokenKey];
953
+ } else {
954
+ nextTokens[normalizedTokenKey] = normalizeTokenProfile(normalizedTokenKey, {
955
+ name: token.name,
956
+ symbol: token.symbol,
957
+ defaultPolicy: token.defaultPolicy,
958
+ destinationOverrides: token.destinationOverrides,
959
+ manualApprovalPolicies: token.manualApprovalPolicies,
960
+ chains: nextChains
961
+ });
962
+ }
963
+ return writeConfig({ tokens: nextTokens });
964
+ }
965
+ function switchActiveChain(selector, options = {}) {
966
+ const config = readConfig();
967
+ const profile = resolveChainProfile(selector, config);
968
+ if (!profile) {
969
+ throw new Error(`Unknown chain selector: ${selector}`);
970
+ }
971
+ const nextRpcUrl = options.rpcUrl ?? profile.rpcUrl;
972
+ const normalizedRpcUrl = nextRpcUrl ? assertSafeRpcUrl(nextRpcUrl, "rpcUrl") : void 0;
973
+ let next = writeConfig({
974
+ chainId: profile.chainId,
975
+ chainName: profile.name,
976
+ rpcUrl: normalizedRpcUrl,
977
+ chains: config.chains ?? {}
978
+ });
979
+ if (options.persistProfile) {
980
+ next = saveChainProfile(profile.key ?? profile.name, {
981
+ chainId: profile.chainId,
982
+ name: profile.name,
983
+ rpcUrl: normalizedRpcUrl
984
+ });
985
+ }
986
+ return next;
987
+ }
988
+ function redactConfig(config) {
989
+ return {
990
+ ...config,
991
+ agentAuthToken: config.agentAuthToken ? "<redacted>" : void 0,
992
+ paths: {
993
+ wlfiHome: resolveWlfiHome(),
994
+ configPath: resolveConfigPath(),
995
+ daemonSocket: config.daemonSocket ?? defaultDaemonSocketPath(),
996
+ stateFile: config.stateFile ?? defaultStateFilePath(),
997
+ rustBinDir: config.rustBinDir ?? defaultRustBinDir()
998
+ }
999
+ };
1000
+ }
1001
+ function resolveRustBinaryPath(binaryName, config = readConfig()) {
1002
+ return path.join(config.rustBinDir ?? defaultRustBinDir(), binaryName + (process.platform === "win32" ? ".exe" : ""));
1003
+ }
1004
+ export {
1005
+ BUILTIN_CHAINS,
1006
+ BUILTIN_TOKENS,
1007
+ CONFIG_FILENAME,
1008
+ WLFI_DIRNAME,
1009
+ allowedOwnerUids,
1010
+ assertSafeRpcUrl,
1011
+ defaultConfig,
1012
+ defaultDaemonSocketPath,
1013
+ defaultRustBinDir,
1014
+ defaultStateFilePath,
1015
+ deleteConfigKey,
1016
+ ensureWlfiHome,
1017
+ listBuiltinChains,
1018
+ listBuiltinTokens,
1019
+ listConfiguredChains,
1020
+ listConfiguredTokens,
1021
+ readConfig,
1022
+ redactConfig,
1023
+ removeChainProfile,
1024
+ removeTokenChainProfile,
1025
+ removeTokenProfile,
1026
+ resolveChainProfile,
1027
+ resolveConfigPath,
1028
+ resolveRustBinaryPath,
1029
+ resolveTokenProfile,
1030
+ resolveWlfiHome,
1031
+ saveChainProfile,
1032
+ saveTokenChainProfile,
1033
+ saveTokenProfile,
1034
+ switchActiveChain,
1035
+ writeConfig
1036
+ };
1037
+ //# sourceMappingURL=index.cjs.map