miladyai 2.0.0-alpha.27
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/dist/_virtual/_rolldown/runtime.js +7 -0
- package/dist/actions/emote.js +64 -0
- package/dist/actions/restart.js +81 -0
- package/dist/actions/send-message.js +152 -0
- package/dist/agent-admin-routes.js +82 -0
- package/dist/agent-lifecycle-routes.js +79 -0
- package/dist/agent-transfer-routes.js +102 -0
- package/dist/api/agent-admin-routes.js +82 -0
- package/dist/api/agent-lifecycle-routes.js +79 -0
- package/dist/api/agent-transfer-routes.js +102 -0
- package/dist/api/apps-hyperscape-routes.js +58 -0
- package/dist/api/apps-routes.js +114 -0
- package/dist/api/auth-routes.js +56 -0
- package/dist/api/autonomy-routes.js +44 -0
- package/dist/api/bug-report-routes.js +111 -0
- package/dist/api/character-routes.js +195 -0
- package/dist/api/cloud-routes.js +330 -0
- package/dist/api/cloud-status-routes.js +155 -0
- package/dist/api/compat-utils.js +111 -0
- package/dist/api/database.js +735 -0
- package/dist/api/diagnostics-routes.js +205 -0
- package/dist/api/drop-service.js +134 -0
- package/dist/api/early-logs.js +86 -0
- package/dist/api/http-helpers.js +131 -0
- package/dist/api/knowledge-routes.js +534 -0
- package/dist/api/memory-bounds.js +71 -0
- package/dist/api/models-routes.js +28 -0
- package/dist/api/og-tracker.js +36 -0
- package/dist/api/permissions-routes.js +109 -0
- package/dist/api/plugin-validation.js +198 -0
- package/dist/api/provider-switch-config.js +41 -0
- package/dist/api/registry-routes.js +86 -0
- package/dist/api/registry-service.js +164 -0
- package/dist/api/sandbox-routes.js +1112 -0
- package/dist/api/server.js +7949 -0
- package/dist/api/subscription-routes.js +172 -0
- package/dist/api/terminal-run-limits.js +24 -0
- package/dist/api/training-routes.js +158 -0
- package/dist/api/trajectory-routes.js +300 -0
- package/dist/api/trigger-routes.js +246 -0
- package/dist/api/twitter-verify.js +134 -0
- package/dist/api/tx-service.js +108 -0
- package/dist/api/wallet-routes.js +266 -0
- package/dist/api/wallet.js +568 -0
- package/dist/api/whatsapp-routes.js +182 -0
- package/dist/api/zip-utils.js +109 -0
- package/dist/apps-hyperscape-routes.js +58 -0
- package/dist/apps-routes.js +114 -0
- package/dist/ascii.js +20 -0
- package/dist/auth/anthropic.js +44 -0
- package/dist/auth/apply-stealth.js +41 -0
- package/dist/auth/claude-code-stealth.js +78 -0
- package/dist/auth/credentials.js +156 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/openai-codex.js +66 -0
- package/dist/auth/types.js +9 -0
- package/dist/auth-routes.js +56 -0
- package/dist/autonomy-routes.js +44 -0
- package/dist/bug-report-routes.js +111 -0
- package/dist/build-info.json +6 -0
- package/dist/character-routes.js +195 -0
- package/dist/cli/argv.js +63 -0
- package/dist/cli/banner.js +34 -0
- package/dist/cli/cli-name.js +21 -0
- package/dist/cli/cli-utils.js +16 -0
- package/dist/cli/git-commit.js +78 -0
- package/dist/cli/parse-duration.js +15 -0
- package/dist/cli/plugins-cli.js +590 -0
- package/dist/cli/profile-utils.js +9 -0
- package/dist/cli/profile.js +95 -0
- package/dist/cli/program/build-program.js +17 -0
- package/dist/cli/program/command-registry.js +23 -0
- package/dist/cli/program/help.js +47 -0
- package/dist/cli/program/preaction.js +33 -0
- package/dist/cli/program/register.config.js +106 -0
- package/dist/cli/program/register.configure.js +20 -0
- package/dist/cli/program/register.dashboard.js +124 -0
- package/dist/cli/program/register.models.js +23 -0
- package/dist/cli/program/register.setup.js +36 -0
- package/dist/cli/program/register.start.js +22 -0
- package/dist/cli/program/register.subclis.js +70 -0
- package/dist/cli/program/register.tui.js +163 -0
- package/dist/cli/program/register.update.js +154 -0
- package/dist/cli/program.js +3 -0
- package/dist/cli/run-main.js +37 -0
- package/dist/cli/version.js +7 -0
- package/dist/cloud/validate-url.js +93 -0
- package/dist/cloud-routes.js +330 -0
- package/dist/cloud-status-routes.js +155 -0
- package/dist/compat-utils.js +111 -0
- package/dist/config/config.js +69 -0
- package/dist/config/env-vars.js +19 -0
- package/dist/config/includes.js +121 -0
- package/dist/config/object-utils.js +7 -0
- package/dist/config/paths.js +38 -0
- package/dist/config/plugin-auto-enable.js +231 -0
- package/dist/config/schema.js +864 -0
- package/dist/config/telegram-custom-commands.js +76 -0
- package/dist/config/zod-schema.agent-runtime.js +519 -0
- package/dist/config/zod-schema.core.js +538 -0
- package/dist/config/zod-schema.hooks.js +103 -0
- package/dist/config/zod-schema.js +488 -0
- package/dist/config/zod-schema.providers-core.js +785 -0
- package/dist/config/zod-schema.session.js +73 -0
- package/dist/core-plugins.js +37 -0
- package/dist/custom-actions.js +250 -0
- package/dist/database.js +735 -0
- package/dist/diagnostics/integration-observability.js +57 -0
- package/dist/diagnostics-routes.js +205 -0
- package/dist/drop-service.js +134 -0
- package/dist/early-logs.js +24 -0
- package/dist/eliza.js +2061 -0
- package/dist/emotes/catalog.js +271 -0
- package/dist/entry.js +40 -0
- package/dist/hooks/discovery.js +167 -0
- package/dist/hooks/eligibility.js +64 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/loader.js +147 -0
- package/dist/hooks/registry.js +55 -0
- package/dist/http-helpers.js +131 -0
- package/dist/index.js +49 -0
- package/dist/knowledge-routes.js +534 -0
- package/dist/memory-bounds.js +71 -0
- package/dist/milady-plugin.js +90 -0
- package/dist/models-routes.js +28 -0
- package/dist/onboarding-names.js +78 -0
- package/dist/onboarding-presets.js +922 -0
- package/dist/package.json +1 -0
- package/dist/permissions-routes.js +109 -0
- package/dist/plugin-validation.js +107 -0
- package/dist/plugins/whatsapp/actions.js +91 -0
- package/dist/plugins/whatsapp/index.js +16 -0
- package/dist/plugins/whatsapp/service.js +270 -0
- package/dist/provider-switch-config.js +41 -0
- package/dist/providers/admin-trust.js +46 -0
- package/dist/providers/autonomous-state.js +101 -0
- package/dist/providers/session-bridge.js +86 -0
- package/dist/providers/session-utils.js +36 -0
- package/dist/providers/simple-mode.js +50 -0
- package/dist/providers/ui-catalog.js +15 -0
- package/dist/providers/workspace-provider.js +93 -0
- package/dist/providers/workspace.js +348 -0
- package/dist/registry-routes.js +86 -0
- package/dist/registry-service.js +164 -0
- package/dist/restart.js +40 -0
- package/dist/runtime/core-plugins.js +37 -0
- package/dist/runtime/custom-actions.js +250 -0
- package/dist/runtime/eliza.js +2061 -0
- package/dist/runtime/embedding-manager-support.js +185 -0
- package/dist/runtime/embedding-manager.js +193 -0
- package/dist/runtime/embedding-presets.js +54 -0
- package/dist/runtime/embedding-state.js +8 -0
- package/dist/runtime/milady-plugin.js +90 -0
- package/dist/runtime/onboarding-names.js +78 -0
- package/dist/runtime/restart.js +40 -0
- package/dist/runtime/version.js +7 -0
- package/dist/sandbox-routes.js +1112 -0
- package/dist/security/audit-log.js +149 -0
- package/dist/security/network-policy.js +70 -0
- package/dist/server.js +7949 -0
- package/dist/services/agent-export.js +559 -0
- package/dist/services/app-manager.js +389 -0
- package/dist/services/browser-capture.js +86 -0
- package/dist/services/fallback-training-service.js +128 -0
- package/dist/services/mcp-marketplace.js +134 -0
- package/dist/services/plugin-installer.js +396 -0
- package/dist/services/plugin-manager-types.js +15 -0
- package/dist/services/registry-client-app-meta.js +144 -0
- package/dist/services/registry-client-endpoints.js +166 -0
- package/dist/services/registry-client-local.js +271 -0
- package/dist/services/registry-client-network.js +93 -0
- package/dist/services/registry-client-queries.js +70 -0
- package/dist/services/registry-client.js +157 -0
- package/dist/services/sandbox-engine.js +511 -0
- package/dist/services/sandbox-manager.js +297 -0
- package/dist/services/self-updater.js +175 -0
- package/dist/services/skill-catalog-client.js +119 -0
- package/dist/services/skill-marketplace.js +521 -0
- package/dist/services/stream-manager.js +236 -0
- package/dist/services/update-checker.js +121 -0
- package/dist/services/update-notifier.js +29 -0
- package/dist/services/version-compat.js +78 -0
- package/dist/services/whatsapp-pairing.js +196 -0
- package/dist/shared/ui-catalog-prompt.js +728 -0
- package/dist/subscription-routes.js +172 -0
- package/dist/terminal/links.js +19 -0
- package/dist/terminal/palette.js +14 -0
- package/dist/terminal/theme.js +25 -0
- package/dist/terminal-run-limits.js +24 -0
- package/dist/training-routes.js +158 -0
- package/dist/trajectory-routes.js +300 -0
- package/dist/trigger-routes.js +246 -0
- package/dist/triggers/action.js +218 -0
- package/dist/triggers/runtime.js +281 -0
- package/dist/triggers/scheduling.js +295 -0
- package/dist/triggers/types.js +5 -0
- package/dist/tui/components/assistant-message.js +76 -0
- package/dist/tui/components/chat-editor.js +34 -0
- package/dist/tui/components/embeddings-overlay.js +46 -0
- package/dist/tui/components/footer.js +60 -0
- package/dist/tui/components/index.js +15 -0
- package/dist/tui/components/modal-frame.js +45 -0
- package/dist/tui/components/modal-style.js +15 -0
- package/dist/tui/components/model-selector.js +70 -0
- package/dist/tui/components/pinned-chat-layout.js +46 -0
- package/dist/tui/components/plugins-endpoints-tab.js +196 -0
- package/dist/tui/components/plugins-installed-tab-view.js +69 -0
- package/dist/tui/components/plugins-installed-tab.js +319 -0
- package/dist/tui/components/plugins-overlay-catalog.js +81 -0
- package/dist/tui/components/plugins-overlay-data-api.js +21 -0
- package/dist/tui/components/plugins-overlay-data-shared.js +20 -0
- package/dist/tui/components/plugins-overlay-data.js +323 -0
- package/dist/tui/components/plugins-overlay.js +117 -0
- package/dist/tui/components/plugins-store-tab.js +148 -0
- package/dist/tui/components/settings-overlay.js +61 -0
- package/dist/tui/components/status-bar.js +64 -0
- package/dist/tui/components/tool-execution.js +68 -0
- package/dist/tui/components/user-message.js +22 -0
- package/dist/tui/eliza-tui-bridge.js +606 -0
- package/dist/tui/index.js +370 -0
- package/dist/tui/modal-presets.js +33 -0
- package/dist/tui/model-spec.js +46 -0
- package/dist/tui/sse-parser.js +78 -0
- package/dist/tui/theme.js +110 -0
- package/dist/tui/titlebar-spinner.js +62 -0
- package/dist/tui/tui-app.js +311 -0
- package/dist/tui/ws-client.js +215 -0
- package/dist/twitter-verify.js +134 -0
- package/dist/tx-service.js +108 -0
- package/dist/utils/exec-safety.js +17 -0
- package/dist/utils/globals.js +20 -0
- package/dist/utils/milady-root.js +61 -0
- package/dist/utils/number-parsing.js +37 -0
- package/dist/version-resolver.js +37 -0
- package/dist/version.js +7 -0
- package/dist/wallet-routes.js +266 -0
- package/dist/wallet.js +568 -0
- package/dist/whatsapp-routes.js +182 -0
- package/dist/zip-utils.js +109 -0
- package/milady.mjs +14 -0
- package/package.json +111 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { logger } from "@elizaos/core";
|
|
2
|
+
import { ethers } from "ethers";
|
|
3
|
+
|
|
4
|
+
//#region src/api/tx-service.ts
|
|
5
|
+
/**
|
|
6
|
+
* Ethereum transaction signing and contract interaction layer.
|
|
7
|
+
*
|
|
8
|
+
* Provides the missing transaction capability to Milady's wallet system,
|
|
9
|
+
* which currently only handles key generation and balance fetching.
|
|
10
|
+
* Used by the registry and drop services for on-chain operations.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Validate that a private key is a valid 32-byte hex string.
|
|
14
|
+
*/
|
|
15
|
+
function isValidPrivateKey(key) {
|
|
16
|
+
const normalized = key.startsWith("0x") ? key.slice(2) : key;
|
|
17
|
+
if (normalized.length !== 64) return false;
|
|
18
|
+
return /^[0-9a-fA-F]+$/.test(normalized);
|
|
19
|
+
}
|
|
20
|
+
var TxService = class {
|
|
21
|
+
constructor(rpcUrl, privateKey) {
|
|
22
|
+
this.rpcUrl = rpcUrl;
|
|
23
|
+
this.provider = new ethers.JsonRpcProvider(rpcUrl);
|
|
24
|
+
if (!isValidPrivateKey(privateKey)) {
|
|
25
|
+
const preview = privateKey.length > 10 ? `${privateKey.slice(0, 6)}...${privateKey.slice(-4)}` : "(empty or too short)";
|
|
26
|
+
throw new Error(`Invalid EVM_PRIVATE_KEY: expected 64-character hex string, got ${preview}. Please set a valid private key in your environment or .env file.`);
|
|
27
|
+
}
|
|
28
|
+
const normalizedKey = privateKey.startsWith("0x") ? privateKey : `0x${privateKey}`;
|
|
29
|
+
this.wallet = new ethers.Wallet(normalizedKey, this.provider);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get fresh nonce for the wallet address.
|
|
33
|
+
* Always fetches from blockchain using a fresh provider to avoid caching issues.
|
|
34
|
+
* This ensures we always get the correct nonce even after failed transactions.
|
|
35
|
+
*/
|
|
36
|
+
async getFreshNonce() {
|
|
37
|
+
const freshProvider = new ethers.JsonRpcProvider(this.rpcUrl);
|
|
38
|
+
try {
|
|
39
|
+
return await freshProvider.getTransactionCount(this.wallet.address, "pending");
|
|
40
|
+
} finally {
|
|
41
|
+
freshProvider.destroy();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
get address() {
|
|
45
|
+
return this.wallet.address;
|
|
46
|
+
}
|
|
47
|
+
async getBalance() {
|
|
48
|
+
return this.provider.getBalance(this.wallet.address);
|
|
49
|
+
}
|
|
50
|
+
async getBalanceFormatted() {
|
|
51
|
+
const balance = await this.getBalance();
|
|
52
|
+
return ethers.formatEther(balance);
|
|
53
|
+
}
|
|
54
|
+
async getChainId() {
|
|
55
|
+
const network = await this.provider.getNetwork();
|
|
56
|
+
return Number(network.chainId);
|
|
57
|
+
}
|
|
58
|
+
getContract(address, abi) {
|
|
59
|
+
return new ethers.Contract(address, abi, this.wallet);
|
|
60
|
+
}
|
|
61
|
+
getReadOnlyContract(address, abi) {
|
|
62
|
+
return new ethers.Contract(address, abi, this.provider);
|
|
63
|
+
}
|
|
64
|
+
async estimateGas(tx) {
|
|
65
|
+
return this.provider.estimateGas(tx);
|
|
66
|
+
}
|
|
67
|
+
async getFeeData() {
|
|
68
|
+
return this.provider.getFeeData();
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Wait for a transaction to be mined and return the receipt.
|
|
72
|
+
* Throws if the transaction fails or times out.
|
|
73
|
+
*/
|
|
74
|
+
async waitForTransaction(txHash, confirmations = 1, timeoutMs = 12e4) {
|
|
75
|
+
const receipt = await this.provider.waitForTransaction(txHash, confirmations, timeoutMs);
|
|
76
|
+
if (!receipt) throw new Error(`Transaction ${txHash} timed out after ${timeoutMs}ms`);
|
|
77
|
+
if (receipt.status === 0) throw new Error(`Transaction ${txHash} reverted`);
|
|
78
|
+
return receipt;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Estimate the gas cost in ETH for a contract call.
|
|
82
|
+
* Useful for showing users how much gas they'll need.
|
|
83
|
+
*/
|
|
84
|
+
async estimateGasCostEth(tx) {
|
|
85
|
+
const gasLimit = await this.estimateGas(tx);
|
|
86
|
+
const feeData = await this.getFeeData();
|
|
87
|
+
const costWei = gasLimit * (feeData.gasPrice ?? feeData.maxFeePerGas ?? 0n);
|
|
88
|
+
return ethers.formatEther(costWei);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Check whether the wallet has enough balance for a given value + estimated gas.
|
|
92
|
+
*/
|
|
93
|
+
async hasEnoughBalance(value, gasEstimate) {
|
|
94
|
+
const balance = await this.getBalance();
|
|
95
|
+
const feeData = await this.getFeeData();
|
|
96
|
+
return balance >= value + gasEstimate * (feeData.gasPrice ?? feeData.maxFeePerGas ?? 0n);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Log a summary of the tx service state for diagnostics.
|
|
100
|
+
*/
|
|
101
|
+
async logStatus() {
|
|
102
|
+
const [balance, chainId] = await Promise.all([this.getBalanceFormatted(), this.getChainId()]);
|
|
103
|
+
logger.info(`[tx-service] address=${this.address} chain=${chainId} balance=${balance} ETH`);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
//#endregion
|
|
108
|
+
export { TxService };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/utils/exec-safety.ts
|
|
2
|
+
const UNSAFE_CHARS = /[\0\r\n;&|`$<>"']/;
|
|
3
|
+
const BARE_NAME = /^[A-Za-z0-9._+-]+$/;
|
|
4
|
+
function isLikelyPath(value) {
|
|
5
|
+
return value.startsWith(".") || value.startsWith("~") || value.includes("/") || value.includes("\\") || /^[A-Za-z]:[\\/]/.test(value);
|
|
6
|
+
}
|
|
7
|
+
function isSafeExecutableValue(value) {
|
|
8
|
+
const trimmed = value?.trim();
|
|
9
|
+
if (!trimmed) return false;
|
|
10
|
+
if (UNSAFE_CHARS.test(trimmed)) return false;
|
|
11
|
+
if (isLikelyPath(trimmed)) return true;
|
|
12
|
+
if (trimmed.startsWith("-")) return false;
|
|
13
|
+
return BARE_NAME.test(trimmed);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { isSafeExecutableValue };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import "../terminal/theme.js";
|
|
2
|
+
import { logger } from "@elizaos/core";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/globals.ts
|
|
5
|
+
const TRUTHY_VALUES = new Set([
|
|
6
|
+
"true",
|
|
7
|
+
"1",
|
|
8
|
+
"yes",
|
|
9
|
+
"on"
|
|
10
|
+
]);
|
|
11
|
+
function isTruthyEnvValue(value) {
|
|
12
|
+
return TRUTHY_VALUES.has((value ?? "").trim().toLowerCase());
|
|
13
|
+
}
|
|
14
|
+
let globalVerbose = false;
|
|
15
|
+
function setVerbose(v) {
|
|
16
|
+
globalVerbose = v;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
export { isTruthyEnvValue, setVerbose };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import fs$1 from "node:fs/promises";
|
|
5
|
+
|
|
6
|
+
//#region src/utils/milady-root.ts
|
|
7
|
+
const CORE_PACKAGE_NAME = "milady";
|
|
8
|
+
function readPackageNameSync(dir) {
|
|
9
|
+
try {
|
|
10
|
+
const raw = fs.readFileSync(path.join(dir, "package.json"), "utf-8");
|
|
11
|
+
const parsed = JSON.parse(raw);
|
|
12
|
+
return typeof parsed.name === "string" ? parsed.name : null;
|
|
13
|
+
} catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function listAncestorDirs(startDir, maxDepth = 12) {
|
|
18
|
+
const dirs = [];
|
|
19
|
+
let current = path.resolve(startDir);
|
|
20
|
+
for (let i = 0; i < maxDepth; i += 1) {
|
|
21
|
+
dirs.push(current);
|
|
22
|
+
const parent = path.dirname(current);
|
|
23
|
+
if (parent === current) break;
|
|
24
|
+
current = parent;
|
|
25
|
+
}
|
|
26
|
+
return dirs;
|
|
27
|
+
}
|
|
28
|
+
function findPackageRootSync(startDir, maxDepth = 12) {
|
|
29
|
+
for (const candidate of listAncestorDirs(startDir, maxDepth)) if (readPackageNameSync(candidate) === CORE_PACKAGE_NAME) return candidate;
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function candidateDirsFromArgv1(argv1) {
|
|
33
|
+
const normalized = path.resolve(argv1);
|
|
34
|
+
const candidates = [path.dirname(normalized)];
|
|
35
|
+
const parts = normalized.split(path.sep);
|
|
36
|
+
const binIndex = parts.lastIndexOf(".bin");
|
|
37
|
+
if (binIndex > 0 && parts[binIndex - 1] === "node_modules") {
|
|
38
|
+
const binName = path.basename(normalized);
|
|
39
|
+
const nodeModulesDir = parts.slice(0, binIndex).join(path.sep);
|
|
40
|
+
candidates.push(path.join(nodeModulesDir, binName));
|
|
41
|
+
}
|
|
42
|
+
return candidates;
|
|
43
|
+
}
|
|
44
|
+
function candidateDirsFromOptions(opts) {
|
|
45
|
+
const candidates = [];
|
|
46
|
+
if (opts.moduleUrl) candidates.push(path.dirname(fileURLToPath(opts.moduleUrl)));
|
|
47
|
+
if (opts.argv1) candidates.push(...candidateDirsFromArgv1(opts.argv1));
|
|
48
|
+
if (opts.cwd) candidates.push(opts.cwd);
|
|
49
|
+
return candidates;
|
|
50
|
+
}
|
|
51
|
+
function resolveMiladyPackageRootSync(opts) {
|
|
52
|
+
const candidates = candidateDirsFromOptions(opts);
|
|
53
|
+
for (const candidate of candidates) {
|
|
54
|
+
const found = findPackageRootSync(candidate);
|
|
55
|
+
if (found) return found;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//#endregion
|
|
61
|
+
export { resolveMiladyPackageRootSync };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//#region src/utils/number-parsing.ts
|
|
2
|
+
function sanitizeNumericText(value) {
|
|
3
|
+
return value == null ? "" : value.trim();
|
|
4
|
+
}
|
|
5
|
+
function normalizeFallback(fallback) {
|
|
6
|
+
return Number.isFinite(fallback) ? fallback : void 0;
|
|
7
|
+
}
|
|
8
|
+
function parsePositiveInteger(value, fallback) {
|
|
9
|
+
const raw = sanitizeNumericText(value);
|
|
10
|
+
if (!raw) return normalizeFallback(fallback);
|
|
11
|
+
const parsed = Number(raw);
|
|
12
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return normalizeFallback(fallback);
|
|
13
|
+
return Math.max(1, Math.floor(parsed));
|
|
14
|
+
}
|
|
15
|
+
function parseClampedFloat(value, options = {}) {
|
|
16
|
+
const raw = sanitizeNumericText(value);
|
|
17
|
+
if (!raw) return normalizeFallback(options.fallback);
|
|
18
|
+
const parsed = Number(raw);
|
|
19
|
+
if (!Number.isFinite(parsed)) return normalizeFallback(options.fallback);
|
|
20
|
+
const min = options.min ?? -Infinity;
|
|
21
|
+
const max = options.max ?? Infinity;
|
|
22
|
+
return Math.max(min, Math.min(max, parsed));
|
|
23
|
+
}
|
|
24
|
+
function parseClampedInteger(value, options = {}) {
|
|
25
|
+
const raw = sanitizeNumericText(value);
|
|
26
|
+
if (!raw) return normalizeFallback(options.fallback);
|
|
27
|
+
const parsed = Number.parseInt(raw, 10);
|
|
28
|
+
if (!Number.isFinite(parsed)) return normalizeFallback(options.fallback);
|
|
29
|
+
const min = options.min;
|
|
30
|
+
if (min !== void 0 && parsed < min) return min;
|
|
31
|
+
const max = options.max;
|
|
32
|
+
if (max !== void 0 && parsed > max) return max;
|
|
33
|
+
return parsed;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { parseClampedFloat, parseClampedInteger, parsePositiveInteger };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
|
|
4
|
+
//#region src/version-resolver.ts
|
|
5
|
+
const PACKAGE_JSON_CANDIDATE = "../../package.json";
|
|
6
|
+
const BUILD_INFO_CANDIDATES = [
|
|
7
|
+
"../../build-info.json",
|
|
8
|
+
"../build-info.json",
|
|
9
|
+
"./build-info.json"
|
|
10
|
+
];
|
|
11
|
+
function isModuleNotFound(err) {
|
|
12
|
+
return typeof err === "object" && err !== null && "code" in err && err.code === "MODULE_NOT_FOUND";
|
|
13
|
+
}
|
|
14
|
+
function readVersionFromPackageJson(requireFn) {
|
|
15
|
+
try {
|
|
16
|
+
return requireFn(PACKAGE_JSON_CANDIDATE).version ?? null;
|
|
17
|
+
} catch (err) {
|
|
18
|
+
if (isModuleNotFound(err)) return null;
|
|
19
|
+
throw err;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function readVersionFromBuildInfo(requireFn) {
|
|
23
|
+
for (const candidate of BUILD_INFO_CANDIDATES) try {
|
|
24
|
+
const info = requireFn(candidate);
|
|
25
|
+
if (info.version) return info.version;
|
|
26
|
+
} catch (err) {
|
|
27
|
+
if (!isModuleNotFound(err)) throw err;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
function resolveMiladyVersion(moduleUrl) {
|
|
32
|
+
const requireFn = createRequire(moduleUrl);
|
|
33
|
+
return typeof __MILADY_VERSION__ === "string" && __MILADY_VERSION__ || process.env.MILADY_BUNDLED_VERSION || readVersionFromPackageJson(requireFn) || readVersionFromBuildInfo(requireFn) || "0.0.0";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { resolveMiladyVersion };
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { fetchEvmBalances, fetchEvmNfts, fetchSolanaBalances, fetchSolanaNfts, generateWalletForChain, getWalletAddresses, importWallet, validatePrivateKey } from "./wallet.js";
|
|
2
|
+
import { createIntegrationTelemetrySpan } from "./diagnostics/integration-observability.js";
|
|
3
|
+
import { logger } from "@elizaos/core";
|
|
4
|
+
|
|
5
|
+
//#region src/api/wallet-routes.ts
|
|
6
|
+
const DEFAULT_WALLET_ROUTE_DEPENDENCIES = {
|
|
7
|
+
getWalletAddresses,
|
|
8
|
+
fetchEvmBalances,
|
|
9
|
+
fetchSolanaBalances,
|
|
10
|
+
fetchEvmNfts,
|
|
11
|
+
fetchSolanaNfts,
|
|
12
|
+
validatePrivateKey,
|
|
13
|
+
importWallet,
|
|
14
|
+
generateWalletForChain
|
|
15
|
+
};
|
|
16
|
+
async function handleWalletRoutes(ctx) {
|
|
17
|
+
const { req, res, method, pathname, config, saveConfig, ensureWalletKeysInEnvAndConfig, resolveWalletExportRejection, readJsonBody, json, error } = ctx;
|
|
18
|
+
const deps = ctx.deps ?? DEFAULT_WALLET_ROUTE_DEPENDENCIES;
|
|
19
|
+
if (method === "GET" && pathname === "/api/wallet/addresses") {
|
|
20
|
+
json(res, deps.getWalletAddresses());
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
if (method === "GET" && pathname === "/api/wallet/balances") {
|
|
24
|
+
const addresses = deps.getWalletAddresses();
|
|
25
|
+
const alchemyKey = process.env.ALCHEMY_API_KEY;
|
|
26
|
+
const heliusKey = process.env.HELIUS_API_KEY;
|
|
27
|
+
const result = {
|
|
28
|
+
evm: null,
|
|
29
|
+
solana: null
|
|
30
|
+
};
|
|
31
|
+
if (addresses.evmAddress && alchemyKey) {
|
|
32
|
+
const evmBalancesSpan = createIntegrationTelemetrySpan({
|
|
33
|
+
boundary: "wallet",
|
|
34
|
+
operation: "fetch_evm_balances"
|
|
35
|
+
});
|
|
36
|
+
try {
|
|
37
|
+
const chains = await deps.fetchEvmBalances(addresses.evmAddress, alchemyKey);
|
|
38
|
+
result.evm = {
|
|
39
|
+
address: addresses.evmAddress,
|
|
40
|
+
chains
|
|
41
|
+
};
|
|
42
|
+
evmBalancesSpan.success();
|
|
43
|
+
} catch (err) {
|
|
44
|
+
evmBalancesSpan.failure({ error: err });
|
|
45
|
+
logger.warn(`[wallet] EVM balance fetch failed: ${err}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (addresses.solanaAddress && heliusKey) {
|
|
49
|
+
const solanaBalancesSpan = createIntegrationTelemetrySpan({
|
|
50
|
+
boundary: "wallet",
|
|
51
|
+
operation: "fetch_solana_balances"
|
|
52
|
+
});
|
|
53
|
+
try {
|
|
54
|
+
const solanaData = await deps.fetchSolanaBalances(addresses.solanaAddress, heliusKey);
|
|
55
|
+
result.solana = {
|
|
56
|
+
address: addresses.solanaAddress,
|
|
57
|
+
...solanaData
|
|
58
|
+
};
|
|
59
|
+
solanaBalancesSpan.success();
|
|
60
|
+
} catch (err) {
|
|
61
|
+
solanaBalancesSpan.failure({ error: err });
|
|
62
|
+
logger.warn(`[wallet] Solana balance fetch failed: ${err}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
json(res, result);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
if (method === "GET" && pathname === "/api/wallet/nfts") {
|
|
69
|
+
const addresses = deps.getWalletAddresses();
|
|
70
|
+
const alchemyKey = process.env.ALCHEMY_API_KEY;
|
|
71
|
+
const heliusKey = process.env.HELIUS_API_KEY;
|
|
72
|
+
const result = {
|
|
73
|
+
evm: [],
|
|
74
|
+
solana: null
|
|
75
|
+
};
|
|
76
|
+
if (addresses.evmAddress && alchemyKey) {
|
|
77
|
+
const evmNftsSpan = createIntegrationTelemetrySpan({
|
|
78
|
+
boundary: "wallet",
|
|
79
|
+
operation: "fetch_evm_nfts"
|
|
80
|
+
});
|
|
81
|
+
try {
|
|
82
|
+
result.evm = await deps.fetchEvmNfts(addresses.evmAddress, alchemyKey);
|
|
83
|
+
evmNftsSpan.success();
|
|
84
|
+
} catch (err) {
|
|
85
|
+
evmNftsSpan.failure({ error: err });
|
|
86
|
+
logger.warn(`[wallet] EVM NFT fetch failed: ${err}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (addresses.solanaAddress && heliusKey) {
|
|
90
|
+
const solanaNftsSpan = createIntegrationTelemetrySpan({
|
|
91
|
+
boundary: "wallet",
|
|
92
|
+
operation: "fetch_solana_nfts"
|
|
93
|
+
});
|
|
94
|
+
try {
|
|
95
|
+
result.solana = { nfts: await deps.fetchSolanaNfts(addresses.solanaAddress, heliusKey) };
|
|
96
|
+
solanaNftsSpan.success();
|
|
97
|
+
} catch (err) {
|
|
98
|
+
solanaNftsSpan.failure({ error: err });
|
|
99
|
+
logger.warn(`[wallet] Solana NFT fetch failed: ${err}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
json(res, result);
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
if (method === "POST" && pathname === "/api/wallet/import") {
|
|
106
|
+
const body = await readJsonBody(req, res);
|
|
107
|
+
if (!body) return true;
|
|
108
|
+
if (!body.privateKey?.trim()) {
|
|
109
|
+
error(res, "privateKey is required");
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
let chain;
|
|
113
|
+
if (body.chain === "evm" || body.chain === "solana") chain = body.chain;
|
|
114
|
+
else if (body.chain) {
|
|
115
|
+
error(res, `Unsupported chain: ${body.chain}. Must be "evm" or "solana".`);
|
|
116
|
+
return true;
|
|
117
|
+
} else chain = deps.validatePrivateKey(body.privateKey.trim()).chain;
|
|
118
|
+
const result = deps.importWallet(chain, body.privateKey.trim());
|
|
119
|
+
if (!result.success) {
|
|
120
|
+
error(res, result.error ?? "Import failed", 422);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
if (!config.env) config.env = {};
|
|
124
|
+
const envKey = chain === "evm" ? "EVM_PRIVATE_KEY" : "SOLANA_PRIVATE_KEY";
|
|
125
|
+
config.env[envKey] = process.env[envKey] ?? "";
|
|
126
|
+
try {
|
|
127
|
+
saveConfig(config);
|
|
128
|
+
} catch (err) {
|
|
129
|
+
logger.warn(`[api] Config save failed: ${err instanceof Error ? err.message : err}`);
|
|
130
|
+
}
|
|
131
|
+
json(res, {
|
|
132
|
+
ok: true,
|
|
133
|
+
chain,
|
|
134
|
+
address: result.address
|
|
135
|
+
});
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
if (method === "POST" && pathname === "/api/wallet/generate") {
|
|
139
|
+
const body = await readJsonBody(req, res);
|
|
140
|
+
if (!body) return true;
|
|
141
|
+
const chain = body.chain;
|
|
142
|
+
if (chain && ![
|
|
143
|
+
"evm",
|
|
144
|
+
"solana",
|
|
145
|
+
"both"
|
|
146
|
+
].includes(chain)) {
|
|
147
|
+
error(res, `Unsupported chain: ${chain}. Must be "evm", "solana", or "both".`);
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
const targetChain = chain ?? "both";
|
|
151
|
+
if (!config.env) config.env = {};
|
|
152
|
+
const generated = [];
|
|
153
|
+
if (targetChain === "both" || targetChain === "evm") {
|
|
154
|
+
const result = deps.generateWalletForChain("evm");
|
|
155
|
+
process.env.EVM_PRIVATE_KEY = result.privateKey;
|
|
156
|
+
config.env.EVM_PRIVATE_KEY = result.privateKey;
|
|
157
|
+
generated.push({
|
|
158
|
+
chain: "evm",
|
|
159
|
+
address: result.address
|
|
160
|
+
});
|
|
161
|
+
logger.info(`[milady-api] Generated EVM wallet: ${result.address}`);
|
|
162
|
+
}
|
|
163
|
+
if (targetChain === "both" || targetChain === "solana") {
|
|
164
|
+
const result = deps.generateWalletForChain("solana");
|
|
165
|
+
process.env.SOLANA_PRIVATE_KEY = result.privateKey;
|
|
166
|
+
config.env.SOLANA_PRIVATE_KEY = result.privateKey;
|
|
167
|
+
generated.push({
|
|
168
|
+
chain: "solana",
|
|
169
|
+
address: result.address
|
|
170
|
+
});
|
|
171
|
+
logger.info(`[milady-api] Generated Solana wallet: ${result.address}`);
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
saveConfig(config);
|
|
175
|
+
} catch (err) {
|
|
176
|
+
logger.warn(`[api] Config save failed: ${err instanceof Error ? err.message : err}`);
|
|
177
|
+
}
|
|
178
|
+
json(res, {
|
|
179
|
+
ok: true,
|
|
180
|
+
wallets: generated
|
|
181
|
+
});
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
if (method === "GET" && pathname === "/api/wallet/config") {
|
|
185
|
+
const addresses = deps.getWalletAddresses();
|
|
186
|
+
json(res, {
|
|
187
|
+
alchemyKeySet: Boolean(process.env.ALCHEMY_API_KEY),
|
|
188
|
+
infuraKeySet: Boolean(process.env.INFURA_API_KEY),
|
|
189
|
+
ankrKeySet: Boolean(process.env.ANKR_API_KEY),
|
|
190
|
+
heliusKeySet: Boolean(process.env.HELIUS_API_KEY),
|
|
191
|
+
birdeyeKeySet: Boolean(process.env.BIRDEYE_API_KEY),
|
|
192
|
+
evmChains: [
|
|
193
|
+
"Ethereum",
|
|
194
|
+
"Base",
|
|
195
|
+
"Arbitrum",
|
|
196
|
+
"Optimism",
|
|
197
|
+
"Polygon"
|
|
198
|
+
],
|
|
199
|
+
evmAddress: addresses.evmAddress,
|
|
200
|
+
solanaAddress: addresses.solanaAddress
|
|
201
|
+
});
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
if (method === "PUT" && pathname === "/api/wallet/config") {
|
|
205
|
+
const body = await readJsonBody(req, res);
|
|
206
|
+
if (!body) return true;
|
|
207
|
+
const allowedKeys = [
|
|
208
|
+
"ALCHEMY_API_KEY",
|
|
209
|
+
"INFURA_API_KEY",
|
|
210
|
+
"ANKR_API_KEY",
|
|
211
|
+
"HELIUS_API_KEY",
|
|
212
|
+
"BIRDEYE_API_KEY"
|
|
213
|
+
];
|
|
214
|
+
if (!config.env) config.env = {};
|
|
215
|
+
for (const key of allowedKeys) {
|
|
216
|
+
const value = body[key];
|
|
217
|
+
if (typeof value === "string" && value.trim()) {
|
|
218
|
+
process.env[key] = value.trim();
|
|
219
|
+
config.env[key] = value.trim();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const heliusValue = body.HELIUS_API_KEY;
|
|
223
|
+
if (typeof heliusValue === "string" && heliusValue.trim()) {
|
|
224
|
+
const rpcUrl = `https://mainnet.helius-rpc.com/?api-key=${heliusValue.trim()}`;
|
|
225
|
+
process.env.SOLANA_RPC_URL = rpcUrl;
|
|
226
|
+
config.env.SOLANA_RPC_URL = rpcUrl;
|
|
227
|
+
}
|
|
228
|
+
ensureWalletKeysInEnvAndConfig(config);
|
|
229
|
+
try {
|
|
230
|
+
saveConfig(config);
|
|
231
|
+
} catch (err) {
|
|
232
|
+
logger.warn(`[api] Config save failed: ${err instanceof Error ? err.message : err}`);
|
|
233
|
+
}
|
|
234
|
+
json(res, { ok: true });
|
|
235
|
+
ctx.scheduleRuntimeRestart?.("Wallet configuration updated");
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
if (method === "POST" && pathname === "/api/wallet/export") {
|
|
239
|
+
const body = await readJsonBody(req, res);
|
|
240
|
+
if (!body) return true;
|
|
241
|
+
const rejection = resolveWalletExportRejection(req, body);
|
|
242
|
+
if (rejection) {
|
|
243
|
+
error(res, rejection.reason, rejection.status);
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
const evmKey = process.env.EVM_PRIVATE_KEY ?? null;
|
|
247
|
+
const solanaKey = process.env.SOLANA_PRIVATE_KEY ?? null;
|
|
248
|
+
const addresses = deps.getWalletAddresses();
|
|
249
|
+
logger.warn("[wallet] Private keys exported via API");
|
|
250
|
+
json(res, {
|
|
251
|
+
evm: evmKey ? {
|
|
252
|
+
privateKey: evmKey,
|
|
253
|
+
address: addresses.evmAddress
|
|
254
|
+
} : null,
|
|
255
|
+
solana: solanaKey ? {
|
|
256
|
+
privateKey: solanaKey,
|
|
257
|
+
address: addresses.solanaAddress
|
|
258
|
+
} : null
|
|
259
|
+
});
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
//#endregion
|
|
266
|
+
export { handleWalletRoutes };
|