@raintree-technology/perps 0.1.0
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/CHANGELOG.md +33 -0
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/adapters/aevo.d.ts +64 -0
- package/dist/adapters/aevo.js +899 -0
- package/dist/adapters/certification.d.ts +33 -0
- package/dist/adapters/certification.js +99 -0
- package/dist/adapters/decibel/order-manager.d.ts +45 -0
- package/dist/adapters/decibel/order-manager.js +140 -0
- package/dist/adapters/decibel/rest-client.d.ts +176 -0
- package/dist/adapters/decibel/rest-client.js +155 -0
- package/dist/adapters/decibel/ws-feed.d.ts +28 -0
- package/dist/adapters/decibel/ws-feed.js +166 -0
- package/dist/adapters/decibel.d.ts +108 -0
- package/dist/adapters/decibel.js +1377 -0
- package/dist/adapters/hyperliquid.d.ts +63 -0
- package/dist/adapters/hyperliquid.js +797 -0
- package/dist/adapters/index.d.ts +11 -0
- package/dist/adapters/index.js +12 -0
- package/dist/adapters/interface.d.ts +310 -0
- package/dist/adapters/interface.js +15 -0
- package/dist/adapters/orderly.d.ts +70 -0
- package/dist/adapters/orderly.js +936 -0
- package/dist/adapters/paradex.d.ts +69 -0
- package/dist/adapters/paradex.js +862 -0
- package/dist/adapters/utils.d.ts +17 -0
- package/dist/adapters/utils.js +122 -0
- package/dist/cli/command-metadata.d.ts +2 -0
- package/dist/cli/command-metadata.js +44 -0
- package/dist/cli/context.d.ts +14 -0
- package/dist/cli/context.js +59 -0
- package/dist/cli/experience.d.ts +48 -0
- package/dist/cli/experience.js +243 -0
- package/dist/cli/ink/app/AppShell.d.ts +12 -0
- package/dist/cli/ink/app/AppShell.js +32 -0
- package/dist/cli/ink/app/MetricStrip.d.ts +6 -0
- package/dist/cli/ink/app/MetricStrip.js +14 -0
- package/dist/cli/ink/app/Panel.d.ts +9 -0
- package/dist/cli/ink/app/Panel.js +7 -0
- package/dist/cli/ink/app/ascii.d.ts +2 -0
- package/dist/cli/ink/app/ascii.js +46 -0
- package/dist/cli/ink/app/index.d.ts +5 -0
- package/dist/cli/ink/app/index.js +4 -0
- package/dist/cli/ink/app/types.d.ts +15 -0
- package/dist/cli/ink/app/types.js +1 -0
- package/dist/cli/ink/components/PnL.d.ts +12 -0
- package/dist/cli/ink/components/PnL.js +23 -0
- package/dist/cli/ink/components/Spinner.d.ts +13 -0
- package/dist/cli/ink/components/Spinner.js +13 -0
- package/dist/cli/ink/components/Table.d.ts +14 -0
- package/dist/cli/ink/components/Table.js +42 -0
- package/dist/cli/ink/components/WatchHeader.d.ts +10 -0
- package/dist/cli/ink/components/WatchHeader.js +18 -0
- package/dist/cli/ink/components/index.d.ts +4 -0
- package/dist/cli/ink/components/index.js +4 -0
- package/dist/cli/ink/index.d.ts +4 -0
- package/dist/cli/ink/index.js +4 -0
- package/dist/cli/ink/render.d.ts +12 -0
- package/dist/cli/ink/render.js +21 -0
- package/dist/cli/ink/theme.d.ts +29 -0
- package/dist/cli/ink/theme.js +40 -0
- package/dist/cli/network-defaults.d.ts +10 -0
- package/dist/cli/network-defaults.js +35 -0
- package/dist/cli/output.d.ts +11 -0
- package/dist/cli/output.js +115 -0
- package/dist/cli/program.d.ts +18 -0
- package/dist/cli/program.js +164 -0
- package/dist/cli/watch.d.ts +19 -0
- package/dist/cli/watch.js +35 -0
- package/dist/client/index.d.ts +55 -0
- package/dist/client/index.js +157 -0
- package/dist/commands/account/add.d.ts +2 -0
- package/dist/commands/account/add.js +510 -0
- package/dist/commands/account/balances-simple.d.ts +5 -0
- package/dist/commands/account/balances-simple.js +63 -0
- package/dist/commands/account/index.d.ts +2 -0
- package/dist/commands/account/index.js +17 -0
- package/dist/commands/account/ls.d.ts +2 -0
- package/dist/commands/account/ls.js +95 -0
- package/dist/commands/account/positions-simple.d.ts +5 -0
- package/dist/commands/account/positions-simple.js +77 -0
- package/dist/commands/account/remove.d.ts +2 -0
- package/dist/commands/account/remove.js +47 -0
- package/dist/commands/account/set-default.d.ts +2 -0
- package/dist/commands/account/set-default.js +47 -0
- package/dist/commands/agent/index.d.ts +2 -0
- package/dist/commands/agent/index.js +126 -0
- package/dist/commands/arb/alert.d.ts +6 -0
- package/dist/commands/arb/alert.js +88 -0
- package/dist/commands/arb/basis-execute.d.ts +6 -0
- package/dist/commands/arb/basis-execute.js +332 -0
- package/dist/commands/arb/basis.d.ts +6 -0
- package/dist/commands/arb/basis.js +181 -0
- package/dist/commands/arb/compare.d.ts +6 -0
- package/dist/commands/arb/compare.js +216 -0
- package/dist/commands/arb/execute.d.ts +6 -0
- package/dist/commands/arb/execute.js +467 -0
- package/dist/commands/arb/funding.d.ts +6 -0
- package/dist/commands/arb/funding.js +201 -0
- package/dist/commands/arb/history.d.ts +6 -0
- package/dist/commands/arb/history.js +153 -0
- package/dist/commands/arb/index.d.ts +6 -0
- package/dist/commands/arb/index.js +29 -0
- package/dist/commands/arb/positions.d.ts +6 -0
- package/dist/commands/arb/positions.js +158 -0
- package/dist/commands/arb/spread.d.ts +6 -0
- package/dist/commands/arb/spread.js +253 -0
- package/dist/commands/arb/track.d.ts +6 -0
- package/dist/commands/arb/track.js +259 -0
- package/dist/commands/asset/book-simple.d.ts +5 -0
- package/dist/commands/asset/book-simple.js +77 -0
- package/dist/commands/asset/index.d.ts +2 -0
- package/dist/commands/asset/index.js +5 -0
- package/dist/commands/completion.d.ts +2 -0
- package/dist/commands/completion.js +161 -0
- package/dist/commands/config/index.d.ts +5 -0
- package/dist/commands/config/index.js +109 -0
- package/dist/commands/data/index.d.ts +31 -0
- package/dist/commands/data/index.js +1466 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +201 -0
- package/dist/commands/exchange/index.d.ts +2 -0
- package/dist/commands/exchange/index.js +107 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +48 -0
- package/dist/commands/markets/index.d.ts +2 -0
- package/dist/commands/markets/index.js +5 -0
- package/dist/commands/markets/ls-simple.d.ts +7 -0
- package/dist/commands/markets/ls-simple.js +277 -0
- package/dist/commands/operator/index.d.ts +2 -0
- package/dist/commands/operator/index.js +146 -0
- package/dist/commands/order/cancel-simple.d.ts +5 -0
- package/dist/commands/order/cancel-simple.js +104 -0
- package/dist/commands/order/index.d.ts +2 -0
- package/dist/commands/order/index.js +13 -0
- package/dist/commands/order/limit-simple.d.ts +5 -0
- package/dist/commands/order/limit-simple.js +195 -0
- package/dist/commands/order/market-simple.d.ts +5 -0
- package/dist/commands/order/market-simple.js +190 -0
- package/dist/commands/order/shared.d.ts +17 -0
- package/dist/commands/order/shared.js +51 -0
- package/dist/commands/order/trigger-simple.d.ts +5 -0
- package/dist/commands/order/trigger-simple.js +246 -0
- package/dist/commands/referral/index.d.ts +2 -0
- package/dist/commands/referral/index.js +7 -0
- package/dist/commands/referral/set.d.ts +2 -0
- package/dist/commands/referral/set.js +26 -0
- package/dist/commands/referral/status.d.ts +2 -0
- package/dist/commands/referral/status.js +31 -0
- package/dist/commands/replay/index.d.ts +2 -0
- package/dist/commands/replay/index.js +152 -0
- package/dist/commands/risk/analytics.d.ts +2 -0
- package/dist/commands/risk/analytics.js +64 -0
- package/dist/commands/risk/audit.d.ts +2 -0
- package/dist/commands/risk/audit.js +52 -0
- package/dist/commands/risk/index.d.ts +2 -0
- package/dist/commands/risk/index.js +9 -0
- package/dist/commands/risk/rules.d.ts +2 -0
- package/dist/commands/risk/rules.js +102 -0
- package/dist/commands/server.d.ts +2 -0
- package/dist/commands/server.js +208 -0
- package/dist/commands/setup/index.d.ts +2 -0
- package/dist/commands/setup/index.js +478 -0
- package/dist/commands/signal/index.d.ts +2 -0
- package/dist/commands/signal/index.js +129 -0
- package/dist/commands/state/index.d.ts +2 -0
- package/dist/commands/state/index.js +5 -0
- package/dist/commands/state/show.d.ts +2 -0
- package/dist/commands/state/show.js +105 -0
- package/dist/commands/strategy/index.d.ts +4 -0
- package/dist/commands/strategy/index.js +73 -0
- package/dist/commands/traces/index.d.ts +2 -0
- package/dist/commands/traces/index.js +76 -0
- package/dist/commands/ui/demo.d.ts +9 -0
- package/dist/commands/ui/demo.js +195 -0
- package/dist/commands/ui/index.d.ts +2 -0
- package/dist/commands/ui/index.js +7 -0
- package/dist/commands/ui/terminal.d.ts +2 -0
- package/dist/commands/ui/terminal.js +255 -0
- package/dist/commands/upgrade.d.ts +2 -0
- package/dist/commands/upgrade.js +98 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/lib/agent/audit.d.ts +12 -0
- package/dist/lib/agent/audit.js +13 -0
- package/dist/lib/agent/gateway.d.ts +13 -0
- package/dist/lib/agent/gateway.js +598 -0
- package/dist/lib/agent/metrics.d.ts +33 -0
- package/dist/lib/agent/metrics.js +175 -0
- package/dist/lib/agent/signature.d.ts +8 -0
- package/dist/lib/agent/signature.js +28 -0
- package/dist/lib/agent/tools.d.ts +28 -0
- package/dist/lib/agent/tools.js +453 -0
- package/dist/lib/agent/x402.d.ts +23 -0
- package/dist/lib/agent/x402.js +62 -0
- package/dist/lib/api-wallet.d.ts +69 -0
- package/dist/lib/api-wallet.js +101 -0
- package/dist/lib/balance-watcher.d.ts +25 -0
- package/dist/lib/balance-watcher.js +83 -0
- package/dist/lib/book-watcher.d.ts +25 -0
- package/dist/lib/book-watcher.js +48 -0
- package/dist/lib/config.d.ts +88 -0
- package/dist/lib/config.js +427 -0
- package/dist/lib/constants.d.ts +50 -0
- package/dist/lib/constants.js +84 -0
- package/dist/lib/contracts.d.ts +7 -0
- package/dist/lib/contracts.js +8 -0
- package/dist/lib/credential-vault.d.ts +22 -0
- package/dist/lib/credential-vault.js +109 -0
- package/dist/lib/db/accounts.d.ts +83 -0
- package/dist/lib/db/accounts.js +203 -0
- package/dist/lib/db/funding-history.d.ts +69 -0
- package/dist/lib/db/funding-history.js +183 -0
- package/dist/lib/db/index.d.ts +11 -0
- package/dist/lib/db/index.js +272 -0
- package/dist/lib/events/bus.d.ts +10 -0
- package/dist/lib/events/bus.js +17 -0
- package/dist/lib/events/types.d.ts +51 -0
- package/dist/lib/events/types.js +1 -0
- package/dist/lib/exchange.d.ts +30 -0
- package/dist/lib/exchange.js +84 -0
- package/dist/lib/execution/journal.d.ts +25 -0
- package/dist/lib/execution/journal.js +158 -0
- package/dist/lib/execution/safety.d.ts +34 -0
- package/dist/lib/execution/safety.js +197 -0
- package/dist/lib/exit-codes.d.ts +18 -0
- package/dist/lib/exit-codes.js +60 -0
- package/dist/lib/fetch.d.ts +18 -0
- package/dist/lib/fetch.js +66 -0
- package/dist/lib/fs-security.d.ts +10 -0
- package/dist/lib/fs-security.js +26 -0
- package/dist/lib/funding-tracker.d.ts +40 -0
- package/dist/lib/funding-tracker.js +118 -0
- package/dist/lib/logger.d.ts +27 -0
- package/dist/lib/logger.js +82 -0
- package/dist/lib/network-model.d.ts +13 -0
- package/dist/lib/network-model.js +30 -0
- package/dist/lib/onboarding.d.ts +133 -0
- package/dist/lib/onboarding.js +1459 -0
- package/dist/lib/operator-state.d.ts +25 -0
- package/dist/lib/operator-state.js +82 -0
- package/dist/lib/orders-watcher.d.ts +24 -0
- package/dist/lib/orders-watcher.js +74 -0
- package/dist/lib/paths.d.ts +20 -0
- package/dist/lib/paths.js +23 -0
- package/dist/lib/portfolio-watcher.d.ts +33 -0
- package/dist/lib/portfolio-watcher.js +95 -0
- package/dist/lib/position-watcher.d.ts +16 -0
- package/dist/lib/position-watcher.js +44 -0
- package/dist/lib/price-watcher.d.ts +15 -0
- package/dist/lib/price-watcher.js +84 -0
- package/dist/lib/prompts.d.ts +32 -0
- package/dist/lib/prompts.js +105 -0
- package/dist/lib/rate-limit.d.ts +32 -0
- package/dist/lib/rate-limit.js +88 -0
- package/dist/lib/risk/analytics.d.ts +39 -0
- package/dist/lib/risk/analytics.js +98 -0
- package/dist/lib/risk/drawdown.d.ts +18 -0
- package/dist/lib/risk/drawdown.js +49 -0
- package/dist/lib/risk/evaluation-log.d.ts +29 -0
- package/dist/lib/risk/evaluation-log.js +61 -0
- package/dist/lib/risk/index.d.ts +4 -0
- package/dist/lib/risk/index.js +4 -0
- package/dist/lib/risk/limits.d.ts +23 -0
- package/dist/lib/risk/limits.js +27 -0
- package/dist/lib/risk/manager.d.ts +32 -0
- package/dist/lib/risk/manager.js +85 -0
- package/dist/lib/risk/policy-middleware.d.ts +33 -0
- package/dist/lib/risk/policy-middleware.js +267 -0
- package/dist/lib/risk/position-sizer.d.ts +9 -0
- package/dist/lib/risk/position-sizer.js +14 -0
- package/dist/lib/risk/rules-store.d.ts +16 -0
- package/dist/lib/risk/rules-store.js +47 -0
- package/dist/lib/schema.d.ts +254 -0
- package/dist/lib/schema.js +199 -0
- package/dist/lib/secrets.d.ts +3 -0
- package/dist/lib/secrets.js +62 -0
- package/dist/lib/settings.d.ts +24 -0
- package/dist/lib/settings.js +86 -0
- package/dist/lib/signals.d.ts +73 -0
- package/dist/lib/signals.js +136 -0
- package/dist/lib/stable-stringify.d.ts +6 -0
- package/dist/lib/stable-stringify.js +17 -0
- package/dist/lib/state-context.d.ts +44 -0
- package/dist/lib/state-context.js +133 -0
- package/dist/lib/strategy/basis-trade.d.ts +2 -0
- package/dist/lib/strategy/basis-trade.js +24 -0
- package/dist/lib/strategy/funding-arb.d.ts +2 -0
- package/dist/lib/strategy/funding-arb.js +23 -0
- package/dist/lib/strategy/interface.d.ts +23 -0
- package/dist/lib/strategy/interface.js +1 -0
- package/dist/lib/strategy/registry.d.ts +4 -0
- package/dist/lib/strategy/registry.js +10 -0
- package/dist/lib/telemetry.d.ts +25 -0
- package/dist/lib/telemetry.js +101 -0
- package/dist/lib/trace-queries.d.ts +20 -0
- package/dist/lib/trace-queries.js +133 -0
- package/dist/lib/trace.d.ts +1 -0
- package/dist/lib/trace.js +4 -0
- package/dist/lib/trade-reputation.d.ts +6 -0
- package/dist/lib/trade-reputation.js +99 -0
- package/dist/lib/ui-tokens.d.ts +21 -0
- package/dist/lib/ui-tokens.js +26 -0
- package/dist/lib/validate.d.ts +39 -0
- package/dist/lib/validate.js +108 -0
- package/dist/lib/validation.d.ts +9 -0
- package/dist/lib/validation.js +64 -0
- package/dist/server/cache.d.ts +38 -0
- package/dist/server/cache.js +56 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.js +89 -0
- package/dist/server/ipc.d.ts +18 -0
- package/dist/server/ipc.js +159 -0
- package/dist/server/subscriptions.d.ts +18 -0
- package/dist/server/subscriptions.js +114 -0
- package/package.json +124 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, render } from "ink";
|
|
3
|
+
import { getOutputOptions } from "../../cli/program.js";
|
|
4
|
+
import { output } from "../../cli/output.js";
|
|
5
|
+
import { getAllAccounts } from "../../lib/db/index.js";
|
|
6
|
+
import { AppShell, MetricStrip, Panel, Table, toBar, } from "../../cli/ink/index.js";
|
|
7
|
+
import { colors } from "../../cli/ink/theme.js";
|
|
8
|
+
function formatAddress(address) {
|
|
9
|
+
if (address.length <= 14) {
|
|
10
|
+
return address;
|
|
11
|
+
}
|
|
12
|
+
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
13
|
+
}
|
|
14
|
+
function buildExchangeCoverage(accounts) {
|
|
15
|
+
const counts = new Map();
|
|
16
|
+
for (const account of accounts) {
|
|
17
|
+
counts.set(account.exchange, (counts.get(account.exchange) || 0) + 1);
|
|
18
|
+
}
|
|
19
|
+
const rows = Array.from(counts.entries())
|
|
20
|
+
.map(([exchange, count]) => ({ exchange, count, bar: "" }))
|
|
21
|
+
.sort((left, right) => right.count - left.count || left.exchange.localeCompare(right.exchange));
|
|
22
|
+
const maxCount = Math.max(1, ...rows.map((row) => row.count));
|
|
23
|
+
return rows.map((row) => ({
|
|
24
|
+
...row,
|
|
25
|
+
bar: toBar(row.count, maxCount, 16, "#", "."),
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
28
|
+
function AccountsList({ accounts }) {
|
|
29
|
+
const hasAccounts = accounts.length > 0;
|
|
30
|
+
const exchangeCoverage = hasAccounts ? buildExchangeCoverage(accounts) : [];
|
|
31
|
+
const defaultCount = accounts.filter((account) => account.isDefault).length;
|
|
32
|
+
const apiWalletCount = accounts.filter((account) => Boolean(account.apiWalletPublicKey)).length;
|
|
33
|
+
const metrics = [
|
|
34
|
+
{ label: "Accounts", value: String(accounts.length), tone: hasAccounts ? "info" : "neutral" },
|
|
35
|
+
{ label: "Default", value: String(defaultCount), tone: defaultCount > 0 ? "success" : "warning" },
|
|
36
|
+
{ label: "API Wallets", value: String(apiWalletCount), tone: "neutral" },
|
|
37
|
+
{ label: "Exchanges", value: String(exchangeCoverage.length), tone: "neutral" },
|
|
38
|
+
];
|
|
39
|
+
if (accounts.length === 0) {
|
|
40
|
+
return (_jsxs(AppShell, { title: "Accounts", subtitle: "Local account profiles", status: [{ label: "EMPTY", tone: "warning" }], children: [_jsx(MetricStrip, { metrics: metrics }), _jsx(Panel, { title: "Profiles", subtitle: "No accounts are configured yet.", children: _jsx(Text, { color: colors.muted, children: "Run `perps account add` to add your first account." }) })] }));
|
|
41
|
+
}
|
|
42
|
+
const rows = accounts.map((acc) => ({
|
|
43
|
+
alias: acc.alias,
|
|
44
|
+
exchange: acc.exchange,
|
|
45
|
+
address: formatAddress(acc.userAddress),
|
|
46
|
+
type: acc.type,
|
|
47
|
+
apiWallet: acc.apiWalletPublicKey
|
|
48
|
+
? formatAddress(acc.apiWalletPublicKey)
|
|
49
|
+
: "-",
|
|
50
|
+
default: acc.isDefault ? "*" : "",
|
|
51
|
+
}));
|
|
52
|
+
const columns = [
|
|
53
|
+
{ key: "default", header: "", width: 2 },
|
|
54
|
+
{ key: "alias", header: "Alias" },
|
|
55
|
+
{ key: "exchange", header: "Exchange" },
|
|
56
|
+
{ key: "address", header: "Address" },
|
|
57
|
+
{ key: "type", header: "Type" },
|
|
58
|
+
{ key: "apiWallet", header: "API Wallet" },
|
|
59
|
+
];
|
|
60
|
+
const exchangeColumns = [
|
|
61
|
+
{ key: "exchange", header: "Exchange", width: 14 },
|
|
62
|
+
{ key: "count", header: "Count", align: "right", width: 5 },
|
|
63
|
+
{ key: "bar", header: "Coverage", width: 16 },
|
|
64
|
+
];
|
|
65
|
+
return (_jsxs(AppShell, { title: "Accounts", subtitle: "Local account profiles", status: [{ label: `${accounts.length} PROFILES`, tone: "info" }], children: [_jsx(MetricStrip, { metrics: metrics }), _jsx(Box, { flexDirection: "column", marginBottom: 1, children: _jsxs(Panel, { title: "Profiles", subtitle: "Saved accounts and default selection", children: [_jsx(Table, { data: rows, columns: columns }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.muted, children: "* = default account" }) })] }) }), _jsx(Panel, { title: "Exchange Coverage", subtitle: "Account distribution by exchange", children: _jsx(Table, { data: exchangeCoverage, columns: exchangeColumns }) })] }));
|
|
66
|
+
}
|
|
67
|
+
export function registerLsCommand(account) {
|
|
68
|
+
account
|
|
69
|
+
.command("ls")
|
|
70
|
+
.description("List all accounts")
|
|
71
|
+
.action(async function () {
|
|
72
|
+
const outputOpts = getOutputOptions(this);
|
|
73
|
+
const accounts = getAllAccounts();
|
|
74
|
+
if (outputOpts.json) {
|
|
75
|
+
// For JSON output, include full addresses but redact private keys
|
|
76
|
+
const jsonAccounts = accounts.map((acc) => ({
|
|
77
|
+
id: acc.id,
|
|
78
|
+
alias: acc.alias,
|
|
79
|
+
userAddress: acc.userAddress,
|
|
80
|
+
type: acc.type,
|
|
81
|
+
source: acc.source,
|
|
82
|
+
apiWalletPublicKey: acc.apiWalletPublicKey,
|
|
83
|
+
isDefault: acc.isDefault,
|
|
84
|
+
createdAt: acc.createdAt,
|
|
85
|
+
updatedAt: acc.updatedAt,
|
|
86
|
+
}));
|
|
87
|
+
output(jsonAccounts, outputOpts);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const { unmount, waitUntilExit } = render(_jsx(AccountsList, { accounts: accounts }));
|
|
91
|
+
await waitUntilExit();
|
|
92
|
+
unmount();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple positions command using the adapter interface
|
|
3
|
+
*/
|
|
4
|
+
import { getContext, getOutputOptions, getSelectedExchange } from "../../cli/program.js";
|
|
5
|
+
import { output, outputError } from "../../cli/output.js";
|
|
6
|
+
import { getExchangeAdapter } from "../../lib/exchange.js";
|
|
7
|
+
import { getExchangeCredentials } from "../../lib/config.js";
|
|
8
|
+
export function registerPositionsSimpleCommand(account) {
|
|
9
|
+
account
|
|
10
|
+
.command("positions")
|
|
11
|
+
.alias("pos")
|
|
12
|
+
.description("Show open positions")
|
|
13
|
+
.action(async function () {
|
|
14
|
+
const ctx = getContext(this);
|
|
15
|
+
const outputOpts = getOutputOptions(this);
|
|
16
|
+
const exchangeId = getSelectedExchange(this);
|
|
17
|
+
const adapter = getExchangeAdapter();
|
|
18
|
+
let connected = false;
|
|
19
|
+
try {
|
|
20
|
+
const credentials = getExchangeCredentials(ctx.config, exchangeId, {
|
|
21
|
+
requireReadAccess: true,
|
|
22
|
+
});
|
|
23
|
+
await adapter.connect({
|
|
24
|
+
testnet: ctx.config.testnet,
|
|
25
|
+
rpcUrl: credentials.fullnodeUrl,
|
|
26
|
+
wsUrl: credentials.wsUrl,
|
|
27
|
+
credentials,
|
|
28
|
+
});
|
|
29
|
+
connected = true;
|
|
30
|
+
const positions = await adapter.getPositions();
|
|
31
|
+
if (outputOpts.json) {
|
|
32
|
+
output(positions, outputOpts);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
if (positions.length === 0) {
|
|
36
|
+
console.log("\nNo open positions.\n");
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
console.log(`\n${adapter.info.name} Positions (${positions.length}):\n`);
|
|
40
|
+
console.log(" " +
|
|
41
|
+
"Market".padEnd(12) +
|
|
42
|
+
"Side".padEnd(7) +
|
|
43
|
+
"Size".padEnd(12) +
|
|
44
|
+
"Entry".padEnd(12) +
|
|
45
|
+
"Mark".padEnd(12) +
|
|
46
|
+
"uPnL".padEnd(14) +
|
|
47
|
+
"Lev");
|
|
48
|
+
console.log(" " + "─".repeat(80));
|
|
49
|
+
for (const pos of positions) {
|
|
50
|
+
const pnl = parseFloat(pos.unrealizedPnl);
|
|
51
|
+
const pnlColor = pnl >= 0 ? "\x1b[32m" : "\x1b[31m";
|
|
52
|
+
const pnlStr = `${pnl >= 0 ? "+" : ""}$${pnl.toFixed(2)}`;
|
|
53
|
+
const sideColor = pos.side === "long" ? "\x1b[32m" : "\x1b[31m";
|
|
54
|
+
console.log(" " +
|
|
55
|
+
pos.market.replace("-PERP", "").padEnd(12) +
|
|
56
|
+
`${sideColor}${pos.side.toUpperCase().padEnd(6)}\x1b[0m ` +
|
|
57
|
+
parseFloat(pos.size).toFixed(4).padEnd(12) +
|
|
58
|
+
`$${parseFloat(pos.entryPrice).toFixed(2)}`.padEnd(12) +
|
|
59
|
+
`$${parseFloat(pos.markPrice).toFixed(2)}`.padEnd(12) +
|
|
60
|
+
`${pnlColor}${pnlStr.padEnd(13)}\x1b[0m ` +
|
|
61
|
+
`${pos.leverage}x`);
|
|
62
|
+
}
|
|
63
|
+
console.log("");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
outputError(err instanceof Error ? err.message : String(err));
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
if (connected) {
|
|
73
|
+
await adapter.disconnect().catch(() => undefined);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getOutputOptions } from "../../cli/program.js";
|
|
2
|
+
import { output, outputError, outputSuccess } from "../../cli/output.js";
|
|
3
|
+
import { deleteAccount, getAccountByAlias } from "../../lib/db/index.js";
|
|
4
|
+
import { getExchangeId } from "../../lib/exchange.js";
|
|
5
|
+
import { confirm } from "../../lib/prompts.js";
|
|
6
|
+
export function registerRemoveCommand(account) {
|
|
7
|
+
account
|
|
8
|
+
.command("remove")
|
|
9
|
+
.description("Remove an account")
|
|
10
|
+
.argument("<alias>", "Account alias to remove")
|
|
11
|
+
.option("-f, --force", "Skip confirmation prompt")
|
|
12
|
+
.action(async function (alias, options) {
|
|
13
|
+
const outputOpts = getOutputOptions(this);
|
|
14
|
+
const exchangeId = getExchangeId();
|
|
15
|
+
try {
|
|
16
|
+
// Check if account exists
|
|
17
|
+
const existingAccount = getAccountByAlias(alias, exchangeId);
|
|
18
|
+
if (!existingAccount) {
|
|
19
|
+
throw new Error(`Account with alias "${alias}" not found for exchange "${exchangeId}". Run 'perps account ls' to see available accounts.`);
|
|
20
|
+
}
|
|
21
|
+
// Confirm deletion unless --force is used
|
|
22
|
+
if (!options.force) {
|
|
23
|
+
const confirmed = await confirm(`Are you sure you want to remove account "${alias}" (${existingAccount.userAddress})?`, false);
|
|
24
|
+
if (!confirmed) {
|
|
25
|
+
console.log("Cancelled.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const deleted = deleteAccount(alias, exchangeId);
|
|
30
|
+
if (deleted) {
|
|
31
|
+
if (outputOpts.json) {
|
|
32
|
+
output({ message: `Account "${alias}" removed`, deleted: true }, outputOpts);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
outputSuccess(`Account "${alias}" removed.`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
throw new Error(`Failed to remove account "${alias}"`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
outputError(err instanceof Error ? err.message : String(err));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getOutputOptions } from "../../cli/program.js";
|
|
2
|
+
import { output, outputError, outputSuccess } from "../../cli/output.js";
|
|
3
|
+
import { setDefaultAccount, getAccountByAlias } from "../../lib/db/index.js";
|
|
4
|
+
import { getExchangeId } from "../../lib/exchange.js";
|
|
5
|
+
export function registerSetDefaultCommand(account) {
|
|
6
|
+
account
|
|
7
|
+
.command("set-default")
|
|
8
|
+
.description("Set an account as the default")
|
|
9
|
+
.argument("<alias>", "Account alias to set as default")
|
|
10
|
+
.action(async function (alias) {
|
|
11
|
+
const outputOpts = getOutputOptions(this);
|
|
12
|
+
const exchangeId = getExchangeId();
|
|
13
|
+
try {
|
|
14
|
+
// Check if account exists
|
|
15
|
+
const existingAccount = getAccountByAlias(alias, exchangeId);
|
|
16
|
+
if (!existingAccount) {
|
|
17
|
+
throw new Error(`Account with alias "${alias}" not found for exchange "${exchangeId}". Run 'perps account ls' to see available accounts.`);
|
|
18
|
+
}
|
|
19
|
+
if (existingAccount.isDefault) {
|
|
20
|
+
if (outputOpts.json) {
|
|
21
|
+
output({ message: `Account "${alias}" is already the default` }, outputOpts);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
console.log(`Account "${alias}" is already the default.`);
|
|
25
|
+
}
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const updatedAccount = setDefaultAccount(alias, exchangeId);
|
|
29
|
+
if (outputOpts.json) {
|
|
30
|
+
output({
|
|
31
|
+
id: updatedAccount.id,
|
|
32
|
+
alias: updatedAccount.alias,
|
|
33
|
+
userAddress: updatedAccount.userAddress,
|
|
34
|
+
type: updatedAccount.type,
|
|
35
|
+
isDefault: updatedAccount.isDefault,
|
|
36
|
+
}, outputOpts);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
outputSuccess(`Account "${alias}" is now the default.`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
outputError(err instanceof Error ? err.message : String(err));
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { getContext, getOutputOptions, getSelectedExchange } from "../../cli/program.js";
|
|
2
|
+
import { output, outputError } from "../../cli/output.js";
|
|
3
|
+
import { withJsonContract } from "../../lib/contracts.js";
|
|
4
|
+
import { createAgentGateway } from "../../lib/agent/gateway.js";
|
|
5
|
+
export function registerAgentCommands(program) {
|
|
6
|
+
const agent = program
|
|
7
|
+
.command("agent")
|
|
8
|
+
.description("Agent gateway controls and metadata");
|
|
9
|
+
agent
|
|
10
|
+
.command("serve")
|
|
11
|
+
.description("Start the HTTP agent gateway")
|
|
12
|
+
.option("--host <host>", "Bind host", process.env.PERPS_AGENT_HOST ?? "127.0.0.1")
|
|
13
|
+
.option("--port <port>", "Bind port", process.env.PERPS_AGENT_PORT ?? "4020")
|
|
14
|
+
.option("--allow-mainnet", "Allow mainnet execute requests")
|
|
15
|
+
.action(async function () {
|
|
16
|
+
const ctx = getContext(this);
|
|
17
|
+
const outputOpts = getOutputOptions(this);
|
|
18
|
+
const exchange = getSelectedExchange(this);
|
|
19
|
+
const opts = this.opts();
|
|
20
|
+
const port = Number.parseInt(opts.port, 10);
|
|
21
|
+
if (!Number.isFinite(port) || port <= 0 || port > 65535) {
|
|
22
|
+
throw new Error("port must be a valid integer between 1 and 65535");
|
|
23
|
+
}
|
|
24
|
+
const allowMainnet = opts.allowMainnet === true ||
|
|
25
|
+
process.env.PERPS_AGENT_ALLOW_MAINNET === "1";
|
|
26
|
+
const gateway = createAgentGateway({
|
|
27
|
+
host: opts.host,
|
|
28
|
+
port,
|
|
29
|
+
defaultExchange: exchange,
|
|
30
|
+
defaultTestnet: ctx.config.testnet,
|
|
31
|
+
allowMainnetExecution: allowMainnet,
|
|
32
|
+
});
|
|
33
|
+
await gateway.start();
|
|
34
|
+
const baseUrl = `http://${opts.host}:${port}`;
|
|
35
|
+
if (outputOpts.json) {
|
|
36
|
+
output(withJsonContract("agent.gateway.started", {
|
|
37
|
+
status: "running",
|
|
38
|
+
baseUrl,
|
|
39
|
+
defaultExchange: exchange,
|
|
40
|
+
defaultTestnet: ctx.config.testnet,
|
|
41
|
+
allowMainnetExecution: allowMainnet,
|
|
42
|
+
}), outputOpts);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.log("");
|
|
46
|
+
console.log(`Agent gateway running at ${baseUrl}`);
|
|
47
|
+
console.log(` GET ${baseUrl}/capabilities`);
|
|
48
|
+
console.log(` POST ${baseUrl}/quote`);
|
|
49
|
+
console.log(` POST ${baseUrl}/execute`);
|
|
50
|
+
console.log(` POST ${baseUrl}/acp/intent`);
|
|
51
|
+
console.log(``);
|
|
52
|
+
console.log("Press Ctrl+C to stop.");
|
|
53
|
+
console.log("");
|
|
54
|
+
}
|
|
55
|
+
await new Promise((resolve) => {
|
|
56
|
+
let stopping = false;
|
|
57
|
+
const shutdown = async () => {
|
|
58
|
+
if (stopping)
|
|
59
|
+
return;
|
|
60
|
+
stopping = true;
|
|
61
|
+
await gateway.stop().catch(() => { });
|
|
62
|
+
resolve();
|
|
63
|
+
};
|
|
64
|
+
process.once("SIGINT", () => {
|
|
65
|
+
void shutdown();
|
|
66
|
+
});
|
|
67
|
+
process.once("SIGTERM", () => {
|
|
68
|
+
void shutdown();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
agent
|
|
73
|
+
.command("status")
|
|
74
|
+
.description("Check whether agent gateway is reachable")
|
|
75
|
+
.option("--host <host>", "Host", process.env.PERPS_AGENT_HOST ?? "127.0.0.1")
|
|
76
|
+
.option("--port <port>", "Port", process.env.PERPS_AGENT_PORT ?? "4020")
|
|
77
|
+
.action(async function () {
|
|
78
|
+
const outputOpts = getOutputOptions(this);
|
|
79
|
+
const opts = this.opts();
|
|
80
|
+
const baseUrl = `http://${opts.host}:${opts.port}`;
|
|
81
|
+
try {
|
|
82
|
+
const res = await fetch(`${baseUrl}/status`);
|
|
83
|
+
const payload = await res.json();
|
|
84
|
+
if (outputOpts.json) {
|
|
85
|
+
output(payload, outputOpts);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
output(`Gateway is reachable at ${baseUrl}`, outputOpts);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
if (outputOpts.json) {
|
|
92
|
+
output(withJsonContract("agent.gateway.status", {
|
|
93
|
+
status: "unreachable",
|
|
94
|
+
baseUrl,
|
|
95
|
+
error: err instanceof Error ? err.message : String(err),
|
|
96
|
+
}), outputOpts);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
outputError(`Gateway is not reachable at ${baseUrl}`);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
agent
|
|
103
|
+
.command("manifest")
|
|
104
|
+
.description("Print endpoint summary for agent orchestration")
|
|
105
|
+
.option("--host <host>", "Host", process.env.PERPS_AGENT_HOST ?? "127.0.0.1")
|
|
106
|
+
.option("--port <port>", "Port", process.env.PERPS_AGENT_PORT ?? "4020")
|
|
107
|
+
.action(function () {
|
|
108
|
+
const outputOpts = getOutputOptions(this);
|
|
109
|
+
const opts = this.opts();
|
|
110
|
+
const baseUrl = `http://${opts.host}:${opts.port}`;
|
|
111
|
+
output(withJsonContract("agent.gateway.manifest", {
|
|
112
|
+
baseUrl,
|
|
113
|
+
endpoints: [
|
|
114
|
+
{ method: "GET", path: "/capabilities" },
|
|
115
|
+
{ method: "GET", path: "/status" },
|
|
116
|
+
{ method: "GET", path: "/metrics" },
|
|
117
|
+
{ method: "GET", path: "/reputation" },
|
|
118
|
+
{ method: "POST", path: "/quote" },
|
|
119
|
+
{ method: "POST", path: "/execute" },
|
|
120
|
+
{ method: "POST", path: "/acp/intent" },
|
|
121
|
+
],
|
|
122
|
+
paymentProtocol: "x402",
|
|
123
|
+
note: "POST /execute requires idempotencyKey and payment proof by default",
|
|
124
|
+
}), outputOpts);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arb Alert Command
|
|
3
|
+
* Set up alerts for funding rate arbitrage opportunities
|
|
4
|
+
*/
|
|
5
|
+
import { getContext } from "../../cli/program.js";
|
|
6
|
+
import { pollFundingRates } from "../../lib/funding-tracker.js";
|
|
7
|
+
import { getAvailableExchanges } from "../../lib/exchange.js";
|
|
8
|
+
import { COMMON_ASSETS, MIN_PROFITABLE_SPREAD_PCT, DEFAULT_ALERT_INTERVAL_MS } from "../../lib/constants.js";
|
|
9
|
+
import { parseAssetList, parsePositiveNumber, parsePositiveInt } from "../../lib/validate.js";
|
|
10
|
+
export function registerArbAlertCommand(arb) {
|
|
11
|
+
arb
|
|
12
|
+
.command("alert")
|
|
13
|
+
.description("Monitor for funding arbitrage opportunities")
|
|
14
|
+
.option("-a, --assets <assets>", "Comma-separated assets to monitor", "BTC,ETH,SOL")
|
|
15
|
+
.option("-t, --threshold <percent>", "Minimum annualized spread to alert on", String(MIN_PROFITABLE_SPREAD_PCT))
|
|
16
|
+
.option("-i, --interval <minutes>", "Check interval in minutes", String(DEFAULT_ALERT_INTERVAL_MS / 60000))
|
|
17
|
+
.action(async function () {
|
|
18
|
+
const ctx = getContext(this);
|
|
19
|
+
const opts = this.opts();
|
|
20
|
+
const config = {
|
|
21
|
+
assets: parseAssetList(opts.assets, COMMON_ASSETS.slice(0, 3)),
|
|
22
|
+
threshold: parsePositiveNumber(opts.threshold, "threshold", MIN_PROFITABLE_SPREAD_PCT),
|
|
23
|
+
intervalMin: parsePositiveInt(opts.interval, "interval", 5),
|
|
24
|
+
};
|
|
25
|
+
const exchanges = getAvailableExchanges();
|
|
26
|
+
const isTestnet = ctx.config.testnet;
|
|
27
|
+
console.log("\n \x1b[1mFunding Rate Alert Monitor\x1b[0m");
|
|
28
|
+
console.log(` Assets: ${config.assets.join(", ")}`);
|
|
29
|
+
console.log(` Threshold: ${config.threshold}% annualized`);
|
|
30
|
+
console.log(` Interval: ${config.intervalMin} minutes`);
|
|
31
|
+
console.log(` Exchanges: ${exchanges.join(", ")}`);
|
|
32
|
+
console.log("\n Monitoring... (Ctrl+C to stop)\n");
|
|
33
|
+
console.log(" " + "─".repeat(60));
|
|
34
|
+
// Check immediately
|
|
35
|
+
await checkAndAlert(config.assets, exchanges, config.threshold, isTestnet);
|
|
36
|
+
// Then check on interval
|
|
37
|
+
const interval = setInterval(async () => {
|
|
38
|
+
await checkAndAlert(config.assets, exchanges, config.threshold, isTestnet);
|
|
39
|
+
}, config.intervalMin * 60 * 1000);
|
|
40
|
+
// Handle Ctrl+C
|
|
41
|
+
process.once("SIGINT", () => {
|
|
42
|
+
clearInterval(interval);
|
|
43
|
+
console.log("\n\n Alert monitor stopped.\n");
|
|
44
|
+
process.exit(0);
|
|
45
|
+
});
|
|
46
|
+
// Keep running
|
|
47
|
+
await new Promise(() => { });
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async function checkAndAlert(assets, exchanges, threshold, isTestnet) {
|
|
51
|
+
try {
|
|
52
|
+
const records = await pollFundingRates(assets, exchanges, undefined, isTestnet);
|
|
53
|
+
const now = new Date().toLocaleTimeString();
|
|
54
|
+
// Group by asset and find opportunities
|
|
55
|
+
const byAsset = new Map();
|
|
56
|
+
for (const r of records) {
|
|
57
|
+
const asset = r.market.replace("-PERP", "");
|
|
58
|
+
const existing = byAsset.get(asset) || [];
|
|
59
|
+
existing.push(r);
|
|
60
|
+
byAsset.set(asset, existing);
|
|
61
|
+
}
|
|
62
|
+
let foundAny = false;
|
|
63
|
+
for (const [asset, assetRecords] of byAsset) {
|
|
64
|
+
if (assetRecords.length < 2)
|
|
65
|
+
continue;
|
|
66
|
+
const sorted = [...assetRecords].sort((a, b) => b.rate - a.rate);
|
|
67
|
+
const high = sorted[0];
|
|
68
|
+
const low = sorted[sorted.length - 1];
|
|
69
|
+
const spread = high.rate - low.rate;
|
|
70
|
+
const annualized = spread * 24 * 365 * 100;
|
|
71
|
+
if (annualized >= threshold) {
|
|
72
|
+
foundAny = true;
|
|
73
|
+
const dailyOn10k = spread * 24 * 10000;
|
|
74
|
+
console.log(`\n \x1b[32m🔔 ${now} - ${asset} OPPORTUNITY\x1b[0m`);
|
|
75
|
+
console.log(` Short ${high.exchange} (${(high.rate * 100).toFixed(4)}%)`);
|
|
76
|
+
console.log(` Long ${low.exchange} (${(low.rate * 100).toFixed(4)}%)`);
|
|
77
|
+
console.log(` Spread: \x1b[32m${annualized.toFixed(1)}%\x1b[0m annualized (~$${dailyOn10k.toFixed(2)}/day on $10k)`);
|
|
78
|
+
// Could add external notifications here (Discord, Telegram, etc.)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!foundAny) {
|
|
82
|
+
process.stdout.write(`\r ${now} - No opportunities above ${threshold}%`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
console.error(`\n \x1b[31mError:\x1b[0m ${err instanceof Error ? err.message : err}`);
|
|
87
|
+
}
|
|
88
|
+
}
|