@waterx/sdk 4.0.0 → 4.0.1
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 +34 -34
- package/dist/cjs/src/account/config.d.ts +0 -16
- package/dist/cjs/src/oracle/aggregate.d.ts +19 -21
- package/dist/cjs/src/oracle/aggregate.js +57 -69
- package/dist/cjs/src/oracle/config.d.ts +32 -52
- package/dist/cjs/src/oracle/config.js +1 -35
- package/dist/cjs/src/oracle/host.d.ts +1 -1
- package/dist/cjs/src/oracle/index.d.ts +2 -2
- package/dist/cjs/src/oracle/index.js +20 -6
- package/dist/cjs/src/oracle/pyth.d.ts +68 -6
- package/dist/cjs/src/oracle/pyth.js +338 -22
- package/dist/cjs/src/oracle/rule-registry.d.ts +10 -6
- package/dist/cjs/src/oracle/rule-registry.js +10 -6
- package/dist/cjs/src/oracle/rules/pyth-core-rule.js +17 -2
- package/dist/cjs/src/oracle/rules/pyth-lazer-rule.d.ts +6 -6
- package/dist/cjs/src/oracle/rules/pyth-lazer-rule.js +25 -22
- package/dist/cjs/src/oracle/rules/pyth-rule.js +5 -0
- package/dist/cjs/src/oracle/update-fetch.d.ts +32 -2
- package/dist/cjs/src/oracle/update-fetch.js +60 -3
- package/dist/cjs/src/perp/client.d.ts +33 -19
- package/dist/cjs/src/perp/client.js +16 -10
- package/dist/cjs/src/perp/config.d.ts +4 -6
- package/dist/cjs/src/perp/config.js +8 -12
- package/dist/cjs/src/perp/index.d.ts +2 -2
- package/dist/cjs/src/perp/index.js +3 -4
- package/dist/cjs/src/unified-client.d.ts +19 -11
- package/dist/cjs/src/unified-client.js +2 -1
- package/dist/src/account/config.d.ts +0 -16
- package/dist/src/oracle/aggregate.d.ts +19 -21
- package/dist/src/oracle/aggregate.js +57 -69
- package/dist/src/oracle/config.d.ts +32 -52
- package/dist/src/oracle/config.js +0 -34
- package/dist/src/oracle/host.d.ts +1 -1
- package/dist/src/oracle/index.d.ts +2 -2
- package/dist/src/oracle/index.js +15 -7
- package/dist/src/oracle/pyth.d.ts +68 -6
- package/dist/src/oracle/pyth.js +334 -22
- package/dist/src/oracle/rule-registry.d.ts +10 -6
- package/dist/src/oracle/rule-registry.js +10 -6
- package/dist/src/oracle/rules/pyth-core-rule.js +18 -3
- package/dist/src/oracle/rules/pyth-lazer-rule.d.ts +6 -6
- package/dist/src/oracle/rules/pyth-lazer-rule.js +26 -23
- package/dist/src/oracle/rules/pyth-rule.js +5 -0
- package/dist/src/oracle/update-fetch.d.ts +32 -2
- package/dist/src/oracle/update-fetch.js +57 -3
- package/dist/src/perp/client.d.ts +33 -19
- package/dist/src/perp/client.js +17 -11
- package/dist/src/perp/config.d.ts +4 -6
- package/dist/src/perp/config.js +9 -12
- package/dist/src/perp/index.d.ts +2 -2
- package/dist/src/perp/index.js +1 -1
- package/dist/src/unified-client.d.ts +19 -11
- package/dist/src/unified-client.js +2 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* updates, plus `feedLazerRule`, the collector-feed leg `aggregateTicker`
|
|
5
5
|
* appends per lazer-routed ticker. Fetches one `leEcdsa` payload for all
|
|
6
6
|
* requested integer feed ids from the Lazer HTTP API (Bearer-authenticated
|
|
7
|
-
* via `
|
|
7
|
+
* via the `pythApiKey` create option), verifies it ONCE on-chain via
|
|
8
8
|
* `pyth_lazer::parse_and_verify_le_ecdsa_update`, and hands the resulting
|
|
9
9
|
* `Update` PTB value back through a `RuleUpdateHandle` for the feed calls.
|
|
10
10
|
*/
|
|
@@ -22,10 +22,17 @@ const update_fetch_ts_1 = require("../update-fetch.js");
|
|
|
22
22
|
* `confidence` is optional on-chain but requested so the rule's
|
|
23
23
|
* fail-closed confidence gate actually engages (a payload without
|
|
24
24
|
* confidence passes the gate unchecked).
|
|
25
|
-
* - `channel` — `real_time`:
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
25
|
+
* - `channel` — `fixed_rate@200ms`, NOT `real_time`: Lazer rejects a request
|
|
26
|
+
* whose channel is faster than ANY requested feed's `min_channel`, and it
|
|
27
|
+
* rejects the WHOLE batch (`400 Feeds do not support channel …`). Only the
|
|
28
|
+
* majors (BTC/ETH/SOL/USDC/DOGE/XRP/BNB/HYPE + EUR/JPY FX) publish
|
|
29
|
+
* `real_time`; the other 19 of the 29 configured feeds — including SUIUSD
|
|
30
|
+
* and every xStock — are `min_channel: fixed_rate@200ms` (Lazer symbol
|
|
31
|
+
* registry, verified 2026-07-22: the same 29-feed batch 400s at
|
|
32
|
+
* `real_time`/`50ms` and serves 200 with the leEcdsa blob at `200ms`).
|
|
33
|
+
* 200ms is the fastest channel every configured feed supports, and the
|
|
34
|
+
* deployed rule accepts it: the v1 on-chain `channel::from_u8` aborts only
|
|
35
|
+
* on the 1000ms fixed-rate channel (real_time / 50ms / 200ms are safe).
|
|
29
36
|
* - `formats: leEcdsa` + `jsonBinaryEncoding: hex` — the Sui verifier takes
|
|
30
37
|
* the `leEcdsa` framing; hex matches `fromHex` below.
|
|
31
38
|
*/
|
|
@@ -33,7 +40,7 @@ const LAZER_LATEST_PRICE_REQUEST = {
|
|
|
33
40
|
properties: ["price", "exponent", "confidence"],
|
|
34
41
|
formats: ["leEcdsa"],
|
|
35
42
|
jsonBinaryEncoding: "hex",
|
|
36
|
-
channel: "
|
|
43
|
+
channel: "fixed_rate@200ms",
|
|
37
44
|
};
|
|
38
45
|
/**
|
|
39
46
|
* Shape check ONLY — the `kind` discriminant is checked separately by the
|
|
@@ -48,16 +55,16 @@ function isPythLazerUpdatePayloadShape(payload) {
|
|
|
48
55
|
}
|
|
49
56
|
/**
|
|
50
57
|
* Thrown by {@link PythLazerRule.fetchUpdateData} when `pyth_lazer_rule` is
|
|
51
|
-
* deployed in config but no `
|
|
52
|
-
* requires a Bearer token and the SDK never reads
|
|
53
|
-
* `instanceof`-able (mirrors
|
|
54
|
-
* so a consumer can branch on
|
|
55
|
-
* string-matching `error.message`.
|
|
58
|
+
* deployed in config but no `pythApiKey` was supplied at client init — the
|
|
59
|
+
* Lazer HTTP API requires a Bearer token and the SDK never reads
|
|
60
|
+
* `process.env` to find one. `instanceof`-able (mirrors
|
|
61
|
+
* `OracleFeeSourceUnavailableError` in `pyth.ts`) so a consumer can branch on
|
|
62
|
+
* the failure type directly instead of string-matching `error.message`.
|
|
56
63
|
*/
|
|
57
64
|
class LazerApiKeyMissingError extends Error {
|
|
58
65
|
constructor() {
|
|
59
66
|
super("LazerApiKeyMissing: pyth_lazer_rule requires a Pyth Lazer access token — " +
|
|
60
|
-
"
|
|
67
|
+
"pass `pythApiKey` when creating the client (the SDK never reads process.env)");
|
|
61
68
|
this.name = "LazerApiKeyMissingError";
|
|
62
69
|
}
|
|
63
70
|
}
|
|
@@ -77,7 +84,11 @@ function requireLazerPackage(host) {
|
|
|
77
84
|
* both oracle sources fail the same way under upstream degradation.
|
|
78
85
|
*/
|
|
79
86
|
async function fetchLazerSignedUpdate(endpoint, apiKey, feedIds, fetchOpts) {
|
|
80
|
-
|
|
87
|
+
// joinEndpointPath preserves any base path on the endpoint — the same
|
|
88
|
+
// leading-slash `new URL` footgun that 404'd every feed on the Pyth Pro
|
|
89
|
+
// Hermes endpoint (see update-fetch.ts). Defensive here: the default
|
|
90
|
+
// Lazer endpoint has no base path, but a config override may.
|
|
91
|
+
const url = (0, update_fetch_ts_1.joinEndpointPath)(endpoint, "v1/latest_price");
|
|
81
92
|
let res;
|
|
82
93
|
try {
|
|
83
94
|
res = await (0, update_fetch_ts_1.fetchWithPolicy)(url.toString(), {
|
|
@@ -87,15 +98,7 @@ async function fetchLazerSignedUpdate(endpoint, apiKey, feedIds, fetchOpts) {
|
|
|
87
98
|
}, { apiKey, ...fetchOpts });
|
|
88
99
|
}
|
|
89
100
|
catch (err) {
|
|
90
|
-
|
|
91
|
-
// never recovered carries `status` on the FetchPolicyError — reformat
|
|
92
|
-
// into this function's own message shape; a network-level exhaustion
|
|
93
|
-
// (no status) propagates as-is.
|
|
94
|
-
if (err instanceof update_fetch_ts_1.FetchPolicyError && err.status !== undefined) {
|
|
95
|
-
const body = err.bodySnippet ? ` ${err.bodySnippet}` : "";
|
|
96
|
-
throw new Error(`Lazer price fetch failed: ${err.status}${body} (retries exhausted after ${err.attempts} attempts)`, { cause: err });
|
|
97
|
-
}
|
|
98
|
-
throw err;
|
|
101
|
+
(0, update_fetch_ts_1.rethrowExhaustedFetch)(err, (e) => `Lazer price fetch failed: ${e.status}${e.bodySnippet ? ` ${e.bodySnippet}` : ""}`);
|
|
99
102
|
}
|
|
100
103
|
if (!res.ok)
|
|
101
104
|
throw new Error(`Lazer price fetch failed: ${res.status} ${await res.text()}`);
|
|
@@ -16,6 +16,11 @@ function feedPythRule(tx, host, collector, priceInfoObjectId) {
|
|
|
16
16
|
arguments: {
|
|
17
17
|
collector,
|
|
18
18
|
config: tx.object(host.config.packages.pyth_rule.config),
|
|
19
|
+
// The deployed pyth_rule package is compiled against the Core pyth
|
|
20
|
+
// dependency, so its `&PythState` parameter is the Core-package-qualified
|
|
21
|
+
// type and `host.pyth` (the fixed per-network Core infra) is always the
|
|
22
|
+
// right state to pass. The config's price_info_object entries are Core
|
|
23
|
+
// objects to match.
|
|
19
24
|
pythState: tx.object(host.pyth.state_id),
|
|
20
25
|
pythPriceInfo: tx.object(priceInfoObjectId),
|
|
21
26
|
},
|
|
@@ -16,7 +16,11 @@
|
|
|
16
16
|
* `Authorization` header at all). This is the Phase-0 invariant of the
|
|
17
17
|
* Pyth Pro migration: existing keyless deployments see no behavior change.
|
|
18
18
|
* - Retries on network errors, HTTP 429, and HTTP 5xx, with exponential
|
|
19
|
-
* backoff (`retryDelayMs * 2^attempt`, capped at `MAX_BACKOFF_MS`).
|
|
19
|
+
* backoff (`retryDelayMs * 2^attempt`, capped at `MAX_BACKOFF_MS`). A 429
|
|
20
|
+
* carrying a numeric `Retry-After` header uses the SERVER'S delay instead,
|
|
21
|
+
* when it fits under the same cap — a longer ask degrades to normal
|
|
22
|
+
* backoff rather than stalling a money-path build for tens of seconds.
|
|
23
|
+
* Other
|
|
20
24
|
* 4xx statuses (401/400/403/404/…) are NOT retried — auth/bad-request
|
|
21
25
|
* failures are deterministic, so that `Response` (`ok: false`) is handed
|
|
22
26
|
* back on the first attempt for the caller to format its own
|
|
@@ -46,7 +50,7 @@
|
|
|
46
50
|
* - Retry worst case: with the defaults (15s timeout × 3 attempts + ~0.75s of
|
|
47
51
|
* backoff between them) a FULL outage takes up to ~46s to surface as a
|
|
48
52
|
* `FetchPolicyError`, vs ~15s pre-3.2.0's single bare-`fetch` attempt.
|
|
49
|
-
* Tunable per client via `
|
|
53
|
+
* Tunable per client via the `pythFetch` create option (`{timeoutMs,retries}`).
|
|
50
54
|
*/
|
|
51
55
|
export interface FetchPolicy {
|
|
52
56
|
/** Per-attempt timeout (ms). Default 15_000. */
|
|
@@ -75,6 +79,32 @@ export declare class FetchPolicyError extends Error {
|
|
|
75
79
|
attempts: number;
|
|
76
80
|
});
|
|
77
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Rethrow a `catch`-ed {@link fetchWithPolicy} failure. When it is a
|
|
84
|
+
* status-carrying `FetchPolicyError` — a retryable status (429/5xx) that never
|
|
85
|
+
* recovered — throw a new Error `${describe(err)} (retries exhausted after N
|
|
86
|
+
* attempts)` with the original as `cause`; otherwise (a network-level
|
|
87
|
+
* exhaustion with no status, or any non-`FetchPolicyError`) rethrow it verbatim,
|
|
88
|
+
* since there is no domain reframing to add. `describe` builds the
|
|
89
|
+
* status-bearing prefix so each caller keeps its own message shape (the e2e
|
|
90
|
+
* transient detector keys off those prefixes) while the guard, the `retries
|
|
91
|
+
* exhausted` suffix, and the `cause` wrapping live in one place. `: never` so a
|
|
92
|
+
* caller's `catch` block is understood not to fall through.
|
|
93
|
+
*/
|
|
94
|
+
export declare function rethrowExhaustedFetch(err: unknown, describe: (err: FetchPolicyError) => string): never;
|
|
95
|
+
/**
|
|
96
|
+
* Join an API `path` onto an `endpoint` PRESERVING the endpoint's own base
|
|
97
|
+
* path. `new URL(path, endpoint)` is the footgun this replaces: a
|
|
98
|
+
* leading-slash path is *absolute* and silently discards the endpoint's path
|
|
99
|
+
* — harmless for a bare-origin endpoint (`https://hermes.pyth.network`) but
|
|
100
|
+
* it dropped the `/hermes` prefix of the Pyth Pro compat endpoint and 404'd
|
|
101
|
+
* every feed (see `fetchPriceFeedsUpdateData`). Every oracle fetch that
|
|
102
|
+
* targets `<endpoint><fixed path>` must build its URL here.
|
|
103
|
+
*/
|
|
104
|
+
/** One canonical trailing-slash trim — `joinEndpointPath` (URL building) and
|
|
105
|
+
* `pyth.ts`'s `memoKey` (endpoint identity) must never drift apart on it. */
|
|
106
|
+
export declare function trimTrailingSlashes(endpoint: string): string;
|
|
107
|
+
export declare function joinEndpointPath(endpoint: string, path: string): URL;
|
|
78
108
|
/**
|
|
79
109
|
* `fetch` with per-attempt timeout, bounded retry + backoff, and optional
|
|
80
110
|
* Bearer auth. See the module header for the full policy. Both `init.signal`
|
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
* `Authorization` header at all). This is the Phase-0 invariant of the
|
|
18
18
|
* Pyth Pro migration: existing keyless deployments see no behavior change.
|
|
19
19
|
* - Retries on network errors, HTTP 429, and HTTP 5xx, with exponential
|
|
20
|
-
* backoff (`retryDelayMs * 2^attempt`, capped at `MAX_BACKOFF_MS`).
|
|
20
|
+
* backoff (`retryDelayMs * 2^attempt`, capped at `MAX_BACKOFF_MS`). A 429
|
|
21
|
+
* carrying a numeric `Retry-After` header uses the SERVER'S delay instead,
|
|
22
|
+
* when it fits under the same cap — a longer ask degrades to normal
|
|
23
|
+
* backoff rather than stalling a money-path build for tens of seconds.
|
|
24
|
+
* Other
|
|
21
25
|
* 4xx statuses (401/400/403/404/…) are NOT retried — auth/bad-request
|
|
22
26
|
* failures are deterministic, so that `Response` (`ok: false`) is handed
|
|
23
27
|
* back on the first attempt for the caller to format its own
|
|
@@ -47,10 +51,13 @@
|
|
|
47
51
|
* - Retry worst case: with the defaults (15s timeout × 3 attempts + ~0.75s of
|
|
48
52
|
* backoff between them) a FULL outage takes up to ~46s to surface as a
|
|
49
53
|
* `FetchPolicyError`, vs ~15s pre-3.2.0's single bare-`fetch` attempt.
|
|
50
|
-
* Tunable per client via `
|
|
54
|
+
* Tunable per client via the `pythFetch` create option (`{timeoutMs,retries}`).
|
|
51
55
|
*/
|
|
52
56
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
57
|
exports.FetchPolicyError = void 0;
|
|
58
|
+
exports.rethrowExhaustedFetch = rethrowExhaustedFetch;
|
|
59
|
+
exports.trimTrailingSlashes = trimTrailingSlashes;
|
|
60
|
+
exports.joinEndpointPath = joinEndpointPath;
|
|
54
61
|
exports.fetchWithPolicy = fetchWithPolicy;
|
|
55
62
|
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
56
63
|
const DEFAULT_RETRIES = 2;
|
|
@@ -75,12 +82,60 @@ class FetchPolicyError extends Error {
|
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
exports.FetchPolicyError = FetchPolicyError;
|
|
85
|
+
/**
|
|
86
|
+
* Rethrow a `catch`-ed {@link fetchWithPolicy} failure. When it is a
|
|
87
|
+
* status-carrying `FetchPolicyError` — a retryable status (429/5xx) that never
|
|
88
|
+
* recovered — throw a new Error `${describe(err)} (retries exhausted after N
|
|
89
|
+
* attempts)` with the original as `cause`; otherwise (a network-level
|
|
90
|
+
* exhaustion with no status, or any non-`FetchPolicyError`) rethrow it verbatim,
|
|
91
|
+
* since there is no domain reframing to add. `describe` builds the
|
|
92
|
+
* status-bearing prefix so each caller keeps its own message shape (the e2e
|
|
93
|
+
* transient detector keys off those prefixes) while the guard, the `retries
|
|
94
|
+
* exhausted` suffix, and the `cause` wrapping live in one place. `: never` so a
|
|
95
|
+
* caller's `catch` block is understood not to fall through.
|
|
96
|
+
*/
|
|
97
|
+
function rethrowExhaustedFetch(err, describe) {
|
|
98
|
+
if (err instanceof FetchPolicyError && err.status !== undefined) {
|
|
99
|
+
throw new Error(`${describe(err)} (retries exhausted after ${err.attempts} attempts)`, {
|
|
100
|
+
cause: err,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
throw err;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Join an API `path` onto an `endpoint` PRESERVING the endpoint's own base
|
|
107
|
+
* path. `new URL(path, endpoint)` is the footgun this replaces: a
|
|
108
|
+
* leading-slash path is *absolute* and silently discards the endpoint's path
|
|
109
|
+
* — harmless for a bare-origin endpoint (`https://hermes.pyth.network`) but
|
|
110
|
+
* it dropped the `/hermes` prefix of the Pyth Pro compat endpoint and 404'd
|
|
111
|
+
* every feed (see `fetchPriceFeedsUpdateData`). Every oracle fetch that
|
|
112
|
+
* targets `<endpoint><fixed path>` must build its URL here.
|
|
113
|
+
*/
|
|
114
|
+
/** One canonical trailing-slash trim — `joinEndpointPath` (URL building) and
|
|
115
|
+
* `pyth.ts`'s `memoKey` (endpoint identity) must never drift apart on it. */
|
|
116
|
+
function trimTrailingSlashes(endpoint) {
|
|
117
|
+
return endpoint.replace(/\/+$/, "");
|
|
118
|
+
}
|
|
119
|
+
function joinEndpointPath(endpoint, path) {
|
|
120
|
+
return new URL(`${trimTrailingSlashes(endpoint)}/${path.replace(/^\/+/, "")}`);
|
|
121
|
+
}
|
|
78
122
|
function isRetryableStatus(status) {
|
|
79
123
|
return status === 429 || status >= 500;
|
|
80
124
|
}
|
|
81
125
|
function backoffMs(retryDelayMs, attempt) {
|
|
82
126
|
return Math.min(retryDelayMs * 2 ** attempt, MAX_BACKOFF_MS);
|
|
83
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* The server's own `Retry-After` (numeric-seconds form only), when present
|
|
130
|
+
* and within `MAX_BACKOFF_MS` — `undefined` otherwise (absent, HTTP-date
|
|
131
|
+
* form, zero/garbage, or an ask too long to honor inside a build path).
|
|
132
|
+
*/
|
|
133
|
+
function retryAfterMs(response) {
|
|
134
|
+
// Optional-chained: minimal test doubles (and some fetch shims) carry no
|
|
135
|
+
// `headers` — a missing header must read as "no hint", never throw.
|
|
136
|
+
const ms = Number(response.headers?.get?.("retry-after")) * 1_000;
|
|
137
|
+
return ms > 0 && ms <= MAX_BACKOFF_MS ? ms : undefined;
|
|
138
|
+
}
|
|
84
139
|
/** `host + pathname` only — never the query string (feed ids are noise, not diagnostic). */
|
|
85
140
|
function describeTarget(url) {
|
|
86
141
|
const parsed = new URL(url);
|
|
@@ -187,11 +242,13 @@ async function fetchWithPolicy(url, init = {}, policy = {}, externalSignal) {
|
|
|
187
242
|
let status;
|
|
188
243
|
let bodySnippet;
|
|
189
244
|
let cause;
|
|
245
|
+
let serverRetryDelay;
|
|
190
246
|
try {
|
|
191
247
|
const response = await doFetch(url, { ...init, headers, signal });
|
|
192
248
|
if (response.ok || !isRetryableStatus(response.status))
|
|
193
249
|
return response;
|
|
194
250
|
status = response.status;
|
|
251
|
+
serverRetryDelay = retryAfterMs(response);
|
|
195
252
|
if (attempt === retries) {
|
|
196
253
|
bodySnippet = await readBodySnippet(response);
|
|
197
254
|
}
|
|
@@ -218,7 +275,7 @@ async function fetchWithPolicy(url, init = {}, policy = {}, externalSignal) {
|
|
|
218
275
|
const detail = statusDetail ?? causeMessage(cause);
|
|
219
276
|
throw new FetchPolicyError(`fetchWithPolicy: ${describeTarget(url)} failed after ${attempt + 1} attempt(s) — ${detail}`, { status, bodySnippet, cause, attempts: attempt + 1 });
|
|
220
277
|
}
|
|
221
|
-
await sleep(backoffMs(retryDelayMs, attempt), combinedExternalSignal);
|
|
278
|
+
await sleep(serverRetryDelay ?? backoffMs(retryDelayMs, attempt), combinedExternalSignal);
|
|
222
279
|
}
|
|
223
280
|
// Unreachable: the loop above always returns or throws on its final
|
|
224
281
|
// (attempt === retries) iteration — this satisfies the compiler only.
|
|
@@ -12,44 +12,58 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { BaseLineClient } from "../base-client.ts";
|
|
14
14
|
import type { OracleSource } from "../oracle/price-update-rule.ts";
|
|
15
|
-
import { type LoadConfigOptions, type
|
|
15
|
+
import { type LoadConfigOptions, type PythFetchPolicy, type PythInfraConfig, type WaterXConfig, type WormholeInfraConfig } from "./config.ts";
|
|
16
16
|
import type { Network } from "./constants.ts";
|
|
17
17
|
export interface CreateClientOptions extends LoadConfigOptions {
|
|
18
18
|
grpcUrl?: string;
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
20
|
+
* Which oracle price-update source drives `refreshOraclePrices`. Each source
|
|
21
|
+
* is self-contained (own infra + config) with NO cross-source fallback:
|
|
22
|
+
*
|
|
23
|
+
* - `'pyth_rule'` (default) — Pyth Core `pyth_rule` updates (Hermes VAA +
|
|
24
|
+
* per-feed update fees), Core state + keyless Core Hermes.
|
|
25
|
+
* - `'pyth_lazer_rule'` — Pyth Lazer signed updates (ONE `leEcdsa` verify
|
|
26
|
+
* per PTB, no per-feed fees); needs `packages.pyth_lazer_rule` with feeds
|
|
27
|
+
* and a `pythApiKey` (Lazer is auth-first).
|
|
28
|
+
*
|
|
29
|
+
* A source-neutral name on purpose — a future source need not be Pyth.
|
|
30
|
+
* Selecting a source whose feed for a requested ticker is absent is NOT an
|
|
31
|
+
* error at client creation: it fails at tx-build time for exactly those
|
|
32
|
+
* tickers (see `refreshOraclePrices`). The Pyth Core infra is fixed per
|
|
33
|
+
* network by `PYTH_DEFAULTS` and is not deployment-overridable.
|
|
24
34
|
*/
|
|
25
35
|
oracleSource?: OracleSource;
|
|
26
36
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* `
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* always wins wholesale (see `PythGeneration`).
|
|
37
|
+
* Pyth Lazer access token (`Authorization: Bearer …`). Required under
|
|
38
|
+
* `oracleSource: 'pyth_lazer_rule'` (Lazer is auth-first) and unused by
|
|
39
|
+
* `'pyth_rule'` (keyless Core Hermes). This is a SECRET and never belongs in
|
|
40
|
+
* the canonical `waterx-config` JSON — pass it at client init from your own
|
|
41
|
+
* env var (e.g. `PYTH_API_KEY`); the SDK never reads `process.env`.
|
|
33
42
|
*/
|
|
34
|
-
|
|
43
|
+
pythApiKey?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Retry/timeout policy for the off-chain Hermes / Lazer update fetches (see
|
|
46
|
+
* `fetchWithPolicy`). Optional — defaults to 15s timeout, 2 retries.
|
|
47
|
+
*/
|
|
48
|
+
pythFetch?: PythFetchPolicy;
|
|
35
49
|
}
|
|
36
50
|
export declare class PerpClient extends BaseLineClient<WaterXConfig> {
|
|
37
|
-
/** Pyth infra (network
|
|
51
|
+
/** Pyth Core infra (fixed per network) plus the caller-supplied credential/policy. */
|
|
38
52
|
pyth: PythInfraConfig;
|
|
39
53
|
/** Wormhole infra for the credit bridge (network defaults unless overridden). */
|
|
40
54
|
wormhole: WormholeInfraConfig;
|
|
41
|
-
/** Selected oracle
|
|
55
|
+
/** Selected oracle price-update source (`oracleSource` create option; default `'pyth_rule'`). */
|
|
42
56
|
readonly oracleSource: OracleSource;
|
|
43
57
|
/** Canonical-schema lookups (delegated to below); no transport. */
|
|
44
58
|
private readonly view;
|
|
45
|
-
constructor(network: Network, config: WaterXConfig, opts?:
|
|
46
|
-
grpcUrl?: string;
|
|
47
|
-
oracleSource?: OracleSource;
|
|
48
|
-
pythGeneration?: PythGeneration;
|
|
49
|
-
});
|
|
59
|
+
constructor(network: Network, config: WaterXConfig, opts?: CreateClientOptions);
|
|
50
60
|
/**
|
|
51
61
|
* Async factory: fetches the deployment config for `network` and returns
|
|
52
62
|
* a ready-to-use client. Pass `opts.cache=true` to memoize the JSON.
|
|
63
|
+
*
|
|
64
|
+
* No oracle-config guard here: selecting a source whose feeds are absent is
|
|
65
|
+
* not an error at init — it surfaces at tx-build time for the specific
|
|
66
|
+
* tickers that source can't serve (see `refreshOraclePrices`).
|
|
53
67
|
*/
|
|
54
68
|
static create(network: Network, opts?: CreateClientOptions): Promise<PerpClient>;
|
|
55
69
|
static mainnet(opts?: CreateClientOptions): Promise<PerpClient>;
|
|
@@ -17,19 +17,25 @@ const base_client_ts_1 = require("../base-client.js");
|
|
|
17
17
|
const config_view_ts_1 = require("./config-view.js");
|
|
18
18
|
const config_ts_1 = require("./config.js");
|
|
19
19
|
class PerpClient extends base_client_ts_1.BaseLineClient {
|
|
20
|
-
/** Pyth infra (network
|
|
20
|
+
/** Pyth Core infra (fixed per network) plus the caller-supplied credential/policy. */
|
|
21
21
|
pyth;
|
|
22
22
|
/** Wormhole infra for the credit bridge (network defaults unless overridden). */
|
|
23
23
|
wormhole;
|
|
24
|
-
/** Selected oracle
|
|
24
|
+
/** Selected oracle price-update source (`oracleSource` create option; default `'pyth_rule'`). */
|
|
25
25
|
oracleSource;
|
|
26
26
|
/** Canonical-schema lookups (delegated to below); no transport. */
|
|
27
27
|
view;
|
|
28
28
|
constructor(network, config, opts = {}) {
|
|
29
29
|
super(network, config, opts);
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
// Pyth Core infra is fixed per network — NOT deployment-overridable and
|
|
31
|
+
// NOT source-dependent (the pyth_lazer_rule source reads only api_key/fetch
|
|
32
|
+
// from here). The api_key + fetch policy are caller-supplied at init: a
|
|
33
|
+
// secret has no place in the canonical waterx-config JSON.
|
|
34
|
+
this.pyth = {
|
|
35
|
+
...config_ts_1.PYTH_DEFAULTS[network],
|
|
36
|
+
...(opts.pythApiKey !== undefined ? { api_key: opts.pythApiKey } : {}),
|
|
37
|
+
...(opts.pythFetch !== undefined ? { fetch: opts.pythFetch } : {}),
|
|
38
|
+
};
|
|
33
39
|
this.wormhole = config.wormhole ?? config_ts_1.WORMHOLE_DEFAULTS[network];
|
|
34
40
|
this.oracleSource = opts.oracleSource ?? "pyth_rule";
|
|
35
41
|
this.view = new config_view_ts_1.PerpConfigView(() => this.config, () => this.wormhole);
|
|
@@ -37,14 +43,14 @@ class PerpClient extends base_client_ts_1.BaseLineClient {
|
|
|
37
43
|
/**
|
|
38
44
|
* Async factory: fetches the deployment config for `network` and returns
|
|
39
45
|
* a ready-to-use client. Pass `opts.cache=true` to memoize the JSON.
|
|
46
|
+
*
|
|
47
|
+
* No oracle-config guard here: selecting a source whose feeds are absent is
|
|
48
|
+
* not an error at init — it surfaces at tx-build time for the specific
|
|
49
|
+
* tickers that source can't serve (see `refreshOraclePrices`).
|
|
40
50
|
*/
|
|
41
51
|
static async create(network, opts = {}) {
|
|
42
52
|
const config = await (0, config_ts_1.loadConfig)(network, opts);
|
|
43
|
-
return new PerpClient(network, config,
|
|
44
|
-
grpcUrl: opts.grpcUrl,
|
|
45
|
-
oracleSource: opts.oracleSource,
|
|
46
|
-
pythGeneration: opts.pythGeneration,
|
|
47
|
-
});
|
|
53
|
+
return new PerpClient(network, config, opts);
|
|
48
54
|
}
|
|
49
55
|
static mainnet(opts = {}) {
|
|
50
56
|
return PerpClient.create("MAINNET", opts);
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
* below, keyed by network.
|
|
10
10
|
*/
|
|
11
11
|
import type { AccountPackages, BasePackageEntry, WormholeInfraConfig } from "../account/config.ts";
|
|
12
|
-
import type { OraclePackages
|
|
12
|
+
import type { OraclePackages } from "../oracle/config.ts";
|
|
13
13
|
import type { Network } from "./constants.ts";
|
|
14
|
-
export type { AccountConfig, AccountPackages, BasePackageEntry, NativeCustodyAsset, NativeCustodyPackage,
|
|
15
|
-
export type { ConstantFeedEntry, OracleConfig, OraclePackages,
|
|
16
|
-
export { PYTH_DEFAULTS
|
|
14
|
+
export type { AccountConfig, AccountPackages, BasePackageEntry, NativeCustodyAsset, NativeCustodyPackage, WaterxCreditPackage, WaterxReferralPackage, WithdrawalQueuePackage, WormholeBridgePackage, WormholeInfraConfig, WxaAccountPackage, } from "../account/config.ts";
|
|
15
|
+
export type { ConstantFeedEntry, OracleConfig, OraclePackages, PythFetchPolicy, PythInfraConfig, PythLazerRulePackage, PythRulePackage, PythSponsorRulePackage, SupraFeedEntry, SupraRulePackage, WaterxConstantRulePackage, WaterxOraclePackage, } from "../oracle/config.ts";
|
|
16
|
+
export { PYTH_DEFAULTS } from "../oracle/config.ts";
|
|
17
17
|
export interface WaterxPerpMarketEntry {
|
|
18
18
|
market: string;
|
|
19
19
|
config: string;
|
|
@@ -82,8 +82,6 @@ export interface WaterXConfig {
|
|
|
82
82
|
/** Sui gRPC base URL (default: public Mysten fullnode for the network). */
|
|
83
83
|
grpcUrl?: string;
|
|
84
84
|
packages: WaterXPackages;
|
|
85
|
-
/** Pyth infra override (defaults from `PYTH_DEFAULTS[network]`). */
|
|
86
|
-
pyth?: PythInfraConfig;
|
|
87
85
|
/** Wormhole infra override (defaults from `WORMHOLE_DEFAULTS[network]`). */
|
|
88
86
|
wormhole?: WormholeInfraConfig;
|
|
89
87
|
/** Sui `CoinRegistry` shared object (credit deployments). */
|
|
@@ -10,13 +10,12 @@
|
|
|
10
10
|
* below, keyed by network.
|
|
11
11
|
*/
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.WORMHOLE_DEFAULTS = exports.
|
|
13
|
+
exports.WORMHOLE_DEFAULTS = exports.PYTH_DEFAULTS = void 0;
|
|
14
14
|
exports.clearConfigCache = clearConfigCache;
|
|
15
15
|
exports.loadConfig = loadConfig;
|
|
16
16
|
const update_fetch_ts_1 = require("../oracle/update-fetch.js");
|
|
17
17
|
var config_ts_1 = require("../oracle/config.js");
|
|
18
18
|
Object.defineProperty(exports, "PYTH_DEFAULTS", { enumerable: true, get: function () { return config_ts_1.PYTH_DEFAULTS; } });
|
|
19
|
-
Object.defineProperty(exports, "PYTH_PRO_DEFAULTS", { enumerable: true, get: function () { return config_ts_1.PYTH_PRO_DEFAULTS; } });
|
|
20
19
|
// ============================================================================
|
|
21
20
|
// Wormhole / Hermes — external chain infra, defaults by network
|
|
22
21
|
// ============================================================================
|
|
@@ -120,16 +119,13 @@ async function loadConfig(network, opts = {}) {
|
|
|
120
119
|
const stale = configCache.get(cacheKey);
|
|
121
120
|
if (stale)
|
|
122
121
|
return stale;
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
// the
|
|
126
|
-
// exhaustion (no status), a `!response.ok` throw, or a JSON
|
|
127
|
-
// `validateConfig` failure has no
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
throw new Error(`loadConfig: HTTP ${err.status} fetching ${url} (retries exhausted after ${err.attempts} attempts)`, { cause: err });
|
|
131
|
-
}
|
|
132
|
-
throw err;
|
|
122
|
+
// Reframe a status-carrying FetchPolicyError into this function's own
|
|
123
|
+
// message shape, mirroring the non-retried `!response.ok` throw above and
|
|
124
|
+
// carrying the URL (the key datum for a config-fetch failure). A
|
|
125
|
+
// network-level exhaustion (no status), a `!response.ok` throw, or a JSON
|
|
126
|
+
// parse / `validateConfig` failure has no reframing to add — the helper
|
|
127
|
+
// propagates those verbatim.
|
|
128
|
+
(0, update_fetch_ts_1.rethrowExhaustedFetch)(err, (e) => `loadConfig: HTTP ${e.status} fetching ${url}`);
|
|
133
129
|
}
|
|
134
130
|
configCache.set(cacheKey, raw);
|
|
135
131
|
return raw;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { PerpClient } from "./client.ts";
|
|
2
2
|
export type { CreateClientOptions } from "./client.ts";
|
|
3
|
-
export { PYTH_DEFAULTS,
|
|
4
|
-
export type { BasePackageEntry, ConstantFeedEntry, WaterxReferralPackage, LoadConfigOptions, NativeCustodyAsset, NativeCustodyPackage,
|
|
3
|
+
export { PYTH_DEFAULTS, WORMHOLE_DEFAULTS, clearConfigCache, loadConfig } from "./config.ts";
|
|
4
|
+
export type { BasePackageEntry, ConstantFeedEntry, WaterxReferralPackage, LoadConfigOptions, NativeCustodyAsset, NativeCustodyPackage, PythFetchPolicy, PythInfraConfig, PythLazerRulePackage, PythRulePackage, PythSponsorRulePackage, SupraFeedEntry, SupraRulePackage, TestnetFaucetPackage, WaterXConfig, WaterXPackages, WaterxCreditPackage, WaterxOraclePackage, WaterxPerpMarketEntry, WaterxPerpPackage, WaterxStakingPackage, WithdrawalQueuePackage, WlpPackage, WormholeBridgePackage, WormholeInfraConfig, WxaAccountPackage, } from "./config.ts";
|
|
5
5
|
export { ACTION_ADD_PRE_ORDER, ACTION_CANCEL_ORDER, ACTION_CANCEL_PRE_ORDER, ACTION_CLOSE_POSITION, ACTION_DECREASE_POSITION, ACTION_DEPOSIT_COLLATERAL, ACTION_INCREASE_POSITION, ACTION_LIQUIDATE, ACTION_OPEN_POSITION, ACTION_PLACE_ORDER, ACTION_UPDATE_ORDER, ACTION_WITHDRAW_COLLATERAL, BPS_SCALE, CRYPTO_FEE_RATE, DOUBLE_SCALE, DRY_RUN_SENDER, FLOAT_SCALE, MAINTENANCE_MARGIN_RATE, ORDER_LIMIT_BUY, ORDER_LIMIT_SELL, ORDER_STOP_BUY, ORDER_STOP_SELL, ORDER_TAG_WILDCARD, PERM_ALL, PERM_ALL_TRADING, PERM_CANCEL_ORDER, PERM_CLOSE_POSITION, PERM_DECREASE_POSITION, PERM_DEPOSIT_COLLATERAL, PERM_INCREASE_POSITION, PERM_MINT_WLP, PERM_OPEN_POSITION, PERM_PLACE_ORDER, PERM_REDEEM_WLP, PERM_WITHDRAW_COLLATERAL, STAKING_PERM_DEPOSIT_STAKE, STAKING_PERM_REDEEM_STAKE, STAKING_PERM_CLAIM_REWARD, STAKING_PERM_ALL, STOCK_FEE_RATE, MS_PER_YEAR, SUI_DECIMALS, WLP_DECIMALS, COLLATERAL_DECIMALS, TOKEN_DECIMALS, } from "./constants.ts";
|
|
6
6
|
export type { Network } from "./constants.ts";
|
|
7
7
|
export { getMarketTickers, getCollateralAssets } from "../utils/config.ts";
|
|
@@ -36,15 +36,14 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.COLLATERAL_DECIMALS = exports.WLP_DECIMALS = exports.SUI_DECIMALS = exports.MS_PER_YEAR = exports.STOCK_FEE_RATE = exports.STAKING_PERM_ALL = exports.STAKING_PERM_CLAIM_REWARD = exports.STAKING_PERM_REDEEM_STAKE = exports.STAKING_PERM_DEPOSIT_STAKE = exports.PERM_WITHDRAW_COLLATERAL = exports.PERM_REDEEM_WLP = exports.PERM_PLACE_ORDER = exports.PERM_OPEN_POSITION = exports.PERM_MINT_WLP = exports.PERM_INCREASE_POSITION = exports.PERM_DEPOSIT_COLLATERAL = exports.PERM_DECREASE_POSITION = exports.PERM_CLOSE_POSITION = exports.PERM_CANCEL_ORDER = exports.PERM_ALL_TRADING = exports.PERM_ALL = exports.ORDER_TAG_WILDCARD = exports.ORDER_STOP_SELL = exports.ORDER_STOP_BUY = exports.ORDER_LIMIT_SELL = exports.ORDER_LIMIT_BUY = exports.MAINTENANCE_MARGIN_RATE = exports.FLOAT_SCALE = exports.DRY_RUN_SENDER = exports.DOUBLE_SCALE = exports.CRYPTO_FEE_RATE = exports.BPS_SCALE = exports.ACTION_WITHDRAW_COLLATERAL = exports.ACTION_UPDATE_ORDER = exports.ACTION_PLACE_ORDER = exports.ACTION_OPEN_POSITION = exports.ACTION_LIQUIDATE = exports.ACTION_INCREASE_POSITION = exports.ACTION_DEPOSIT_COLLATERAL = exports.ACTION_DECREASE_POSITION = exports.ACTION_CLOSE_POSITION = exports.ACTION_CANCEL_PRE_ORDER = exports.ACTION_CANCEL_ORDER = exports.ACTION_ADD_PRE_ORDER = exports.loadConfig = exports.clearConfigCache = exports.WORMHOLE_DEFAULTS = exports.
|
|
40
|
-
exports.AccountDataBcs = exports.waitForVaa = exports.vaaBytesToBase64 = exports.vaaBase64ToHex = exports.vaaBase64ToBytes = exports.toWormholescanEmitter = exports.padEvmEmitter = exports.listVaasByEmitter = exports.listBridgeWithdrawalVaas = exports.fetchVaa = exports.fetchDepositVaa = exports.updatePythPrices = exports.refreshOraclePrices = exports.fetchPriceFeedsUpdateData = exports.buildPythPriceUpdateCalls = exports.aggregateTickerWithPyth = exports.aggregateTickerWithConstant = exports.aggregateTicker = exports.PythCache = exports.OracleSourceNotImplementedError = exports.OracleFeeSourceUnavailableError = exports.LazerApiKeyMissingError = exports.FetchPolicyError = exports.rawPrice = exports.decodeFundingIndexDelta = exports.calcWlpRedeemOut = exports.calcWlpPrice = exports.calcWlpMintOut = exports.calcWlpIncentiveApy = exports.calcUnrealizedPnl = exports.calcTotalTradingFeeRate = exports.calcTokenUtilizationBps = exports.calcPositionBorrowFee = exports.calcNotional = exports.calcMaxReducibleCollateralUsd = exports.calcLeverage = exports.calcImpactFeeRate = exports.calcFundingRate = exports.calcFundingFeeUsd = exports.calcFee = exports.calcEstLiqPrice = exports.calcEffectiveCollateralUsd = exports.calcDynamicFeeBps = exports.calcBorrowRateAccrual = exports.calcBorrowRate = exports.annualizeFundingRate = exports.annualizedApyFromRatio = exports.getCollateralAssets = exports.getMarketTickers =
|
|
41
|
-
exports.withdrawalQueueCalls = exports.nativeCustodyCalls = exports.referralCalls = exports.pythSponsorRuleCalls = exports.pythRuleCalls = exports.oracleCalls = exports.stakingCalls = exports.wxaAccountCalls = exports.viewCalls = exports.lpPoolCalls = exports.tradingCalls = exports.MarketConfigBcs = exports.MarketBcs = exports.OrderBcs = exports.PositionBcs = exports.TokenPoolDataBcs = exports.RedeemRequestDataBcs = exports.PositionDataBcs = exports.PoolDataBcs = exports.OrderDataBcs = exports.MarketDataBcs =
|
|
39
|
+
exports.TOKEN_DECIMALS = exports.COLLATERAL_DECIMALS = exports.WLP_DECIMALS = exports.SUI_DECIMALS = exports.MS_PER_YEAR = exports.STOCK_FEE_RATE = exports.STAKING_PERM_ALL = exports.STAKING_PERM_CLAIM_REWARD = exports.STAKING_PERM_REDEEM_STAKE = exports.STAKING_PERM_DEPOSIT_STAKE = exports.PERM_WITHDRAW_COLLATERAL = exports.PERM_REDEEM_WLP = exports.PERM_PLACE_ORDER = exports.PERM_OPEN_POSITION = exports.PERM_MINT_WLP = exports.PERM_INCREASE_POSITION = exports.PERM_DEPOSIT_COLLATERAL = exports.PERM_DECREASE_POSITION = exports.PERM_CLOSE_POSITION = exports.PERM_CANCEL_ORDER = exports.PERM_ALL_TRADING = exports.PERM_ALL = exports.ORDER_TAG_WILDCARD = exports.ORDER_STOP_SELL = exports.ORDER_STOP_BUY = exports.ORDER_LIMIT_SELL = exports.ORDER_LIMIT_BUY = exports.MAINTENANCE_MARGIN_RATE = exports.FLOAT_SCALE = exports.DRY_RUN_SENDER = exports.DOUBLE_SCALE = exports.CRYPTO_FEE_RATE = exports.BPS_SCALE = exports.ACTION_WITHDRAW_COLLATERAL = exports.ACTION_UPDATE_ORDER = exports.ACTION_PLACE_ORDER = exports.ACTION_OPEN_POSITION = exports.ACTION_LIQUIDATE = exports.ACTION_INCREASE_POSITION = exports.ACTION_DEPOSIT_COLLATERAL = exports.ACTION_DECREASE_POSITION = exports.ACTION_CLOSE_POSITION = exports.ACTION_CANCEL_PRE_ORDER = exports.ACTION_CANCEL_ORDER = exports.ACTION_ADD_PRE_ORDER = exports.loadConfig = exports.clearConfigCache = exports.WORMHOLE_DEFAULTS = exports.PYTH_DEFAULTS = exports.PerpClient = void 0;
|
|
40
|
+
exports.GlobalConfigDataBcs = exports.AccountDataBcs = exports.waitForVaa = exports.vaaBytesToBase64 = exports.vaaBase64ToHex = exports.vaaBase64ToBytes = exports.toWormholescanEmitter = exports.padEvmEmitter = exports.listVaasByEmitter = exports.listBridgeWithdrawalVaas = exports.fetchVaa = exports.fetchDepositVaa = exports.updatePythPrices = exports.refreshOraclePrices = exports.fetchPriceFeedsUpdateData = exports.buildPythPriceUpdateCalls = exports.aggregateTickerWithPyth = exports.aggregateTickerWithConstant = exports.aggregateTicker = exports.PythCache = exports.OracleSourceNotImplementedError = exports.OracleFeeSourceUnavailableError = exports.LazerApiKeyMissingError = exports.FetchPolicyError = exports.rawPrice = exports.decodeFundingIndexDelta = exports.calcWlpRedeemOut = exports.calcWlpPrice = exports.calcWlpMintOut = exports.calcWlpIncentiveApy = exports.calcUnrealizedPnl = exports.calcTotalTradingFeeRate = exports.calcTokenUtilizationBps = exports.calcPositionBorrowFee = exports.calcNotional = exports.calcMaxReducibleCollateralUsd = exports.calcLeverage = exports.calcImpactFeeRate = exports.calcFundingRate = exports.calcFundingFeeUsd = exports.calcFee = exports.calcEstLiqPrice = exports.calcEffectiveCollateralUsd = exports.calcDynamicFeeBps = exports.calcBorrowRateAccrual = exports.calcBorrowRate = exports.annualizeFundingRate = exports.annualizedApyFromRatio = exports.getCollateralAssets = exports.getMarketTickers = void 0;
|
|
41
|
+
exports.withdrawalQueueCalls = exports.nativeCustodyCalls = exports.referralCalls = exports.pythSponsorRuleCalls = exports.pythRuleCalls = exports.oracleCalls = exports.stakingCalls = exports.wxaAccountCalls = exports.viewCalls = exports.lpPoolCalls = exports.tradingCalls = exports.MarketConfigBcs = exports.MarketBcs = exports.OrderBcs = exports.PositionBcs = exports.TokenPoolDataBcs = exports.RedeemRequestDataBcs = exports.PositionDataBcs = exports.PoolDataBcs = exports.OrderDataBcs = exports.MarketDataBcs = void 0;
|
|
42
42
|
// ======== Core ========
|
|
43
43
|
var client_ts_1 = require("./client.js");
|
|
44
44
|
Object.defineProperty(exports, "PerpClient", { enumerable: true, get: function () { return client_ts_1.PerpClient; } });
|
|
45
45
|
var config_ts_1 = require("./config.js");
|
|
46
46
|
Object.defineProperty(exports, "PYTH_DEFAULTS", { enumerable: true, get: function () { return config_ts_1.PYTH_DEFAULTS; } });
|
|
47
|
-
Object.defineProperty(exports, "PYTH_PRO_DEFAULTS", { enumerable: true, get: function () { return config_ts_1.PYTH_PRO_DEFAULTS; } });
|
|
48
47
|
Object.defineProperty(exports, "WORMHOLE_DEFAULTS", { enumerable: true, get: function () { return config_ts_1.WORMHOLE_DEFAULTS; } });
|
|
49
48
|
Object.defineProperty(exports, "clearConfigCache", { enumerable: true, get: function () { return config_ts_1.clearConfigCache; } });
|
|
50
49
|
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_ts_1.loadConfig; } });
|
|
@@ -32,7 +32,7 @@ import { Transaction } from "@mysten/sui/transactions";
|
|
|
32
32
|
import * as accountOps from "./account/index.ts";
|
|
33
33
|
import * as perpReferral from "./account/referral.ts";
|
|
34
34
|
import type { Network } from "./constants.ts";
|
|
35
|
-
import type {
|
|
35
|
+
import type { PythFetchPolicy } from "./oracle/config.ts";
|
|
36
36
|
import type { OracleSource } from "./oracle/price-update-rule.ts";
|
|
37
37
|
import { PerpClient, type CreateClientOptions as PerpCreateOptions } from "./perp/client.ts";
|
|
38
38
|
import * as perpFetch from "./perp/fetch.ts";
|
|
@@ -366,20 +366,28 @@ export interface ClientCreateOptions {
|
|
|
366
366
|
/** Memoize the fetched config JSON. */
|
|
367
367
|
cache?: boolean;
|
|
368
368
|
/**
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
369
|
+
* The perp line's oracle price-update source (perp-line only — the
|
|
370
|
+
* prediction line has no oracle leg), forwarded to `PerpClient.create`.
|
|
371
|
+
* Source-neutral by design: a future source need not be Pyth.
|
|
372
|
+
*
|
|
373
|
+
* - `'pyth_rule'` (default) — Pyth Core updates on Core infra.
|
|
374
|
+
* - `'pyth_lazer_rule'` — Pyth Lazer signed updates (pair with `pythApiKey`
|
|
375
|
+
* and a config carrying `packages.pyth_lazer_rule`).
|
|
376
|
+
*
|
|
377
|
+
* Each source is self-contained with no cross-source fallback; selecting a
|
|
378
|
+
* source whose feed for a ticker is absent fails at tx-build (not at init).
|
|
379
|
+
* See perp `CreateClientOptions.oracleSource` for the full note.
|
|
373
380
|
*/
|
|
374
381
|
oracleSource?: OracleSource;
|
|
375
382
|
/**
|
|
376
|
-
*
|
|
377
|
-
* `
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
* See `PythGeneration` / `PYTH_PRO_DEFAULTS`.
|
|
383
|
+
* Pyth Lazer access token, forwarded to the perp line. Required under
|
|
384
|
+
* `oracleSource: 'pyth_lazer_rule'`, unused by `'pyth_rule'`. A SECRET —
|
|
385
|
+
* pass it at init from your own env var; it is never read from the config
|
|
386
|
+
* JSON or `process.env`.
|
|
381
387
|
*/
|
|
382
|
-
|
|
388
|
+
pythApiKey?: string;
|
|
389
|
+
/** Retry/timeout policy for the perp line's off-chain oracle fetches. */
|
|
390
|
+
pythFetch?: PythFetchPolicy;
|
|
383
391
|
/** Perp-line overrides (network, grpcUrl, waterxConfigUrl, cache, …). */
|
|
384
392
|
perp?: PerpLineOptions;
|
|
385
393
|
/** Prediction-line overrides (network, grpcUrl, waterxConfigUrl, cache, settlement, …). */
|
|
@@ -205,7 +205,8 @@ class WaterXClient {
|
|
|
205
205
|
waterxConfigUrl: opts.waterxConfigUrl,
|
|
206
206
|
cache: opts.cache,
|
|
207
207
|
oracleSource: opts.oracleSource,
|
|
208
|
-
|
|
208
|
+
pythApiKey: opts.pythApiKey,
|
|
209
|
+
pythFetch: opts.pythFetch,
|
|
209
210
|
...perpRest,
|
|
210
211
|
});
|
|
211
212
|
const predictClient = await client_ts_2.PredictClient.create(resolvedPredictNetwork, {
|
|
@@ -48,28 +48,12 @@ export interface NativeCustodyPackage {
|
|
|
48
48
|
/** Backing assets registered via `add_asset` (array, identified by `type`). */
|
|
49
49
|
assets: NativeCustodyAsset[];
|
|
50
50
|
}
|
|
51
|
-
export interface TrustedEmitterRow {
|
|
52
|
-
/** Source EVM chain's Wormhole chain id (e.g. 10002 = Sepolia). */
|
|
53
|
-
chain_id: number;
|
|
54
|
-
/** 32-byte left-padded EVM bridge address (0x form). */
|
|
55
|
-
evm_bridge_address_32b: string;
|
|
56
|
-
/** Whitelisted 20-byte EVM token addresses (0x form). */
|
|
57
|
-
evm_tokens_20b: string[];
|
|
58
|
-
}
|
|
59
51
|
export interface WormholeBridgePackage {
|
|
60
52
|
published_at: string;
|
|
61
53
|
/** Shared Sui Wormhole `State` object id for this deployment. */
|
|
62
54
|
wormhole_state: string;
|
|
63
|
-
hourly_mint_limit?: string;
|
|
64
55
|
max_mint_per_tx?: string;
|
|
65
|
-
hourly_burn_limit?: string;
|
|
66
56
|
max_burn_per_tx?: string;
|
|
67
|
-
/**
|
|
68
|
-
* @deprecated EVM emitter↔token config now lives solely under `evm.bridge.chains`
|
|
69
|
-
* (deposit_vault = emitter, wormhole_chain_id = chain key). The runtime allowlist is
|
|
70
|
-
* read from the on-chain `Bridge` object, not from config. Kept optional for back-compat.
|
|
71
|
-
*/
|
|
72
|
-
trusted_emitters?: TrustedEmitterRow[];
|
|
73
57
|
/** Shared `Bridge` (phase-5 output). */
|
|
74
58
|
bridge?: string;
|
|
75
59
|
/**
|