@elizaos/plugin-steward-app 2.0.3-beta.6 → 2.0.3-beta.7
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/ApprovalQueue.d.ts +18 -0
- package/dist/ApprovalQueue.d.ts.map +1 -0
- package/dist/ApprovalQueue.js +420 -0
- package/dist/ApprovalQueue.js.map +1 -0
- package/dist/StewardLogo.d.ts +11 -0
- package/dist/StewardLogo.d.ts.map +1 -0
- package/dist/StewardLogo.js +36 -0
- package/dist/StewardLogo.js.map +1 -0
- package/dist/StewardView.d.ts +13 -0
- package/dist/StewardView.d.ts.map +1 -0
- package/dist/StewardView.helpers.d.ts +15 -0
- package/dist/StewardView.helpers.d.ts.map +1 -0
- package/dist/StewardView.helpers.js +45 -0
- package/dist/StewardView.helpers.js.map +1 -0
- package/dist/StewardView.interact.d.ts +2 -0
- package/dist/StewardView.interact.d.ts.map +1 -0
- package/dist/StewardView.interact.js +54 -0
- package/dist/StewardView.interact.js.map +1 -0
- package/dist/StewardView.js +249 -0
- package/dist/StewardView.js.map +1 -0
- package/dist/TransactionHistory.d.ts +22 -0
- package/dist/TransactionHistory.d.ts.map +1 -0
- package/dist/TransactionHistory.js +361 -0
- package/dist/TransactionHistory.js.map +1 -0
- package/dist/__fixtures__/steward-sdk-fixtures.d.ts +10 -0
- package/dist/__fixtures__/steward-sdk-fixtures.d.ts.map +1 -0
- package/dist/__fixtures__/steward-sdk-fixtures.js +60 -0
- package/dist/__fixtures__/steward-sdk-fixtures.js.map +1 -0
- package/dist/actions/wallet-action-shared.d.ts +15 -0
- package/dist/actions/wallet-action-shared.d.ts.map +1 -0
- package/dist/actions/wallet-action-shared.js +16 -0
- package/dist/actions/wallet-action-shared.js.map +1 -0
- package/dist/api/binance-skill-helpers.d.ts +21 -0
- package/dist/api/binance-skill-helpers.d.ts.map +1 -0
- package/dist/api/binance-skill-helpers.js +790 -0
- package/dist/api/binance-skill-helpers.js.map +1 -0
- package/dist/api/bsc-trade.d.ts +36 -0
- package/dist/api/bsc-trade.d.ts.map +1 -0
- package/dist/api/bsc-trade.js +796 -0
- package/dist/api/bsc-trade.js.map +1 -0
- package/dist/api/trade-safety.d.ts +35 -0
- package/dist/api/trade-safety.d.ts.map +1 -0
- package/dist/api/trade-safety.js +56 -0
- package/dist/api/trade-safety.js.map +1 -0
- package/dist/api/tx-service.d.ts +53 -0
- package/dist/api/tx-service.d.ts.map +1 -0
- package/dist/api/tx-service.js +206 -0
- package/dist/api/tx-service.js.map +1 -0
- package/dist/api/wallet-bsc-routes.d.ts +63 -0
- package/dist/api/wallet-bsc-routes.d.ts.map +1 -0
- package/dist/api/wallet-bsc-routes.js +337 -0
- package/dist/api/wallet-bsc-routes.js.map +1 -0
- package/dist/api/wallet-capability.d.ts +2 -0
- package/dist/api/wallet-capability.d.ts.map +1 -0
- package/dist/api/wallet-capability.js +15 -0
- package/dist/api/wallet-capability.js.map +1 -0
- package/dist/api/wallet-dex-prices.d.ts +43 -0
- package/dist/api/wallet-dex-prices.d.ts.map +1 -0
- package/dist/api/wallet-dex-prices.js +132 -0
- package/dist/api/wallet-dex-prices.js.map +1 -0
- package/dist/api/wallet-evm-balance.d.ts +72 -0
- package/dist/api/wallet-evm-balance.d.ts.map +1 -0
- package/dist/api/wallet-evm-balance.js +697 -0
- package/dist/api/wallet-evm-balance.js.map +1 -0
- package/dist/api/wallet-routes.d.ts +27 -0
- package/dist/api/wallet-routes.d.ts.map +1 -0
- package/dist/api/wallet-routes.js +556 -0
- package/dist/api/wallet-routes.js.map +1 -0
- package/dist/api/wallet-rpc.d.ts +73 -0
- package/dist/api/wallet-rpc.d.ts.map +1 -0
- package/dist/api/wallet-rpc.js +460 -0
- package/dist/api/wallet-rpc.js.map +1 -0
- package/dist/api/wallet-trade-routes.d.ts +104 -0
- package/dist/api/wallet-trade-routes.d.ts.map +1 -0
- package/dist/api/wallet-trade-routes.js +353 -0
- package/dist/api/wallet-trade-routes.js.map +1 -0
- package/dist/api/wallet-trading-profile.d.ts +31 -0
- package/dist/api/wallet-trading-profile.d.ts.map +1 -0
- package/dist/api/wallet-trading-profile.js +500 -0
- package/dist/api/wallet-trading-profile.js.map +1 -0
- package/dist/api/wallet.d.ts +60 -0
- package/dist/api/wallet.d.ts.map +1 -0
- package/dist/api/wallet.js +617 -0
- package/dist/api/wallet.js.map +1 -0
- package/dist/chain-utils.d.ts +10 -0
- package/dist/chain-utils.d.ts.map +1 -0
- package/dist/chain-utils.js +81 -0
- package/dist/chain-utils.js.map +1 -0
- package/dist/components/StewardSpatialView.d.ts +74 -0
- package/dist/components/StewardSpatialView.d.ts.map +1 -0
- package/dist/components/StewardSpatialView.js +309 -0
- package/dist/components/StewardSpatialView.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +21 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +319 -0
- package/dist/plugin.js.map +1 -0
- package/dist/providers/steward-balance.d.ts +12 -0
- package/dist/providers/steward-balance.d.ts.map +1 -0
- package/dist/providers/steward-balance.js +85 -0
- package/dist/providers/steward-balance.js.map +1 -0
- package/dist/providers/steward-receive-address.d.ts +12 -0
- package/dist/providers/steward-receive-address.d.ts.map +1 -0
- package/dist/providers/steward-receive-address.js +47 -0
- package/dist/providers/steward-receive-address.js.map +1 -0
- package/dist/register-routes.d.ts +2 -0
- package/dist/register-routes.d.ts.map +1 -0
- package/dist/register-routes.js +6 -0
- package/dist/register-routes.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +34 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/routes/steward-bridge.d.ts +202 -0
- package/dist/routes/steward-bridge.d.ts.map +1 -0
- package/dist/routes/steward-bridge.js +776 -0
- package/dist/routes/steward-bridge.js.map +1 -0
- package/dist/routes/steward-compat-routes.d.ts +21 -0
- package/dist/routes/steward-compat-routes.d.ts.map +1 -0
- package/dist/routes/steward-compat-routes.js +350 -0
- package/dist/routes/steward-compat-routes.js.map +1 -0
- package/dist/routes/wallet-browser-compat-routes.d.ts +6 -0
- package/dist/routes/wallet-browser-compat-routes.d.ts.map +1 -0
- package/dist/routes/wallet-browser-compat-routes.js +402 -0
- package/dist/routes/wallet-browser-compat-routes.js.map +1 -0
- package/dist/routes/wallet-bsc-core-routes.d.ts +15 -0
- package/dist/routes/wallet-bsc-core-routes.d.ts.map +1 -0
- package/dist/routes/wallet-bsc-core-routes.js +59 -0
- package/dist/routes/wallet-bsc-core-routes.js.map +1 -0
- package/dist/routes/wallet-compat-routes.d.ts +13 -0
- package/dist/routes/wallet-compat-routes.d.ts.map +1 -0
- package/dist/routes/wallet-compat-routes.js +206 -0
- package/dist/routes/wallet-compat-routes.js.map +1 -0
- package/dist/routes/wallet-core-routes.d.ts +16 -0
- package/dist/routes/wallet-core-routes.d.ts.map +1 -0
- package/dist/routes/wallet-core-routes.js +48 -0
- package/dist/routes/wallet-core-routes.js.map +1 -0
- package/dist/routes/wallet-trade-compat-routes.d.ts +11 -0
- package/dist/routes/wallet-trade-compat-routes.d.ts.map +1 -0
- package/dist/routes/wallet-trade-compat-routes.js +570 -0
- package/dist/routes/wallet-trade-compat-routes.js.map +1 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.d.ts +7 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.d.ts.map +1 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.js +43 -0
- package/dist/security/hydrate-wallet-keys-from-platform-store.js.map +1 -0
- package/dist/security/wallet-os-store-actions.d.ts +14 -0
- package/dist/security/wallet-os-store-actions.d.ts.map +1 -0
- package/dist/security/wallet-os-store-actions.js +63 -0
- package/dist/security/wallet-os-store-actions.js.map +1 -0
- package/dist/services/steward-credentials.d.ts +2 -0
- package/dist/services/steward-credentials.d.ts.map +1 -0
- package/dist/services/steward-credentials.js +2 -0
- package/dist/services/steward-credentials.js.map +1 -0
- package/dist/services/steward-evm-account.d.ts +75 -0
- package/dist/services/steward-evm-account.d.ts.map +1 -0
- package/dist/services/steward-evm-account.js +279 -0
- package/dist/services/steward-evm-account.js.map +1 -0
- package/dist/services/steward-evm-bridge.d.ts +36 -0
- package/dist/services/steward-evm-bridge.d.ts.map +1 -0
- package/dist/services/steward-evm-bridge.js +78 -0
- package/dist/services/steward-evm-bridge.js.map +1 -0
- package/dist/services/steward-sidecar/health-check.d.ts +2 -0
- package/dist/services/steward-sidecar/health-check.d.ts.map +1 -0
- package/dist/services/steward-sidecar/health-check.js +2 -0
- package/dist/services/steward-sidecar/health-check.js.map +1 -0
- package/dist/services/steward-sidecar/helpers.d.ts +2 -0
- package/dist/services/steward-sidecar/helpers.d.ts.map +1 -0
- package/dist/services/steward-sidecar/helpers.js +2 -0
- package/dist/services/steward-sidecar/helpers.js.map +1 -0
- package/dist/services/steward-sidecar/process-management.d.ts +2 -0
- package/dist/services/steward-sidecar/process-management.d.ts.map +1 -0
- package/dist/services/steward-sidecar/process-management.js +2 -0
- package/dist/services/steward-sidecar/process-management.js.map +1 -0
- package/dist/services/steward-sidecar/types.d.ts +2 -0
- package/dist/services/steward-sidecar/types.d.ts.map +1 -0
- package/dist/services/steward-sidecar/types.js +2 -0
- package/dist/services/steward-sidecar/types.js.map +1 -0
- package/dist/services/steward-sidecar/wallet-setup.d.ts +2 -0
- package/dist/services/steward-sidecar/wallet-setup.d.ts.map +1 -0
- package/dist/services/steward-sidecar/wallet-setup.js +2 -0
- package/dist/services/steward-sidecar/wallet-setup.js.map +1 -0
- package/dist/services/steward-sidecar.d.ts +2 -0
- package/dist/services/steward-sidecar.d.ts.map +1 -0
- package/dist/services/steward-sidecar.js +2 -0
- package/dist/services/steward-sidecar.js.map +1 -0
- package/dist/services/steward-wallet.d.ts +25 -0
- package/dist/services/steward-wallet.d.ts.map +1 -0
- package/dist/services/steward-wallet.js +333 -0
- package/dist/services/steward-wallet.js.map +1 -0
- package/dist/steward-ui-state.d.ts +14 -0
- package/dist/steward-ui-state.d.ts.map +1 -0
- package/dist/steward-ui-state.js +46 -0
- package/dist/steward-ui-state.js.map +1 -0
- package/dist/steward-view-bundle.d.ts +3 -0
- package/dist/steward-view-bundle.d.ts.map +1 -0
- package/dist/steward-view-bundle.js +7 -0
- package/dist/steward-view-bundle.js.map +1 -0
- package/dist/types/bsc-trade.d.ts +180 -0
- package/dist/types/bsc-trade.d.ts.map +1 -0
- package/dist/types/bsc-trade.js +1 -0
- package/dist/types/bsc-trade.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/steward.d.ts +83 -0
- package/dist/types/steward.d.ts.map +1 -0
- package/dist/types/steward.js +1 -0
- package/dist/types/steward.js.map +1 -0
- package/dist/ui.d.ts +7 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +7 -0
- package/dist/ui.js.map +1 -0
- package/dist/views/bundle.js +601 -0
- package/dist/views/bundle.js.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createIntegrationTelemetrySpan,
|
|
3
|
+
persistConfigEnv
|
|
4
|
+
} from "@elizaos/agent";
|
|
5
|
+
import {
|
|
6
|
+
logger,
|
|
7
|
+
normalizeWalletRpcSelections
|
|
8
|
+
} from "@elizaos/core";
|
|
9
|
+
import {
|
|
10
|
+
fetchEvmBalances,
|
|
11
|
+
fetchSolanaBalances,
|
|
12
|
+
fetchSolanaNativeBalanceViaRpc,
|
|
13
|
+
generateWalletForChain,
|
|
14
|
+
getWalletAddresses,
|
|
15
|
+
importWallet,
|
|
16
|
+
setSolanaWalletEnv,
|
|
17
|
+
validatePrivateKey
|
|
18
|
+
} from "./wallet.js";
|
|
19
|
+
import { resolveWalletCapabilityStatus } from "./wallet-capability.js";
|
|
20
|
+
import {
|
|
21
|
+
applyWalletRpcConfigUpdate,
|
|
22
|
+
getStoredWalletRpcSelections,
|
|
23
|
+
resolveWalletNetworkMode,
|
|
24
|
+
resolveWalletRpcReadiness
|
|
25
|
+
} from "./wallet-rpc.js";
|
|
26
|
+
const IS_TEST = process.env.NODE_ENV === "test" || !!process.env.VITEST;
|
|
27
|
+
const WALLET_EXPORT_MAX_ATTEMPTS = IS_TEST ? 500 : 5;
|
|
28
|
+
const WALLET_EXPORT_WINDOW_MS = 15 * 6e4;
|
|
29
|
+
const walletExportAttempts = /* @__PURE__ */ new Map();
|
|
30
|
+
function rateLimitWalletExport(req) {
|
|
31
|
+
const key = req.socket?.remoteAddress ?? "unknown";
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
if (walletExportAttempts.size > 50) {
|
|
34
|
+
for (const [k, v] of walletExportAttempts) {
|
|
35
|
+
if (now > v.resetAt) walletExportAttempts.delete(k);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const current = walletExportAttempts.get(key);
|
|
39
|
+
if (!current || now > current.resetAt) {
|
|
40
|
+
walletExportAttempts.set(key, {
|
|
41
|
+
count: 1,
|
|
42
|
+
resetAt: now + WALLET_EXPORT_WINDOW_MS
|
|
43
|
+
});
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
if (current.count >= WALLET_EXPORT_MAX_ATTEMPTS) return false;
|
|
47
|
+
current.count += 1;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
const WALLET_CONFIG_COMPAT_KEYS = /* @__PURE__ */ new Set([
|
|
51
|
+
"ALCHEMY_API_KEY",
|
|
52
|
+
"INFURA_API_KEY",
|
|
53
|
+
"ANKR_API_KEY",
|
|
54
|
+
"ETHEREUM_RPC_URL",
|
|
55
|
+
"BASE_RPC_URL",
|
|
56
|
+
"AVALANCHE_RPC_URL",
|
|
57
|
+
"HELIUS_API_KEY",
|
|
58
|
+
"BIRDEYE_API_KEY",
|
|
59
|
+
"NODEREAL_BSC_RPC_URL",
|
|
60
|
+
"QUICKNODE_BSC_RPC_URL",
|
|
61
|
+
"BSC_RPC_URL",
|
|
62
|
+
"SOLANA_RPC_URL"
|
|
63
|
+
]);
|
|
64
|
+
function isRecord(value) {
|
|
65
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
66
|
+
}
|
|
67
|
+
function readStringField(record, key) {
|
|
68
|
+
const value = record[key];
|
|
69
|
+
return typeof value === "string" ? value : void 0;
|
|
70
|
+
}
|
|
71
|
+
function readStewardAgentWalletPayload(value) {
|
|
72
|
+
const envelope = isRecord(value) ? value : {};
|
|
73
|
+
const payload = isRecord(envelope.data) ? envelope.data : envelope;
|
|
74
|
+
const walletAddresses = isRecord(payload.walletAddresses) ? {
|
|
75
|
+
evm: readStringField(payload.walletAddresses, "evm"),
|
|
76
|
+
solana: readStringField(payload.walletAddresses, "solana")
|
|
77
|
+
} : void 0;
|
|
78
|
+
return {
|
|
79
|
+
walletAddress: readStringField(payload, "walletAddress"),
|
|
80
|
+
walletAddresses
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function resolveWalletConfigUpdateRequest(body, currentSelections) {
|
|
84
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const record = body;
|
|
88
|
+
if (record.selections && typeof record.selections === "object" && !Array.isArray(record.selections)) {
|
|
89
|
+
const walletNetwork = record.walletNetwork === "testnet" || record.walletNetwork === "mainnet" ? record.walletNetwork : void 0;
|
|
90
|
+
const credentials = record.credentials && typeof record.credentials === "object" && !Array.isArray(record.credentials) ? Object.fromEntries(
|
|
91
|
+
Object.entries(
|
|
92
|
+
record.credentials
|
|
93
|
+
).filter(([, value]) => typeof value === "string")
|
|
94
|
+
) : void 0;
|
|
95
|
+
return {
|
|
96
|
+
selections: normalizeWalletRpcSelections(
|
|
97
|
+
record.selections
|
|
98
|
+
),
|
|
99
|
+
walletNetwork,
|
|
100
|
+
credentials
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const compatCredentials = Object.fromEntries(
|
|
104
|
+
Object.entries(record).filter(
|
|
105
|
+
([key, value]) => WALLET_CONFIG_COMPAT_KEYS.has(key) && typeof value === "string"
|
|
106
|
+
)
|
|
107
|
+
);
|
|
108
|
+
if (Object.keys(compatCredentials).length === 0) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
selections: currentSelections,
|
|
113
|
+
walletNetwork: record.walletNetwork === "testnet" || record.walletNetwork === "mainnet" ? record.walletNetwork : void 0,
|
|
114
|
+
credentials: compatCredentials
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const DEFAULT_WALLET_ROUTE_DEPENDENCIES = {
|
|
118
|
+
getWalletAddresses,
|
|
119
|
+
fetchEvmBalances,
|
|
120
|
+
fetchSolanaBalances,
|
|
121
|
+
fetchSolanaNativeBalanceViaRpc,
|
|
122
|
+
validatePrivateKey,
|
|
123
|
+
importWallet,
|
|
124
|
+
generateWalletForChain
|
|
125
|
+
};
|
|
126
|
+
function persistPrimarySelection(config, chain, source) {
|
|
127
|
+
if (!config.wallet) {
|
|
128
|
+
config.wallet = {};
|
|
129
|
+
}
|
|
130
|
+
const wallet = config.wallet;
|
|
131
|
+
const primary = { ...wallet.primary ?? {} };
|
|
132
|
+
primary[chain] = source;
|
|
133
|
+
wallet.primary = primary;
|
|
134
|
+
config.wallet = wallet;
|
|
135
|
+
}
|
|
136
|
+
async function triggerWalletRuntimeReload(ctx, reason) {
|
|
137
|
+
const restarted = ctx.restartRuntime ? await ctx.restartRuntime(reason) : false;
|
|
138
|
+
if (!restarted) {
|
|
139
|
+
ctx.scheduleRuntimeRestart?.(reason);
|
|
140
|
+
}
|
|
141
|
+
return restarted;
|
|
142
|
+
}
|
|
143
|
+
const LOCAL_WALLET_SOURCE_ENV_KEYS = {
|
|
144
|
+
evm: "WALLET_SOURCE_EVM",
|
|
145
|
+
solana: "WALLET_SOURCE_SOLANA"
|
|
146
|
+
};
|
|
147
|
+
async function handleWalletRoutes(ctx) {
|
|
148
|
+
const {
|
|
149
|
+
req,
|
|
150
|
+
res,
|
|
151
|
+
method,
|
|
152
|
+
pathname,
|
|
153
|
+
config,
|
|
154
|
+
saveConfig,
|
|
155
|
+
resolveWalletExportRejection,
|
|
156
|
+
readJsonBody,
|
|
157
|
+
json,
|
|
158
|
+
error
|
|
159
|
+
} = ctx;
|
|
160
|
+
const deps = ctx.deps ?? DEFAULT_WALLET_ROUTE_DEPENDENCIES;
|
|
161
|
+
if (method === "GET" && pathname === "/api/wallet/addresses") {
|
|
162
|
+
json(res, deps.getWalletAddresses());
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
if (method === "GET" && pathname === "/api/wallet/balances") {
|
|
166
|
+
const addresses = deps.getWalletAddresses();
|
|
167
|
+
const rpcReadiness = resolveWalletRpcReadiness(config);
|
|
168
|
+
const alchemyKey = process.env.ALCHEMY_API_KEY?.trim() || null;
|
|
169
|
+
const ankrKey = process.env.ANKR_API_KEY?.trim() || null;
|
|
170
|
+
const heliusKey = process.env.HELIUS_API_KEY?.trim() || null;
|
|
171
|
+
const result = { evm: null, solana: null };
|
|
172
|
+
if (addresses.evmAddress && rpcReadiness.evmBalanceReady) {
|
|
173
|
+
const evmBalancesSpan = createIntegrationTelemetrySpan({
|
|
174
|
+
boundary: "wallet",
|
|
175
|
+
operation: "fetch_evm_balances"
|
|
176
|
+
});
|
|
177
|
+
try {
|
|
178
|
+
const chains = await deps.fetchEvmBalances(addresses.evmAddress, {
|
|
179
|
+
alchemyKey,
|
|
180
|
+
ankrKey,
|
|
181
|
+
cloudManagedAccess: rpcReadiness.cloudManagedAccess,
|
|
182
|
+
bscRpcUrls: rpcReadiness.bscRpcUrls,
|
|
183
|
+
ethereumRpcUrls: rpcReadiness.ethereumRpcUrls,
|
|
184
|
+
baseRpcUrls: rpcReadiness.baseRpcUrls,
|
|
185
|
+
avaxRpcUrls: rpcReadiness.avalancheRpcUrls,
|
|
186
|
+
nodeRealBscRpcUrl: process.env.NODEREAL_BSC_RPC_URL,
|
|
187
|
+
quickNodeBscRpcUrl: process.env.QUICKNODE_BSC_RPC_URL,
|
|
188
|
+
bscRpcUrl: process.env.BSC_RPC_URL,
|
|
189
|
+
ethereumRpcUrl: process.env.ETHEREUM_RPC_URL,
|
|
190
|
+
baseRpcUrl: process.env.BASE_RPC_URL,
|
|
191
|
+
avaxRpcUrl: process.env.AVALANCHE_RPC_URL
|
|
192
|
+
});
|
|
193
|
+
result.evm = { address: addresses.evmAddress, chains };
|
|
194
|
+
evmBalancesSpan.success();
|
|
195
|
+
} catch (err) {
|
|
196
|
+
evmBalancesSpan.failure({ error: err });
|
|
197
|
+
logger.warn(`[wallet] EVM balance fetch failed: ${err}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (addresses.solanaAddress && rpcReadiness.solanaBalanceReady) {
|
|
201
|
+
const solanaBalancesSpan = createIntegrationTelemetrySpan({
|
|
202
|
+
boundary: "wallet",
|
|
203
|
+
operation: "fetch_solana_balances"
|
|
204
|
+
});
|
|
205
|
+
try {
|
|
206
|
+
const solanaData = heliusKey ? await deps.fetchSolanaBalances(addresses.solanaAddress, heliusKey) : await deps.fetchSolanaNativeBalanceViaRpc(
|
|
207
|
+
addresses.solanaAddress,
|
|
208
|
+
rpcReadiness.solanaRpcUrls
|
|
209
|
+
);
|
|
210
|
+
result.solana = { address: addresses.solanaAddress, ...solanaData };
|
|
211
|
+
solanaBalancesSpan.success();
|
|
212
|
+
} catch (err) {
|
|
213
|
+
solanaBalancesSpan.failure({ error: err });
|
|
214
|
+
logger.warn(`[wallet] Solana balance fetch failed: ${err}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
json(res, result);
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
if (method === "POST" && pathname === "/api/wallet/import") {
|
|
221
|
+
const body = await readJsonBody(
|
|
222
|
+
req,
|
|
223
|
+
res
|
|
224
|
+
);
|
|
225
|
+
if (!body) return true;
|
|
226
|
+
if (!body.privateKey?.trim()) {
|
|
227
|
+
error(res, "privateKey is required");
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
let chain;
|
|
231
|
+
if (body.chain === "evm" || body.chain === "solana") {
|
|
232
|
+
chain = body.chain;
|
|
233
|
+
} else if (body.chain) {
|
|
234
|
+
error(
|
|
235
|
+
res,
|
|
236
|
+
`Unsupported chain: ${body.chain}. Must be "evm" or "solana".`
|
|
237
|
+
);
|
|
238
|
+
return true;
|
|
239
|
+
} else {
|
|
240
|
+
const detection = deps.validatePrivateKey(body.privateKey.trim());
|
|
241
|
+
chain = detection.chain;
|
|
242
|
+
}
|
|
243
|
+
const stewardWarning = process.env.STEWARD_API_URL?.trim() ? "Steward vault is configured. Consider importing keys directly into the vault instead of storing plaintext keys locally." : void 0;
|
|
244
|
+
const result = deps.importWallet(chain, body.privateKey.trim());
|
|
245
|
+
if (!result.success) {
|
|
246
|
+
error(res, result.error ?? "Import failed", 422);
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
if (!config.env) config.env = {};
|
|
250
|
+
const envKey = chain === "evm" ? "EVM_PRIVATE_KEY" : "SOLANA_PRIVATE_KEY";
|
|
251
|
+
config.env[envKey] = process.env[envKey] ?? "";
|
|
252
|
+
persistPrimarySelection(config, chain, "local");
|
|
253
|
+
let configSaveWarning;
|
|
254
|
+
try {
|
|
255
|
+
saveConfig(config);
|
|
256
|
+
} catch (err) {
|
|
257
|
+
const msg = `Config save failed: ${String(err)}`;
|
|
258
|
+
logger.warn(`[api] ${msg}`);
|
|
259
|
+
configSaveWarning = msg;
|
|
260
|
+
}
|
|
261
|
+
const warnings = [];
|
|
262
|
+
if (configSaveWarning) warnings.push(configSaveWarning);
|
|
263
|
+
if (stewardWarning) warnings.push(stewardWarning);
|
|
264
|
+
const walletSourceEnvKey = LOCAL_WALLET_SOURCE_ENV_KEYS[chain];
|
|
265
|
+
process.env[walletSourceEnvKey] = "local";
|
|
266
|
+
try {
|
|
267
|
+
await persistConfigEnv(walletSourceEnvKey, "local");
|
|
268
|
+
} catch (err) {
|
|
269
|
+
error(
|
|
270
|
+
res,
|
|
271
|
+
`Failed to persist ${walletSourceEnvKey}: ${String(err)}`,
|
|
272
|
+
500
|
|
273
|
+
);
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
const restarted = await triggerWalletRuntimeReload(
|
|
277
|
+
ctx,
|
|
278
|
+
"Wallet configuration updated"
|
|
279
|
+
);
|
|
280
|
+
json(res, {
|
|
281
|
+
ok: true,
|
|
282
|
+
chain,
|
|
283
|
+
address: result.address,
|
|
284
|
+
restarting: restarted,
|
|
285
|
+
...warnings.length > 0 ? { warnings } : {}
|
|
286
|
+
});
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
if (method === "POST" && pathname === "/api/wallet/generate") {
|
|
290
|
+
const body = await readJsonBody(req, res);
|
|
291
|
+
if (!body) return true;
|
|
292
|
+
const chain = body.chain;
|
|
293
|
+
const validChains = ["evm", "solana", "both"];
|
|
294
|
+
if (chain && !validChains.includes(chain)) {
|
|
295
|
+
error(
|
|
296
|
+
res,
|
|
297
|
+
`Unsupported chain: ${chain}. Must be "evm", "solana", or "both".`
|
|
298
|
+
);
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
const targetChain = chain ?? "both";
|
|
302
|
+
const stewardApiUrl = process.env.STEWARD_API_URL?.trim();
|
|
303
|
+
if (stewardApiUrl) {
|
|
304
|
+
try {
|
|
305
|
+
const agentId = process.env.STEWARD_AGENT_ID?.trim() || process.env.ELIZA_STEWARD_AGENT_ID?.trim() || null;
|
|
306
|
+
if (!agentId) {
|
|
307
|
+
error(
|
|
308
|
+
res,
|
|
309
|
+
"Steward is configured but no agent ID is set (STEWARD_AGENT_ID).",
|
|
310
|
+
500
|
|
311
|
+
);
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
const headers = {
|
|
315
|
+
Accept: "application/json",
|
|
316
|
+
"Content-Type": "application/json"
|
|
317
|
+
};
|
|
318
|
+
const bearerToken = process.env.STEWARD_AGENT_TOKEN?.trim();
|
|
319
|
+
const apiKey = process.env.STEWARD_API_KEY?.trim();
|
|
320
|
+
const tenantId = process.env.STEWARD_TENANT_ID?.trim();
|
|
321
|
+
if (bearerToken) {
|
|
322
|
+
headers.Authorization = `Bearer ${bearerToken}`;
|
|
323
|
+
} else if (apiKey) {
|
|
324
|
+
headers["X-Steward-Key"] = apiKey;
|
|
325
|
+
}
|
|
326
|
+
if (tenantId) {
|
|
327
|
+
headers["X-Steward-Tenant"] = tenantId;
|
|
328
|
+
}
|
|
329
|
+
let agentEvm = null;
|
|
330
|
+
let agentSolana = null;
|
|
331
|
+
let agentExists = false;
|
|
332
|
+
try {
|
|
333
|
+
const agentRes = await fetch(
|
|
334
|
+
`${stewardApiUrl}/agents/${encodeURIComponent(agentId)}`,
|
|
335
|
+
{ headers: { ...headers }, signal: AbortSignal.timeout(15e3) }
|
|
336
|
+
);
|
|
337
|
+
if (agentRes.ok) {
|
|
338
|
+
agentExists = true;
|
|
339
|
+
const agent = readStewardAgentWalletPayload(await agentRes.json());
|
|
340
|
+
agentEvm = agent?.walletAddresses?.evm?.trim() || agent?.walletAddress?.trim() || null;
|
|
341
|
+
agentSolana = agent?.walletAddresses?.solana?.trim() || null;
|
|
342
|
+
}
|
|
343
|
+
} catch {
|
|
344
|
+
}
|
|
345
|
+
if (!agentExists) {
|
|
346
|
+
const createRes = await fetch(`${stewardApiUrl}/agents`, {
|
|
347
|
+
method: "POST",
|
|
348
|
+
headers,
|
|
349
|
+
body: JSON.stringify({ id: agentId, name: agentId }),
|
|
350
|
+
signal: AbortSignal.timeout(15e3)
|
|
351
|
+
});
|
|
352
|
+
if (!createRes.ok) {
|
|
353
|
+
const errText = await createRes.text().catch(() => "Unknown error");
|
|
354
|
+
error(res, `Steward agent creation failed: ${errText}`, 502);
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
const created = readStewardAgentWalletPayload(await createRes.json());
|
|
358
|
+
agentEvm = created?.walletAddresses?.evm?.trim() || created?.walletAddress?.trim() || null;
|
|
359
|
+
agentSolana = created?.walletAddresses?.solana?.trim() || null;
|
|
360
|
+
logger.info(
|
|
361
|
+
`[wallet] Created steward agent "${agentId}" with wallets`
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
const generated2 = [];
|
|
365
|
+
if (agentEvm && (targetChain === "both" || targetChain === "evm")) {
|
|
366
|
+
process.env.STEWARD_EVM_ADDRESS = agentEvm;
|
|
367
|
+
generated2.push({ chain: "evm", address: agentEvm });
|
|
368
|
+
logger.info(`[wallet] Steward EVM wallet: ${agentEvm}`);
|
|
369
|
+
}
|
|
370
|
+
if (agentSolana && (targetChain === "both" || targetChain === "solana")) {
|
|
371
|
+
process.env.STEWARD_SOLANA_ADDRESS = agentSolana;
|
|
372
|
+
generated2.push({ chain: "solana", address: agentSolana });
|
|
373
|
+
logger.info(`[wallet] Steward Solana wallet: ${agentSolana}`);
|
|
374
|
+
}
|
|
375
|
+
json(res, {
|
|
376
|
+
ok: true,
|
|
377
|
+
wallets: generated2,
|
|
378
|
+
source: "steward"
|
|
379
|
+
});
|
|
380
|
+
return true;
|
|
381
|
+
} catch (err) {
|
|
382
|
+
logger.warn(
|
|
383
|
+
`[wallet] Steward wallet generation failed, falling back to local: ${err}`
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (!config.env) config.env = {};
|
|
388
|
+
const generated = [];
|
|
389
|
+
const generatedChains = [];
|
|
390
|
+
if (targetChain === "both" || targetChain === "evm") {
|
|
391
|
+
const result = deps.generateWalletForChain("evm");
|
|
392
|
+
process.env.EVM_PRIVATE_KEY = result.privateKey;
|
|
393
|
+
config.env.EVM_PRIVATE_KEY = result.privateKey;
|
|
394
|
+
persistPrimarySelection(config, "evm", "local");
|
|
395
|
+
generatedChains.push("evm");
|
|
396
|
+
generated.push({ chain: "evm", address: result.address });
|
|
397
|
+
logger.info(`[eliza-api] Generated EVM wallet: ${result.address}`);
|
|
398
|
+
}
|
|
399
|
+
if (targetChain === "both" || targetChain === "solana") {
|
|
400
|
+
const result = deps.generateWalletForChain("solana");
|
|
401
|
+
setSolanaWalletEnv(result.privateKey);
|
|
402
|
+
config.env.SOLANA_PRIVATE_KEY = result.privateKey;
|
|
403
|
+
persistPrimarySelection(config, "solana", "local");
|
|
404
|
+
generatedChains.push("solana");
|
|
405
|
+
generated.push({ chain: "solana", address: result.address });
|
|
406
|
+
logger.info(`[eliza-api] Generated Solana wallet: ${result.address}`);
|
|
407
|
+
}
|
|
408
|
+
let configSaveWarning;
|
|
409
|
+
try {
|
|
410
|
+
saveConfig(config);
|
|
411
|
+
} catch (err) {
|
|
412
|
+
const msg = `Config save failed: ${String(err)}`;
|
|
413
|
+
logger.warn(`[api] ${msg}`);
|
|
414
|
+
configSaveWarning = msg;
|
|
415
|
+
}
|
|
416
|
+
for (const chainName of generatedChains) {
|
|
417
|
+
const walletSourceEnvKey = LOCAL_WALLET_SOURCE_ENV_KEYS[chainName];
|
|
418
|
+
process.env[walletSourceEnvKey] = "local";
|
|
419
|
+
try {
|
|
420
|
+
await persistConfigEnv(walletSourceEnvKey, "local");
|
|
421
|
+
} catch (err) {
|
|
422
|
+
error(
|
|
423
|
+
res,
|
|
424
|
+
`Failed to persist ${walletSourceEnvKey}: ${String(err)}`,
|
|
425
|
+
500
|
|
426
|
+
);
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
const restarted = await triggerWalletRuntimeReload(
|
|
431
|
+
ctx,
|
|
432
|
+
"Wallet configuration updated"
|
|
433
|
+
);
|
|
434
|
+
json(res, {
|
|
435
|
+
ok: true,
|
|
436
|
+
wallets: generated,
|
|
437
|
+
source: "local",
|
|
438
|
+
restarting: restarted,
|
|
439
|
+
...configSaveWarning ? { warnings: [configSaveWarning] } : {}
|
|
440
|
+
});
|
|
441
|
+
return true;
|
|
442
|
+
}
|
|
443
|
+
if (method === "GET" && pathname === "/api/wallet/config") {
|
|
444
|
+
const addresses = deps.getWalletAddresses();
|
|
445
|
+
const rpcReadiness = resolveWalletRpcReadiness(config);
|
|
446
|
+
const localSolanaSignerAvailable = Boolean(
|
|
447
|
+
process.env.SOLANA_PRIVATE_KEY?.trim()
|
|
448
|
+
);
|
|
449
|
+
const capability = resolveWalletCapabilityStatus({
|
|
450
|
+
config,
|
|
451
|
+
runtime: ctx.runtime ?? null,
|
|
452
|
+
getWalletAddresses: deps.getWalletAddresses
|
|
453
|
+
});
|
|
454
|
+
const alchemyKeySet = Boolean(process.env.ALCHEMY_API_KEY?.trim());
|
|
455
|
+
const ankrKeySet = Boolean(process.env.ANKR_API_KEY?.trim());
|
|
456
|
+
const nodeRealSet = Boolean(process.env.NODEREAL_BSC_RPC_URL?.trim());
|
|
457
|
+
const quickNodeSet = Boolean(process.env.QUICKNODE_BSC_RPC_URL?.trim());
|
|
458
|
+
const configStatus = {
|
|
459
|
+
selectedRpcProviders: rpcReadiness.selectedRpcProviders,
|
|
460
|
+
walletNetwork: resolveWalletNetworkMode(config),
|
|
461
|
+
legacyCustomChains: rpcReadiness.legacyCustomChains,
|
|
462
|
+
alchemyKeySet,
|
|
463
|
+
infuraKeySet: Boolean(process.env.INFURA_API_KEY?.trim()),
|
|
464
|
+
ankrKeySet,
|
|
465
|
+
nodeRealBscRpcSet: nodeRealSet,
|
|
466
|
+
quickNodeBscRpcSet: quickNodeSet,
|
|
467
|
+
managedBscRpcReady: rpcReadiness.managedBscRpcReady,
|
|
468
|
+
cloudManagedAccess: rpcReadiness.cloudManagedAccess,
|
|
469
|
+
evmBalanceReady: rpcReadiness.evmBalanceReady,
|
|
470
|
+
ethereumBalanceReady: alchemyKeySet || rpcReadiness.ethereumRpcUrls.length > 0,
|
|
471
|
+
baseBalanceReady: alchemyKeySet || rpcReadiness.baseRpcUrls.length > 0,
|
|
472
|
+
bscBalanceReady: ankrKeySet || rpcReadiness.bscRpcUrls.length > 0,
|
|
473
|
+
avalancheBalanceReady: alchemyKeySet || rpcReadiness.avalancheRpcUrls.length > 0,
|
|
474
|
+
solanaBalanceReady: rpcReadiness.solanaBalanceReady,
|
|
475
|
+
heliusKeySet: Boolean(process.env.HELIUS_API_KEY?.trim()),
|
|
476
|
+
birdeyeKeySet: Boolean(process.env.BIRDEYE_API_KEY?.trim()),
|
|
477
|
+
evmChains: [
|
|
478
|
+
"Ethereum",
|
|
479
|
+
"Base",
|
|
480
|
+
"Arbitrum",
|
|
481
|
+
"Optimism",
|
|
482
|
+
"Polygon",
|
|
483
|
+
"BSC",
|
|
484
|
+
"Avalanche"
|
|
485
|
+
],
|
|
486
|
+
evmAddress: addresses.evmAddress,
|
|
487
|
+
solanaAddress: addresses.solanaAddress,
|
|
488
|
+
walletSource: capability.walletSource,
|
|
489
|
+
automationMode: capability.automationMode,
|
|
490
|
+
pluginEvmLoaded: capability.pluginEvmLoaded,
|
|
491
|
+
pluginEvmRequired: capability.pluginEvmRequired,
|
|
492
|
+
executionReady: capability.executionReady,
|
|
493
|
+
executionBlockedReason: capability.executionBlockedReason,
|
|
494
|
+
solanaSigningAvailable: localSolanaSignerAvailable && Boolean(addresses.solanaAddress)
|
|
495
|
+
};
|
|
496
|
+
json(res, configStatus);
|
|
497
|
+
return true;
|
|
498
|
+
}
|
|
499
|
+
if (method === "PUT" && pathname === "/api/wallet/config") {
|
|
500
|
+
const body = await readJsonBody(req, res);
|
|
501
|
+
if (!body) return true;
|
|
502
|
+
const updateRequest = resolveWalletConfigUpdateRequest(
|
|
503
|
+
body,
|
|
504
|
+
getStoredWalletRpcSelections(config)
|
|
505
|
+
);
|
|
506
|
+
if (!updateRequest) {
|
|
507
|
+
error(res, "Invalid wallet config update");
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
applyWalletRpcConfigUpdate(config, updateRequest);
|
|
511
|
+
let configSaveWarning;
|
|
512
|
+
try {
|
|
513
|
+
saveConfig(config);
|
|
514
|
+
} catch (err) {
|
|
515
|
+
const msg = `Config save failed: ${String(err)}`;
|
|
516
|
+
logger.warn(`[api] ${msg}`);
|
|
517
|
+
configSaveWarning = msg;
|
|
518
|
+
}
|
|
519
|
+
json(res, {
|
|
520
|
+
ok: true,
|
|
521
|
+
...configSaveWarning ? { warnings: [configSaveWarning] } : {}
|
|
522
|
+
});
|
|
523
|
+
ctx.scheduleRuntimeRestart?.("Wallet configuration updated");
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
526
|
+
if (method === "POST" && pathname === "/api/wallet/export") {
|
|
527
|
+
if (!rateLimitWalletExport(req)) {
|
|
528
|
+
error(res, "Too many export attempts. Try again later.", 429);
|
|
529
|
+
return true;
|
|
530
|
+
}
|
|
531
|
+
const body = await readJsonBody(req, res);
|
|
532
|
+
if (!body) return true;
|
|
533
|
+
const rejection = resolveWalletExportRejection(req, body);
|
|
534
|
+
if (rejection) {
|
|
535
|
+
error(res, rejection.reason, rejection.status);
|
|
536
|
+
return true;
|
|
537
|
+
}
|
|
538
|
+
const evmKey = process.env.EVM_PRIVATE_KEY ?? null;
|
|
539
|
+
const solanaKey = process.env.SOLANA_PRIVATE_KEY ?? null;
|
|
540
|
+
const addresses = deps.getWalletAddresses();
|
|
541
|
+
logger.warn(
|
|
542
|
+
`[wallet] Private keys exported via API (ip=${req.socket?.remoteAddress ?? "unknown"})`
|
|
543
|
+
);
|
|
544
|
+
json(res, {
|
|
545
|
+
evm: evmKey ? { privateKey: evmKey, address: addresses.evmAddress } : null,
|
|
546
|
+
solana: solanaKey ? { privateKey: solanaKey, address: addresses.solanaAddress } : null
|
|
547
|
+
});
|
|
548
|
+
return true;
|
|
549
|
+
}
|
|
550
|
+
return false;
|
|
551
|
+
}
|
|
552
|
+
export {
|
|
553
|
+
DEFAULT_WALLET_ROUTE_DEPENDENCIES,
|
|
554
|
+
handleWalletRoutes
|
|
555
|
+
};
|
|
556
|
+
//# sourceMappingURL=wallet-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/api/wallet-routes.ts"],"sourcesContent":["import type http from \"node:http\";\nimport type { ElizaConfig } from \"@elizaos/agent\";\nimport {\n createIntegrationTelemetrySpan,\n persistConfigEnv,\n} from \"@elizaos/agent\";\nimport type {\n AgentRuntime,\n RouteHelpers,\n WalletExportRejection as WalletExportRejectionLike,\n WalletExportRequestBody,\n} from \"@elizaos/core\";\nimport {\n logger,\n normalizeWalletRpcSelections,\n type RouteRequestMeta,\n type WalletConfigUpdateRequest,\n type WalletRpcSelections,\n} from \"@elizaos/core\";\nimport {\n fetchEvmBalances,\n fetchSolanaBalances,\n fetchSolanaNativeBalanceViaRpc,\n generateWalletForChain,\n getWalletAddresses,\n importWallet,\n setSolanaWalletEnv,\n validatePrivateKey,\n type WalletBalancesResponse,\n type WalletChain,\n type WalletConfigStatus,\n} from \"./wallet.js\";\nimport { resolveWalletCapabilityStatus } from \"./wallet-capability.js\";\nimport {\n applyWalletRpcConfigUpdate,\n getStoredWalletRpcSelections,\n resolveWalletNetworkMode,\n resolveWalletRpcReadiness,\n} from \"./wallet-rpc.js\";\n\n// Rate limiter for wallet export.\n// In test/CI mode the limit is relaxed to avoid blocking E2E suites.\nconst IS_TEST = process.env.NODE_ENV === \"test\" || !!process.env.VITEST;\nconst WALLET_EXPORT_MAX_ATTEMPTS = IS_TEST ? 500 : 5;\nconst WALLET_EXPORT_WINDOW_MS = 15 * 60_000;\nconst walletExportAttempts = new Map<\n string,\n { count: number; resetAt: number }\n>();\n\nfunction rateLimitWalletExport(req: http.IncomingMessage): boolean {\n const key = req.socket?.remoteAddress ?? \"unknown\";\n const now = Date.now();\n // Lazy sweep\n if (walletExportAttempts.size > 50) {\n for (const [k, v] of walletExportAttempts) {\n if (now > v.resetAt) walletExportAttempts.delete(k);\n }\n }\n const current = walletExportAttempts.get(key);\n if (!current || now > current.resetAt) {\n walletExportAttempts.set(key, {\n count: 1,\n resetAt: now + WALLET_EXPORT_WINDOW_MS,\n });\n return true;\n }\n if (current.count >= WALLET_EXPORT_MAX_ATTEMPTS) return false;\n current.count += 1;\n return true;\n}\n\nconst WALLET_CONFIG_COMPAT_KEYS = new Set([\n \"ALCHEMY_API_KEY\",\n \"INFURA_API_KEY\",\n \"ANKR_API_KEY\",\n \"ETHEREUM_RPC_URL\",\n \"BASE_RPC_URL\",\n \"AVALANCHE_RPC_URL\",\n \"HELIUS_API_KEY\",\n \"BIRDEYE_API_KEY\",\n \"NODEREAL_BSC_RPC_URL\",\n \"QUICKNODE_BSC_RPC_URL\",\n \"BSC_RPC_URL\",\n \"SOLANA_RPC_URL\",\n]);\n\ntype StewardAgentWalletPayload = {\n walletAddress?: string;\n walletAddresses?: { evm?: string; solana?: string };\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction readStringField(\n record: Record<string, unknown>,\n key: string,\n): string | undefined {\n const value = record[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction readStewardAgentWalletPayload(\n value: unknown,\n): StewardAgentWalletPayload {\n const envelope = isRecord(value) ? value : {};\n const payload = isRecord(envelope.data) ? envelope.data : envelope;\n const walletAddresses = isRecord(payload.walletAddresses)\n ? {\n evm: readStringField(payload.walletAddresses, \"evm\"),\n solana: readStringField(payload.walletAddresses, \"solana\"),\n }\n : undefined;\n return {\n walletAddress: readStringField(payload, \"walletAddress\"),\n walletAddresses,\n };\n}\n\nfunction resolveWalletConfigUpdateRequest(\n body: unknown,\n currentSelections: WalletRpcSelections,\n): WalletConfigUpdateRequest | null {\n if (!body || typeof body !== \"object\" || Array.isArray(body)) {\n return null;\n }\n\n const record = body as Record<string, unknown>;\n if (\n record.selections &&\n typeof record.selections === \"object\" &&\n !Array.isArray(record.selections)\n ) {\n const walletNetwork =\n record.walletNetwork === \"testnet\" || record.walletNetwork === \"mainnet\"\n ? record.walletNetwork\n : undefined;\n const credentials =\n record.credentials &&\n typeof record.credentials === \"object\" &&\n !Array.isArray(record.credentials)\n ? Object.fromEntries(\n Object.entries(\n record.credentials as Record<string, unknown>,\n ).filter(([, value]) => typeof value === \"string\"),\n )\n : undefined;\n\n return {\n selections: normalizeWalletRpcSelections(\n record.selections as Partial<Record<keyof WalletRpcSelections, string>>,\n ),\n walletNetwork,\n credentials: credentials as WalletConfigUpdateRequest[\"credentials\"],\n };\n }\n\n const compatCredentials = Object.fromEntries(\n Object.entries(record).filter(\n ([key, value]) =>\n WALLET_CONFIG_COMPAT_KEYS.has(key) && typeof value === \"string\",\n ),\n );\n\n if (Object.keys(compatCredentials).length === 0) {\n return null;\n }\n\n return {\n selections: currentSelections,\n walletNetwork:\n record.walletNetwork === \"testnet\" || record.walletNetwork === \"mainnet\"\n ? record.walletNetwork\n : undefined,\n credentials: compatCredentials as WalletConfigUpdateRequest[\"credentials\"],\n };\n}\n\nexport interface WalletRouteDependencies {\n getWalletAddresses: typeof getWalletAddresses;\n fetchEvmBalances: typeof fetchEvmBalances;\n fetchSolanaBalances: typeof fetchSolanaBalances;\n fetchSolanaNativeBalanceViaRpc: typeof fetchSolanaNativeBalanceViaRpc;\n validatePrivateKey: typeof validatePrivateKey;\n importWallet: typeof importWallet;\n generateWalletForChain: typeof generateWalletForChain;\n}\n\nexport const DEFAULT_WALLET_ROUTE_DEPENDENCIES: WalletRouteDependencies = {\n getWalletAddresses,\n fetchEvmBalances,\n fetchSolanaBalances,\n fetchSolanaNativeBalanceViaRpc,\n validatePrivateKey,\n importWallet,\n generateWalletForChain,\n};\n\nfunction persistPrimarySelection(\n config: ElizaConfig,\n chain: WalletChain,\n source: \"local\" | \"cloud\",\n): void {\n if (!config.wallet) {\n config.wallet = {};\n }\n const wallet = config.wallet;\n const primary = { ...((wallet.primary as Record<string, unknown>) ?? {}) };\n primary[chain] = source;\n wallet.primary = primary as typeof wallet.primary;\n config.wallet = wallet;\n}\n\nexport interface WalletRouteContext\n extends RouteRequestMeta,\n Pick<RouteHelpers, \"readJsonBody\" | \"json\" | \"error\"> {\n config: ElizaConfig;\n saveConfig: (config: ElizaConfig) => void;\n ensureWalletKeysInEnvAndConfig: (config: ElizaConfig) => boolean;\n resolveWalletExportRejection: (\n req: http.IncomingMessage,\n body: WalletExportRequestBody,\n ) => WalletExportRejectionLike | null;\n restartRuntime?: (reason: string) => Promise<boolean>;\n scheduleRuntimeRestart?: (reason: string) => void;\n deps?: WalletRouteDependencies;\n runtime?: AgentRuntime | null;\n}\n\nasync function triggerWalletRuntimeReload(\n ctx: WalletRouteContext,\n reason: string,\n): Promise<boolean> {\n const restarted = ctx.restartRuntime\n ? await ctx.restartRuntime(reason)\n : false;\n if (!restarted) {\n ctx.scheduleRuntimeRestart?.(reason);\n }\n return restarted;\n}\n\nconst LOCAL_WALLET_SOURCE_ENV_KEYS: Record<WalletChain, string> = {\n evm: \"WALLET_SOURCE_EVM\",\n solana: \"WALLET_SOURCE_SOLANA\",\n};\n\nexport async function handleWalletRoutes(\n ctx: WalletRouteContext,\n): Promise<boolean> {\n const {\n req,\n res,\n method,\n pathname,\n config,\n saveConfig,\n resolveWalletExportRejection,\n readJsonBody,\n json,\n error,\n } = ctx;\n const deps = ctx.deps ?? DEFAULT_WALLET_ROUTE_DEPENDENCIES;\n\n // GET /api/wallet/addresses\n if (method === \"GET\" && pathname === \"/api/wallet/addresses\") {\n json(res, deps.getWalletAddresses());\n return true;\n }\n\n // GET /api/wallet/balances\n if (method === \"GET\" && pathname === \"/api/wallet/balances\") {\n const addresses = deps.getWalletAddresses();\n const rpcReadiness = resolveWalletRpcReadiness(config);\n const alchemyKey = process.env.ALCHEMY_API_KEY?.trim() || null;\n const ankrKey = process.env.ANKR_API_KEY?.trim() || null;\n const heliusKey = process.env.HELIUS_API_KEY?.trim() || null;\n\n const result: WalletBalancesResponse = { evm: null, solana: null };\n\n if (addresses.evmAddress && rpcReadiness.evmBalanceReady) {\n const evmBalancesSpan = createIntegrationTelemetrySpan({\n boundary: \"wallet\",\n operation: \"fetch_evm_balances\",\n });\n try {\n const chains = await deps.fetchEvmBalances(addresses.evmAddress, {\n alchemyKey,\n ankrKey,\n cloudManagedAccess: rpcReadiness.cloudManagedAccess,\n bscRpcUrls: rpcReadiness.bscRpcUrls,\n ethereumRpcUrls: rpcReadiness.ethereumRpcUrls,\n baseRpcUrls: rpcReadiness.baseRpcUrls,\n avaxRpcUrls: rpcReadiness.avalancheRpcUrls,\n nodeRealBscRpcUrl: process.env.NODEREAL_BSC_RPC_URL,\n quickNodeBscRpcUrl: process.env.QUICKNODE_BSC_RPC_URL,\n bscRpcUrl: process.env.BSC_RPC_URL,\n ethereumRpcUrl: process.env.ETHEREUM_RPC_URL,\n baseRpcUrl: process.env.BASE_RPC_URL,\n avaxRpcUrl: process.env.AVALANCHE_RPC_URL,\n });\n result.evm = { address: addresses.evmAddress, chains };\n evmBalancesSpan.success();\n } catch (err) {\n evmBalancesSpan.failure({ error: err });\n logger.warn(`[wallet] EVM balance fetch failed: ${err}`);\n }\n }\n\n if (addresses.solanaAddress && rpcReadiness.solanaBalanceReady) {\n const solanaBalancesSpan = createIntegrationTelemetrySpan({\n boundary: \"wallet\",\n operation: \"fetch_solana_balances\",\n });\n try {\n const solanaData = heliusKey\n ? await deps.fetchSolanaBalances(addresses.solanaAddress, heliusKey)\n : await deps.fetchSolanaNativeBalanceViaRpc(\n addresses.solanaAddress,\n rpcReadiness.solanaRpcUrls,\n );\n result.solana = { address: addresses.solanaAddress, ...solanaData };\n solanaBalancesSpan.success();\n } catch (err) {\n solanaBalancesSpan.failure({ error: err });\n logger.warn(`[wallet] Solana balance fetch failed: ${err}`);\n }\n }\n\n json(res, result);\n return true;\n }\n\n // POST /api/wallet/import\n if (method === \"POST\" && pathname === \"/api/wallet/import\") {\n const body = await readJsonBody<{ chain?: string; privateKey?: string }>(\n req,\n res,\n );\n if (!body) return true;\n\n if (!body.privateKey?.trim()) {\n error(res, \"privateKey is required\");\n return true;\n }\n\n let chain: WalletChain;\n if (body.chain === \"evm\" || body.chain === \"solana\") {\n chain = body.chain;\n } else if (body.chain) {\n error(\n res,\n `Unsupported chain: ${body.chain}. Must be \"evm\" or \"solana\".`,\n );\n return true;\n } else {\n const detection = deps.validatePrivateKey(body.privateKey.trim());\n chain = detection.chain;\n }\n\n // When steward is configured, warn that keys should be imported via vault\n const stewardWarning = process.env.STEWARD_API_URL?.trim()\n ? \"Steward vault is configured. Consider importing keys directly into the vault instead of storing plaintext keys locally.\"\n : undefined;\n\n const result = deps.importWallet(chain, body.privateKey.trim());\n\n if (!result.success) {\n error(res, result.error ?? \"Import failed\", 422);\n return true;\n }\n\n if (!config.env) config.env = {};\n const envKey = chain === \"evm\" ? \"EVM_PRIVATE_KEY\" : \"SOLANA_PRIVATE_KEY\";\n (config.env as Record<string, string>)[envKey] = process.env[envKey] ?? \"\";\n persistPrimarySelection(config, chain, \"local\");\n\n let configSaveWarning: string | undefined;\n try {\n saveConfig(config);\n } catch (err) {\n const msg = `Config save failed: ${String(err)}`;\n logger.warn(`[api] ${msg}`);\n configSaveWarning = msg;\n }\n\n const warnings: string[] = [];\n if (configSaveWarning) warnings.push(configSaveWarning);\n if (stewardWarning) warnings.push(stewardWarning);\n\n const walletSourceEnvKey = LOCAL_WALLET_SOURCE_ENV_KEYS[chain];\n process.env[walletSourceEnvKey] = \"local\";\n try {\n await persistConfigEnv(walletSourceEnvKey, \"local\");\n } catch (err) {\n error(\n res,\n `Failed to persist ${walletSourceEnvKey}: ${String(err)}`,\n 500,\n );\n return true;\n }\n\n const restarted = await triggerWalletRuntimeReload(\n ctx,\n \"Wallet configuration updated\",\n );\n\n json(res, {\n ok: true,\n chain,\n address: result.address,\n restarting: restarted,\n ...(warnings.length > 0 ? { warnings } : {}),\n });\n return true;\n }\n\n // POST /api/wallet/generate\n if (method === \"POST\" && pathname === \"/api/wallet/generate\") {\n const body = await readJsonBody<{ chain?: string }>(req, res);\n if (!body) return true;\n\n const chain = body.chain as string | undefined;\n const validChains: Array<WalletChain | \"both\"> = [\"evm\", \"solana\", \"both\"];\n\n if (chain && !validChains.includes(chain as WalletChain | \"both\")) {\n error(\n res,\n `Unsupported chain: ${chain}. Must be \"evm\", \"solana\", or \"both\".`,\n );\n return true;\n }\n\n const targetChain = (chain ?? \"both\") as WalletChain | \"both\";\n\n // ── Steward-first: delegate wallet generation to steward ──────────\n const stewardApiUrl = process.env.STEWARD_API_URL?.trim();\n if (stewardApiUrl) {\n try {\n const agentId =\n process.env.STEWARD_AGENT_ID?.trim() ||\n process.env.ELIZA_STEWARD_AGENT_ID?.trim() ||\n null;\n\n if (!agentId) {\n error(\n res,\n \"Steward is configured but no agent ID is set (STEWARD_AGENT_ID).\",\n 500,\n );\n return true;\n }\n\n // Build auth headers\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n };\n const bearerToken = process.env.STEWARD_AGENT_TOKEN?.trim();\n const apiKey = process.env.STEWARD_API_KEY?.trim();\n const tenantId = process.env.STEWARD_TENANT_ID?.trim();\n if (bearerToken) {\n headers.Authorization = `Bearer ${bearerToken}`;\n } else if (apiKey) {\n headers[\"X-Steward-Key\"] = apiKey;\n }\n if (tenantId) {\n headers[\"X-Steward-Tenant\"] = tenantId;\n }\n\n // Check if agent already exists (has wallets)\n let agentEvm: string | null = null;\n let agentSolana: string | null = null;\n let agentExists = false;\n\n try {\n const agentRes = await fetch(\n `${stewardApiUrl}/agents/${encodeURIComponent(agentId)}`,\n { headers: { ...headers }, signal: AbortSignal.timeout(15_000) },\n );\n if (agentRes.ok) {\n agentExists = true;\n const agent = readStewardAgentWalletPayload(await agentRes.json());\n agentEvm =\n agent?.walletAddresses?.evm?.trim() ||\n agent?.walletAddress?.trim() ||\n null;\n agentSolana = agent?.walletAddresses?.solana?.trim() || null;\n }\n } catch {\n // agent doesn't exist or fetch failed — will try to create\n }\n\n // If agent doesn't exist, create it (steward auto-generates wallets)\n if (!agentExists) {\n const createRes = await fetch(`${stewardApiUrl}/agents`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ id: agentId, name: agentId }),\n signal: AbortSignal.timeout(15_000),\n });\n\n if (!createRes.ok) {\n const errText = await createRes.text().catch(() => \"Unknown error\");\n error(res, `Steward agent creation failed: ${errText}`, 502);\n return true;\n }\n\n const created = readStewardAgentWalletPayload(await createRes.json());\n agentEvm =\n created?.walletAddresses?.evm?.trim() ||\n created?.walletAddress?.trim() ||\n null;\n agentSolana = created?.walletAddresses?.solana?.trim() || null;\n\n logger.info(\n `[wallet] Created steward agent \"${agentId}\" with wallets`,\n );\n }\n\n // Cache steward addresses in env for synchronous access\n const generated: Array<{ chain: WalletChain; address: string }> = [];\n if (agentEvm && (targetChain === \"both\" || targetChain === \"evm\")) {\n process.env.STEWARD_EVM_ADDRESS = agentEvm;\n generated.push({ chain: \"evm\", address: agentEvm });\n logger.info(`[wallet] Steward EVM wallet: ${agentEvm}`);\n }\n if (\n agentSolana &&\n (targetChain === \"both\" || targetChain === \"solana\")\n ) {\n process.env.STEWARD_SOLANA_ADDRESS = agentSolana;\n generated.push({ chain: \"solana\", address: agentSolana });\n logger.info(`[wallet] Steward Solana wallet: ${agentSolana}`);\n }\n\n json(res, {\n ok: true,\n wallets: generated,\n source: \"steward\",\n });\n return true;\n } catch (err) {\n logger.warn(\n `[wallet] Steward wallet generation failed, falling back to local: ${err}`,\n );\n // Fall through to local generation\n }\n }\n\n // ── Legacy local key generation (fallback) ────────────────────────\n if (!config.env) config.env = {};\n\n const generated: Array<{ chain: WalletChain; address: string }> = [];\n const generatedChains: WalletChain[] = [];\n\n if (targetChain === \"both\" || targetChain === \"evm\") {\n const result = deps.generateWalletForChain(\"evm\");\n process.env.EVM_PRIVATE_KEY = result.privateKey;\n (config.env as Record<string, string>).EVM_PRIVATE_KEY =\n result.privateKey;\n persistPrimarySelection(config, \"evm\", \"local\");\n generatedChains.push(\"evm\");\n generated.push({ chain: \"evm\", address: result.address });\n logger.info(`[eliza-api] Generated EVM wallet: ${result.address}`);\n }\n\n if (targetChain === \"both\" || targetChain === \"solana\") {\n const result = deps.generateWalletForChain(\"solana\");\n setSolanaWalletEnv(result.privateKey);\n (config.env as Record<string, string>).SOLANA_PRIVATE_KEY =\n result.privateKey;\n persistPrimarySelection(config, \"solana\", \"local\");\n generatedChains.push(\"solana\");\n generated.push({ chain: \"solana\", address: result.address });\n logger.info(`[eliza-api] Generated Solana wallet: ${result.address}`);\n }\n\n let configSaveWarning: string | undefined;\n try {\n saveConfig(config);\n } catch (err) {\n const msg = `Config save failed: ${String(err)}`;\n logger.warn(`[api] ${msg}`);\n configSaveWarning = msg;\n }\n\n for (const chainName of generatedChains) {\n const walletSourceEnvKey = LOCAL_WALLET_SOURCE_ENV_KEYS[chainName];\n process.env[walletSourceEnvKey] = \"local\";\n try {\n await persistConfigEnv(walletSourceEnvKey, \"local\");\n } catch (err) {\n error(\n res,\n `Failed to persist ${walletSourceEnvKey}: ${String(err)}`,\n 500,\n );\n return true;\n }\n }\n\n const restarted = await triggerWalletRuntimeReload(\n ctx,\n \"Wallet configuration updated\",\n );\n\n json(res, {\n ok: true,\n wallets: generated,\n source: \"local\",\n restarting: restarted,\n ...(configSaveWarning ? { warnings: [configSaveWarning] } : {}),\n });\n return true;\n }\n\n // GET /api/wallet/config\n if (method === \"GET\" && pathname === \"/api/wallet/config\") {\n const addresses = deps.getWalletAddresses();\n const rpcReadiness = resolveWalletRpcReadiness(config);\n const localSolanaSignerAvailable = Boolean(\n process.env.SOLANA_PRIVATE_KEY?.trim(),\n );\n const capability = resolveWalletCapabilityStatus({\n config,\n runtime: ctx.runtime ?? null,\n getWalletAddresses: deps.getWalletAddresses,\n });\n const alchemyKeySet = Boolean(process.env.ALCHEMY_API_KEY?.trim());\n const ankrKeySet = Boolean(process.env.ANKR_API_KEY?.trim());\n const nodeRealSet = Boolean(process.env.NODEREAL_BSC_RPC_URL?.trim());\n const quickNodeSet = Boolean(process.env.QUICKNODE_BSC_RPC_URL?.trim());\n const configStatus: WalletConfigStatus = {\n selectedRpcProviders: rpcReadiness.selectedRpcProviders,\n walletNetwork: resolveWalletNetworkMode(config),\n legacyCustomChains: rpcReadiness.legacyCustomChains,\n alchemyKeySet,\n infuraKeySet: Boolean(process.env.INFURA_API_KEY?.trim()),\n ankrKeySet,\n nodeRealBscRpcSet: nodeRealSet,\n quickNodeBscRpcSet: quickNodeSet,\n managedBscRpcReady: rpcReadiness.managedBscRpcReady,\n cloudManagedAccess: rpcReadiness.cloudManagedAccess,\n evmBalanceReady: rpcReadiness.evmBalanceReady,\n ethereumBalanceReady:\n alchemyKeySet || rpcReadiness.ethereumRpcUrls.length > 0,\n baseBalanceReady: alchemyKeySet || rpcReadiness.baseRpcUrls.length > 0,\n bscBalanceReady: ankrKeySet || rpcReadiness.bscRpcUrls.length > 0,\n avalancheBalanceReady:\n alchemyKeySet || rpcReadiness.avalancheRpcUrls.length > 0,\n solanaBalanceReady: rpcReadiness.solanaBalanceReady,\n heliusKeySet: Boolean(process.env.HELIUS_API_KEY?.trim()),\n birdeyeKeySet: Boolean(process.env.BIRDEYE_API_KEY?.trim()),\n evmChains: [\n \"Ethereum\",\n \"Base\",\n \"Arbitrum\",\n \"Optimism\",\n \"Polygon\",\n \"BSC\",\n \"Avalanche\",\n ],\n evmAddress: addresses.evmAddress,\n solanaAddress: addresses.solanaAddress,\n walletSource: capability.walletSource,\n automationMode: capability.automationMode,\n pluginEvmLoaded: capability.pluginEvmLoaded,\n pluginEvmRequired: capability.pluginEvmRequired,\n executionReady: capability.executionReady,\n executionBlockedReason: capability.executionBlockedReason,\n solanaSigningAvailable:\n localSolanaSignerAvailable && Boolean(addresses.solanaAddress),\n };\n json(res, configStatus);\n return true;\n }\n\n // PUT /api/wallet/config\n if (method === \"PUT\" && pathname === \"/api/wallet/config\") {\n const body = await readJsonBody<Record<string, unknown>>(req, res);\n if (!body) return true;\n\n const updateRequest = resolveWalletConfigUpdateRequest(\n body,\n getStoredWalletRpcSelections(config),\n );\n if (!updateRequest) {\n error(res, \"Invalid wallet config update\");\n return true;\n }\n\n applyWalletRpcConfigUpdate(config, updateRequest);\n\n let configSaveWarning: string | undefined;\n try {\n saveConfig(config);\n } catch (err) {\n const msg = `Config save failed: ${String(err)}`;\n logger.warn(`[api] ${msg}`);\n configSaveWarning = msg;\n }\n\n json(res, {\n ok: true,\n ...(configSaveWarning ? { warnings: [configSaveWarning] } : {}),\n });\n ctx.scheduleRuntimeRestart?.(\"Wallet configuration updated\");\n return true;\n }\n\n // POST /api/wallet/export\n if (method === \"POST\" && pathname === \"/api/wallet/export\") {\n if (!rateLimitWalletExport(req)) {\n error(res, \"Too many export attempts. Try again later.\", 429);\n return true;\n }\n\n const body = await readJsonBody<WalletExportRequestBody>(req, res);\n if (!body) return true;\n\n const rejection = resolveWalletExportRejection(req, body);\n if (rejection) {\n error(res, rejection.reason, rejection.status);\n return true;\n }\n\n const evmKey = process.env.EVM_PRIVATE_KEY ?? null;\n const solanaKey = process.env.SOLANA_PRIVATE_KEY ?? null;\n const addresses = deps.getWalletAddresses();\n\n logger.warn(\n `[wallet] Private keys exported via API (ip=${req.socket?.remoteAddress ?? \"unknown\"})`,\n );\n\n json(res, {\n evm: evmKey\n ? { privateKey: evmKey, address: addresses.evmAddress }\n : null,\n solana: solanaKey\n ? { privateKey: solanaKey, address: addresses.solanaAddress }\n : null,\n });\n return true;\n }\n\n return false;\n}\n"],"mappings":"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","names":["generated"]}
|