@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,500 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { resolveStateDir } from "@elizaos/agent";
|
|
4
|
+
const WALLET_PROFILE_LEDGER_VERSION = 1;
|
|
5
|
+
const MAX_WALLET_PROFILE_LEDGER_ENTRIES = 2e3;
|
|
6
|
+
const ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
7
|
+
const FLOAT_EPSILON = 1e-12;
|
|
8
|
+
const TRADE_STATUS_SET = /* @__PURE__ */ new Set([
|
|
9
|
+
"pending",
|
|
10
|
+
"success",
|
|
11
|
+
"reverted",
|
|
12
|
+
"not_found"
|
|
13
|
+
]);
|
|
14
|
+
const ALLOWED_STATUS_TRANSITIONS = {
|
|
15
|
+
pending: /* @__PURE__ */ new Set(["pending", "success", "reverted", "not_found"]),
|
|
16
|
+
not_found: /* @__PURE__ */ new Set(["pending", "success", "reverted", "not_found"]),
|
|
17
|
+
success: /* @__PURE__ */ new Set(["success"]),
|
|
18
|
+
reverted: /* @__PURE__ */ new Set(["reverted"])
|
|
19
|
+
};
|
|
20
|
+
const TRADE_SIDE_SET = /* @__PURE__ */ new Set(["buy", "sell"]);
|
|
21
|
+
function nowIso() {
|
|
22
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
23
|
+
}
|
|
24
|
+
function toFiniteNumber(value) {
|
|
25
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : 0;
|
|
26
|
+
if (typeof value === "string") {
|
|
27
|
+
const parsed = Number.parseFloat(value.trim());
|
|
28
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
29
|
+
}
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
function toBnbString(value) {
|
|
33
|
+
if (!Number.isFinite(value) || Math.abs(value) < FLOAT_EPSILON) return "0";
|
|
34
|
+
const fixed = value.toFixed(8).replace(/\.?0+$/, "");
|
|
35
|
+
return fixed === "-0" ? "0" : fixed;
|
|
36
|
+
}
|
|
37
|
+
function toRatePercent(numerator, denominator) {
|
|
38
|
+
if (!Number.isFinite(denominator) || denominator <= 0) return null;
|
|
39
|
+
if (!Number.isFinite(numerator) || numerator <= 0) return 0;
|
|
40
|
+
return numerator / denominator * 100;
|
|
41
|
+
}
|
|
42
|
+
function normalizeStatus(value) {
|
|
43
|
+
if (typeof value !== "string") return "pending";
|
|
44
|
+
const normalized = value.trim().toLowerCase();
|
|
45
|
+
if (!TRADE_STATUS_SET.has(normalized)) return "pending";
|
|
46
|
+
return normalized;
|
|
47
|
+
}
|
|
48
|
+
function canTransitionTradeStatus(current, next) {
|
|
49
|
+
return ALLOWED_STATUS_TRANSITIONS[current].has(next);
|
|
50
|
+
}
|
|
51
|
+
function normalizeSide(value) {
|
|
52
|
+
if (typeof value !== "string") return "buy";
|
|
53
|
+
const normalized = value.trim().toLowerCase();
|
|
54
|
+
if (!TRADE_SIDE_SET.has(normalized)) return "buy";
|
|
55
|
+
return normalized;
|
|
56
|
+
}
|
|
57
|
+
function normalizeSource(value) {
|
|
58
|
+
if (typeof value !== "string") return "manual";
|
|
59
|
+
return value.trim().toLowerCase() === "agent" ? "agent" : "manual";
|
|
60
|
+
}
|
|
61
|
+
function normalizeIsoDate(value) {
|
|
62
|
+
if (typeof value !== "string") return nowIso();
|
|
63
|
+
const trimmed = value.trim();
|
|
64
|
+
if (!trimmed) return nowIso();
|
|
65
|
+
const timestamp = Date.parse(trimmed);
|
|
66
|
+
if (!Number.isFinite(timestamp)) return nowIso();
|
|
67
|
+
return new Date(timestamp).toISOString();
|
|
68
|
+
}
|
|
69
|
+
function normalizeNullableInteger(value) {
|
|
70
|
+
if (value === null || value === void 0) return null;
|
|
71
|
+
if (typeof value === "string" && !value.trim()) return null;
|
|
72
|
+
const parsed = toFiniteNumber(value);
|
|
73
|
+
if (!Number.isFinite(parsed)) return null;
|
|
74
|
+
return Math.floor(parsed);
|
|
75
|
+
}
|
|
76
|
+
function normalizeAddress(value) {
|
|
77
|
+
if (typeof value !== "string") return "";
|
|
78
|
+
return value.trim().toLowerCase();
|
|
79
|
+
}
|
|
80
|
+
function normalizeLeg(value) {
|
|
81
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
82
|
+
const record = value;
|
|
83
|
+
const symbol = typeof record.symbol === "string" ? record.symbol.trim() : "";
|
|
84
|
+
const amount = typeof record.amount === "string" ? record.amount.trim() : toFiniteNumber(record.amount).toString();
|
|
85
|
+
const amountWei = typeof record.amountWei === "string" ? record.amountWei.trim() : "";
|
|
86
|
+
if (!symbol || !amount || !amountWei) return null;
|
|
87
|
+
return { symbol, amount, amountWei };
|
|
88
|
+
}
|
|
89
|
+
function normalizeLedgerEntry(value) {
|
|
90
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
91
|
+
const record = value;
|
|
92
|
+
const hash = typeof record.hash === "string" ? record.hash.trim() : "";
|
|
93
|
+
const tokenAddress = normalizeAddress(record.tokenAddress);
|
|
94
|
+
const quoteIn = normalizeLeg(record.quoteIn);
|
|
95
|
+
const quoteOut = normalizeLeg(record.quoteOut);
|
|
96
|
+
if (!hash || !tokenAddress || !quoteIn || !quoteOut) return null;
|
|
97
|
+
const routeRaw = Array.isArray(record.route) ? record.route : [];
|
|
98
|
+
const route = routeRaw.map((item) => typeof item === "string" ? item.trim() : "").filter((item) => item.length > 0);
|
|
99
|
+
const explorerUrl = typeof record.explorerUrl === "string" ? record.explorerUrl.trim() : `https://bscscan.com/tx/${hash}`;
|
|
100
|
+
return {
|
|
101
|
+
hash,
|
|
102
|
+
createdAt: normalizeIsoDate(record.createdAt),
|
|
103
|
+
updatedAt: normalizeIsoDate(record.updatedAt),
|
|
104
|
+
source: normalizeSource(record.source),
|
|
105
|
+
side: normalizeSide(record.side),
|
|
106
|
+
tokenAddress,
|
|
107
|
+
slippageBps: Math.max(0, Math.round(toFiniteNumber(record.slippageBps))),
|
|
108
|
+
route,
|
|
109
|
+
quoteIn,
|
|
110
|
+
quoteOut,
|
|
111
|
+
status: normalizeStatus(record.status),
|
|
112
|
+
confirmations: Math.max(
|
|
113
|
+
0,
|
|
114
|
+
Math.floor(toFiniteNumber(record.confirmations))
|
|
115
|
+
),
|
|
116
|
+
nonce: (() => {
|
|
117
|
+
const nonce = normalizeNullableInteger(record.nonce);
|
|
118
|
+
return nonce === null ? null : Math.max(0, nonce);
|
|
119
|
+
})(),
|
|
120
|
+
blockNumber: (() => {
|
|
121
|
+
const blockNumber = normalizeNullableInteger(record.blockNumber);
|
|
122
|
+
return blockNumber === null ? null : Math.max(0, blockNumber);
|
|
123
|
+
})(),
|
|
124
|
+
gasUsed: typeof record.gasUsed === "string" && record.gasUsed.trim() ? record.gasUsed.trim() : null,
|
|
125
|
+
effectiveGasPriceWei: typeof record.effectiveGasPriceWei === "string" && record.effectiveGasPriceWei.trim() ? record.effectiveGasPriceWei.trim() : null,
|
|
126
|
+
...typeof record.reason === "string" && record.reason.trim() ? { reason: record.reason.trim() } : {},
|
|
127
|
+
explorerUrl
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function sortAndTrimEntries(entries) {
|
|
131
|
+
const sorted = [...entries].sort((a, b) => {
|
|
132
|
+
const aMs = Date.parse(a.createdAt);
|
|
133
|
+
const bMs = Date.parse(b.createdAt);
|
|
134
|
+
if (Number.isFinite(aMs) && Number.isFinite(bMs) && aMs !== bMs) {
|
|
135
|
+
return aMs - bMs;
|
|
136
|
+
}
|
|
137
|
+
return a.hash.localeCompare(b.hash);
|
|
138
|
+
});
|
|
139
|
+
if (sorted.length <= MAX_WALLET_PROFILE_LEDGER_ENTRIES) return sorted;
|
|
140
|
+
return sorted.slice(sorted.length - MAX_WALLET_PROFILE_LEDGER_ENTRIES);
|
|
141
|
+
}
|
|
142
|
+
function ensureLedgerDir(filePath) {
|
|
143
|
+
const dir = path.dirname(filePath);
|
|
144
|
+
if (!fs.existsSync(dir)) {
|
|
145
|
+
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function atomicWriteLedger(filePath, store) {
|
|
149
|
+
ensureLedgerDir(filePath);
|
|
150
|
+
const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
151
|
+
try {
|
|
152
|
+
fs.writeFileSync(tmpPath, JSON.stringify(store, null, 2), {
|
|
153
|
+
encoding: "utf-8",
|
|
154
|
+
mode: 384
|
|
155
|
+
});
|
|
156
|
+
fs.renameSync(tmpPath, filePath);
|
|
157
|
+
} finally {
|
|
158
|
+
if (fs.existsSync(tmpPath)) {
|
|
159
|
+
fs.rmSync(tmpPath, { force: true });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function defaultLedgerStore() {
|
|
164
|
+
return {
|
|
165
|
+
version: WALLET_PROFILE_LEDGER_VERSION,
|
|
166
|
+
updatedAt: nowIso(),
|
|
167
|
+
entries: []
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function resolveWalletTradingProfileFilePath(stateDir = resolveStateDir()) {
|
|
171
|
+
return path.join(stateDir, "wallet", "trading-profile.v1.json");
|
|
172
|
+
}
|
|
173
|
+
function readWalletTradeLedgerStore(stateDir = resolveStateDir()) {
|
|
174
|
+
const filePath = resolveWalletTradingProfileFilePath(stateDir);
|
|
175
|
+
if (!fs.existsSync(filePath)) return defaultLedgerStore();
|
|
176
|
+
try {
|
|
177
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
178
|
+
const parsed = JSON.parse(raw);
|
|
179
|
+
const rawEntries = Array.isArray(parsed.entries) ? parsed.entries : [];
|
|
180
|
+
const entries = rawEntries.map((item) => normalizeLedgerEntry(item)).filter((item) => item !== null);
|
|
181
|
+
return {
|
|
182
|
+
version: WALLET_PROFILE_LEDGER_VERSION,
|
|
183
|
+
updatedAt: normalizeIsoDate(parsed.updatedAt),
|
|
184
|
+
entries: sortAndTrimEntries(entries)
|
|
185
|
+
};
|
|
186
|
+
} catch {
|
|
187
|
+
try {
|
|
188
|
+
const corruptPath = `${filePath}.corrupt-${Date.now()}.json`;
|
|
189
|
+
fs.renameSync(filePath, corruptPath);
|
|
190
|
+
} catch {
|
|
191
|
+
}
|
|
192
|
+
return defaultLedgerStore();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function writeWalletTradeLedgerStore(store, stateDir = resolveStateDir()) {
|
|
196
|
+
const filePath = resolveWalletTradingProfileFilePath(stateDir);
|
|
197
|
+
const normalized = {
|
|
198
|
+
version: WALLET_PROFILE_LEDGER_VERSION,
|
|
199
|
+
updatedAt: nowIso(),
|
|
200
|
+
entries: sortAndTrimEntries(store.entries)
|
|
201
|
+
};
|
|
202
|
+
atomicWriteLedger(filePath, normalized);
|
|
203
|
+
return normalized;
|
|
204
|
+
}
|
|
205
|
+
function recordWalletTradeLedgerEntry(input, stateDir = resolveStateDir()) {
|
|
206
|
+
const store = readWalletTradeLedgerStore(stateDir);
|
|
207
|
+
const entry = {
|
|
208
|
+
hash: input.hash.trim(),
|
|
209
|
+
createdAt: normalizeIsoDate(input.createdAt ?? nowIso()),
|
|
210
|
+
updatedAt: normalizeIsoDate(input.updatedAt ?? nowIso()),
|
|
211
|
+
source: normalizeSource(input.source),
|
|
212
|
+
side: normalizeSide(input.side),
|
|
213
|
+
tokenAddress: normalizeAddress(input.tokenAddress),
|
|
214
|
+
slippageBps: Math.max(0, Math.round(toFiniteNumber(input.slippageBps))),
|
|
215
|
+
route: (input.route ?? []).map((item) => item.trim()).filter((item) => item.length > 0),
|
|
216
|
+
quoteIn: {
|
|
217
|
+
symbol: input.quoteIn.symbol.trim(),
|
|
218
|
+
amount: input.quoteIn.amount.trim(),
|
|
219
|
+
amountWei: input.quoteIn.amountWei.trim()
|
|
220
|
+
},
|
|
221
|
+
quoteOut: {
|
|
222
|
+
symbol: input.quoteOut.symbol.trim(),
|
|
223
|
+
amount: input.quoteOut.amount.trim(),
|
|
224
|
+
amountWei: input.quoteOut.amountWei.trim()
|
|
225
|
+
},
|
|
226
|
+
status: normalizeStatus(input.status),
|
|
227
|
+
confirmations: Math.max(0, Math.floor(toFiniteNumber(input.confirmations))),
|
|
228
|
+
nonce: input.nonce === null ? null : Math.floor(toFiniteNumber(input.nonce)),
|
|
229
|
+
blockNumber: input.blockNumber === null ? null : Math.max(0, Math.floor(toFiniteNumber(input.blockNumber))),
|
|
230
|
+
gasUsed: input.gasUsed?.trim() || null,
|
|
231
|
+
effectiveGasPriceWei: input.effectiveGasPriceWei?.trim() || null,
|
|
232
|
+
...input.reason?.trim() ? { reason: input.reason.trim() } : {},
|
|
233
|
+
explorerUrl: input.explorerUrl.trim() || `https://bscscan.com/tx/${input.hash.trim()}`
|
|
234
|
+
};
|
|
235
|
+
const existingIndex = store.entries.findIndex(
|
|
236
|
+
(item) => item.hash === entry.hash
|
|
237
|
+
);
|
|
238
|
+
if (existingIndex >= 0) {
|
|
239
|
+
store.entries[existingIndex] = entry;
|
|
240
|
+
} else {
|
|
241
|
+
store.entries.push(entry);
|
|
242
|
+
}
|
|
243
|
+
writeWalletTradeLedgerStore(store, stateDir);
|
|
244
|
+
return entry;
|
|
245
|
+
}
|
|
246
|
+
function updateWalletTradeLedgerEntryStatus(hash, patch, stateDir = resolveStateDir()) {
|
|
247
|
+
const normalizedHash = hash.trim();
|
|
248
|
+
if (!normalizedHash) return null;
|
|
249
|
+
const store = readWalletTradeLedgerStore(stateDir);
|
|
250
|
+
const index = store.entries.findIndex(
|
|
251
|
+
(entry) => entry.hash === normalizedHash
|
|
252
|
+
);
|
|
253
|
+
if (index < 0) return null;
|
|
254
|
+
const current = store.entries[index];
|
|
255
|
+
const nextStatus = normalizeStatus(patch.status);
|
|
256
|
+
if (!canTransitionTradeStatus(current.status, nextStatus)) {
|
|
257
|
+
return current;
|
|
258
|
+
}
|
|
259
|
+
const updated = {
|
|
260
|
+
...current,
|
|
261
|
+
status: nextStatus,
|
|
262
|
+
confirmations: Math.max(0, Math.floor(toFiniteNumber(patch.confirmations))),
|
|
263
|
+
nonce: patch.nonce === null ? null : Math.floor(toFiniteNumber(patch.nonce)),
|
|
264
|
+
blockNumber: patch.blockNumber === null ? null : Math.max(0, Math.floor(toFiniteNumber(patch.blockNumber))),
|
|
265
|
+
gasUsed: patch.gasUsed?.trim() || null,
|
|
266
|
+
effectiveGasPriceWei: patch.effectiveGasPriceWei?.trim() || null,
|
|
267
|
+
...patch.explorerUrl?.trim() ? { explorerUrl: patch.explorerUrl.trim() } : {},
|
|
268
|
+
updatedAt: normalizeIsoDate(patch.updatedAt ?? nowIso())
|
|
269
|
+
};
|
|
270
|
+
if (typeof patch.reason === "string") {
|
|
271
|
+
const reason = patch.reason.trim();
|
|
272
|
+
if (reason) {
|
|
273
|
+
updated.reason = reason;
|
|
274
|
+
} else {
|
|
275
|
+
delete updated.reason;
|
|
276
|
+
}
|
|
277
|
+
} else if (updated.status === "success" || updated.status === "pending") {
|
|
278
|
+
delete updated.reason;
|
|
279
|
+
}
|
|
280
|
+
store.entries[index] = updated;
|
|
281
|
+
writeWalletTradeLedgerStore(store, stateDir);
|
|
282
|
+
return updated;
|
|
283
|
+
}
|
|
284
|
+
function resolveWindow(window) {
|
|
285
|
+
if (window === "7d" || window === "30d" || window === "all") return window;
|
|
286
|
+
return "30d";
|
|
287
|
+
}
|
|
288
|
+
function resolveSource(source) {
|
|
289
|
+
if (source === "all" || source === "agent" || source === "manual")
|
|
290
|
+
return source;
|
|
291
|
+
return "all";
|
|
292
|
+
}
|
|
293
|
+
function resolveTokenSymbol(entry) {
|
|
294
|
+
return entry.side === "buy" ? entry.quoteOut.symbol : entry.quoteIn.symbol;
|
|
295
|
+
}
|
|
296
|
+
function toDayBucket(isoDate) {
|
|
297
|
+
const timestamp = Date.parse(isoDate);
|
|
298
|
+
if (!Number.isFinite(timestamp)) return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
299
|
+
return new Date(timestamp).toISOString().slice(0, 10);
|
|
300
|
+
}
|
|
301
|
+
function consumeLots(lots, qtyToSell) {
|
|
302
|
+
if (!Number.isFinite(qtyToSell) || qtyToSell <= FLOAT_EPSILON) return 0;
|
|
303
|
+
let remaining = qtyToSell;
|
|
304
|
+
let matchedCost = 0;
|
|
305
|
+
while (remaining > FLOAT_EPSILON && lots.length > 0) {
|
|
306
|
+
const lot = lots[0];
|
|
307
|
+
if (lot.qty <= FLOAT_EPSILON) {
|
|
308
|
+
lots.shift();
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
const take = Math.min(remaining, lot.qty);
|
|
312
|
+
const ratio = take / lot.qty;
|
|
313
|
+
const consumedCost = lot.costBnb * ratio;
|
|
314
|
+
matchedCost += consumedCost;
|
|
315
|
+
lot.qty -= take;
|
|
316
|
+
lot.costBnb -= consumedCost;
|
|
317
|
+
remaining -= take;
|
|
318
|
+
if (lot.qty <= FLOAT_EPSILON || lot.costBnb <= FLOAT_EPSILON) {
|
|
319
|
+
lots.shift();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return matchedCost;
|
|
323
|
+
}
|
|
324
|
+
function toRecentSwap(entry) {
|
|
325
|
+
return {
|
|
326
|
+
hash: entry.hash,
|
|
327
|
+
createdAt: entry.createdAt,
|
|
328
|
+
source: entry.source,
|
|
329
|
+
side: entry.side,
|
|
330
|
+
status: entry.status,
|
|
331
|
+
tokenAddress: entry.tokenAddress,
|
|
332
|
+
tokenSymbol: resolveTokenSymbol(entry),
|
|
333
|
+
inputAmount: entry.quoteIn.amount,
|
|
334
|
+
inputSymbol: entry.quoteIn.symbol,
|
|
335
|
+
outputAmount: entry.quoteOut.amount,
|
|
336
|
+
outputSymbol: entry.quoteOut.symbol,
|
|
337
|
+
explorerUrl: entry.explorerUrl || `https://bscscan.com/tx/${entry.hash}`,
|
|
338
|
+
confirmations: entry.confirmations,
|
|
339
|
+
...entry.reason ? { reason: entry.reason } : {}
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
function buildWalletTradingProfile(entries, options = {}) {
|
|
343
|
+
const window = resolveWindow(options.window);
|
|
344
|
+
const source = resolveSource(options.source);
|
|
345
|
+
const now = Date.now();
|
|
346
|
+
const cutoffMs = window === "7d" ? now - 7 * ONE_DAY_MS : window === "30d" ? now - 30 * ONE_DAY_MS : 0;
|
|
347
|
+
const filtered = entries.filter((entry) => {
|
|
348
|
+
if (source !== "all" && entry.source !== source) return false;
|
|
349
|
+
if (cutoffMs > 0) {
|
|
350
|
+
const createdAtMs = Date.parse(entry.createdAt);
|
|
351
|
+
if (!Number.isFinite(createdAtMs) || createdAtMs < cutoffMs)
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
return true;
|
|
355
|
+
}).sort((a, b) => {
|
|
356
|
+
const aMs = Date.parse(a.createdAt);
|
|
357
|
+
const bMs = Date.parse(b.createdAt);
|
|
358
|
+
if (Number.isFinite(aMs) && Number.isFinite(bMs) && aMs !== bMs) {
|
|
359
|
+
return aMs - bMs;
|
|
360
|
+
}
|
|
361
|
+
return a.hash.localeCompare(b.hash);
|
|
362
|
+
});
|
|
363
|
+
let buyCount = 0;
|
|
364
|
+
let sellCount = 0;
|
|
365
|
+
let successCount = 0;
|
|
366
|
+
let revertedCount = 0;
|
|
367
|
+
let settledCount = 0;
|
|
368
|
+
let winningTrades = 0;
|
|
369
|
+
let evaluatedTrades = 0;
|
|
370
|
+
let realizedPnlBnb = 0;
|
|
371
|
+
let volumeBnb = 0;
|
|
372
|
+
const tokenMap = /* @__PURE__ */ new Map();
|
|
373
|
+
const seriesMap = /* @__PURE__ */ new Map();
|
|
374
|
+
for (const entry of filtered) {
|
|
375
|
+
if (entry.side === "buy") buyCount += 1;
|
|
376
|
+
else sellCount += 1;
|
|
377
|
+
if (entry.status === "success") successCount += 1;
|
|
378
|
+
if (entry.status === "reverted") revertedCount += 1;
|
|
379
|
+
if (entry.status === "success" || entry.status === "reverted")
|
|
380
|
+
settledCount += 1;
|
|
381
|
+
if (entry.status !== "success") continue;
|
|
382
|
+
const tokenAddress = entry.tokenAddress;
|
|
383
|
+
const tokenSymbol = resolveTokenSymbol(entry);
|
|
384
|
+
let token = tokenMap.get(tokenAddress);
|
|
385
|
+
if (!token) {
|
|
386
|
+
token = {
|
|
387
|
+
tokenAddress,
|
|
388
|
+
symbol: tokenSymbol,
|
|
389
|
+
buyCount: 0,
|
|
390
|
+
sellCount: 0,
|
|
391
|
+
realizedPnlBnb: 0,
|
|
392
|
+
volumeBnb: 0,
|
|
393
|
+
winningTrades: 0,
|
|
394
|
+
evaluatedTrades: 0,
|
|
395
|
+
lots: []
|
|
396
|
+
};
|
|
397
|
+
tokenMap.set(tokenAddress, token);
|
|
398
|
+
} else if (!token.symbol && tokenSymbol) {
|
|
399
|
+
token.symbol = tokenSymbol;
|
|
400
|
+
}
|
|
401
|
+
const day = toDayBucket(entry.createdAt);
|
|
402
|
+
let series = seriesMap.get(day);
|
|
403
|
+
if (!series) {
|
|
404
|
+
series = {
|
|
405
|
+
day,
|
|
406
|
+
realizedPnlBnb: 0,
|
|
407
|
+
volumeBnb: 0,
|
|
408
|
+
swaps: 0
|
|
409
|
+
};
|
|
410
|
+
seriesMap.set(day, series);
|
|
411
|
+
}
|
|
412
|
+
if (entry.side === "buy") {
|
|
413
|
+
const qtyBought = toFiniteNumber(entry.quoteOut.amount);
|
|
414
|
+
const spendBnb = toFiniteNumber(entry.quoteIn.amount);
|
|
415
|
+
token.buyCount += 1;
|
|
416
|
+
token.volumeBnb += spendBnb;
|
|
417
|
+
if (qtyBought > FLOAT_EPSILON && spendBnb >= 0) {
|
|
418
|
+
token.lots.push({ qty: qtyBought, costBnb: spendBnb });
|
|
419
|
+
}
|
|
420
|
+
volumeBnb += spendBnb;
|
|
421
|
+
series.volumeBnb += spendBnb;
|
|
422
|
+
series.swaps += 1;
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
const qtySold = toFiniteNumber(entry.quoteIn.amount);
|
|
426
|
+
const proceedsBnb = toFiniteNumber(entry.quoteOut.amount);
|
|
427
|
+
const matchedCostBnb = consumeLots(token.lots, qtySold);
|
|
428
|
+
const tradePnlBnb = proceedsBnb - matchedCostBnb;
|
|
429
|
+
token.sellCount += 1;
|
|
430
|
+
token.volumeBnb += proceedsBnb;
|
|
431
|
+
token.realizedPnlBnb += tradePnlBnb;
|
|
432
|
+
token.evaluatedTrades += 1;
|
|
433
|
+
if (tradePnlBnb > 0) token.winningTrades += 1;
|
|
434
|
+
evaluatedTrades += 1;
|
|
435
|
+
if (tradePnlBnb > 0) winningTrades += 1;
|
|
436
|
+
realizedPnlBnb += tradePnlBnb;
|
|
437
|
+
volumeBnb += proceedsBnb;
|
|
438
|
+
series.realizedPnlBnb += tradePnlBnb;
|
|
439
|
+
series.volumeBnb += proceedsBnb;
|
|
440
|
+
series.swaps += 1;
|
|
441
|
+
}
|
|
442
|
+
const tokenBreakdown = [
|
|
443
|
+
...tokenMap.values()
|
|
444
|
+
].map((token) => ({
|
|
445
|
+
tokenAddress: token.tokenAddress,
|
|
446
|
+
symbol: token.symbol || "TOKEN",
|
|
447
|
+
buyCount: token.buyCount,
|
|
448
|
+
sellCount: token.sellCount,
|
|
449
|
+
realizedPnlBnb: toBnbString(token.realizedPnlBnb),
|
|
450
|
+
volumeBnb: toBnbString(token.volumeBnb),
|
|
451
|
+
tradeWinRate: toRatePercent(token.winningTrades, token.evaluatedTrades),
|
|
452
|
+
winningTrades: token.winningTrades,
|
|
453
|
+
evaluatedTrades: token.evaluatedTrades
|
|
454
|
+
})).sort(
|
|
455
|
+
(a, b) => Number.parseFloat(b.volumeBnb) - Number.parseFloat(a.volumeBnb)
|
|
456
|
+
);
|
|
457
|
+
const pnlSeries = [...seriesMap.values()].sort((a, b) => a.day.localeCompare(b.day)).map((point) => ({
|
|
458
|
+
day: point.day,
|
|
459
|
+
realizedPnlBnb: toBnbString(point.realizedPnlBnb),
|
|
460
|
+
volumeBnb: toBnbString(point.volumeBnb),
|
|
461
|
+
swaps: point.swaps
|
|
462
|
+
}));
|
|
463
|
+
const recentSwaps = [...filtered].sort((a, b) => Date.parse(b.createdAt) - Date.parse(a.createdAt)).slice(0, 20).map(toRecentSwap);
|
|
464
|
+
return {
|
|
465
|
+
window,
|
|
466
|
+
source,
|
|
467
|
+
generatedAt: nowIso(),
|
|
468
|
+
summary: {
|
|
469
|
+
totalSwaps: filtered.length,
|
|
470
|
+
buyCount,
|
|
471
|
+
sellCount,
|
|
472
|
+
settledCount,
|
|
473
|
+
successCount,
|
|
474
|
+
revertedCount,
|
|
475
|
+
tradeWinRate: toRatePercent(winningTrades, evaluatedTrades),
|
|
476
|
+
txSuccessRate: toRatePercent(successCount, settledCount),
|
|
477
|
+
winningTrades,
|
|
478
|
+
evaluatedTrades,
|
|
479
|
+
realizedPnlBnb: toBnbString(realizedPnlBnb),
|
|
480
|
+
volumeBnb: toBnbString(volumeBnb)
|
|
481
|
+
},
|
|
482
|
+
pnlSeries,
|
|
483
|
+
tokenBreakdown,
|
|
484
|
+
recentSwaps
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
function loadWalletTradingProfile(options = {}) {
|
|
488
|
+
const store = readWalletTradeLedgerStore(options.stateDir);
|
|
489
|
+
return buildWalletTradingProfile(store.entries, options);
|
|
490
|
+
}
|
|
491
|
+
export {
|
|
492
|
+
buildWalletTradingProfile,
|
|
493
|
+
loadWalletTradingProfile,
|
|
494
|
+
readWalletTradeLedgerStore,
|
|
495
|
+
recordWalletTradeLedgerEntry,
|
|
496
|
+
resolveWalletTradingProfileFilePath,
|
|
497
|
+
updateWalletTradeLedgerEntryStatus,
|
|
498
|
+
writeWalletTradeLedgerStore
|
|
499
|
+
};
|
|
500
|
+
//# sourceMappingURL=wallet-trading-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/api/wallet-trading-profile.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { resolveStateDir } from \"@elizaos/agent\";\nimport type {\n BscTradeSide,\n BscTradeTxStatus,\n WalletTradeLedgerEntry,\n WalletTradeLedgerQuoteLeg,\n WalletTradeLedgerRecordInput,\n WalletTradeSource,\n WalletTradingProfileRecentSwap,\n WalletTradingProfileResponse,\n WalletTradingProfileSourceFilter,\n WalletTradingProfileTokenBreakdown,\n WalletTradingProfileWindow,\n} from \"@elizaos/core\";\n\nconst WALLET_PROFILE_LEDGER_VERSION = 1;\nconst MAX_WALLET_PROFILE_LEDGER_ENTRIES = 2000;\nconst ONE_DAY_MS = 24 * 60 * 60 * 1000;\nconst FLOAT_EPSILON = 1e-12;\n\ninterface WalletTradeLedgerStore {\n version: 1;\n updatedAt: string;\n entries: WalletTradeLedgerEntry[];\n}\n\nexport type { WalletTradeLedgerRecordInput };\n\nexport interface WalletTradeLedgerStatusPatch {\n status: BscTradeTxStatus;\n confirmations: number;\n nonce: number | null;\n blockNumber: number | null;\n gasUsed: string | null;\n effectiveGasPriceWei: string | null;\n reason?: string;\n explorerUrl?: string;\n updatedAt?: string;\n}\n\nexport interface WalletTradingProfileOptions {\n window?: WalletTradingProfileWindow;\n source?: WalletTradingProfileSourceFilter;\n stateDir?: string;\n}\n\ninterface TokenLot {\n qty: number;\n costBnb: number;\n}\n\ninterface TokenAccumulator {\n tokenAddress: string;\n symbol: string;\n buyCount: number;\n sellCount: number;\n realizedPnlBnb: number;\n volumeBnb: number;\n winningTrades: number;\n evaluatedTrades: number;\n lots: TokenLot[];\n}\n\ninterface SeriesAccumulator {\n day: string;\n realizedPnlBnb: number;\n volumeBnb: number;\n swaps: number;\n}\n\nconst TRADE_STATUS_SET = new Set<BscTradeTxStatus>([\n \"pending\",\n \"success\",\n \"reverted\",\n \"not_found\",\n]);\n\nconst ALLOWED_STATUS_TRANSITIONS: Record<\n BscTradeTxStatus,\n Set<BscTradeTxStatus>\n> = {\n pending: new Set([\"pending\", \"success\", \"reverted\", \"not_found\"]),\n not_found: new Set([\"pending\", \"success\", \"reverted\", \"not_found\"]),\n success: new Set([\"success\"]),\n reverted: new Set([\"reverted\"]),\n};\n\nconst TRADE_SIDE_SET = new Set<BscTradeSide>([\"buy\", \"sell\"]);\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction toFiniteNumber(value: unknown): number {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : 0;\n if (typeof value === \"string\") {\n const parsed = Number.parseFloat(value.trim());\n return Number.isFinite(parsed) ? parsed : 0;\n }\n return 0;\n}\n\nfunction toBnbString(value: number): string {\n if (!Number.isFinite(value) || Math.abs(value) < FLOAT_EPSILON) return \"0\";\n const fixed = value.toFixed(8).replace(/\\.?0+$/, \"\");\n return fixed === \"-0\" ? \"0\" : fixed;\n}\n\nfunction toRatePercent(numerator: number, denominator: number): number | null {\n if (!Number.isFinite(denominator) || denominator <= 0) return null;\n if (!Number.isFinite(numerator) || numerator <= 0) return 0;\n return (numerator / denominator) * 100;\n}\n\nfunction normalizeStatus(value: unknown): BscTradeTxStatus {\n if (typeof value !== \"string\") return \"pending\";\n const normalized = value.trim().toLowerCase() as BscTradeTxStatus;\n if (!TRADE_STATUS_SET.has(normalized)) return \"pending\";\n return normalized;\n}\n\nfunction canTransitionTradeStatus(\n current: BscTradeTxStatus,\n next: BscTradeTxStatus,\n): boolean {\n return ALLOWED_STATUS_TRANSITIONS[current].has(next);\n}\n\nfunction normalizeSide(value: unknown): BscTradeSide {\n if (typeof value !== \"string\") return \"buy\";\n const normalized = value.trim().toLowerCase() as BscTradeSide;\n if (!TRADE_SIDE_SET.has(normalized)) return \"buy\";\n return normalized;\n}\n\nfunction normalizeSource(value: unknown): WalletTradeSource {\n if (typeof value !== \"string\") return \"manual\";\n return value.trim().toLowerCase() === \"agent\" ? \"agent\" : \"manual\";\n}\n\nfunction normalizeIsoDate(value: unknown): string {\n if (typeof value !== \"string\") return nowIso();\n const trimmed = value.trim();\n if (!trimmed) return nowIso();\n const timestamp = Date.parse(trimmed);\n if (!Number.isFinite(timestamp)) return nowIso();\n return new Date(timestamp).toISOString();\n}\n\nfunction normalizeNullableInteger(value: unknown): number | null {\n if (value === null || value === undefined) return null;\n if (typeof value === \"string\" && !value.trim()) return null;\n const parsed = toFiniteNumber(value);\n if (!Number.isFinite(parsed)) return null;\n return Math.floor(parsed);\n}\n\nfunction normalizeAddress(value: unknown): string {\n if (typeof value !== \"string\") return \"\";\n return value.trim().toLowerCase();\n}\n\nfunction normalizeLeg(value: unknown): WalletTradeLedgerQuoteLeg | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n const record = value as Record<string, unknown>;\n const symbol = typeof record.symbol === \"string\" ? record.symbol.trim() : \"\";\n const amount =\n typeof record.amount === \"string\"\n ? record.amount.trim()\n : toFiniteNumber(record.amount).toString();\n const amountWei =\n typeof record.amountWei === \"string\" ? record.amountWei.trim() : \"\";\n if (!symbol || !amount || !amountWei) return null;\n return { symbol, amount, amountWei };\n}\n\nfunction normalizeLedgerEntry(value: unknown): WalletTradeLedgerEntry | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n const record = value as Record<string, unknown>;\n const hash = typeof record.hash === \"string\" ? record.hash.trim() : \"\";\n const tokenAddress = normalizeAddress(record.tokenAddress);\n const quoteIn = normalizeLeg(record.quoteIn);\n const quoteOut = normalizeLeg(record.quoteOut);\n if (!hash || !tokenAddress || !quoteIn || !quoteOut) return null;\n\n const routeRaw = Array.isArray(record.route) ? record.route : [];\n const route = routeRaw\n .map((item) => (typeof item === \"string\" ? item.trim() : \"\"))\n .filter((item) => item.length > 0);\n\n const explorerUrl =\n typeof record.explorerUrl === \"string\"\n ? record.explorerUrl.trim()\n : `https://bscscan.com/tx/${hash}`;\n\n return {\n hash,\n createdAt: normalizeIsoDate(record.createdAt),\n updatedAt: normalizeIsoDate(record.updatedAt),\n source: normalizeSource(record.source),\n side: normalizeSide(record.side),\n tokenAddress,\n slippageBps: Math.max(0, Math.round(toFiniteNumber(record.slippageBps))),\n route,\n quoteIn,\n quoteOut,\n status: normalizeStatus(record.status),\n confirmations: Math.max(\n 0,\n Math.floor(toFiniteNumber(record.confirmations)),\n ),\n nonce: (() => {\n const nonce = normalizeNullableInteger(record.nonce);\n return nonce === null ? null : Math.max(0, nonce);\n })(),\n blockNumber: (() => {\n const blockNumber = normalizeNullableInteger(record.blockNumber);\n return blockNumber === null ? null : Math.max(0, blockNumber);\n })(),\n gasUsed:\n typeof record.gasUsed === \"string\" && record.gasUsed.trim()\n ? record.gasUsed.trim()\n : null,\n effectiveGasPriceWei:\n typeof record.effectiveGasPriceWei === \"string\" &&\n record.effectiveGasPriceWei.trim()\n ? record.effectiveGasPriceWei.trim()\n : null,\n ...(typeof record.reason === \"string\" && record.reason.trim()\n ? { reason: record.reason.trim() }\n : {}),\n explorerUrl,\n };\n}\n\nfunction sortAndTrimEntries(\n entries: WalletTradeLedgerEntry[],\n): WalletTradeLedgerEntry[] {\n const sorted = [...entries].sort((a, b) => {\n const aMs = Date.parse(a.createdAt);\n const bMs = Date.parse(b.createdAt);\n if (Number.isFinite(aMs) && Number.isFinite(bMs) && aMs !== bMs) {\n return aMs - bMs;\n }\n return a.hash.localeCompare(b.hash);\n });\n if (sorted.length <= MAX_WALLET_PROFILE_LEDGER_ENTRIES) return sorted;\n return sorted.slice(sorted.length - MAX_WALLET_PROFILE_LEDGER_ENTRIES);\n}\n\nfunction ensureLedgerDir(filePath: string): void {\n const dir = path.dirname(filePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n}\n\nfunction atomicWriteLedger(\n filePath: string,\n store: WalletTradeLedgerStore,\n): void {\n ensureLedgerDir(filePath);\n const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;\n try {\n fs.writeFileSync(tmpPath, JSON.stringify(store, null, 2), {\n encoding: \"utf-8\",\n mode: 0o600,\n });\n fs.renameSync(tmpPath, filePath);\n } finally {\n if (fs.existsSync(tmpPath)) {\n fs.rmSync(tmpPath, { force: true });\n }\n }\n}\n\nfunction defaultLedgerStore(): WalletTradeLedgerStore {\n return {\n version: WALLET_PROFILE_LEDGER_VERSION,\n updatedAt: nowIso(),\n entries: [],\n };\n}\n\nexport function resolveWalletTradingProfileFilePath(\n stateDir: string = resolveStateDir(),\n): string {\n return path.join(stateDir, \"wallet\", \"trading-profile.v1.json\");\n}\n\nexport function readWalletTradeLedgerStore(\n stateDir: string = resolveStateDir(),\n): WalletTradeLedgerStore {\n const filePath = resolveWalletTradingProfileFilePath(stateDir);\n if (!fs.existsSync(filePath)) return defaultLedgerStore();\n\n try {\n const raw = fs.readFileSync(filePath, \"utf-8\");\n const parsed = JSON.parse(raw) as Record<string, unknown>;\n const rawEntries = Array.isArray(parsed.entries) ? parsed.entries : [];\n const entries = rawEntries\n .map((item) => normalizeLedgerEntry(item))\n .filter((item): item is WalletTradeLedgerEntry => item !== null);\n return {\n version: WALLET_PROFILE_LEDGER_VERSION,\n updatedAt: normalizeIsoDate(parsed.updatedAt),\n entries: sortAndTrimEntries(entries),\n };\n } catch {\n try {\n const corruptPath = `${filePath}.corrupt-${Date.now()}.json`;\n fs.renameSync(filePath, corruptPath);\n } catch {\n // Best effort backup; continue with empty store.\n }\n return defaultLedgerStore();\n }\n}\n\nexport function writeWalletTradeLedgerStore(\n store: WalletTradeLedgerStore,\n stateDir: string = resolveStateDir(),\n): WalletTradeLedgerStore {\n const filePath = resolveWalletTradingProfileFilePath(stateDir);\n const normalized: WalletTradeLedgerStore = {\n version: WALLET_PROFILE_LEDGER_VERSION,\n updatedAt: nowIso(),\n entries: sortAndTrimEntries(store.entries),\n };\n atomicWriteLedger(filePath, normalized);\n return normalized;\n}\n\nexport function recordWalletTradeLedgerEntry(\n input: WalletTradeLedgerRecordInput,\n stateDir: string = resolveStateDir(),\n): WalletTradeLedgerEntry {\n const store = readWalletTradeLedgerStore(stateDir);\n const entry: WalletTradeLedgerEntry = {\n hash: input.hash.trim(),\n createdAt: normalizeIsoDate(input.createdAt ?? nowIso()),\n updatedAt: normalizeIsoDate(input.updatedAt ?? nowIso()),\n source: normalizeSource(input.source),\n side: normalizeSide(input.side),\n tokenAddress: normalizeAddress(input.tokenAddress),\n slippageBps: Math.max(0, Math.round(toFiniteNumber(input.slippageBps))),\n route: (input.route ?? [])\n .map((item) => item.trim())\n .filter((item) => item.length > 0),\n quoteIn: {\n symbol: input.quoteIn.symbol.trim(),\n amount: input.quoteIn.amount.trim(),\n amountWei: input.quoteIn.amountWei.trim(),\n },\n quoteOut: {\n symbol: input.quoteOut.symbol.trim(),\n amount: input.quoteOut.amount.trim(),\n amountWei: input.quoteOut.amountWei.trim(),\n },\n status: normalizeStatus(input.status),\n confirmations: Math.max(0, Math.floor(toFiniteNumber(input.confirmations))),\n nonce:\n input.nonce === null ? null : Math.floor(toFiniteNumber(input.nonce)),\n blockNumber:\n input.blockNumber === null\n ? null\n : Math.max(0, Math.floor(toFiniteNumber(input.blockNumber))),\n gasUsed: input.gasUsed?.trim() || null,\n effectiveGasPriceWei: input.effectiveGasPriceWei?.trim() || null,\n ...(input.reason?.trim() ? { reason: input.reason.trim() } : {}),\n explorerUrl:\n input.explorerUrl.trim() || `https://bscscan.com/tx/${input.hash.trim()}`,\n };\n\n const existingIndex = store.entries.findIndex(\n (item) => item.hash === entry.hash,\n );\n if (existingIndex >= 0) {\n store.entries[existingIndex] = entry;\n } else {\n store.entries.push(entry);\n }\n writeWalletTradeLedgerStore(store, stateDir);\n return entry;\n}\n\nexport function updateWalletTradeLedgerEntryStatus(\n hash: string,\n patch: WalletTradeLedgerStatusPatch,\n stateDir: string = resolveStateDir(),\n): WalletTradeLedgerEntry | null {\n const normalizedHash = hash.trim();\n if (!normalizedHash) return null;\n\n const store = readWalletTradeLedgerStore(stateDir);\n const index = store.entries.findIndex(\n (entry) => entry.hash === normalizedHash,\n );\n if (index < 0) return null;\n\n const current = store.entries[index];\n const nextStatus = normalizeStatus(patch.status);\n if (!canTransitionTradeStatus(current.status, nextStatus)) {\n return current;\n }\n const updated: WalletTradeLedgerEntry = {\n ...current,\n status: nextStatus,\n confirmations: Math.max(0, Math.floor(toFiniteNumber(patch.confirmations))),\n nonce:\n patch.nonce === null ? null : Math.floor(toFiniteNumber(patch.nonce)),\n blockNumber:\n patch.blockNumber === null\n ? null\n : Math.max(0, Math.floor(toFiniteNumber(patch.blockNumber))),\n gasUsed: patch.gasUsed?.trim() || null,\n effectiveGasPriceWei: patch.effectiveGasPriceWei?.trim() || null,\n ...(patch.explorerUrl?.trim()\n ? { explorerUrl: patch.explorerUrl.trim() }\n : {}),\n updatedAt: normalizeIsoDate(patch.updatedAt ?? nowIso()),\n };\n if (typeof patch.reason === \"string\") {\n const reason = patch.reason.trim();\n if (reason) {\n updated.reason = reason;\n } else {\n delete updated.reason;\n }\n } else if (updated.status === \"success\" || updated.status === \"pending\") {\n delete updated.reason;\n }\n store.entries[index] = updated;\n writeWalletTradeLedgerStore(store, stateDir);\n return updated;\n}\n\nfunction resolveWindow(\n window: WalletTradingProfileWindow | undefined,\n): WalletTradingProfileWindow {\n if (window === \"7d\" || window === \"30d\" || window === \"all\") return window;\n return \"30d\";\n}\n\nfunction resolveSource(\n source: WalletTradingProfileSourceFilter | undefined,\n): WalletTradingProfileSourceFilter {\n if (source === \"all\" || source === \"agent\" || source === \"manual\")\n return source;\n return \"all\";\n}\n\nfunction resolveTokenSymbol(entry: WalletTradeLedgerEntry): string {\n return entry.side === \"buy\" ? entry.quoteOut.symbol : entry.quoteIn.symbol;\n}\n\nfunction toDayBucket(isoDate: string): string {\n const timestamp = Date.parse(isoDate);\n if (!Number.isFinite(timestamp)) return new Date().toISOString().slice(0, 10);\n return new Date(timestamp).toISOString().slice(0, 10);\n}\n\nfunction consumeLots(lots: TokenLot[], qtyToSell: number): number {\n if (!Number.isFinite(qtyToSell) || qtyToSell <= FLOAT_EPSILON) return 0;\n let remaining = qtyToSell;\n let matchedCost = 0;\n\n while (remaining > FLOAT_EPSILON && lots.length > 0) {\n const lot = lots[0];\n if (lot.qty <= FLOAT_EPSILON) {\n lots.shift();\n continue;\n }\n const take = Math.min(remaining, lot.qty);\n const ratio = take / lot.qty;\n const consumedCost = lot.costBnb * ratio;\n matchedCost += consumedCost;\n lot.qty -= take;\n lot.costBnb -= consumedCost;\n remaining -= take;\n\n if (lot.qty <= FLOAT_EPSILON || lot.costBnb <= FLOAT_EPSILON) {\n lots.shift();\n }\n }\n return matchedCost;\n}\n\nfunction toRecentSwap(\n entry: WalletTradeLedgerEntry,\n): WalletTradingProfileRecentSwap {\n return {\n hash: entry.hash,\n createdAt: entry.createdAt,\n source: entry.source,\n side: entry.side,\n status: entry.status,\n tokenAddress: entry.tokenAddress,\n tokenSymbol: resolveTokenSymbol(entry),\n inputAmount: entry.quoteIn.amount,\n inputSymbol: entry.quoteIn.symbol,\n outputAmount: entry.quoteOut.amount,\n outputSymbol: entry.quoteOut.symbol,\n explorerUrl: entry.explorerUrl || `https://bscscan.com/tx/${entry.hash}`,\n confirmations: entry.confirmations,\n ...(entry.reason ? { reason: entry.reason } : {}),\n };\n}\n\nexport function buildWalletTradingProfile(\n entries: WalletTradeLedgerEntry[],\n options: Pick<WalletTradingProfileOptions, \"window\" | \"source\"> = {},\n): WalletTradingProfileResponse {\n const window = resolveWindow(options.window);\n const source = resolveSource(options.source);\n const now = Date.now();\n const cutoffMs =\n window === \"7d\"\n ? now - 7 * ONE_DAY_MS\n : window === \"30d\"\n ? now - 30 * ONE_DAY_MS\n : 0;\n\n const filtered = entries\n .filter((entry) => {\n if (source !== \"all\" && entry.source !== source) return false;\n if (cutoffMs > 0) {\n const createdAtMs = Date.parse(entry.createdAt);\n if (!Number.isFinite(createdAtMs) || createdAtMs < cutoffMs)\n return false;\n }\n return true;\n })\n .sort((a, b) => {\n const aMs = Date.parse(a.createdAt);\n const bMs = Date.parse(b.createdAt);\n if (Number.isFinite(aMs) && Number.isFinite(bMs) && aMs !== bMs) {\n return aMs - bMs;\n }\n return a.hash.localeCompare(b.hash);\n });\n\n let buyCount = 0;\n let sellCount = 0;\n let successCount = 0;\n let revertedCount = 0;\n let settledCount = 0;\n let winningTrades = 0;\n let evaluatedTrades = 0;\n let realizedPnlBnb = 0;\n let volumeBnb = 0;\n\n const tokenMap = new Map<string, TokenAccumulator>();\n const seriesMap = new Map<string, SeriesAccumulator>();\n\n for (const entry of filtered) {\n if (entry.side === \"buy\") buyCount += 1;\n else sellCount += 1;\n\n if (entry.status === \"success\") successCount += 1;\n if (entry.status === \"reverted\") revertedCount += 1;\n if (entry.status === \"success\" || entry.status === \"reverted\")\n settledCount += 1;\n\n if (entry.status !== \"success\") continue;\n\n const tokenAddress = entry.tokenAddress;\n const tokenSymbol = resolveTokenSymbol(entry);\n let token = tokenMap.get(tokenAddress);\n if (!token) {\n token = {\n tokenAddress,\n symbol: tokenSymbol,\n buyCount: 0,\n sellCount: 0,\n realizedPnlBnb: 0,\n volumeBnb: 0,\n winningTrades: 0,\n evaluatedTrades: 0,\n lots: [],\n };\n tokenMap.set(tokenAddress, token);\n } else if (!token.symbol && tokenSymbol) {\n token.symbol = tokenSymbol;\n }\n\n const day = toDayBucket(entry.createdAt);\n let series = seriesMap.get(day);\n if (!series) {\n series = {\n day,\n realizedPnlBnb: 0,\n volumeBnb: 0,\n swaps: 0,\n };\n seriesMap.set(day, series);\n }\n\n if (entry.side === \"buy\") {\n const qtyBought = toFiniteNumber(entry.quoteOut.amount);\n const spendBnb = toFiniteNumber(entry.quoteIn.amount);\n token.buyCount += 1;\n token.volumeBnb += spendBnb;\n if (qtyBought > FLOAT_EPSILON && spendBnb >= 0) {\n token.lots.push({ qty: qtyBought, costBnb: spendBnb });\n }\n volumeBnb += spendBnb;\n series.volumeBnb += spendBnb;\n series.swaps += 1;\n continue;\n }\n\n const qtySold = toFiniteNumber(entry.quoteIn.amount);\n const proceedsBnb = toFiniteNumber(entry.quoteOut.amount);\n const matchedCostBnb = consumeLots(token.lots, qtySold);\n const tradePnlBnb = proceedsBnb - matchedCostBnb;\n\n token.sellCount += 1;\n token.volumeBnb += proceedsBnb;\n token.realizedPnlBnb += tradePnlBnb;\n token.evaluatedTrades += 1;\n if (tradePnlBnb > 0) token.winningTrades += 1;\n\n evaluatedTrades += 1;\n if (tradePnlBnb > 0) winningTrades += 1;\n realizedPnlBnb += tradePnlBnb;\n volumeBnb += proceedsBnb;\n\n series.realizedPnlBnb += tradePnlBnb;\n series.volumeBnb += proceedsBnb;\n series.swaps += 1;\n }\n\n const tokenBreakdown: WalletTradingProfileTokenBreakdown[] = [\n ...tokenMap.values(),\n ]\n .map((token) => ({\n tokenAddress: token.tokenAddress,\n symbol: token.symbol || \"TOKEN\",\n buyCount: token.buyCount,\n sellCount: token.sellCount,\n realizedPnlBnb: toBnbString(token.realizedPnlBnb),\n volumeBnb: toBnbString(token.volumeBnb),\n tradeWinRate: toRatePercent(token.winningTrades, token.evaluatedTrades),\n winningTrades: token.winningTrades,\n evaluatedTrades: token.evaluatedTrades,\n }))\n .sort(\n (a, b) => Number.parseFloat(b.volumeBnb) - Number.parseFloat(a.volumeBnb),\n );\n\n const pnlSeries = [...seriesMap.values()]\n .sort((a, b) => a.day.localeCompare(b.day))\n .map((point) => ({\n day: point.day,\n realizedPnlBnb: toBnbString(point.realizedPnlBnb),\n volumeBnb: toBnbString(point.volumeBnb),\n swaps: point.swaps,\n }));\n\n const recentSwaps = [...filtered]\n .sort((a, b) => Date.parse(b.createdAt) - Date.parse(a.createdAt))\n .slice(0, 20)\n .map(toRecentSwap);\n\n return {\n window,\n source,\n generatedAt: nowIso(),\n summary: {\n totalSwaps: filtered.length,\n buyCount,\n sellCount,\n settledCount,\n successCount,\n revertedCount,\n tradeWinRate: toRatePercent(winningTrades, evaluatedTrades),\n txSuccessRate: toRatePercent(successCount, settledCount),\n winningTrades,\n evaluatedTrades,\n realizedPnlBnb: toBnbString(realizedPnlBnb),\n volumeBnb: toBnbString(volumeBnb),\n },\n pnlSeries,\n tokenBreakdown,\n recentSwaps,\n };\n}\n\nexport function loadWalletTradingProfile(\n options: WalletTradingProfileOptions = {},\n): WalletTradingProfileResponse {\n const store = readWalletTradeLedgerStore(options.stateDir);\n return buildWalletTradingProfile(store.entries, options);\n}\n"],"mappings":"AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,uBAAuB;AAehC,MAAM,gCAAgC;AACtC,MAAM,oCAAoC;AAC1C,MAAM,aAAa,KAAK,KAAK,KAAK;AAClC,MAAM,gBAAgB;AAoDtB,MAAM,mBAAmB,oBAAI,IAAsB;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,MAAM,6BAGF;AAAA,EACF,SAAS,oBAAI,IAAI,CAAC,WAAW,WAAW,YAAY,WAAW,CAAC;AAAA,EAChE,WAAW,oBAAI,IAAI,CAAC,WAAW,WAAW,YAAY,WAAW,CAAC;AAAA,EAClE,SAAS,oBAAI,IAAI,CAAC,SAAS,CAAC;AAAA,EAC5B,UAAU,oBAAI,IAAI,CAAC,UAAU,CAAC;AAChC;AAEA,MAAM,iBAAiB,oBAAI,IAAkB,CAAC,OAAO,MAAM,CAAC;AAE5D,SAAS,SAAiB;AACxB,UAAO,oBAAI,KAAK,GAAE,YAAY;AAChC;AAEA,SAAS,eAAe,OAAwB;AAC9C,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,SAAS,OAAO,WAAW,MAAM,KAAK,CAAC;AAC7C,WAAO,OAAO,SAAS,MAAM,IAAI,SAAS;AAAA,EAC5C;AACA,SAAO;AACT;AAEA,SAAS,YAAY,OAAuB;AAC1C,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,cAAe,QAAO;AACvE,QAAM,QAAQ,MAAM,QAAQ,CAAC,EAAE,QAAQ,UAAU,EAAE;AACnD,SAAO,UAAU,OAAO,MAAM;AAChC;AAEA,SAAS,cAAc,WAAmB,aAAoC;AAC5E,MAAI,CAAC,OAAO,SAAS,WAAW,KAAK,eAAe,EAAG,QAAO;AAC9D,MAAI,CAAC,OAAO,SAAS,SAAS,KAAK,aAAa,EAAG,QAAO;AAC1D,SAAQ,YAAY,cAAe;AACrC;AAEA,SAAS,gBAAgB,OAAkC;AACzD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,aAAa,MAAM,KAAK,EAAE,YAAY;AAC5C,MAAI,CAAC,iBAAiB,IAAI,UAAU,EAAG,QAAO;AAC9C,SAAO;AACT;AAEA,SAAS,yBACP,SACA,MACS;AACT,SAAO,2BAA2B,OAAO,EAAE,IAAI,IAAI;AACrD;AAEA,SAAS,cAAc,OAA8B;AACnD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,aAAa,MAAM,KAAK,EAAE,YAAY;AAC5C,MAAI,CAAC,eAAe,IAAI,UAAU,EAAG,QAAO;AAC5C,SAAO;AACT;AAEA,SAAS,gBAAgB,OAAmC;AAC1D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,SAAO,MAAM,KAAK,EAAE,YAAY,MAAM,UAAU,UAAU;AAC5D;AAEA,SAAS,iBAAiB,OAAwB;AAChD,MAAI,OAAO,UAAU,SAAU,QAAO,OAAO;AAC7C,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAS,QAAO,OAAO;AAC5B,QAAM,YAAY,KAAK,MAAM,OAAO;AACpC,MAAI,CAAC,OAAO,SAAS,SAAS,EAAG,QAAO,OAAO;AAC/C,SAAO,IAAI,KAAK,SAAS,EAAE,YAAY;AACzC;AAEA,SAAS,yBAAyB,OAA+B;AAC/D,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,EAAG,QAAO;AACvD,QAAM,SAAS,eAAe,KAAK;AACnC,MAAI,CAAC,OAAO,SAAS,MAAM,EAAG,QAAO;AACrC,SAAO,KAAK,MAAM,MAAM;AAC1B;AAEA,SAAS,iBAAiB,OAAwB;AAChD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,SAAO,MAAM,KAAK,EAAE,YAAY;AAClC;AAEA,SAAS,aAAa,OAAkD;AACtE,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AACxE,QAAM,SAAS;AACf,QAAM,SAAS,OAAO,OAAO,WAAW,WAAW,OAAO,OAAO,KAAK,IAAI;AAC1E,QAAM,SACJ,OAAO,OAAO,WAAW,WACrB,OAAO,OAAO,KAAK,IACnB,eAAe,OAAO,MAAM,EAAE,SAAS;AAC7C,QAAM,YACJ,OAAO,OAAO,cAAc,WAAW,OAAO,UAAU,KAAK,IAAI;AACnE,MAAI,CAAC,UAAU,CAAC,UAAU,CAAC,UAAW,QAAO;AAC7C,SAAO,EAAE,QAAQ,QAAQ,UAAU;AACrC;AAEA,SAAS,qBAAqB,OAA+C;AAC3E,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,EAAG,QAAO;AACxE,QAAM,SAAS;AACf,QAAM,OAAO,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK,KAAK,IAAI;AACpE,QAAM,eAAe,iBAAiB,OAAO,YAAY;AACzD,QAAM,UAAU,aAAa,OAAO,OAAO;AAC3C,QAAM,WAAW,aAAa,OAAO,QAAQ;AAC7C,MAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,SAAU,QAAO;AAE5D,QAAM,WAAW,MAAM,QAAQ,OAAO,KAAK,IAAI,OAAO,QAAQ,CAAC;AAC/D,QAAM,QAAQ,SACX,IAAI,CAAC,SAAU,OAAO,SAAS,WAAW,KAAK,KAAK,IAAI,EAAG,EAC3D,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AAEnC,QAAM,cACJ,OAAO,OAAO,gBAAgB,WAC1B,OAAO,YAAY,KAAK,IACxB,0BAA0B,IAAI;AAEpC,SAAO;AAAA,IACL;AAAA,IACA,WAAW,iBAAiB,OAAO,SAAS;AAAA,IAC5C,WAAW,iBAAiB,OAAO,SAAS;AAAA,IAC5C,QAAQ,gBAAgB,OAAO,MAAM;AAAA,IACrC,MAAM,cAAc,OAAO,IAAI;AAAA,IAC/B;AAAA,IACA,aAAa,KAAK,IAAI,GAAG,KAAK,MAAM,eAAe,OAAO,WAAW,CAAC,CAAC;AAAA,IACvE;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,gBAAgB,OAAO,MAAM;AAAA,IACrC,eAAe,KAAK;AAAA,MAClB;AAAA,MACA,KAAK,MAAM,eAAe,OAAO,aAAa,CAAC;AAAA,IACjD;AAAA,IACA,QAAQ,MAAM;AACZ,YAAM,QAAQ,yBAAyB,OAAO,KAAK;AACnD,aAAO,UAAU,OAAO,OAAO,KAAK,IAAI,GAAG,KAAK;AAAA,IAClD,GAAG;AAAA,IACH,cAAc,MAAM;AAClB,YAAM,cAAc,yBAAyB,OAAO,WAAW;AAC/D,aAAO,gBAAgB,OAAO,OAAO,KAAK,IAAI,GAAG,WAAW;AAAA,IAC9D,GAAG;AAAA,IACH,SACE,OAAO,OAAO,YAAY,YAAY,OAAO,QAAQ,KAAK,IACtD,OAAO,QAAQ,KAAK,IACpB;AAAA,IACN,sBACE,OAAO,OAAO,yBAAyB,YACvC,OAAO,qBAAqB,KAAK,IAC7B,OAAO,qBAAqB,KAAK,IACjC;AAAA,IACN,GAAI,OAAO,OAAO,WAAW,YAAY,OAAO,OAAO,KAAK,IACxD,EAAE,QAAQ,OAAO,OAAO,KAAK,EAAE,IAC/B,CAAC;AAAA,IACL;AAAA,EACF;AACF;AAEA,SAAS,mBACP,SAC0B;AAC1B,QAAM,SAAS,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACzC,UAAM,MAAM,KAAK,MAAM,EAAE,SAAS;AAClC,UAAM,MAAM,KAAK,MAAM,EAAE,SAAS;AAClC,QAAI,OAAO,SAAS,GAAG,KAAK,OAAO,SAAS,GAAG,KAAK,QAAQ,KAAK;AAC/D,aAAO,MAAM;AAAA,IACf;AACA,WAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,EACpC,CAAC;AACD,MAAI,OAAO,UAAU,kCAAmC,QAAO;AAC/D,SAAO,OAAO,MAAM,OAAO,SAAS,iCAAiC;AACvE;AAEA,SAAS,gBAAgB,UAAwB;AAC/C,QAAM,MAAM,KAAK,QAAQ,QAAQ;AACjC,MAAI,CAAC,GAAG,WAAW,GAAG,GAAG;AACvB,OAAG,UAAU,KAAK,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AAAA,EACpD;AACF;AAEA,SAAS,kBACP,UACA,OACM;AACN,kBAAgB,QAAQ;AACxB,QAAM,UAAU,GAAG,QAAQ,QAAQ,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;AAC5D,MAAI;AACF,OAAG,cAAc,SAAS,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG;AAAA,MACxD,UAAU;AAAA,MACV,MAAM;AAAA,IACR,CAAC;AACD,OAAG,WAAW,SAAS,QAAQ;AAAA,EACjC,UAAE;AACA,QAAI,GAAG,WAAW,OAAO,GAAG;AAC1B,SAAG,OAAO,SAAS,EAAE,OAAO,KAAK,CAAC;AAAA,IACpC;AAAA,EACF;AACF;AAEA,SAAS,qBAA6C;AACpD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,WAAW,OAAO;AAAA,IAClB,SAAS,CAAC;AAAA,EACZ;AACF;AAEO,SAAS,oCACd,WAAmB,gBAAgB,GAC3B;AACR,SAAO,KAAK,KAAK,UAAU,UAAU,yBAAyB;AAChE;AAEO,SAAS,2BACd,WAAmB,gBAAgB,GACX;AACxB,QAAM,WAAW,oCAAoC,QAAQ;AAC7D,MAAI,CAAC,GAAG,WAAW,QAAQ,EAAG,QAAO,mBAAmB;AAExD,MAAI;AACF,UAAM,MAAM,GAAG,aAAa,UAAU,OAAO;AAC7C,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,UAAM,aAAa,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,UAAU,CAAC;AACrE,UAAM,UAAU,WACb,IAAI,CAAC,SAAS,qBAAqB,IAAI,CAAC,EACxC,OAAO,CAAC,SAAyC,SAAS,IAAI;AACjE,WAAO;AAAA,MACL,SAAS;AAAA,MACT,WAAW,iBAAiB,OAAO,SAAS;AAAA,MAC5C,SAAS,mBAAmB,OAAO;AAAA,IACrC;AAAA,EACF,QAAQ;AACN,QAAI;AACF,YAAM,cAAc,GAAG,QAAQ,YAAY,KAAK,IAAI,CAAC;AACrD,SAAG,WAAW,UAAU,WAAW;AAAA,IACrC,QAAQ;AAAA,IAER;AACA,WAAO,mBAAmB;AAAA,EAC5B;AACF;AAEO,SAAS,4BACd,OACA,WAAmB,gBAAgB,GACX;AACxB,QAAM,WAAW,oCAAoC,QAAQ;AAC7D,QAAM,aAAqC;AAAA,IACzC,SAAS;AAAA,IACT,WAAW,OAAO;AAAA,IAClB,SAAS,mBAAmB,MAAM,OAAO;AAAA,EAC3C;AACA,oBAAkB,UAAU,UAAU;AACtC,SAAO;AACT;AAEO,SAAS,6BACd,OACA,WAAmB,gBAAgB,GACX;AACxB,QAAM,QAAQ,2BAA2B,QAAQ;AACjD,QAAM,QAAgC;AAAA,IACpC,MAAM,MAAM,KAAK,KAAK;AAAA,IACtB,WAAW,iBAAiB,MAAM,aAAa,OAAO,CAAC;AAAA,IACvD,WAAW,iBAAiB,MAAM,aAAa,OAAO,CAAC;AAAA,IACvD,QAAQ,gBAAgB,MAAM,MAAM;AAAA,IACpC,MAAM,cAAc,MAAM,IAAI;AAAA,IAC9B,cAAc,iBAAiB,MAAM,YAAY;AAAA,IACjD,aAAa,KAAK,IAAI,GAAG,KAAK,MAAM,eAAe,MAAM,WAAW,CAAC,CAAC;AAAA,IACtE,QAAQ,MAAM,SAAS,CAAC,GACrB,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AAAA,IACnC,SAAS;AAAA,MACP,QAAQ,MAAM,QAAQ,OAAO,KAAK;AAAA,MAClC,QAAQ,MAAM,QAAQ,OAAO,KAAK;AAAA,MAClC,WAAW,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC1C;AAAA,IACA,UAAU;AAAA,MACR,QAAQ,MAAM,SAAS,OAAO,KAAK;AAAA,MACnC,QAAQ,MAAM,SAAS,OAAO,KAAK;AAAA,MACnC,WAAW,MAAM,SAAS,UAAU,KAAK;AAAA,IAC3C;AAAA,IACA,QAAQ,gBAAgB,MAAM,MAAM;AAAA,IACpC,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,eAAe,MAAM,aAAa,CAAC,CAAC;AAAA,IAC1E,OACE,MAAM,UAAU,OAAO,OAAO,KAAK,MAAM,eAAe,MAAM,KAAK,CAAC;AAAA,IACtE,aACE,MAAM,gBAAgB,OAClB,OACA,KAAK,IAAI,GAAG,KAAK,MAAM,eAAe,MAAM,WAAW,CAAC,CAAC;AAAA,IAC/D,SAAS,MAAM,SAAS,KAAK,KAAK;AAAA,IAClC,sBAAsB,MAAM,sBAAsB,KAAK,KAAK;AAAA,IAC5D,GAAI,MAAM,QAAQ,KAAK,IAAI,EAAE,QAAQ,MAAM,OAAO,KAAK,EAAE,IAAI,CAAC;AAAA,IAC9D,aACE,MAAM,YAAY,KAAK,KAAK,0BAA0B,MAAM,KAAK,KAAK,CAAC;AAAA,EAC3E;AAEA,QAAM,gBAAgB,MAAM,QAAQ;AAAA,IAClC,CAAC,SAAS,KAAK,SAAS,MAAM;AAAA,EAChC;AACA,MAAI,iBAAiB,GAAG;AACtB,UAAM,QAAQ,aAAa,IAAI;AAAA,EACjC,OAAO;AACL,UAAM,QAAQ,KAAK,KAAK;AAAA,EAC1B;AACA,8BAA4B,OAAO,QAAQ;AAC3C,SAAO;AACT;AAEO,SAAS,mCACd,MACA,OACA,WAAmB,gBAAgB,GACJ;AAC/B,QAAM,iBAAiB,KAAK,KAAK;AACjC,MAAI,CAAC,eAAgB,QAAO;AAE5B,QAAM,QAAQ,2BAA2B,QAAQ;AACjD,QAAM,QAAQ,MAAM,QAAQ;AAAA,IAC1B,CAAC,UAAU,MAAM,SAAS;AAAA,EAC5B;AACA,MAAI,QAAQ,EAAG,QAAO;AAEtB,QAAM,UAAU,MAAM,QAAQ,KAAK;AACnC,QAAM,aAAa,gBAAgB,MAAM,MAAM;AAC/C,MAAI,CAAC,yBAAyB,QAAQ,QAAQ,UAAU,GAAG;AACzD,WAAO;AAAA,EACT;AACA,QAAM,UAAkC;AAAA,IACtC,GAAG;AAAA,IACH,QAAQ;AAAA,IACR,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,eAAe,MAAM,aAAa,CAAC,CAAC;AAAA,IAC1E,OACE,MAAM,UAAU,OAAO,OAAO,KAAK,MAAM,eAAe,MAAM,KAAK,CAAC;AAAA,IACtE,aACE,MAAM,gBAAgB,OAClB,OACA,KAAK,IAAI,GAAG,KAAK,MAAM,eAAe,MAAM,WAAW,CAAC,CAAC;AAAA,IAC/D,SAAS,MAAM,SAAS,KAAK,KAAK;AAAA,IAClC,sBAAsB,MAAM,sBAAsB,KAAK,KAAK;AAAA,IAC5D,GAAI,MAAM,aAAa,KAAK,IACxB,EAAE,aAAa,MAAM,YAAY,KAAK,EAAE,IACxC,CAAC;AAAA,IACL,WAAW,iBAAiB,MAAM,aAAa,OAAO,CAAC;AAAA,EACzD;AACA,MAAI,OAAO,MAAM,WAAW,UAAU;AACpC,UAAM,SAAS,MAAM,OAAO,KAAK;AACjC,QAAI,QAAQ;AACV,cAAQ,SAAS;AAAA,IACnB,OAAO;AACL,aAAO,QAAQ;AAAA,IACjB;AAAA,EACF,WAAW,QAAQ,WAAW,aAAa,QAAQ,WAAW,WAAW;AACvE,WAAO,QAAQ;AAAA,EACjB;AACA,QAAM,QAAQ,KAAK,IAAI;AACvB,8BAA4B,OAAO,QAAQ;AAC3C,SAAO;AACT;AAEA,SAAS,cACP,QAC4B;AAC5B,MAAI,WAAW,QAAQ,WAAW,SAAS,WAAW,MAAO,QAAO;AACpE,SAAO;AACT;AAEA,SAAS,cACP,QACkC;AAClC,MAAI,WAAW,SAAS,WAAW,WAAW,WAAW;AACvD,WAAO;AACT,SAAO;AACT;AAEA,SAAS,mBAAmB,OAAuC;AACjE,SAAO,MAAM,SAAS,QAAQ,MAAM,SAAS,SAAS,MAAM,QAAQ;AACtE;AAEA,SAAS,YAAY,SAAyB;AAC5C,QAAM,YAAY,KAAK,MAAM,OAAO;AACpC,MAAI,CAAC,OAAO,SAAS,SAAS,EAAG,SAAO,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAC5E,SAAO,IAAI,KAAK,SAAS,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AACtD;AAEA,SAAS,YAAY,MAAkB,WAA2B;AAChE,MAAI,CAAC,OAAO,SAAS,SAAS,KAAK,aAAa,cAAe,QAAO;AACtE,MAAI,YAAY;AAChB,MAAI,cAAc;AAElB,SAAO,YAAY,iBAAiB,KAAK,SAAS,GAAG;AACnD,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,IAAI,OAAO,eAAe;AAC5B,WAAK,MAAM;AACX;AAAA,IACF;AACA,UAAM,OAAO,KAAK,IAAI,WAAW,IAAI,GAAG;AACxC,UAAM,QAAQ,OAAO,IAAI;AACzB,UAAM,eAAe,IAAI,UAAU;AACnC,mBAAe;AACf,QAAI,OAAO;AACX,QAAI,WAAW;AACf,iBAAa;AAEb,QAAI,IAAI,OAAO,iBAAiB,IAAI,WAAW,eAAe;AAC5D,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,aACP,OACgC;AAChC,SAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ,WAAW,MAAM;AAAA,IACjB,QAAQ,MAAM;AAAA,IACd,MAAM,MAAM;AAAA,IACZ,QAAQ,MAAM;AAAA,IACd,cAAc,MAAM;AAAA,IACpB,aAAa,mBAAmB,KAAK;AAAA,IACrC,aAAa,MAAM,QAAQ;AAAA,IAC3B,aAAa,MAAM,QAAQ;AAAA,IAC3B,cAAc,MAAM,SAAS;AAAA,IAC7B,cAAc,MAAM,SAAS;AAAA,IAC7B,aAAa,MAAM,eAAe,0BAA0B,MAAM,IAAI;AAAA,IACtE,eAAe,MAAM;AAAA,IACrB,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,EACjD;AACF;AAEO,SAAS,0BACd,SACA,UAAkE,CAAC,GACrC;AAC9B,QAAM,SAAS,cAAc,QAAQ,MAAM;AAC3C,QAAM,SAAS,cAAc,QAAQ,MAAM;AAC3C,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,WACJ,WAAW,OACP,MAAM,IAAI,aACV,WAAW,QACT,MAAM,KAAK,aACX;AAER,QAAM,WAAW,QACd,OAAO,CAAC,UAAU;AACjB,QAAI,WAAW,SAAS,MAAM,WAAW,OAAQ,QAAO;AACxD,QAAI,WAAW,GAAG;AAChB,YAAM,cAAc,KAAK,MAAM,MAAM,SAAS;AAC9C,UAAI,CAAC,OAAO,SAAS,WAAW,KAAK,cAAc;AACjD,eAAO;AAAA,IACX;AACA,WAAO;AAAA,EACT,CAAC,EACA,KAAK,CAAC,GAAG,MAAM;AACd,UAAM,MAAM,KAAK,MAAM,EAAE,SAAS;AAClC,UAAM,MAAM,KAAK,MAAM,EAAE,SAAS;AAClC,QAAI,OAAO,SAAS,GAAG,KAAK,OAAO,SAAS,GAAG,KAAK,QAAQ,KAAK;AAC/D,aAAO,MAAM;AAAA,IACf;AACA,WAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,EACpC,CAAC;AAEH,MAAI,WAAW;AACf,MAAI,YAAY;AAChB,MAAI,eAAe;AACnB,MAAI,gBAAgB;AACpB,MAAI,eAAe;AACnB,MAAI,gBAAgB;AACpB,MAAI,kBAAkB;AACtB,MAAI,iBAAiB;AACrB,MAAI,YAAY;AAEhB,QAAM,WAAW,oBAAI,IAA8B;AACnD,QAAM,YAAY,oBAAI,IAA+B;AAErD,aAAW,SAAS,UAAU;AAC5B,QAAI,MAAM,SAAS,MAAO,aAAY;AAAA,QACjC,cAAa;AAElB,QAAI,MAAM,WAAW,UAAW,iBAAgB;AAChD,QAAI,MAAM,WAAW,WAAY,kBAAiB;AAClD,QAAI,MAAM,WAAW,aAAa,MAAM,WAAW;AACjD,sBAAgB;AAElB,QAAI,MAAM,WAAW,UAAW;AAEhC,UAAM,eAAe,MAAM;AAC3B,UAAM,cAAc,mBAAmB,KAAK;AAC5C,QAAI,QAAQ,SAAS,IAAI,YAAY;AACrC,QAAI,CAAC,OAAO;AACV,cAAQ;AAAA,QACN;AAAA,QACA,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,WAAW;AAAA,QACX,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,MAAM,CAAC;AAAA,MACT;AACA,eAAS,IAAI,cAAc,KAAK;AAAA,IAClC,WAAW,CAAC,MAAM,UAAU,aAAa;AACvC,YAAM,SAAS;AAAA,IACjB;AAEA,UAAM,MAAM,YAAY,MAAM,SAAS;AACvC,QAAI,SAAS,UAAU,IAAI,GAAG;AAC9B,QAAI,CAAC,QAAQ;AACX,eAAS;AAAA,QACP;AAAA,QACA,gBAAgB;AAAA,QAChB,WAAW;AAAA,QACX,OAAO;AAAA,MACT;AACA,gBAAU,IAAI,KAAK,MAAM;AAAA,IAC3B;AAEA,QAAI,MAAM,SAAS,OAAO;AACxB,YAAM,YAAY,eAAe,MAAM,SAAS,MAAM;AACtD,YAAM,WAAW,eAAe,MAAM,QAAQ,MAAM;AACpD,YAAM,YAAY;AAClB,YAAM,aAAa;AACnB,UAAI,YAAY,iBAAiB,YAAY,GAAG;AAC9C,cAAM,KAAK,KAAK,EAAE,KAAK,WAAW,SAAS,SAAS,CAAC;AAAA,MACvD;AACA,mBAAa;AACb,aAAO,aAAa;AACpB,aAAO,SAAS;AAChB;AAAA,IACF;AAEA,UAAM,UAAU,eAAe,MAAM,QAAQ,MAAM;AACnD,UAAM,cAAc,eAAe,MAAM,SAAS,MAAM;AACxD,UAAM,iBAAiB,YAAY,MAAM,MAAM,OAAO;AACtD,UAAM,cAAc,cAAc;AAElC,UAAM,aAAa;AACnB,UAAM,aAAa;AACnB,UAAM,kBAAkB;AACxB,UAAM,mBAAmB;AACzB,QAAI,cAAc,EAAG,OAAM,iBAAiB;AAE5C,uBAAmB;AACnB,QAAI,cAAc,EAAG,kBAAiB;AACtC,sBAAkB;AAClB,iBAAa;AAEb,WAAO,kBAAkB;AACzB,WAAO,aAAa;AACpB,WAAO,SAAS;AAAA,EAClB;AAEA,QAAM,iBAAuD;AAAA,IAC3D,GAAG,SAAS,OAAO;AAAA,EACrB,EACG,IAAI,CAAC,WAAW;AAAA,IACf,cAAc,MAAM;AAAA,IACpB,QAAQ,MAAM,UAAU;AAAA,IACxB,UAAU,MAAM;AAAA,IAChB,WAAW,MAAM;AAAA,IACjB,gBAAgB,YAAY,MAAM,cAAc;AAAA,IAChD,WAAW,YAAY,MAAM,SAAS;AAAA,IACtC,cAAc,cAAc,MAAM,eAAe,MAAM,eAAe;AAAA,IACtE,eAAe,MAAM;AAAA,IACrB,iBAAiB,MAAM;AAAA,EACzB,EAAE,EACD;AAAA,IACC,CAAC,GAAG,MAAM,OAAO,WAAW,EAAE,SAAS,IAAI,OAAO,WAAW,EAAE,SAAS;AAAA,EAC1E;AAEF,QAAM,YAAY,CAAC,GAAG,UAAU,OAAO,CAAC,EACrC,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,cAAc,EAAE,GAAG,CAAC,EACzC,IAAI,CAAC,WAAW;AAAA,IACf,KAAK,MAAM;AAAA,IACX,gBAAgB,YAAY,MAAM,cAAc;AAAA,IAChD,WAAW,YAAY,MAAM,SAAS;AAAA,IACtC,OAAO,MAAM;AAAA,EACf,EAAE;AAEJ,QAAM,cAAc,CAAC,GAAG,QAAQ,EAC7B,KAAK,CAAC,GAAG,MAAM,KAAK,MAAM,EAAE,SAAS,IAAI,KAAK,MAAM,EAAE,SAAS,CAAC,EAChE,MAAM,GAAG,EAAE,EACX,IAAI,YAAY;AAEnB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,OAAO;AAAA,IACpB,SAAS;AAAA,MACP,YAAY,SAAS;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc,cAAc,eAAe,eAAe;AAAA,MAC1D,eAAe,cAAc,cAAc,YAAY;AAAA,MACvD;AAAA,MACA;AAAA,MACA,gBAAgB,YAAY,cAAc;AAAA,MAC1C,WAAW,YAAY,SAAS;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,yBACd,UAAuC,CAAC,GACV;AAC9B,QAAM,QAAQ,2BAA2B,QAAQ,QAAQ;AACzD,SAAO,0BAA0B,MAAM,SAAS,OAAO;AACzD;","names":[]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { KeyValidationResult, SolanaTokenBalance, WalletAddresses, WalletChain, WalletGenerateResult, WalletImportResult, WalletKeys } from "@elizaos/core";
|
|
2
|
+
export type { BscTradeExecuteRequest, BscTradeExecuteResponse, BscTradeExecutionResult, BscTradePreflightRequest, BscTradePreflightResponse, BscTradeQuoteRequest, BscTradeQuoteResponse, BscTradeSide, BscTradeTxStatus, BscTradeTxStatusResponse, BscTransferExecuteRequest, BscTransferExecuteResponse, BscTransferExecutionResult, BscUnsignedApprovalTx, BscUnsignedTradeTx, BscUnsignedTransferTx, EvmChainBalance, EvmTokenBalance, KeyValidationResult, SolanaTokenBalance, TradePermissionMode, WalletAddresses, WalletBalancesResponse, WalletChain, WalletConfigStatus, WalletGenerateResult, WalletImportResult, WalletKeys, WalletTradeLedgerEntry, WalletTradeSource, WalletTradingProfileResponse, WalletTradingProfileSourceFilter, WalletTradingProfileWindow, } from "@elizaos/core";
|
|
3
|
+
export { computeValueUsd, DEX_PRICE_TIMEOUT_MS, DEXPAPRIKA_CHAIN_MAP, DEXSCREENER_CHAIN_MAP, type DexScreenerPair, type DexTokenMeta, fetchDexPaprikaPrices, fetchDexPrices, fetchDexScreenerPrices, WRAPPED_NATIVE, } from "./wallet-dex-prices.js";
|
|
4
|
+
export { type AnkrTokenAsset, DEFAULT_EVM_CHAINS, type EvmProviderKeys, fetchEvmBalances, resolveEvmProviderKeys, } from "./wallet-evm-balance.js";
|
|
5
|
+
export declare const MANAGED_EVM_ADDRESS_ENV_KEY = "ELIZA_MANAGED_EVM_ADDRESS";
|
|
6
|
+
export declare const MANAGED_SOLANA_ADDRESS_ENV_KEY = "ELIZA_MANAGED_SOLANA_ADDRESS";
|
|
7
|
+
export declare function deriveEvmAddress(privateKeyHex: string): string;
|
|
8
|
+
export declare function deriveSolanaAddress(privateKeyString: string): string;
|
|
9
|
+
export declare function validateEvmPrivateKey(key: string): KeyValidationResult;
|
|
10
|
+
export declare function validateSolanaPrivateKey(key: string): KeyValidationResult;
|
|
11
|
+
/** Auto-detect chain from key format and validate. */
|
|
12
|
+
export declare function validatePrivateKey(key: string): KeyValidationResult;
|
|
13
|
+
/** Mask a secret string for safe display (e.g. logs, UI). */
|
|
14
|
+
export declare function maskSecret(value: string): string;
|
|
15
|
+
export declare function generateWalletKeys(): WalletKeys;
|
|
16
|
+
export declare function generateWalletForChain(chain: WalletChain): WalletGenerateResult;
|
|
17
|
+
export declare function syncSolanaPublicKeyEnv(privateKey?: string | undefined): string | null;
|
|
18
|
+
export declare function setSolanaWalletEnv(privateKey: string): string | null;
|
|
19
|
+
/** Validate key, store in process.env. Caller persists to config if needed. */
|
|
20
|
+
export declare function importWallet(chain: WalletChain, privateKey: string): WalletImportResult;
|
|
21
|
+
export declare const STEWARD_EVM_ADDRESS_ENV_KEY = "STEWARD_EVM_ADDRESS";
|
|
22
|
+
export declare const STEWARD_SOLANA_ADDRESS_ENV_KEY = "STEWARD_SOLANA_ADDRESS";
|
|
23
|
+
/**
|
|
24
|
+
* Initialise the steward wallet address cache.
|
|
25
|
+
*
|
|
26
|
+
* Call once during server startup. Fetches addresses from the steward API
|
|
27
|
+
* and writes them to `process.env.STEWARD_EVM_ADDRESS` /
|
|
28
|
+
* `process.env.STEWARD_SOLANA_ADDRESS` so the synchronous
|
|
29
|
+
* `getWalletAddresses()` can use them without hitting the network.
|
|
30
|
+
*/
|
|
31
|
+
export declare function initStewardWalletCache(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Derive addresses from env keys. Works without a running runtime.
|
|
34
|
+
*
|
|
35
|
+
* Resolution order (steward-first):
|
|
36
|
+
* 1. Steward cached addresses (`STEWARD_EVM_ADDRESS` / `STEWARD_SOLANA_ADDRESS`)
|
|
37
|
+
* 2. Local private key derivation (`EVM_PRIVATE_KEY` / `SOLANA_PRIVATE_KEY`)
|
|
38
|
+
* 3. Managed address env vars (`ELIZA_MANAGED_EVM_ADDRESS` / `ELIZA_MANAGED_SOLANA_ADDRESS`)
|
|
39
|
+
*/
|
|
40
|
+
export declare function getWalletAddresses(): WalletAddresses;
|
|
41
|
+
/**
|
|
42
|
+
* Extended wallet addresses including steward-managed wallets.
|
|
43
|
+
* Calls steward API (async) to discover additional addresses.
|
|
44
|
+
* Key-derived addresses are always preferred; steward addresses fill gaps.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getWalletAddressesWithSteward(): Promise<WalletAddresses & {
|
|
47
|
+
stewardEvmAddress?: string | null;
|
|
48
|
+
stewardSolanaAddress?: string | null;
|
|
49
|
+
}>;
|
|
50
|
+
export declare function fetchSolanaBalances(address: string, heliusKey: string): Promise<{
|
|
51
|
+
solBalance: string;
|
|
52
|
+
solValueUsd: string;
|
|
53
|
+
tokens: SolanaTokenBalance[];
|
|
54
|
+
}>;
|
|
55
|
+
export declare function fetchSolanaNativeBalanceViaRpc(address: string, rpcUrls: string[]): Promise<{
|
|
56
|
+
solBalance: string;
|
|
57
|
+
solValueUsd: string;
|
|
58
|
+
tokens: SolanaTokenBalance[];
|
|
59
|
+
}>;
|
|
60
|
+
//# sourceMappingURL=wallet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../src/api/wallet.ts"],"names":[],"mappings":"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"}
|