@jinn-network/client 0.1.0 → 0.1.1-canary.4a6ed8b2
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/README.md +98 -11
- package/deployments/deployment-jinn-testnet-faucet-baseSepolia-fast.json +15 -0
- package/dist/adapters/claim-registry/abi.d.ts +127 -0
- package/dist/adapters/claim-registry/abi.js +93 -0
- package/dist/adapters/claim-registry/abi.js.map +1 -0
- package/dist/adapters/claim-registry/client.d.ts +89 -0
- package/dist/adapters/claim-registry/client.js +205 -0
- package/dist/adapters/claim-registry/client.js.map +1 -0
- package/dist/adapters/mech/adapter.d.ts +2 -0
- package/dist/adapters/mech/adapter.js +110 -41
- package/dist/adapters/mech/adapter.js.map +1 -1
- package/dist/adapters/mech/contracts.d.ts +2 -0
- package/dist/adapters/mech/contracts.js +32 -7
- package/dist/adapters/mech/contracts.js.map +1 -1
- package/dist/adapters/mech/ipfs.d.ts +8 -0
- package/dist/adapters/mech/ipfs.js +12 -0
- package/dist/adapters/mech/ipfs.js.map +1 -1
- package/dist/adapters/mech/types.d.ts +20 -46
- package/dist/adapters/mech/types.js +16 -35
- package/dist/adapters/mech/types.js.map +1 -1
- package/dist/api/gather-status.js +11 -0
- package/dist/api/gather-status.js.map +1 -1
- package/dist/api/portfolio-v0-build.d.ts +81 -0
- package/dist/api/portfolio-v0-build.js +141 -0
- package/dist/api/portfolio-v0-build.js.map +1 -0
- package/dist/api/portfolio-v0-doctor.d.ts +37 -0
- package/dist/api/portfolio-v0-doctor.js +123 -0
- package/dist/api/portfolio-v0-doctor.js.map +1 -0
- package/dist/api/server.js +12 -0
- package/dist/api/server.js.map +1 -1
- package/dist/api/status-build.d.ts +6 -0
- package/dist/api/status-build.js +1 -0
- package/dist/api/status-build.js.map +1 -1
- package/dist/api/status-rollup-build.d.ts +4 -0
- package/dist/api/status-rollup-build.js +4 -0
- package/dist/api/status-rollup-build.js.map +1 -1
- package/dist/bin/jinn-mcp.d.ts +14 -0
- package/dist/bin/jinn-mcp.js +19 -0
- package/dist/bin/jinn-mcp.js.map +1 -0
- package/dist/build-meta.json +1 -1
- package/dist/cli/commands/auth.d.ts +3 -0
- package/dist/cli/commands/auth.js +236 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/bootstrap.js +1 -0
- package/dist/cli/commands/bootstrap.js.map +1 -1
- package/dist/cli/commands/doctor.js +148 -15
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/fund-requirements.js +69 -1
- package/dist/cli/commands/fund-requirements.js.map +1 -1
- package/dist/cli/commands/history.js +1 -0
- package/dist/cli/commands/history.js.map +1 -1
- package/dist/cli/commands/init.js +31 -7
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/keys-backup.js +142 -10
- package/dist/cli/commands/keys-backup.js.map +1 -1
- package/dist/cli/commands/logs.js +28 -13
- package/dist/cli/commands/logs.js.map +1 -1
- package/dist/cli/commands/plugin-install.d.ts +3 -0
- package/dist/cli/commands/plugin-install.js +799 -0
- package/dist/cli/commands/plugin-install.js.map +1 -0
- package/dist/cli/commands/quickstart.d.ts +3 -0
- package/dist/cli/commands/quickstart.js +236 -0
- package/dist/cli/commands/quickstart.js.map +1 -0
- package/dist/cli/commands/run.js +6 -0
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/stop.js +1 -0
- package/dist/cli/commands/stop.js.map +1 -1
- package/dist/cli/commands/submit-intent.js +79 -5
- package/dist/cli/commands/submit-intent.js.map +1 -1
- package/dist/cli/commands/update.d.ts +3 -0
- package/dist/cli/commands/update.js +154 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/version.js +15 -1
- package/dist/cli/commands/version.js.map +1 -1
- package/dist/cli/deployment-digest.js +20 -4
- package/dist/cli/deployment-digest.js.map +1 -1
- package/dist/cli/index.js +8 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/password.d.ts +15 -0
- package/dist/cli/password.js +29 -1
- package/dist/cli/password.js.map +1 -1
- package/dist/config.d.ts +110 -7
- package/dist/config.js +38 -5
- package/dist/config.js.map +1 -1
- package/dist/daemon/balance-topup-loop.d.ts +40 -0
- package/dist/daemon/balance-topup-loop.js +96 -0
- package/dist/daemon/balance-topup-loop.js.map +1 -0
- package/dist/daemon/daemon.d.ts +37 -0
- package/dist/daemon/daemon.js +98 -1
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/dashboard/index.html +500 -0
- package/dist/earning/bootstrap.d.ts +3 -1
- package/dist/earning/bootstrap.js +138 -17
- package/dist/earning/bootstrap.js.map +1 -1
- package/dist/earning/contracts.d.ts +24 -0
- package/dist/earning/contracts.js +20 -1
- package/dist/earning/contracts.js.map +1 -1
- package/dist/earning/faucet.d.ts +15 -0
- package/dist/earning/faucet.js +64 -0
- package/dist/earning/faucet.js.map +1 -0
- package/dist/earning/store.d.ts +5 -0
- package/dist/earning/store.js +7 -3
- package/dist/earning/store.js.map +1 -1
- package/dist/errors/unauthorized-account.d.ts +10 -0
- package/dist/errors/unauthorized-account.js +14 -0
- package/dist/errors/unauthorized-account.js.map +1 -0
- package/dist/main.js +128 -1
- package/dist/main.js.map +1 -1
- package/dist/mcp/operator-server.d.ts +34 -0
- package/dist/mcp/operator-server.js +219 -0
- package/dist/mcp/operator-server.js.map +1 -0
- package/dist/operator-errors.js +11 -0
- package/dist/operator-errors.js.map +1 -1
- package/dist/preflight/claude-auth.d.ts +68 -0
- package/dist/preflight/claude-auth.js +171 -0
- package/dist/preflight/claude-auth.js.map +1 -0
- package/dist/restorer/engine/canonical-json.d.ts +18 -0
- package/dist/restorer/engine/canonical-json.js +59 -0
- package/dist/restorer/engine/canonical-json.js.map +1 -0
- package/dist/restorer/engine/claim.d.ts +69 -0
- package/dist/restorer/engine/claim.js +104 -0
- package/dist/restorer/engine/claim.js.map +1 -0
- package/dist/restorer/engine/delivery.d.ts +52 -0
- package/dist/restorer/engine/delivery.js +63 -0
- package/dist/restorer/engine/delivery.js.map +1 -0
- package/dist/restorer/engine/engine.d.ts +203 -0
- package/dist/restorer/engine/engine.js +658 -0
- package/dist/restorer/engine/engine.js.map +1 -0
- package/dist/restorer/engine/manifest-assembly.d.ts +67 -0
- package/dist/restorer/engine/manifest-assembly.js +79 -0
- package/dist/restorer/engine/manifest-assembly.js.map +1 -0
- package/dist/restorer/engine/packaging.d.ts +87 -0
- package/dist/restorer/engine/packaging.js +350 -0
- package/dist/restorer/engine/packaging.js.map +1 -0
- package/dist/restorer/engine/persistence.d.ts +170 -0
- package/dist/restorer/engine/persistence.js +381 -0
- package/dist/restorer/engine/persistence.js.map +1 -0
- package/dist/restorer/engine/recovery.d.ts +22 -0
- package/dist/restorer/engine/recovery.js +24 -0
- package/dist/restorer/engine/recovery.js.map +1 -0
- package/dist/restorer/engine/registry.d.ts +62 -0
- package/dist/restorer/engine/registry.js +73 -0
- package/dist/restorer/engine/registry.js.map +1 -0
- package/dist/restorer/engine/signing.d.ts +30 -0
- package/dist/restorer/engine/signing.js +39 -0
- package/dist/restorer/engine/signing.js.map +1 -0
- package/dist/restorer/engine/state.d.ts +42 -0
- package/dist/restorer/engine/state.js +87 -0
- package/dist/restorer/engine/state.js.map +1 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/api-wallet.d.ts +64 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/api-wallet.js +96 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/api-wallet.js.map +1 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/index.d.ts +88 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/index.js +560 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/index.js.map +1 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/mcp-tools.d.ts +137 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/mcp-tools.js +865 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/mcp-tools.js.map +1 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/safety-rails.d.ts +74 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/safety-rails.js +74 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/safety-rails.js.map +1 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/session-orchestrator.d.ts +97 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/session-orchestrator.js +226 -0
- package/dist/restorer/impls/claude-mcp-hyperliquid/session-orchestrator.js.map +1 -0
- package/dist/restorer/impls/legacy-claude/index.d.ts +42 -0
- package/dist/restorer/impls/legacy-claude/index.js +60 -0
- package/dist/restorer/impls/legacy-claude/index.js.map +1 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/canonical-metrics.d.ts +68 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/canonical-metrics.js +117 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/canonical-metrics.js.map +1 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/availability.d.ts +49 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/availability.js +91 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/availability.js.map +1 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/consistency.d.ts +78 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/consistency.js +274 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/consistency.js.map +1 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/eligibility.d.ts +23 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/eligibility.js +49 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/eligibility.js.map +1 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/integrity.d.ts +25 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/integrity.js +44 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/integrity.js.map +1 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/spec.d.ts +17 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/spec.js +43 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/checks/spec.js.map +1 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/index.d.ts +43 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/index.js +431 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/index.js.map +1 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/score.d.ts +21 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/score.js +32 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/score.js.map +1 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/types.d.ts +32 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/types.js +8 -0
- package/dist/restorer/impls/portfolio-v0-evaluator/types.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-baseline/index.d.ts +26 -0
- package/dist/restorer/impls/prediction-v0-baseline/index.js +82 -0
- package/dist/restorer/impls/prediction-v0-baseline/index.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-baseline/strategy.d.ts +8 -0
- package/dist/restorer/impls/prediction-v0-baseline/strategy.js +41 -0
- package/dist/restorer/impls/prediction-v0-baseline/strategy.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-baseline/types.d.ts +7 -0
- package/dist/restorer/impls/prediction-v0-baseline/types.js +2 -0
- package/dist/restorer/impls/prediction-v0-baseline/types.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-evaluator/canonical-metrics.d.ts +20 -0
- package/dist/restorer/impls/prediction-v0-evaluator/canonical-metrics.js +66 -0
- package/dist/restorer/impls/prediction-v0-evaluator/canonical-metrics.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/availability.d.ts +9 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/availability.js +23 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/availability.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/eligibility.d.ts +3 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/eligibility.js +13 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/eligibility.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/integrity.d.ts +7 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/integrity.js +74 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/integrity.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/spec.d.ts +5 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/spec.js +20 -0
- package/dist/restorer/impls/prediction-v0-evaluator/checks/spec.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-evaluator/index.d.ts +33 -0
- package/dist/restorer/impls/prediction-v0-evaluator/index.js +179 -0
- package/dist/restorer/impls/prediction-v0-evaluator/index.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-evaluator/score.d.ts +8 -0
- package/dist/restorer/impls/prediction-v0-evaluator/score.js +15 -0
- package/dist/restorer/impls/prediction-v0-evaluator/score.js.map +1 -0
- package/dist/restorer/impls/prediction-v0-evaluator/types.d.ts +7 -0
- package/dist/restorer/impls/prediction-v0-evaluator/types.js +2 -0
- package/dist/restorer/impls/prediction-v0-evaluator/types.js.map +1 -0
- package/dist/restorer/types.d.ts +62 -0
- package/dist/restorer/types.js +7 -0
- package/dist/restorer/types.js.map +1 -0
- package/dist/runner/claude.js +15 -0
- package/dist/runner/claude.js.map +1 -1
- package/dist/store/store.d.ts +3 -1
- package/dist/store/store.js +8 -0
- package/dist/store/store.js.map +1 -1
- package/dist/tx-retry.js +11 -1
- package/dist/tx-retry.js.map +1 -1
- package/dist/types/desired-state.d.ts +53 -0
- package/dist/types/desired-state.js +20 -0
- package/dist/types/desired-state.js.map +1 -1
- package/dist/types/index.d.ts +3 -1
- package/dist/types/index.js +3 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/portfolio.d.ts +1000 -0
- package/dist/types/portfolio.js +168 -0
- package/dist/types/portfolio.js.map +1 -0
- package/dist/types/prediction.d.ts +751 -0
- package/dist/types/prediction.js +128 -0
- package/dist/types/prediction.js.map +1 -0
- package/dist/venues/chainlink/client.d.ts +99 -0
- package/dist/venues/chainlink/client.js +130 -0
- package/dist/venues/chainlink/client.js.map +1 -0
- package/dist/venues/chainlink/feeds.d.ts +8 -0
- package/dist/venues/chainlink/feeds.js +9 -0
- package/dist/venues/chainlink/feeds.js.map +1 -0
- package/dist/venues/hyperliquid/account-value.d.ts +30 -0
- package/dist/venues/hyperliquid/account-value.js +30 -0
- package/dist/venues/hyperliquid/account-value.js.map +1 -0
- package/dist/venues/hyperliquid/client.d.ts +63 -0
- package/dist/venues/hyperliquid/client.js +135 -0
- package/dist/venues/hyperliquid/client.js.map +1 -0
- package/dist/venues/hyperliquid/grid.d.ts +36 -0
- package/dist/venues/hyperliquid/grid.js +61 -0
- package/dist/venues/hyperliquid/grid.js.map +1 -0
- package/dist/venues/hyperliquid/types.d.ts +81 -0
- package/dist/venues/hyperliquid/types.js +8 -0
- package/dist/venues/hyperliquid/types.js.map +1 -0
- package/package.json +18 -3
- package/skills/jinn-operator/SKILL.md +213 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* prediction.v0 — typed intent spec, submission manifest, verdict manifest.
|
|
3
|
+
*
|
|
4
|
+
* §4 of spec/2026-04-20-prediction-v0-pis-phase-1-design.md
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { WindowSchema } from './desired-state.js';
|
|
8
|
+
const HexStringSchema = z.string().regex(/^0x[0-9a-fA-F]*$/, 'must be a 0x-prefixed hex string');
|
|
9
|
+
const SignatureSchema = z.object({
|
|
10
|
+
algo: z.literal('secp256k1'),
|
|
11
|
+
signer: HexStringSchema,
|
|
12
|
+
hash: HexStringSchema,
|
|
13
|
+
sig: HexStringSchema,
|
|
14
|
+
});
|
|
15
|
+
const IntentProvenanceSchema = z.object({
|
|
16
|
+
cid: z.string().min(1),
|
|
17
|
+
onchainCreationTx: HexStringSchema,
|
|
18
|
+
onchainCreationBlock: z.number().int(),
|
|
19
|
+
requestId: HexStringSchema,
|
|
20
|
+
});
|
|
21
|
+
const ParticipantSchema = z.object({
|
|
22
|
+
safeAddress: HexStringSchema,
|
|
23
|
+
agentEoa: HexStringSchema,
|
|
24
|
+
});
|
|
25
|
+
// ── Question kinds ────────────────────────────────────────────────────────────
|
|
26
|
+
const ThresholdQuestionSchema = z.object({
|
|
27
|
+
kind: z.literal('threshold'),
|
|
28
|
+
operator: z.enum(['GT', 'GTE', 'LT', 'LTE']),
|
|
29
|
+
threshold: z.string(),
|
|
30
|
+
resolveTs: z.number().int(),
|
|
31
|
+
});
|
|
32
|
+
const RangeQuestionSchema = z.object({
|
|
33
|
+
kind: z.literal('range'),
|
|
34
|
+
lowerBound: z.string(),
|
|
35
|
+
upperBound: z.string(),
|
|
36
|
+
resolveTs: z.number().int(),
|
|
37
|
+
});
|
|
38
|
+
// ── Spec + eligibility + intent ────────────────────────────────────────────────
|
|
39
|
+
export const PredictionV0SpecSchema = z.object({
|
|
40
|
+
kind: z.literal('prediction.v0'),
|
|
41
|
+
oracle: z.object({
|
|
42
|
+
venue: z.enum(['chainlink-base-sepolia', 'chainlink-base']),
|
|
43
|
+
feed: HexStringSchema,
|
|
44
|
+
feedDescription: z.string(),
|
|
45
|
+
}),
|
|
46
|
+
question: z.discriminatedUnion('kind', [ThresholdQuestionSchema, RangeQuestionSchema]),
|
|
47
|
+
});
|
|
48
|
+
export const PredictionV0EligibilitySchema = z.object({
|
|
49
|
+
maxSubmissionDelayMs: z.number().int().default(60_000),
|
|
50
|
+
});
|
|
51
|
+
export const PredictionV0IntentSchema = z
|
|
52
|
+
.object({
|
|
53
|
+
id: z.string(),
|
|
54
|
+
description: z.string().min(1),
|
|
55
|
+
window: WindowSchema,
|
|
56
|
+
spec: PredictionV0SpecSchema,
|
|
57
|
+
eligibility: PredictionV0EligibilitySchema.default({}),
|
|
58
|
+
})
|
|
59
|
+
.refine(d => d.window.endTs - d.window.startTs === 3_600_000, {
|
|
60
|
+
message: 'window must be exactly 1h (endTs - startTs === 3_600_000 ms)',
|
|
61
|
+
path: ['window'],
|
|
62
|
+
})
|
|
63
|
+
.refine(d => d.spec.question.resolveTs === d.window.endTs + 900_000, {
|
|
64
|
+
message: 'resolveTs must equal window.endTs + 900_000 ms (15min)',
|
|
65
|
+
path: ['spec', 'question', 'resolveTs'],
|
|
66
|
+
});
|
|
67
|
+
// ── Submission manifest ───────────────────────────────────────────────────────
|
|
68
|
+
export const PredictionSubmissionManifestSchema = z.object({
|
|
69
|
+
schemaVersion: z.literal('prediction.v0.submission.v1'),
|
|
70
|
+
generatedAt: z.number().int(),
|
|
71
|
+
intent: IntentProvenanceSchema,
|
|
72
|
+
restorer: ParticipantSchema,
|
|
73
|
+
window: WindowSchema,
|
|
74
|
+
prediction: z.object({
|
|
75
|
+
probability: z.string().regex(/^(0(\.\d+)?|1(\.0+)?)$/, 'must be a decimal in [0,1]'),
|
|
76
|
+
submittedAt: z.number().int(),
|
|
77
|
+
modelId: z.string().min(1),
|
|
78
|
+
}),
|
|
79
|
+
oracleSnapshot: z
|
|
80
|
+
.object({
|
|
81
|
+
feed: HexStringSchema,
|
|
82
|
+
roundId: z.string(),
|
|
83
|
+
answer: z.string(),
|
|
84
|
+
updatedAt: z.number().int(),
|
|
85
|
+
})
|
|
86
|
+
.optional(),
|
|
87
|
+
rationale: z
|
|
88
|
+
.array(z.object({
|
|
89
|
+
ts: z.number().int(),
|
|
90
|
+
note: z.string(),
|
|
91
|
+
}))
|
|
92
|
+
.optional(),
|
|
93
|
+
signature: SignatureSchema,
|
|
94
|
+
});
|
|
95
|
+
// ── Verdict manifest ──────────────────────────────────────────────────────────
|
|
96
|
+
const CheckSchema = z.object({
|
|
97
|
+
name: z.string(),
|
|
98
|
+
status: z.enum(['PASS', 'FAIL', 'SKIP']),
|
|
99
|
+
detail: z.union([z.string(), z.record(z.unknown())]).optional(),
|
|
100
|
+
});
|
|
101
|
+
export const PredictionVerdictManifestSchema = z.object({
|
|
102
|
+
schemaVersion: z.literal('prediction.v0.verdict.v1'),
|
|
103
|
+
generatedAt: z.number().int(),
|
|
104
|
+
intent: IntentProvenanceSchema,
|
|
105
|
+
evaluator: ParticipantSchema,
|
|
106
|
+
window: WindowSchema,
|
|
107
|
+
verdict: z.enum(['PASS', 'FAIL', 'REJECTED', 'INDETERMINATE']),
|
|
108
|
+
score: z.string(),
|
|
109
|
+
scoreBasis: z.literal('brier.v1'),
|
|
110
|
+
scoreVersion: z.string(),
|
|
111
|
+
oracleReading: z.object({
|
|
112
|
+
feed: HexStringSchema,
|
|
113
|
+
roundId: z.string(),
|
|
114
|
+
answer: z.string(),
|
|
115
|
+
updatedAt: z.number().int(),
|
|
116
|
+
nextRoundUpdatedAt: z.number().int().optional(),
|
|
117
|
+
}),
|
|
118
|
+
claimed: z.object({
|
|
119
|
+
probability: z.string(),
|
|
120
|
+
submittedAt: z.number().int(),
|
|
121
|
+
modelId: z.string(),
|
|
122
|
+
submissionManifestCid: z.string(),
|
|
123
|
+
}),
|
|
124
|
+
groundTruth: z.enum(['YES', 'NO']),
|
|
125
|
+
checks: z.array(CheckSchema),
|
|
126
|
+
signature: SignatureSchema,
|
|
127
|
+
});
|
|
128
|
+
//# sourceMappingURL=prediction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prediction.js","sourceRoot":"","sources":["../../src/types/prediction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chainlink AggregatorV3 read client.
|
|
3
|
+
*
|
|
4
|
+
* §7 of spec/2026-04-20-prediction-v0-pis-phase-1-design.md
|
|
5
|
+
*/
|
|
6
|
+
import type { PublicClient } from 'viem';
|
|
7
|
+
export declare const AGGREGATOR_V3_ABI: readonly [{
|
|
8
|
+
readonly name: "latestRoundData";
|
|
9
|
+
readonly type: "function";
|
|
10
|
+
readonly stateMutability: "view";
|
|
11
|
+
readonly inputs: readonly [];
|
|
12
|
+
readonly outputs: readonly [{
|
|
13
|
+
readonly name: "roundId";
|
|
14
|
+
readonly type: "uint80";
|
|
15
|
+
}, {
|
|
16
|
+
readonly name: "answer";
|
|
17
|
+
readonly type: "int256";
|
|
18
|
+
}, {
|
|
19
|
+
readonly name: "startedAt";
|
|
20
|
+
readonly type: "uint256";
|
|
21
|
+
}, {
|
|
22
|
+
readonly name: "updatedAt";
|
|
23
|
+
readonly type: "uint256";
|
|
24
|
+
}, {
|
|
25
|
+
readonly name: "answeredInRound";
|
|
26
|
+
readonly type: "uint80";
|
|
27
|
+
}];
|
|
28
|
+
}, {
|
|
29
|
+
readonly name: "getRoundData";
|
|
30
|
+
readonly type: "function";
|
|
31
|
+
readonly stateMutability: "view";
|
|
32
|
+
readonly inputs: readonly [{
|
|
33
|
+
readonly name: "_roundId";
|
|
34
|
+
readonly type: "uint80";
|
|
35
|
+
}];
|
|
36
|
+
readonly outputs: readonly [{
|
|
37
|
+
readonly name: "roundId";
|
|
38
|
+
readonly type: "uint80";
|
|
39
|
+
}, {
|
|
40
|
+
readonly name: "answer";
|
|
41
|
+
readonly type: "int256";
|
|
42
|
+
}, {
|
|
43
|
+
readonly name: "startedAt";
|
|
44
|
+
readonly type: "uint256";
|
|
45
|
+
}, {
|
|
46
|
+
readonly name: "updatedAt";
|
|
47
|
+
readonly type: "uint256";
|
|
48
|
+
}, {
|
|
49
|
+
readonly name: "answeredInRound";
|
|
50
|
+
readonly type: "uint80";
|
|
51
|
+
}];
|
|
52
|
+
}, {
|
|
53
|
+
readonly name: "decimals";
|
|
54
|
+
readonly type: "function";
|
|
55
|
+
readonly stateMutability: "view";
|
|
56
|
+
readonly inputs: readonly [];
|
|
57
|
+
readonly outputs: readonly [{
|
|
58
|
+
readonly name: "";
|
|
59
|
+
readonly type: "uint8";
|
|
60
|
+
}];
|
|
61
|
+
}, {
|
|
62
|
+
readonly name: "description";
|
|
63
|
+
readonly type: "function";
|
|
64
|
+
readonly stateMutability: "view";
|
|
65
|
+
readonly inputs: readonly [];
|
|
66
|
+
readonly outputs: readonly [{
|
|
67
|
+
readonly name: "";
|
|
68
|
+
readonly type: "string";
|
|
69
|
+
}];
|
|
70
|
+
}];
|
|
71
|
+
export interface RoundReading {
|
|
72
|
+
roundId: bigint;
|
|
73
|
+
answer: bigint;
|
|
74
|
+
startedAt: number;
|
|
75
|
+
updatedAt: number;
|
|
76
|
+
answeredInRound: bigint;
|
|
77
|
+
decimals: number;
|
|
78
|
+
}
|
|
79
|
+
/** Scale a raw Chainlink int256 answer to a decimal string. */
|
|
80
|
+
export declare function scaleToDecimal(answer: bigint, decimals: number): string;
|
|
81
|
+
export declare function readChainlinkLatest(feed: `0x${string}`, publicClient: PublicClient): Promise<RoundReading>;
|
|
82
|
+
export declare function readChainlinkRound(feed: `0x${string}`, roundId: bigint, publicClient: PublicClient, decimals: number): Promise<RoundReading>;
|
|
83
|
+
export interface SpanningResult {
|
|
84
|
+
/** Round R with updatedAt ≤ resolveTs. */
|
|
85
|
+
round: RoundReading;
|
|
86
|
+
/** Round R+1 with updatedAt > resolveTs. null if no newer round exists yet. */
|
|
87
|
+
nextRound: RoundReading | null;
|
|
88
|
+
/** True iff nextRound exists — then the spanning property is satisfied. */
|
|
89
|
+
spanning: boolean;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Find the Chainlink round that "spans" resolveTs: round R where
|
|
93
|
+
* R.updatedAt ≤ resolveTs < (R+1).updatedAt.
|
|
94
|
+
*
|
|
95
|
+
* If the latest round's updatedAt ≤ resolveTs (i.e. no newer round yet),
|
|
96
|
+
* returns { round: latest, nextRound: null, spanning: false }. Caller should
|
|
97
|
+
* retry later (availability check will mark SKIP → INDETERMINATE verdict).
|
|
98
|
+
*/
|
|
99
|
+
export declare function oraclePriceAtResolveTs(feed: `0x${string}`, resolveTs: number, publicClient: PublicClient): Promise<SpanningResult>;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
export const AGGREGATOR_V3_ABI = [
|
|
2
|
+
{
|
|
3
|
+
name: 'latestRoundData',
|
|
4
|
+
type: 'function',
|
|
5
|
+
stateMutability: 'view',
|
|
6
|
+
inputs: [],
|
|
7
|
+
outputs: [
|
|
8
|
+
{ name: 'roundId', type: 'uint80' },
|
|
9
|
+
{ name: 'answer', type: 'int256' },
|
|
10
|
+
{ name: 'startedAt', type: 'uint256' },
|
|
11
|
+
{ name: 'updatedAt', type: 'uint256' },
|
|
12
|
+
{ name: 'answeredInRound', type: 'uint80' },
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'getRoundData',
|
|
17
|
+
type: 'function',
|
|
18
|
+
stateMutability: 'view',
|
|
19
|
+
inputs: [{ name: '_roundId', type: 'uint80' }],
|
|
20
|
+
outputs: [
|
|
21
|
+
{ name: 'roundId', type: 'uint80' },
|
|
22
|
+
{ name: 'answer', type: 'int256' },
|
|
23
|
+
{ name: 'startedAt', type: 'uint256' },
|
|
24
|
+
{ name: 'updatedAt', type: 'uint256' },
|
|
25
|
+
{ name: 'answeredInRound', type: 'uint80' },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'decimals',
|
|
30
|
+
type: 'function',
|
|
31
|
+
stateMutability: 'view',
|
|
32
|
+
inputs: [],
|
|
33
|
+
outputs: [{ name: '', type: 'uint8' }],
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'description',
|
|
37
|
+
type: 'function',
|
|
38
|
+
stateMutability: 'view',
|
|
39
|
+
inputs: [],
|
|
40
|
+
outputs: [{ name: '', type: 'string' }],
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
/** Scale a raw Chainlink int256 answer to a decimal string. */
|
|
44
|
+
export function scaleToDecimal(answer, decimals) {
|
|
45
|
+
if (answer < 0n) {
|
|
46
|
+
throw new Error(`scaleToDecimal: negative value not supported in v0 (got ${answer})`);
|
|
47
|
+
}
|
|
48
|
+
const s = answer.toString();
|
|
49
|
+
if (decimals === 0)
|
|
50
|
+
return s;
|
|
51
|
+
if (s.length <= decimals) {
|
|
52
|
+
const frac = s.padStart(decimals, '0').replace(/0+$/, '');
|
|
53
|
+
return frac.length > 0 ? `0.${frac}` : '0';
|
|
54
|
+
}
|
|
55
|
+
const intPart = s.slice(0, s.length - decimals);
|
|
56
|
+
const fracRaw = s.slice(s.length - decimals);
|
|
57
|
+
const frac = fracRaw.replace(/0+$/, '');
|
|
58
|
+
return frac.length > 0 ? `${intPart}.${frac}` : intPart;
|
|
59
|
+
}
|
|
60
|
+
export async function readChainlinkLatest(feed, publicClient) {
|
|
61
|
+
const [latest, decimals] = await Promise.all([
|
|
62
|
+
publicClient.readContract({
|
|
63
|
+
address: feed,
|
|
64
|
+
abi: AGGREGATOR_V3_ABI,
|
|
65
|
+
functionName: 'latestRoundData',
|
|
66
|
+
}),
|
|
67
|
+
publicClient.readContract({
|
|
68
|
+
address: feed,
|
|
69
|
+
abi: AGGREGATOR_V3_ABI,
|
|
70
|
+
functionName: 'decimals',
|
|
71
|
+
}),
|
|
72
|
+
]);
|
|
73
|
+
const [roundId, answer, startedAt, updatedAt, answeredInRound] = latest;
|
|
74
|
+
return {
|
|
75
|
+
roundId,
|
|
76
|
+
answer,
|
|
77
|
+
// Chainlink timestamps are SECONDS → convert to ms for consistency with rest of codebase
|
|
78
|
+
startedAt: Number(startedAt) * 1000,
|
|
79
|
+
updatedAt: Number(updatedAt) * 1000,
|
|
80
|
+
answeredInRound,
|
|
81
|
+
decimals: decimals,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export async function readChainlinkRound(feed, roundId, publicClient, decimals) {
|
|
85
|
+
const round = await publicClient.readContract({
|
|
86
|
+
address: feed,
|
|
87
|
+
abi: AGGREGATOR_V3_ABI,
|
|
88
|
+
functionName: 'getRoundData',
|
|
89
|
+
args: [roundId],
|
|
90
|
+
});
|
|
91
|
+
const [rid, answer, startedAt, updatedAt, answeredInRound] = round;
|
|
92
|
+
return {
|
|
93
|
+
roundId: rid,
|
|
94
|
+
answer,
|
|
95
|
+
startedAt: Number(startedAt) * 1000,
|
|
96
|
+
updatedAt: Number(updatedAt) * 1000,
|
|
97
|
+
answeredInRound,
|
|
98
|
+
decimals,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Find the Chainlink round that "spans" resolveTs: round R where
|
|
103
|
+
* R.updatedAt ≤ resolveTs < (R+1).updatedAt.
|
|
104
|
+
*
|
|
105
|
+
* If the latest round's updatedAt ≤ resolveTs (i.e. no newer round yet),
|
|
106
|
+
* returns { round: latest, nextRound: null, spanning: false }. Caller should
|
|
107
|
+
* retry later (availability check will mark SKIP → INDETERMINATE verdict).
|
|
108
|
+
*/
|
|
109
|
+
export async function oraclePriceAtResolveTs(feed, resolveTs, publicClient) {
|
|
110
|
+
const latest = await readChainlinkLatest(feed, publicClient);
|
|
111
|
+
// Case A: latest is at-or-before resolveTs → no newer round yet
|
|
112
|
+
if (latest.updatedAt <= resolveTs) {
|
|
113
|
+
return { round: latest, nextRound: null, spanning: false };
|
|
114
|
+
}
|
|
115
|
+
// Case B: latest is after resolveTs → walk back to find spanning round
|
|
116
|
+
let nextRound = latest;
|
|
117
|
+
let cursor = latest.roundId - 1n;
|
|
118
|
+
while (cursor > 0n) {
|
|
119
|
+
const r = await readChainlinkRound(feed, cursor, publicClient, latest.decimals);
|
|
120
|
+
if (r.updatedAt <= resolveTs) {
|
|
121
|
+
return { round: r, nextRound, spanning: true };
|
|
122
|
+
}
|
|
123
|
+
nextRound = r;
|
|
124
|
+
cursor -= 1n;
|
|
125
|
+
}
|
|
126
|
+
// Walked back to round 0 without finding a pre-resolveTs round — oracle is
|
|
127
|
+
// newer than the window. Surface as not-spanning so caller INDETERMINATE-s.
|
|
128
|
+
return { round: latest, nextRound: null, spanning: false };
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/venues/chainlink/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Known Chainlink AggregatorV3 feeds on Base + Base Sepolia. */
|
|
2
|
+
export declare const BASE_SEPOLIA_FEEDS: {
|
|
3
|
+
readonly 'ETH / USD': "0x4aDC67696bA383F43DD60A9e78F2C97Fbbfc7cb1";
|
|
4
|
+
readonly 'BTC / USD': "0x0FB99723Aee6f420beAD13e6bBB79b7E6F034298";
|
|
5
|
+
};
|
|
6
|
+
export declare const BASE_FEEDS: {
|
|
7
|
+
readonly 'ETH / USD': "0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70";
|
|
8
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Known Chainlink AggregatorV3 feeds on Base + Base Sepolia. */
|
|
2
|
+
export const BASE_SEPOLIA_FEEDS = {
|
|
3
|
+
'ETH / USD': '0x4aDC67696bA383F43DD60A9e78F2C97Fbbfc7cb1',
|
|
4
|
+
'BTC / USD': '0x0FB99723Aee6f420beAD13e6bBB79b7E6F034298',
|
|
5
|
+
};
|
|
6
|
+
export const BASE_FEEDS = {
|
|
7
|
+
'ETH / USD': '0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70',
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=feeds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feeds.js","sourceRoot":"","sources":["../../../src/venues/chainlink/feeds.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,WAAW,EAAE,4CAAqD;IAClE,WAAW,EAAE,4CAAqD;CAC1D,CAAC;AAEX,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,WAAW,EAAE,4CAAqD;CAC1D,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified account-value helper.
|
|
3
|
+
*
|
|
4
|
+
* Returns a single equity figure that sums perps margin + spot USDC. This
|
|
5
|
+
* matches HL's `portfolio` endpoint `accountValueHistory` (which also
|
|
6
|
+
* reports the unified view), so restorer-claimed equity and evaluator-
|
|
7
|
+
* rederived grid points compare cleanly.
|
|
8
|
+
*
|
|
9
|
+
* Non-USDC spot tokens are NOT valued in v0 — their midprice lookup and
|
|
10
|
+
* safety semantics are out of scope for the first cut of portfolio.v0.
|
|
11
|
+
*/
|
|
12
|
+
import type { HlClearinghouseState, HlSpotClearinghouseState } from './types.js';
|
|
13
|
+
export interface UnifiedAccountValue {
|
|
14
|
+
/** Sum of perps accountValue + spot USDC balance, as a decimal string. */
|
|
15
|
+
accountValue: string;
|
|
16
|
+
/** Perps-only accountValue (marginSummary.accountValue). */
|
|
17
|
+
perpsAccountValue: string;
|
|
18
|
+
/** Spot USDC balance (0 if absent). */
|
|
19
|
+
spotUsdc: string;
|
|
20
|
+
/** Raw perps payload from HL. */
|
|
21
|
+
clearinghouseState: HlClearinghouseState;
|
|
22
|
+
/** Raw spot payload from HL. */
|
|
23
|
+
spotClearinghouseState: HlSpotClearinghouseState;
|
|
24
|
+
}
|
|
25
|
+
interface HlClientLike {
|
|
26
|
+
clearinghouseState: (user: string) => Promise<HlClearinghouseState>;
|
|
27
|
+
spotClearinghouseState: (user: string) => Promise<HlSpotClearinghouseState>;
|
|
28
|
+
}
|
|
29
|
+
export declare function getUnifiedAccountValue(hlClient: HlClientLike, user: string): Promise<UnifiedAccountValue>;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified account-value helper.
|
|
3
|
+
*
|
|
4
|
+
* Returns a single equity figure that sums perps margin + spot USDC. This
|
|
5
|
+
* matches HL's `portfolio` endpoint `accountValueHistory` (which also
|
|
6
|
+
* reports the unified view), so restorer-claimed equity and evaluator-
|
|
7
|
+
* rederived grid points compare cleanly.
|
|
8
|
+
*
|
|
9
|
+
* Non-USDC spot tokens are NOT valued in v0 — their midprice lookup and
|
|
10
|
+
* safety semantics are out of scope for the first cut of portfolio.v0.
|
|
11
|
+
*/
|
|
12
|
+
export async function getUnifiedAccountValue(hlClient, user) {
|
|
13
|
+
const [clearinghouseState, spotClearinghouseState] = await Promise.all([
|
|
14
|
+
hlClient.clearinghouseState(user),
|
|
15
|
+
hlClient.spotClearinghouseState(user),
|
|
16
|
+
]);
|
|
17
|
+
const perpsAccountValue = clearinghouseState.marginSummary.accountValue;
|
|
18
|
+
const usdcBalance = spotClearinghouseState.balances.find((b) => b.coin === 'USDC');
|
|
19
|
+
const spotUsdc = usdcBalance ? usdcBalance.total : '0';
|
|
20
|
+
const total = parseFloat(perpsAccountValue) + parseFloat(spotUsdc);
|
|
21
|
+
const accountValue = String(total);
|
|
22
|
+
return {
|
|
23
|
+
accountValue,
|
|
24
|
+
perpsAccountValue,
|
|
25
|
+
spotUsdc,
|
|
26
|
+
clearinghouseState,
|
|
27
|
+
spotClearinghouseState,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=account-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-value.js","sourceRoot":"","sources":["../../../src/venues/hyperliquid/account-value.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAyBH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,QAAsB,EACtB,IAAY;IAEZ,MAAM,CAAC,kBAAkB,EAAE,sBAAsB,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACrE,QAAQ,CAAC,kBAAkB,CAAC,IAAI,CAAC;QACjC,QAAQ,CAAC,sBAAsB,CAAC,IAAI,CAAC;KACtC,CAAC,CAAC;IAEH,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,aAAa,CAAC,YAAY,CAAC;IACxE,MAAM,WAAW,GAAG,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACnF,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAEvD,MAAM,KAAK,GAAG,UAAU,CAAC,iBAAiB,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACnE,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEnC,OAAO;QACL,YAAY;QACZ,iBAAiB;QACjB,QAAQ;QACR,kBAAkB;QAClB,sBAAsB;KACvB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only Hyperliquid public API client.
|
|
3
|
+
*
|
|
4
|
+
* All endpoints are POST /info with a JSON body. No authentication required.
|
|
5
|
+
* This client is intentionally read-only — write paths are out of scope.
|
|
6
|
+
*/
|
|
7
|
+
import type { HlAllMidsResponse, HlClearinghouseState, HlMetaResponse, HlPeriodData, HlPortfolioPeriod, HlPortfolioResponse, HlSpotClearinghouseState, HlUserFills, HlUserFillsByTimeResult } from './types.js';
|
|
8
|
+
export declare const HL_MAINNET_BASE_URL = "https://api.hyperliquid.xyz";
|
|
9
|
+
export declare const HL_TESTNET_BASE_URL = "https://api.hyperliquid-testnet.xyz";
|
|
10
|
+
export declare class HyperliquidClient {
|
|
11
|
+
readonly baseUrl: string;
|
|
12
|
+
readonly timeoutMs: number;
|
|
13
|
+
constructor(baseUrl?: string, timeoutMs?: number);
|
|
14
|
+
private post;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the current clearinghouse (margin) state for a user.
|
|
17
|
+
* This reflects the LIVE state — there is no historical point-in-time lookup.
|
|
18
|
+
*/
|
|
19
|
+
clearinghouseState(user: string): Promise<HlClearinghouseState>;
|
|
20
|
+
/**
|
|
21
|
+
* Returns the current spot (non-perps) clearinghouse state for a user.
|
|
22
|
+
* Includes USDC and other spot token balances.
|
|
23
|
+
*/
|
|
24
|
+
spotClearinghouseState(user: string): Promise<HlSpotClearinghouseState>;
|
|
25
|
+
/**
|
|
26
|
+
* Returns recent fills for a user, in descending time order.
|
|
27
|
+
*/
|
|
28
|
+
userFills(user: string): Promise<HlUserFills>;
|
|
29
|
+
/**
|
|
30
|
+
* Returns fills for a user in ascending time order, with optional pagination.
|
|
31
|
+
*
|
|
32
|
+
* The HL API silently clamps `startTime` to its retention horizon (typically
|
|
33
|
+
* ~30 days). When clamping occurs the first fill's `.time` will be greater
|
|
34
|
+
* than the requested `startTime`. This method detects that and sets
|
|
35
|
+
* `result.startTimeClamped = true`.
|
|
36
|
+
*
|
|
37
|
+
* @param user Ethereum address of the account.
|
|
38
|
+
* @param startTime Start of the window in epoch milliseconds.
|
|
39
|
+
* @param endTime Optional end of the window in epoch milliseconds.
|
|
40
|
+
* @param aggregateByTime Passed directly to the API (default false).
|
|
41
|
+
*/
|
|
42
|
+
userFillsByTime(user: string, startTime: number, endTime?: number, aggregateByTime?: boolean): Promise<HlUserFillsByTimeResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Returns historical account-value snapshots (~140-minute grid) for a user.
|
|
45
|
+
*
|
|
46
|
+
* The response is an array of [periodName, periodData] tuples where period
|
|
47
|
+
* is one of "day", "week", "month", "allTime".
|
|
48
|
+
*/
|
|
49
|
+
portfolio(user: string): Promise<HlPortfolioResponse>;
|
|
50
|
+
/**
|
|
51
|
+
* Fetches the portfolio response and extracts a specific period bucket.
|
|
52
|
+
* Returns null if the period is not present in the response.
|
|
53
|
+
*/
|
|
54
|
+
portfolioPeriod(user: string, period: HlPortfolioPeriod): Promise<HlPeriodData | null>;
|
|
55
|
+
/**
|
|
56
|
+
* Returns the universe of perpetual markets (metadata).
|
|
57
|
+
*/
|
|
58
|
+
meta(): Promise<HlMetaResponse>;
|
|
59
|
+
/**
|
|
60
|
+
* Returns current mid prices for all assets.
|
|
61
|
+
*/
|
|
62
|
+
allMids(): Promise<HlAllMidsResponse>;
|
|
63
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only Hyperliquid public API client.
|
|
3
|
+
*
|
|
4
|
+
* All endpoints are POST /info with a JSON body. No authentication required.
|
|
5
|
+
* This client is intentionally read-only — write paths are out of scope.
|
|
6
|
+
*/
|
|
7
|
+
export const HL_MAINNET_BASE_URL = 'https://api.hyperliquid.xyz';
|
|
8
|
+
export const HL_TESTNET_BASE_URL = 'https://api.hyperliquid-testnet.xyz';
|
|
9
|
+
export class HyperliquidClient {
|
|
10
|
+
baseUrl;
|
|
11
|
+
timeoutMs;
|
|
12
|
+
constructor(baseUrl = HL_MAINNET_BASE_URL, timeoutMs = 15_000) {
|
|
13
|
+
this.baseUrl = baseUrl.replace(/\/$/, '');
|
|
14
|
+
this.timeoutMs = timeoutMs;
|
|
15
|
+
}
|
|
16
|
+
// -------------------------------------------------------------------------
|
|
17
|
+
// Private helpers
|
|
18
|
+
// -------------------------------------------------------------------------
|
|
19
|
+
async post(body) {
|
|
20
|
+
const url = `${this.baseUrl}/info`;
|
|
21
|
+
const ac = new AbortController();
|
|
22
|
+
const t = setTimeout(() => ac.abort(), this.timeoutMs);
|
|
23
|
+
try {
|
|
24
|
+
const res = await fetch(url, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: { 'Content-Type': 'application/json' },
|
|
27
|
+
body: JSON.stringify(body),
|
|
28
|
+
signal: ac.signal,
|
|
29
|
+
});
|
|
30
|
+
if (!res.ok) {
|
|
31
|
+
const excerpt = await res.text().then((t) => t.slice(0, 200));
|
|
32
|
+
throw new Error(`Hyperliquid API error: HTTP ${res.status} ${res.statusText} — ${excerpt}`);
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
return (await res.json());
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
throw new Error(`Hyperliquid API error: could not parse JSON response from ${url}: ${err instanceof Error ? err.message : String(err)}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
43
|
+
throw new Error(`Hyperliquid API timeout after ${this.timeoutMs}ms calling ${url}`);
|
|
44
|
+
}
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
clearTimeout(t);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// -------------------------------------------------------------------------
|
|
52
|
+
// Public endpoints
|
|
53
|
+
// -------------------------------------------------------------------------
|
|
54
|
+
/**
|
|
55
|
+
* Returns the current clearinghouse (margin) state for a user.
|
|
56
|
+
* This reflects the LIVE state — there is no historical point-in-time lookup.
|
|
57
|
+
*/
|
|
58
|
+
async clearinghouseState(user) {
|
|
59
|
+
return this.post({ type: 'clearinghouseState', user });
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns the current spot (non-perps) clearinghouse state for a user.
|
|
63
|
+
* Includes USDC and other spot token balances.
|
|
64
|
+
*/
|
|
65
|
+
async spotClearinghouseState(user) {
|
|
66
|
+
return this.post({ type: 'spotClearinghouseState', user });
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Returns recent fills for a user, in descending time order.
|
|
70
|
+
*/
|
|
71
|
+
async userFills(user) {
|
|
72
|
+
return this.post({ type: 'userFills', user });
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Returns fills for a user in ascending time order, with optional pagination.
|
|
76
|
+
*
|
|
77
|
+
* The HL API silently clamps `startTime` to its retention horizon (typically
|
|
78
|
+
* ~30 days). When clamping occurs the first fill's `.time` will be greater
|
|
79
|
+
* than the requested `startTime`. This method detects that and sets
|
|
80
|
+
* `result.startTimeClamped = true`.
|
|
81
|
+
*
|
|
82
|
+
* @param user Ethereum address of the account.
|
|
83
|
+
* @param startTime Start of the window in epoch milliseconds.
|
|
84
|
+
* @param endTime Optional end of the window in epoch milliseconds.
|
|
85
|
+
* @param aggregateByTime Passed directly to the API (default false).
|
|
86
|
+
*/
|
|
87
|
+
async userFillsByTime(user, startTime, endTime, aggregateByTime = false) {
|
|
88
|
+
const body = {
|
|
89
|
+
type: 'userFillsByTime',
|
|
90
|
+
user,
|
|
91
|
+
startTime,
|
|
92
|
+
aggregateByTime,
|
|
93
|
+
};
|
|
94
|
+
if (endTime !== undefined) {
|
|
95
|
+
body['endTime'] = endTime;
|
|
96
|
+
}
|
|
97
|
+
const fills = await this.post(body);
|
|
98
|
+
// Clamp detection: if the first fill's time is strictly greater than the
|
|
99
|
+
// requested startTime, HL quietly moved the window forward to its retention
|
|
100
|
+
// horizon. An empty result is NOT treated as clamped — we can't tell.
|
|
101
|
+
const startTimeClamped = fills.length > 0 && fills[0] !== undefined && fills[0].time > startTime;
|
|
102
|
+
return { fills, startTimeClamped };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Returns historical account-value snapshots (~140-minute grid) for a user.
|
|
106
|
+
*
|
|
107
|
+
* The response is an array of [periodName, periodData] tuples where period
|
|
108
|
+
* is one of "day", "week", "month", "allTime".
|
|
109
|
+
*/
|
|
110
|
+
async portfolio(user) {
|
|
111
|
+
return this.post({ type: 'portfolio', user });
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Fetches the portfolio response and extracts a specific period bucket.
|
|
115
|
+
* Returns null if the period is not present in the response.
|
|
116
|
+
*/
|
|
117
|
+
async portfolioPeriod(user, period) {
|
|
118
|
+
const response = await this.portfolio(user);
|
|
119
|
+
const entry = response.find(([name]) => name === period);
|
|
120
|
+
return entry ? entry[1] : null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Returns the universe of perpetual markets (metadata).
|
|
124
|
+
*/
|
|
125
|
+
async meta() {
|
|
126
|
+
return this.post({ type: 'meta' });
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Returns current mid prices for all assets.
|
|
130
|
+
*/
|
|
131
|
+
async allMids() {
|
|
132
|
+
return this.post({ type: 'allMids' });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=client.js.map
|