@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,23 @@
|
|
|
1
|
+
import type { IncomingMessage } from "node:http";
|
|
2
|
+
export interface X402Requirement {
|
|
3
|
+
protocol: "x402";
|
|
4
|
+
version: string;
|
|
5
|
+
payTo: string;
|
|
6
|
+
network: string;
|
|
7
|
+
asset: string;
|
|
8
|
+
amount: string;
|
|
9
|
+
timeoutSeconds: number;
|
|
10
|
+
}
|
|
11
|
+
export interface X402Receipt {
|
|
12
|
+
paymentId: string;
|
|
13
|
+
proofHash: string;
|
|
14
|
+
rawProof: string;
|
|
15
|
+
}
|
|
16
|
+
export interface X402ValidationResult {
|
|
17
|
+
ok: boolean;
|
|
18
|
+
receipt?: X402Receipt;
|
|
19
|
+
requirement?: X402Requirement;
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function getX402Requirement(): X402Requirement;
|
|
23
|
+
export declare function validateX402Payment(req: IncomingMessage): X402ValidationResult;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
function header(message, name) {
|
|
3
|
+
const value = message.headers[name];
|
|
4
|
+
if (Array.isArray(value)) {
|
|
5
|
+
return value[0];
|
|
6
|
+
}
|
|
7
|
+
if (typeof value === "string") {
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
export function getX402Requirement() {
|
|
13
|
+
return {
|
|
14
|
+
protocol: "x402",
|
|
15
|
+
version: "1",
|
|
16
|
+
payTo: (() => {
|
|
17
|
+
const addr = process.env.X402_PAY_TO;
|
|
18
|
+
if (!addr) {
|
|
19
|
+
console.warn("Warning: X402_PAY_TO is not set — payments will be sent to the zero address (burned).");
|
|
20
|
+
return "0x0000000000000000000000000000000000000000";
|
|
21
|
+
}
|
|
22
|
+
return addr;
|
|
23
|
+
})(),
|
|
24
|
+
network: process.env.X402_NETWORK ?? "base",
|
|
25
|
+
asset: process.env.X402_ASSET ?? "USDC",
|
|
26
|
+
amount: process.env.X402_AMOUNT ?? "0.05",
|
|
27
|
+
timeoutSeconds: Number(process.env.X402_TIMEOUT_SECONDS ?? 300),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function validateX402Payment(req) {
|
|
31
|
+
const rawProof = header(req, "x402-payment") ??
|
|
32
|
+
header(req, "x-payment") ??
|
|
33
|
+
header(req, "payment");
|
|
34
|
+
if (!rawProof) {
|
|
35
|
+
return {
|
|
36
|
+
ok: false,
|
|
37
|
+
requirement: getX402Requirement(),
|
|
38
|
+
error: "missing_payment_proof",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const trimmed = rawProof.trim();
|
|
42
|
+
if (trimmed.length < 16) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
requirement: getX402Requirement(),
|
|
46
|
+
error: "invalid_payment_proof",
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const proofHash = createHash("sha256").update(trimmed).digest("hex");
|
|
50
|
+
const externalPaymentId = header(req, "x402-payment-id")?.trim();
|
|
51
|
+
const paymentId = externalPaymentId && externalPaymentId.length > 0
|
|
52
|
+
? externalPaymentId
|
|
53
|
+
: `x402:${proofHash.slice(0, 24)}`;
|
|
54
|
+
return {
|
|
55
|
+
ok: true,
|
|
56
|
+
receipt: {
|
|
57
|
+
paymentId,
|
|
58
|
+
proofHash,
|
|
59
|
+
rawProof: trimmed,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Address, Hex } from "viem";
|
|
2
|
+
/**
|
|
3
|
+
* Result of validating an API key
|
|
4
|
+
*/
|
|
5
|
+
export type ValidateApiKeyResult = {
|
|
6
|
+
valid: true;
|
|
7
|
+
masterAddress: Address;
|
|
8
|
+
apiWalletAddress: Address;
|
|
9
|
+
} | {
|
|
10
|
+
valid: false;
|
|
11
|
+
error: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Validate an API private key by checking if it's registered as an agent wallet
|
|
15
|
+
* Returns the master address if valid, or an error message if not
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateApiKey(apiPrivateKey: Hex, isTestnet?: boolean): Promise<ValidateApiKeyResult>;
|
|
18
|
+
/**
|
|
19
|
+
* API wallet credentials
|
|
20
|
+
*/
|
|
21
|
+
export interface ApiWalletCredentials {
|
|
22
|
+
privateKey: Hex;
|
|
23
|
+
publicKey: Address;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate a new API wallet (random private key)
|
|
27
|
+
*/
|
|
28
|
+
export declare function generateApiWallet(): ApiWalletCredentials;
|
|
29
|
+
/**
|
|
30
|
+
* User role response types from Hyperliquid API
|
|
31
|
+
*/
|
|
32
|
+
export type UserRoleResponse = {
|
|
33
|
+
role: "missing" | "user" | "vault";
|
|
34
|
+
} | {
|
|
35
|
+
role: "agent";
|
|
36
|
+
data: {
|
|
37
|
+
user: Address;
|
|
38
|
+
};
|
|
39
|
+
} | {
|
|
40
|
+
role: "subAccount";
|
|
41
|
+
data: {
|
|
42
|
+
master: Address;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Check if an API wallet is approved as an agent for a user
|
|
47
|
+
*/
|
|
48
|
+
export declare function checkApiWalletApproval(apiWalletAddress: Address, userAddress: Address, isTestnet?: boolean): Promise<{
|
|
49
|
+
approved: boolean;
|
|
50
|
+
masterAddress?: Address;
|
|
51
|
+
}>;
|
|
52
|
+
/**
|
|
53
|
+
* Get the Hyperliquid API approval URL
|
|
54
|
+
*/
|
|
55
|
+
export declare function getApprovalUrl(isTestnet?: boolean): string;
|
|
56
|
+
/**
|
|
57
|
+
* Poll for API wallet approval with timeout
|
|
58
|
+
* Returns true if approved, false if timed out
|
|
59
|
+
*/
|
|
60
|
+
export declare function waitForApproval(apiWalletAddress: Address, userAddress: Address, isTestnet?: boolean, pollIntervalMs?: number, maxAttempts?: number): Promise<boolean>;
|
|
61
|
+
/**
|
|
62
|
+
* Get all extra agents (API wallets) for a user address
|
|
63
|
+
*/
|
|
64
|
+
export interface ExtraAgent {
|
|
65
|
+
address: Address;
|
|
66
|
+
name: string;
|
|
67
|
+
validUntil: number;
|
|
68
|
+
}
|
|
69
|
+
export declare function getExtraAgents(userAddress: Address, isTestnet?: boolean): Promise<ExtraAgent[]>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
|
|
2
|
+
import { HttpTransport, InfoClient } from "@nktkas/hyperliquid";
|
|
3
|
+
/**
|
|
4
|
+
* Validate an API private key by checking if it's registered as an agent wallet
|
|
5
|
+
* Returns the master address if valid, or an error message if not
|
|
6
|
+
*/
|
|
7
|
+
export async function validateApiKey(apiPrivateKey, isTestnet = false) {
|
|
8
|
+
const account = privateKeyToAccount(apiPrivateKey);
|
|
9
|
+
const apiWalletAddress = account.address;
|
|
10
|
+
const transport = new HttpTransport({ isTestnet });
|
|
11
|
+
const client = new InfoClient({ transport });
|
|
12
|
+
try {
|
|
13
|
+
const response = (await client.userRole({ user: apiWalletAddress }));
|
|
14
|
+
if (response.role === "agent") {
|
|
15
|
+
return {
|
|
16
|
+
valid: true,
|
|
17
|
+
masterAddress: response.data.user,
|
|
18
|
+
apiWalletAddress,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (response.role === "missing") {
|
|
22
|
+
return { valid: false, error: "This key is not registered as an API wallet on Hyperliquid" };
|
|
23
|
+
}
|
|
24
|
+
return { valid: false, error: `Invalid role: ${response.role}. Expected an agent wallet.` };
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
return { valid: false, error: `Failed to validate API key: ${err instanceof Error ? err.message : String(err)}` };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generate a new API wallet (random private key)
|
|
32
|
+
*/
|
|
33
|
+
export function generateApiWallet() {
|
|
34
|
+
const privateKey = generatePrivateKey();
|
|
35
|
+
const account = privateKeyToAccount(privateKey);
|
|
36
|
+
return {
|
|
37
|
+
privateKey,
|
|
38
|
+
publicKey: account.address,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if an API wallet is approved as an agent for a user
|
|
43
|
+
*/
|
|
44
|
+
export async function checkApiWalletApproval(apiWalletAddress, userAddress, isTestnet = false) {
|
|
45
|
+
const transport = new HttpTransport({ isTestnet });
|
|
46
|
+
const client = new InfoClient({ transport });
|
|
47
|
+
try {
|
|
48
|
+
const response = await client.userRole({ user: apiWalletAddress });
|
|
49
|
+
if (response.role === "agent") {
|
|
50
|
+
// Check if the agent is approved for the specified user
|
|
51
|
+
const isApprovedForUser = response.data.user.toLowerCase() === userAddress.toLowerCase();
|
|
52
|
+
return {
|
|
53
|
+
approved: isApprovedForUser,
|
|
54
|
+
masterAddress: response.data.user,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return { approved: false };
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return { approved: false };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get the Hyperliquid API approval URL
|
|
65
|
+
*/
|
|
66
|
+
export function getApprovalUrl(isTestnet = false) {
|
|
67
|
+
return isTestnet
|
|
68
|
+
? "https://app.hyperliquid-testnet.xyz/API"
|
|
69
|
+
: "https://app.hyperliquid.xyz/API";
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Poll for API wallet approval with timeout
|
|
73
|
+
* Returns true if approved, false if timed out
|
|
74
|
+
*/
|
|
75
|
+
export async function waitForApproval(apiWalletAddress, userAddress, isTestnet = false, pollIntervalMs = 3000, maxAttempts = 100 // About 5 minutes with 3s interval
|
|
76
|
+
) {
|
|
77
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
78
|
+
const result = await checkApiWalletApproval(apiWalletAddress, userAddress, isTestnet);
|
|
79
|
+
if (result.approved) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
// Wait before next poll
|
|
83
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
84
|
+
}
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
export async function getExtraAgents(userAddress, isTestnet = false) {
|
|
88
|
+
const transport = new HttpTransport({ isTestnet });
|
|
89
|
+
const client = new InfoClient({ transport });
|
|
90
|
+
try {
|
|
91
|
+
const response = await client.extraAgents({ user: userAddress });
|
|
92
|
+
return response.map((agent) => ({
|
|
93
|
+
address: agent.address,
|
|
94
|
+
name: agent.name,
|
|
95
|
+
validUntil: agent.validUntil,
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
export interface BalanceData {
|
|
3
|
+
spotBalances: Array<{
|
|
4
|
+
token: string;
|
|
5
|
+
total: string;
|
|
6
|
+
hold: string;
|
|
7
|
+
available: string;
|
|
8
|
+
}>;
|
|
9
|
+
perpBalance: string;
|
|
10
|
+
}
|
|
11
|
+
export interface BalanceWatcher {
|
|
12
|
+
start(): Promise<void>;
|
|
13
|
+
stop(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export interface BalanceWatcherConfig {
|
|
16
|
+
user: Address;
|
|
17
|
+
isTestnet: boolean;
|
|
18
|
+
onUpdate: (data: BalanceData) => void;
|
|
19
|
+
onError: (error: Error) => void;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Creates a balance watcher that subscribes to clearinghouse state updates
|
|
23
|
+
* and polls spot balances on each update
|
|
24
|
+
*/
|
|
25
|
+
export declare function createBalanceWatcher(config: BalanceWatcherConfig): BalanceWatcher;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { WebSocketTransport, SubscriptionClient, HttpTransport, InfoClient } from "@nktkas/hyperliquid";
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a balance watcher that subscribes to clearinghouse state updates
|
|
5
|
+
* and polls spot balances on each update
|
|
6
|
+
*/
|
|
7
|
+
export function createBalanceWatcher(config) {
|
|
8
|
+
let wsTransport = null;
|
|
9
|
+
let subscriptionClient = null;
|
|
10
|
+
let perpSubscription = null;
|
|
11
|
+
let httpClient = null;
|
|
12
|
+
return {
|
|
13
|
+
async start() {
|
|
14
|
+
// Create HTTP client for spot balance polling
|
|
15
|
+
const httpTransport = new HttpTransport({ isTestnet: config.isTestnet });
|
|
16
|
+
httpClient = new InfoClient({ transport: httpTransport });
|
|
17
|
+
// Fetch initial spot state
|
|
18
|
+
const spotState = await httpClient.spotClearinghouseState({ user: config.user });
|
|
19
|
+
let currentSpotBalances = spotState.balances
|
|
20
|
+
.filter((b) => parseFloat(b.total) !== 0)
|
|
21
|
+
.map((b) => ({
|
|
22
|
+
token: b.coin,
|
|
23
|
+
total: b.total,
|
|
24
|
+
hold: b.hold,
|
|
25
|
+
available: (parseFloat(b.total) - parseFloat(b.hold)).toString(),
|
|
26
|
+
}));
|
|
27
|
+
wsTransport = new WebSocketTransport({
|
|
28
|
+
isTestnet: config.isTestnet,
|
|
29
|
+
reconnect: { WebSocket: WebSocket },
|
|
30
|
+
});
|
|
31
|
+
subscriptionClient = new SubscriptionClient({ transport: wsTransport });
|
|
32
|
+
await wsTransport.ready();
|
|
33
|
+
// Subscribe to perp clearinghouse state
|
|
34
|
+
perpSubscription = await subscriptionClient.allDexsClearinghouseState({ user: config.user }, async (state) => {
|
|
35
|
+
const clearinghouseState = state.clearinghouseStates[0]?.[1];
|
|
36
|
+
const perpBalance = clearinghouseState?.marginSummary.accountValue || "0";
|
|
37
|
+
// Refresh spot balances on each perp update
|
|
38
|
+
if (httpClient) {
|
|
39
|
+
try {
|
|
40
|
+
const freshSpotState = await httpClient.spotClearinghouseState({ user: config.user });
|
|
41
|
+
currentSpotBalances = freshSpotState.balances
|
|
42
|
+
.filter((b) => parseFloat(b.total) !== 0)
|
|
43
|
+
.map((b) => ({
|
|
44
|
+
token: b.coin,
|
|
45
|
+
total: b.total,
|
|
46
|
+
hold: b.hold,
|
|
47
|
+
available: (parseFloat(b.total) - parseFloat(b.hold)).toString(),
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Keep previous spot balances on error
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
config.onUpdate({
|
|
55
|
+
spotBalances: currentSpotBalances,
|
|
56
|
+
perpBalance,
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
async stop() {
|
|
61
|
+
if (perpSubscription) {
|
|
62
|
+
try {
|
|
63
|
+
await perpSubscription.unsubscribe();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Ignore errors during unsubscribe
|
|
67
|
+
}
|
|
68
|
+
perpSubscription = null;
|
|
69
|
+
}
|
|
70
|
+
if (wsTransport) {
|
|
71
|
+
try {
|
|
72
|
+
await wsTransport.close();
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Ignore errors during close
|
|
76
|
+
}
|
|
77
|
+
wsTransport = null;
|
|
78
|
+
}
|
|
79
|
+
subscriptionClient = null;
|
|
80
|
+
httpClient = null;
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface BookLevel {
|
|
2
|
+
px: string;
|
|
3
|
+
sz: string;
|
|
4
|
+
n: number;
|
|
5
|
+
}
|
|
6
|
+
export interface BookData {
|
|
7
|
+
coin: string;
|
|
8
|
+
bids: BookLevel[];
|
|
9
|
+
asks: BookLevel[];
|
|
10
|
+
time: number;
|
|
11
|
+
}
|
|
12
|
+
export interface BookWatcher {
|
|
13
|
+
start(): Promise<void>;
|
|
14
|
+
stop(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export interface BookWatcherConfig {
|
|
17
|
+
coin: string;
|
|
18
|
+
isTestnet: boolean;
|
|
19
|
+
onUpdate: (data: BookData) => void;
|
|
20
|
+
onError: (error: Error) => void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Creates a book watcher that subscribes to L2 order book updates via WebSocket
|
|
24
|
+
*/
|
|
25
|
+
export declare function createBookWatcher(config: BookWatcherConfig): BookWatcher;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { WebSocketTransport, SubscriptionClient } from "@nktkas/hyperliquid";
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a book watcher that subscribes to L2 order book updates via WebSocket
|
|
5
|
+
*/
|
|
6
|
+
export function createBookWatcher(config) {
|
|
7
|
+
let wsTransport = null;
|
|
8
|
+
let subscription = null;
|
|
9
|
+
return {
|
|
10
|
+
async start() {
|
|
11
|
+
wsTransport = new WebSocketTransport({
|
|
12
|
+
isTestnet: config.isTestnet,
|
|
13
|
+
reconnect: { WebSocket: WebSocket },
|
|
14
|
+
});
|
|
15
|
+
const subscriptionClient = new SubscriptionClient({ transport: wsTransport });
|
|
16
|
+
await wsTransport.ready();
|
|
17
|
+
subscription = await subscriptionClient.l2Book({ coin: config.coin }, (event) => {
|
|
18
|
+
const levels = event.levels;
|
|
19
|
+
config.onUpdate({
|
|
20
|
+
coin: config.coin,
|
|
21
|
+
bids: levels[0] || [],
|
|
22
|
+
asks: levels[1] || [],
|
|
23
|
+
time: event.time,
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
async stop() {
|
|
28
|
+
if (subscription) {
|
|
29
|
+
try {
|
|
30
|
+
await subscription.unsubscribe();
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Ignore errors during unsubscribe
|
|
34
|
+
}
|
|
35
|
+
subscription = null;
|
|
36
|
+
}
|
|
37
|
+
if (wsTransport) {
|
|
38
|
+
try {
|
|
39
|
+
await wsTransport.close();
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Ignore errors during close
|
|
43
|
+
}
|
|
44
|
+
wsTransport = null;
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Address, Hex } from "viem";
|
|
2
|
+
import type { ExchangeCredentials } from "../adapters/interface.js";
|
|
3
|
+
type ExchangeNetwork = "testnet" | "mainnet";
|
|
4
|
+
interface HyperliquidSettings {
|
|
5
|
+
network: ExchangeNetwork;
|
|
6
|
+
privateKey?: Hex;
|
|
7
|
+
walletAddress?: Address;
|
|
8
|
+
}
|
|
9
|
+
export interface DecibelCredentials {
|
|
10
|
+
apiWalletPrivateKey?: Hex;
|
|
11
|
+
apiWalletAddress?: string;
|
|
12
|
+
apiBearerToken?: string;
|
|
13
|
+
subaccountAddress?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface DecibelSettings {
|
|
16
|
+
network: "testnet" | "mainnet";
|
|
17
|
+
fullnodeUrl: string;
|
|
18
|
+
restUrl: string;
|
|
19
|
+
wsUrl: string;
|
|
20
|
+
packageAddress: string;
|
|
21
|
+
credentials?: DecibelCredentials;
|
|
22
|
+
}
|
|
23
|
+
interface AevoSettings {
|
|
24
|
+
network: ExchangeNetwork;
|
|
25
|
+
restUrl: string;
|
|
26
|
+
apiKey?: string;
|
|
27
|
+
apiSecret?: string;
|
|
28
|
+
signingKey?: Hex;
|
|
29
|
+
}
|
|
30
|
+
interface OrderlySettings {
|
|
31
|
+
network: ExchangeNetwork;
|
|
32
|
+
restUrl: string;
|
|
33
|
+
accountId?: string;
|
|
34
|
+
key?: string;
|
|
35
|
+
secret?: string;
|
|
36
|
+
tradingKey?: string;
|
|
37
|
+
tradingSecret?: string;
|
|
38
|
+
}
|
|
39
|
+
interface ParadexSettings {
|
|
40
|
+
network: ExchangeNetwork;
|
|
41
|
+
restUrl: string;
|
|
42
|
+
apiBearerToken?: string;
|
|
43
|
+
account?: string;
|
|
44
|
+
ethereumAccount?: string;
|
|
45
|
+
privateKey?: string;
|
|
46
|
+
chainId?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface RiskPolicyConfig {
|
|
49
|
+
maxPositionSizeUsd: number;
|
|
50
|
+
maxTotalExposureUsd: number;
|
|
51
|
+
maxLeverage: number;
|
|
52
|
+
minSignalConfidence: number;
|
|
53
|
+
maxDrawdownPct: number;
|
|
54
|
+
defaultLeverage: number;
|
|
55
|
+
}
|
|
56
|
+
export interface ExecutionSafetyConfig {
|
|
57
|
+
stopLossPct: number;
|
|
58
|
+
takeProfitPct: number;
|
|
59
|
+
spreadOffset: number;
|
|
60
|
+
}
|
|
61
|
+
export interface Config {
|
|
62
|
+
privateKey?: Hex;
|
|
63
|
+
walletAddress?: Address;
|
|
64
|
+
testnet: boolean;
|
|
65
|
+
account?: {
|
|
66
|
+
alias: string;
|
|
67
|
+
type: "readonly" | "api_wallet";
|
|
68
|
+
};
|
|
69
|
+
risk: RiskPolicyConfig;
|
|
70
|
+
executionSafety: ExecutionSafetyConfig;
|
|
71
|
+
operator: {
|
|
72
|
+
heartbeatIntervalMs: number;
|
|
73
|
+
};
|
|
74
|
+
exchanges: {
|
|
75
|
+
hyperliquid: HyperliquidSettings;
|
|
76
|
+
decibel: DecibelSettings;
|
|
77
|
+
aevo: AevoSettings;
|
|
78
|
+
orderly: OrderlySettings;
|
|
79
|
+
paradex: ParadexSettings;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export declare function loadConfig(testnet: boolean, exchangeId?: string): Config;
|
|
83
|
+
interface CredentialRequirement {
|
|
84
|
+
requireReadAccess?: boolean;
|
|
85
|
+
requireTrading?: boolean;
|
|
86
|
+
}
|
|
87
|
+
export declare function getExchangeCredentials(config: Config, exchangeId: string, requirement?: CredentialRequirement): ExchangeCredentials;
|
|
88
|
+
export {};
|