@waterx/sdk 4.1.0 → 4.3.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 +29 -19
- package/dist/cjs/src/account/config.d.ts +3 -2
- package/dist/cjs/src/generated/waterx_rule/waterx_rule.d.ts +7 -134
- package/dist/cjs/src/generated/waterx_rule/waterx_rule.js +8 -154
- package/dist/cjs/src/oracle/aggregate.d.ts +21 -21
- package/dist/cjs/src/oracle/aggregate.js +121 -71
- package/dist/cjs/src/oracle/config.d.ts +38 -72
- package/dist/cjs/src/oracle/config.js +0 -56
- package/dist/cjs/src/oracle/host.d.ts +24 -20
- package/dist/cjs/src/oracle/index.d.ts +7 -3
- package/dist/cjs/src/oracle/index.js +41 -8
- package/dist/cjs/src/oracle/price-update-rule.d.ts +32 -11
- package/dist/cjs/src/oracle/price-update-rule.js +23 -3
- package/dist/cjs/src/oracle/pyth.d.ts +44 -0
- package/dist/cjs/src/oracle/pyth.js +48 -6
- package/dist/cjs/src/oracle/read-plane.d.ts +70 -0
- package/dist/cjs/src/oracle/read-plane.js +85 -0
- package/dist/cjs/src/oracle/rule-registry.d.ts +6 -4
- package/dist/cjs/src/oracle/rule-registry.js +6 -4
- package/dist/cjs/src/oracle/rules/pyth-core-rule.js +6 -5
- package/dist/cjs/src/oracle/rules/pyth-lazer-rule.d.ts +21 -0
- package/dist/cjs/src/oracle/rules/pyth-lazer-rule.js +34 -6
- package/dist/cjs/src/oracle/rules/pyth-rule.js +5 -4
- package/dist/cjs/src/oracle/rules/waterx-rule.d.ts +42 -5
- package/dist/cjs/src/oracle/rules/waterx-rule.js +61 -18
- package/dist/cjs/src/oracle/source-list.d.ts +36 -0
- package/dist/cjs/src/oracle/source-list.js +57 -0
- package/dist/cjs/src/perp/client.d.ts +41 -28
- package/dist/cjs/src/perp/client.js +32 -20
- package/dist/cjs/src/perp/config-view.js +7 -6
- package/dist/cjs/src/perp/config.d.ts +6 -6
- package/dist/cjs/src/perp/config.js +12 -12
- package/dist/cjs/src/perp/index.d.ts +3 -3
- package/dist/cjs/src/perp/index.js +11 -4
- package/dist/cjs/src/perp/user/staking.js +2 -1
- package/dist/cjs/src/unified-client.d.ts +14 -9
- package/dist/cjs/src/unified-client.js +2 -2
- package/dist/cjs/src/utils/config.js +2 -1
- package/dist/cjs/src/utils/record.d.ts +12 -0
- package/dist/cjs/src/utils/record.js +22 -0
- package/dist/src/account/config.d.ts +3 -2
- package/dist/src/generated/waterx_rule/waterx_rule.d.ts +7 -134
- package/dist/src/generated/waterx_rule/waterx_rule.js +7 -143
- package/dist/src/oracle/aggregate.d.ts +21 -21
- package/dist/src/oracle/aggregate.js +121 -71
- package/dist/src/oracle/config.d.ts +38 -72
- package/dist/src/oracle/config.js +1 -55
- package/dist/src/oracle/host.d.ts +24 -20
- package/dist/src/oracle/index.d.ts +7 -3
- package/dist/src/oracle/index.js +32 -10
- package/dist/src/oracle/price-update-rule.d.ts +32 -11
- package/dist/src/oracle/price-update-rule.js +22 -3
- package/dist/src/oracle/pyth.d.ts +44 -0
- package/dist/src/oracle/pyth.js +45 -5
- package/dist/src/oracle/read-plane.d.ts +70 -0
- package/dist/src/oracle/read-plane.js +81 -0
- package/dist/src/oracle/rule-registry.d.ts +6 -4
- package/dist/src/oracle/rule-registry.js +6 -4
- package/dist/src/oracle/rules/pyth-core-rule.js +7 -6
- package/dist/src/oracle/rules/pyth-lazer-rule.d.ts +21 -0
- package/dist/src/oracle/rules/pyth-lazer-rule.js +33 -5
- package/dist/src/oracle/rules/pyth-rule.js +5 -4
- package/dist/src/oracle/rules/waterx-rule.d.ts +42 -5
- package/dist/src/oracle/rules/waterx-rule.js +57 -15
- package/dist/src/oracle/source-list.d.ts +36 -0
- package/dist/src/oracle/source-list.js +53 -0
- package/dist/src/perp/client.d.ts +41 -28
- package/dist/src/perp/client.js +33 -21
- package/dist/src/perp/config-view.js +7 -6
- package/dist/src/perp/config.d.ts +6 -6
- package/dist/src/perp/config.js +11 -9
- package/dist/src/perp/index.d.ts +3 -3
- package/dist/src/perp/index.js +2 -2
- package/dist/src/perp/user/staking.js +2 -1
- package/dist/src/unified-client.d.ts +14 -9
- package/dist/src/unified-client.js +2 -2
- package/dist/src/utils/config.js +2 -1
- package/dist/src/utils/record.d.ts +12 -0
- package/dist/src/utils/record.js +19 -0
- package/package.json +1 -1
|
@@ -11,37 +11,50 @@
|
|
|
11
11
|
* {@link PerpConfigView}. This class is just the wiring + factory between them.
|
|
12
12
|
*/
|
|
13
13
|
import { BaseLineClient } from "../base-client.ts";
|
|
14
|
-
import type
|
|
14
|
+
import { type OracleSource } from "../oracle/price-update-rule.ts";
|
|
15
15
|
import type { FetchPolicy } from "../oracle/update-fetch.ts";
|
|
16
|
-
import { type LoadConfigOptions, type
|
|
16
|
+
import { type LoadConfigOptions, type PythAccessConfig, type PythFetchPolicy, type WaterxAccessConfig, type WaterXConfig, type WormholeInfraConfig } from "./config.ts";
|
|
17
17
|
import type { Network } from "./constants.ts";
|
|
18
18
|
export interface CreateClientOptions extends LoadConfigOptions {
|
|
19
19
|
grpcUrl?: string;
|
|
20
20
|
/**
|
|
21
|
-
* Which oracle price-update source drives `refreshOraclePrices`.
|
|
22
|
-
* is
|
|
21
|
+
* Which oracle price-update source drives `refreshOraclePrices`. REQUIRED —
|
|
22
|
+
* there is NO default source: every deployment names its source explicitly
|
|
23
|
+
* (wire it from your own env var, e.g. `ORACLE_SOURCE`). Each source is
|
|
24
|
+
* self-contained (own infra, own endpoints, own config) with NO cross-source
|
|
25
|
+
* fallback:
|
|
23
26
|
*
|
|
24
|
-
* - `'pyth_rule'`
|
|
25
|
-
*
|
|
27
|
+
* - `'pyth_rule'` — Pyth Core `pyth_rule` updates (Hermes VAA + per-feed
|
|
28
|
+
* update fees); Core state + Hermes endpoint live in the source's own
|
|
29
|
+
* `PYTH_CORE_INFRA` table.
|
|
26
30
|
* - `'pyth_lazer_rule'` — Pyth Lazer signed updates (ONE `leEcdsa` verify
|
|
27
31
|
* per PTB, no per-feed fees); needs `packages.pyth_lazer_rule` with feeds
|
|
28
|
-
* and a `pythApiKey` (Lazer is auth-first)
|
|
32
|
+
* and a `pythApiKey` (Lazer is auth-first); Lazer infra lives in the
|
|
33
|
+
* source's own `LAZER_INFRA` table.
|
|
29
34
|
* - `'waterx_rule'` — the first-party WaterX quote-center (Nautilus-TEE,
|
|
30
35
|
* ed25519-signed batches): ONE envelope covering the build's tickers,
|
|
31
36
|
* verified AND fed by a single `collect_batch_latest` per collector. No
|
|
32
37
|
* credential and no per-update fee; needs `packages.waterx_rule` with
|
|
33
|
-
* feeds.
|
|
34
|
-
* /
|
|
38
|
+
* feeds. Quote-center infra lives in the source's own `WATERX_INFRA`
|
|
39
|
+
* table; endpoint/transport overridable via
|
|
40
|
+
* {@link CreateClientOptions.waterxEndpoint} /
|
|
41
|
+
* {@link CreateClientOptions.waterxFetch} — the browser-CORS proxy hook,
|
|
35
42
|
* since this is the one source fetched from the page.
|
|
36
43
|
*
|
|
37
44
|
* The name is source-neutral on purpose — a source need not be Pyth (as
|
|
38
45
|
* `'waterx_rule'` shows). Selecting a source whose feed for a requested
|
|
39
46
|
* ticker is absent is NOT an error at client creation: it fails at tx-build
|
|
40
|
-
* time for exactly those tickers (see `refreshOraclePrices`).
|
|
41
|
-
*
|
|
42
|
-
*
|
|
47
|
+
* time for exactly those tickers (see `refreshOraclePrices`).
|
|
48
|
+
*
|
|
49
|
+
* Accepts a SINGLE source or a LIST. A list means every listed source's
|
|
50
|
+
* data is fetched and fed in one build — required whenever the on-chain
|
|
51
|
+
* weight tables have more than one rule weighted (e.g. a Core→Pro or
|
|
52
|
+
* Pro+Waterx coexistence window): the chain drops unweighted contributions
|
|
53
|
+
* (harmless) but aborts on a starved weighted rule, so the list must stay a
|
|
54
|
+
* SUPERSET of every ticker's weighted set. Order is meaningful to consumers
|
|
55
|
+
* (read-plane priority), not to the on-chain build.
|
|
43
56
|
*/
|
|
44
|
-
oracleSource
|
|
57
|
+
oracleSource: OracleSource | OracleSource[];
|
|
45
58
|
/**
|
|
46
59
|
* Pyth Lazer access token (`Authorization: Bearer …`). Required under
|
|
47
60
|
* `oracleSource: 'pyth_lazer_rule'` (Lazer is auth-first) and unused by
|
|
@@ -57,7 +70,7 @@ export interface CreateClientOptions extends LoadConfigOptions {
|
|
|
57
70
|
pythFetch?: PythFetchPolicy;
|
|
58
71
|
/**
|
|
59
72
|
* Quote-center base URL for `oracleSource: 'waterx_rule'` — overrides the
|
|
60
|
-
* per-network
|
|
73
|
+
* source's own per-network `WATERX_INFRA` default.
|
|
61
74
|
*
|
|
62
75
|
* This is the one source a BROWSER fetches itself (the signed envelope is
|
|
63
76
|
* pulled from the page), so it is bound by the quote-center deployment's CORS
|
|
@@ -73,28 +86,28 @@ export interface CreateClientOptions extends LoadConfigOptions {
|
|
|
73
86
|
waterxEndpoint?: string;
|
|
74
87
|
/**
|
|
75
88
|
* Retry/timeout policy — and `fetchImpl` — for the quote-center fetch (see
|
|
76
|
-
* `fetchWithPolicy`). Optional: falls back to
|
|
77
|
-
*
|
|
89
|
+
* `fetchWithPolicy`). Optional: falls back to the built-in defaults — never
|
|
90
|
+
* to `pythFetch` (sources stay independent). Supply `fetchImpl` to route the request through your own
|
|
78
91
|
* transport (a proxying `fetch` wrapper, a non-global `fetch`, a test double).
|
|
79
92
|
*/
|
|
80
93
|
waterxFetch?: FetchPolicy;
|
|
81
94
|
}
|
|
82
95
|
export declare class PerpClient extends BaseLineClient<WaterXConfig> {
|
|
83
|
-
/** Pyth
|
|
84
|
-
pyth:
|
|
96
|
+
/** Caller-supplied Pyth credential + fetch policy — NO infra; each source owns its own tables. */
|
|
97
|
+
pyth: PythAccessConfig;
|
|
85
98
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
99
|
+
* Caller-supplied quote-center overrides for `oracleSource: 'waterx_rule'`
|
|
100
|
+
* (`waterxEndpoint` / `waterxFetch` create options) — access-only, mirroring
|
|
101
|
+
* `pyth` above; unset fields resolve against the rule's own `WATERX_INFRA`.
|
|
89
102
|
*/
|
|
90
|
-
waterx:
|
|
103
|
+
waterx: WaterxAccessConfig;
|
|
91
104
|
/** Wormhole infra for the credit bridge (network defaults unless overridden). */
|
|
92
105
|
wormhole: WormholeInfraConfig;
|
|
93
|
-
/**
|
|
94
|
-
readonly
|
|
106
|
+
/** The fed set: `oracleSource` create option normalized to a non-empty, deduped list. */
|
|
107
|
+
readonly oracleSources: readonly OracleSource[];
|
|
95
108
|
/** Canonical-schema lookups (delegated to below); no transport. */
|
|
96
109
|
private readonly view;
|
|
97
|
-
constructor(network: Network, config: WaterXConfig, opts
|
|
110
|
+
constructor(network: Network, config: WaterXConfig, opts: CreateClientOptions);
|
|
98
111
|
/**
|
|
99
112
|
* Async factory: fetches the deployment config for `network` and returns
|
|
100
113
|
* a ready-to-use client. Pass `opts.cache=true` to memoize the JSON.
|
|
@@ -103,9 +116,9 @@ export declare class PerpClient extends BaseLineClient<WaterXConfig> {
|
|
|
103
116
|
* not an error at init — it surfaces at tx-build time for the specific
|
|
104
117
|
* tickers that source can't serve (see `refreshOraclePrices`).
|
|
105
118
|
*/
|
|
106
|
-
static create(network: Network, opts
|
|
107
|
-
static mainnet(opts
|
|
108
|
-
static testnet(opts
|
|
119
|
+
static create(network: Network, opts: CreateClientOptions): Promise<PerpClient>;
|
|
120
|
+
static mainnet(opts: CreateClientOptions): Promise<PerpClient>;
|
|
121
|
+
static testnet(opts: CreateClientOptions): Promise<PerpClient>;
|
|
109
122
|
/** @see PerpConfigView.getMarket */
|
|
110
123
|
getMarket(ticker: string): import("./config.ts").WaterxPerpMarketEntry;
|
|
111
124
|
/** @see PerpConfigView.getAggregator */
|
package/dist/src/perp/client.js
CHANGED
|
@@ -11,44 +11,56 @@
|
|
|
11
11
|
* {@link PerpConfigView}. This class is just the wiring + factory between them.
|
|
12
12
|
*/
|
|
13
13
|
import { BaseLineClient } from "../base-client.js";
|
|
14
|
+
import { ORACLE_SOURCES } from "../oracle/price-update-rule.js";
|
|
15
|
+
import { isOracleSource } from "../oracle/source-list.js";
|
|
14
16
|
import { PerpConfigView } from "./config-view.js";
|
|
15
|
-
import { loadConfig,
|
|
17
|
+
import { loadConfig, WORMHOLE_DEFAULTS, } from "./config.js";
|
|
16
18
|
export class PerpClient extends BaseLineClient {
|
|
17
|
-
/** Pyth
|
|
19
|
+
/** Caller-supplied Pyth credential + fetch policy — NO infra; each source owns its own tables. */
|
|
18
20
|
pyth;
|
|
19
21
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
22
|
+
* Caller-supplied quote-center overrides for `oracleSource: 'waterx_rule'`
|
|
23
|
+
* (`waterxEndpoint` / `waterxFetch` create options) — access-only, mirroring
|
|
24
|
+
* `pyth` above; unset fields resolve against the rule's own `WATERX_INFRA`.
|
|
23
25
|
*/
|
|
24
26
|
waterx;
|
|
25
27
|
/** Wormhole infra for the credit bridge (network defaults unless overridden). */
|
|
26
28
|
wormhole;
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
+
/** The fed set: `oracleSource` create option normalized to a non-empty, deduped list. */
|
|
30
|
+
oracleSources;
|
|
29
31
|
/** Canonical-schema lookups (delegated to below); no transport. */
|
|
30
32
|
view;
|
|
31
|
-
constructor(network, config, opts
|
|
33
|
+
constructor(network, config, opts) {
|
|
32
34
|
super(network, config, opts);
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
35
|
+
// Access-only slice: the api_key + fetch policy are caller-supplied at
|
|
36
|
+
// init (a secret has no place in the canonical waterx-config JSON). All
|
|
37
|
+
// endpoint/object-id infra is per-source, owned by the rule modules —
|
|
38
|
+
// nothing infra-shaped lives on the client.
|
|
37
39
|
this.pyth = {
|
|
38
|
-
...PYTH_DEFAULTS[network],
|
|
39
40
|
...(opts.pythApiKey !== undefined ? { api_key: opts.pythApiKey } : {}),
|
|
40
41
|
...(opts.pythFetch !== undefined ? { fetch: opts.pythFetch } : {}),
|
|
41
42
|
};
|
|
42
43
|
this.wormhole = config.wormhole ?? WORMHOLE_DEFAULTS[network];
|
|
43
|
-
// Quote-center
|
|
44
|
-
//
|
|
45
|
-
//
|
|
44
|
+
// Quote-center access slice: overrides only — a browser blocked by the
|
|
45
|
+
// quote-center's CORS allowlist swaps `endpoint` for a same-origin proxy;
|
|
46
|
+
// unset fields resolve inside the rule against WATERX_INFRA[network].
|
|
46
47
|
this.waterx = {
|
|
47
|
-
...WATERX_DEFAULTS[network],
|
|
48
48
|
...(opts.waterxEndpoint !== undefined ? { endpoint: opts.waterxEndpoint } : {}),
|
|
49
49
|
...(opts.waterxFetch !== undefined ? { fetch: opts.waterxFetch } : {}),
|
|
50
50
|
};
|
|
51
|
-
|
|
51
|
+
// Normalize single-or-list to a deduped, order-preserving list, gated by
|
|
52
|
+
// `isOracleSource` — the SAME predicate `parseOracleSourceList` uses. An
|
|
53
|
+
// empty list, a nullish entry (an untyped caller omitting the REQUIRED
|
|
54
|
+
// option), or an unregistered value (`'core'`, `'pyth'`, …) fails
|
|
55
|
+
// construction loudly instead of booting green and surfacing as
|
|
56
|
+
// `OracleSourceNotImplemented` at the first tx-build.
|
|
57
|
+
const sources = Array.isArray(opts.oracleSource) ? opts.oracleSource : [opts.oracleSource];
|
|
58
|
+
this.oracleSources = [...new Set(sources)];
|
|
59
|
+
if (this.oracleSources.length === 0 ||
|
|
60
|
+
this.oracleSources.some((source) => !isOracleSource(source))) {
|
|
61
|
+
throw new Error(`oracleSource is REQUIRED and must name at least one of ${ORACLE_SOURCES.join(" | ")} ` +
|
|
62
|
+
`(got ${JSON.stringify(sources)})`);
|
|
63
|
+
}
|
|
52
64
|
this.view = new PerpConfigView(() => this.config, () => this.wormhole);
|
|
53
65
|
}
|
|
54
66
|
/**
|
|
@@ -59,14 +71,14 @@ export class PerpClient extends BaseLineClient {
|
|
|
59
71
|
* not an error at init — it surfaces at tx-build time for the specific
|
|
60
72
|
* tickers that source can't serve (see `refreshOraclePrices`).
|
|
61
73
|
*/
|
|
62
|
-
static async create(network, opts
|
|
74
|
+
static async create(network, opts) {
|
|
63
75
|
const config = await loadConfig(network, opts);
|
|
64
76
|
return new PerpClient(network, config, opts);
|
|
65
77
|
}
|
|
66
|
-
static mainnet(opts
|
|
78
|
+
static mainnet(opts) {
|
|
67
79
|
return PerpClient.create("MAINNET", opts);
|
|
68
80
|
}
|
|
69
|
-
static testnet(opts
|
|
81
|
+
static testnet(opts) {
|
|
70
82
|
return PerpClient.create("TESTNET", opts);
|
|
71
83
|
}
|
|
72
84
|
// ========================================================
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* callers keep calling `client.getMarket(...)` / `client.wlpType()` unchanged.
|
|
9
9
|
* Tested in isolation against a plain config object — no network needed.
|
|
10
10
|
*/
|
|
11
|
+
import { ownEntry } from "../utils/record.js";
|
|
11
12
|
export class PerpConfigView {
|
|
12
13
|
getConfig;
|
|
13
14
|
getWormhole;
|
|
@@ -26,21 +27,21 @@ export class PerpConfigView {
|
|
|
26
27
|
}
|
|
27
28
|
/** `waterx_perp.markets[ticker]`, throws if unknown. */
|
|
28
29
|
getMarket(ticker) {
|
|
29
|
-
const m = this.config.packages.waterx_perp?.markets
|
|
30
|
+
const m = ownEntry(this.config.packages.waterx_perp?.markets, ticker);
|
|
30
31
|
if (!m)
|
|
31
32
|
throw new Error(`Unknown market ticker: ${ticker}`);
|
|
32
33
|
return m;
|
|
33
34
|
}
|
|
34
35
|
/** `waterx_oracle.aggregators[ticker]`, throws if unknown. */
|
|
35
36
|
getAggregator(ticker) {
|
|
36
|
-
const a = this.config.packages.waterx_oracle?.aggregators
|
|
37
|
+
const a = ownEntry(this.config.packages.waterx_oracle?.aggregators, ticker);
|
|
37
38
|
if (!a)
|
|
38
39
|
throw new Error(`No aggregator listed for ticker: ${ticker}`);
|
|
39
40
|
return a;
|
|
40
41
|
}
|
|
41
42
|
/** `pyth_rule.feeds[ticker]`, throws if unknown. */
|
|
42
43
|
getPythFeed(ticker) {
|
|
43
|
-
const f = this.config.packages.pyth_rule?.feeds
|
|
44
|
+
const f = ownEntry(this.config.packages.pyth_rule?.feeds, ticker);
|
|
44
45
|
if (!f)
|
|
45
46
|
throw new Error(`No pyth feed listed for ticker: ${ticker}`);
|
|
46
47
|
return f;
|
|
@@ -66,7 +67,7 @@ export class PerpConfigView {
|
|
|
66
67
|
const c = this.config.packages.constant_rule;
|
|
67
68
|
if (!c?.published_at || !c.config)
|
|
68
69
|
return false;
|
|
69
|
-
return c.feeds
|
|
70
|
+
return ownEntry(c.feeds, ticker) !== undefined;
|
|
70
71
|
}
|
|
71
72
|
/**
|
|
72
73
|
* The `supra_rule` config when it is deployed, enabled, and fully wired
|
|
@@ -92,7 +93,7 @@ export class PerpConfigView {
|
|
|
92
93
|
*/
|
|
93
94
|
getPoolTokenType(tickerOrName) {
|
|
94
95
|
const poolTokens = this.config.packages.wlp?.pool_tokens ?? {};
|
|
95
|
-
const exact = poolTokens
|
|
96
|
+
const exact = ownEntry(poolTokens, tickerOrName);
|
|
96
97
|
if (exact)
|
|
97
98
|
return exact;
|
|
98
99
|
for (const t of Object.values(poolTokens)) {
|
|
@@ -115,7 +116,7 @@ export class PerpConfigView {
|
|
|
115
116
|
* reward coin type, so callers don't need a separate alias-to-type lookup.
|
|
116
117
|
*/
|
|
117
118
|
getRewarders(stakeAlias) {
|
|
118
|
-
const map = this.config.packages.waterx_staking?.rewarders
|
|
119
|
+
const map = ownEntry(this.config.packages.waterx_staking?.rewarders, stakeAlias);
|
|
119
120
|
if (!map)
|
|
120
121
|
return [];
|
|
121
122
|
return Object.entries(map).map(([alias, entry]) => ({ alias, ...entry }));
|
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
* `waterx-config` repo (default: GitHub raw).
|
|
4
4
|
*
|
|
5
5
|
* The schema mirrors the canonical JSON layout one-to-one (each package
|
|
6
|
-
* groups its own object IDs + per-ticker maps). External chain infra
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* groups its own object IDs + per-ticker maps). External chain infra is
|
|
7
|
+
* **not** in the JSON — each oracle source owns its own per-network table
|
|
8
|
+
* (`PYTH_CORE_INFRA` in `oracle/pyth.ts`, `LAZER_INFRA` in
|
|
9
|
+
* `oracle/rules/pyth-lazer-rule.ts`); Wormhole bridge infra lives in
|
|
10
|
+
* `WORMHOLE_DEFAULTS` below.
|
|
10
11
|
*/
|
|
11
12
|
import type { AccountPackages, BasePackageEntry, WormholeInfraConfig } from "../account/config.ts";
|
|
12
13
|
import type { OraclePackages } from "../oracle/config.ts";
|
|
13
14
|
import type { Network } from "./constants.ts";
|
|
14
15
|
export type { AccountConfig, AccountPackages, BasePackageEntry, NativeCustodyAsset, NativeCustodyPackage, WaterxCreditPackage, WaterxReferralPackage, WithdrawalQueuePackage, WormholeBridgePackage, WormholeInfraConfig, WxaAccountPackage, } from "../account/config.ts";
|
|
15
|
-
export type { ConstantFeedEntry, OracleConfig, OraclePackages,
|
|
16
|
-
export { PYTH_DEFAULTS, WATERX_DEFAULTS } from "../oracle/config.ts";
|
|
16
|
+
export type { ConstantFeedEntry, OracleConfig, OraclePackages, PythAccessConfig, PythFetchPolicy, PythLazerRulePackage, PythRulePackage, PythSponsorRulePackage, SupraFeedEntry, SupraRulePackage, WaterxConstantRulePackage, WaterxAccessConfig, WaterxOraclePackage, WaterxRulePackage, } from "../oracle/config.ts";
|
|
17
17
|
export interface WaterxPerpMarketEntry {
|
|
18
18
|
market: string;
|
|
19
19
|
config: string;
|
package/dist/src/perp/config.js
CHANGED
|
@@ -3,23 +3,25 @@
|
|
|
3
3
|
* `waterx-config` repo (default: GitHub raw).
|
|
4
4
|
*
|
|
5
5
|
* The schema mirrors the canonical JSON layout one-to-one (each package
|
|
6
|
-
* groups its own object IDs + per-ticker maps). External chain infra
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* groups its own object IDs + per-ticker maps). External chain infra is
|
|
7
|
+
* **not** in the JSON — each oracle source owns its own per-network table
|
|
8
|
+
* (`PYTH_CORE_INFRA` in `oracle/pyth.ts`, `LAZER_INFRA` in
|
|
9
|
+
* `oracle/rules/pyth-lazer-rule.ts`); Wormhole bridge infra lives in
|
|
10
|
+
* `WORMHOLE_DEFAULTS` below.
|
|
10
11
|
*/
|
|
11
12
|
import { fetchWithPolicy, rethrowExhaustedFetch } from "../oracle/update-fetch.js";
|
|
12
|
-
export { PYTH_DEFAULTS, WATERX_DEFAULTS } from "../oracle/config.js";
|
|
13
13
|
// ============================================================================
|
|
14
|
-
// Wormhole
|
|
14
|
+
// Wormhole — external chain infra, defaults by network
|
|
15
15
|
// ============================================================================
|
|
16
16
|
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
17
|
+
// Oracle-source infra lives with each source (`PYTH_CORE_INFRA` in
|
|
18
|
+
// `oracle/pyth.ts`, `LAZER_INFRA` in `oracle/rules/pyth-lazer-rule.ts`);
|
|
19
|
+
// `client.pyth` is the caller-supplied access slice only (`PythAccessConfig`,
|
|
20
|
+
// re-exported at the top of this file).
|
|
19
21
|
// `WormholeInfraConfig` is defined in `account/config.ts` (funding base) and
|
|
20
22
|
// re-exported at the top of this file. `state_id` is the same shared Sui
|
|
21
23
|
// Wormhole `State` object Pyth uses (kept in sync with
|
|
22
|
-
// `
|
|
24
|
+
// `PYTH_CORE_INFRA[*].wormhole_state_id`).
|
|
23
25
|
export const WORMHOLE_DEFAULTS = {
|
|
24
26
|
MAINNET: {
|
|
25
27
|
state_id: "0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c",
|
package/dist/src/perp/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { PerpClient } from "./client.ts";
|
|
2
2
|
export type { CreateClientOptions } from "./client.ts";
|
|
3
|
-
export {
|
|
4
|
-
export type { BasePackageEntry, ConstantFeedEntry, WaterxReferralPackage, LoadConfigOptions, NativeCustodyAsset, NativeCustodyPackage,
|
|
3
|
+
export { WORMHOLE_DEFAULTS, clearConfigCache, loadConfig } from "./config.ts";
|
|
4
|
+
export type { BasePackageEntry, ConstantFeedEntry, WaterxReferralPackage, LoadConfigOptions, NativeCustodyAsset, NativeCustodyPackage, PythAccessConfig, PythFetchPolicy, 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, DOUBLE_SCALE, DRY_RUN_SENDER, FLOAT_SCALE, 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, MS_PER_MINUTE, MS_PER_HOUR, 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";
|
|
@@ -13,7 +13,7 @@ export type { EstLiqPriceViewOpts } from "./liq-view.ts";
|
|
|
13
13
|
export * from "./user/index.ts";
|
|
14
14
|
export * from "./tx-builders.ts";
|
|
15
15
|
export * from "./fetch.ts";
|
|
16
|
-
export { FetchPolicyError, LazerApiKeyMissingError, OracleFeeSourceUnavailableError, OracleSourceNotImplementedError, PythCache, aggregateTicker, aggregateTickerWithConstant, aggregateTickerWithPyth, buildPythPriceUpdateCalls, fetchPriceFeedsUpdateData, refreshOraclePrices, updatePythPrices, } from "../oracle/index.ts";
|
|
16
|
+
export { FetchPolicyError, LazerApiKeyMissingError, OracleFeeSourceUnavailableError, OracleSourceNotImplementedError, PythCache, aggregateTicker, aggregateTickerWithConstant, aggregateTickerWithPyth, ORACLE_SOURCES, buildPythPriceUpdateCalls, fetchPriceFeedsUpdateData, isOracleSource, parseOracleSourceList, pythCoreHermesEndpoint, pythProHermesEndpoint, refreshOraclePrices, resolveHermesReadEndpoint, updatePythPrices, waterxEnvelopeOf, waterxQuoteCenterEndpoint, } from "../oracle/index.ts";
|
|
17
17
|
export type { FetchPolicy, OracleFeeSource, OracleSource, UpdateDataProvider, } from "../oracle/index.ts";
|
|
18
18
|
export { fetchDepositVaa, fetchVaa, listBridgeWithdrawalVaas, listVaasByEmitter, padEvmEmitter, toWormholescanEmitter, vaaBase64ToBytes, vaaBase64ToHex, vaaBytesToBase64, waitForVaa, } from "../account/funding/wormhole.ts";
|
|
19
19
|
export type { VaaListItem, VaaResponse, WormholescanOptions } from "../account/funding/wormhole.ts";
|
package/dist/src/perp/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// ======== Core ========
|
|
2
2
|
export { PerpClient } from "./client.js";
|
|
3
|
-
export {
|
|
3
|
+
export { WORMHOLE_DEFAULTS, clearConfigCache, loadConfig } from "./config.js";
|
|
4
4
|
// ======== Constants & enums ========
|
|
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, DOUBLE_SCALE, DRY_RUN_SENDER, FLOAT_SCALE, 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, MS_PER_MINUTE, MS_PER_HOUR, MS_PER_YEAR, SUI_DECIMALS, WLP_DECIMALS, COLLATERAL_DECIMALS, TOKEN_DECIMALS, } from "./constants.js";
|
|
6
6
|
// ======== Utilities ========
|
|
@@ -15,7 +15,7 @@ export * from "./tx-builders.js";
|
|
|
15
15
|
// ======== Read-only queries ========
|
|
16
16
|
export * from "./fetch.js";
|
|
17
17
|
// ======== Oracle utilities (Pyth source + rule aggregation) ========
|
|
18
|
-
export { FetchPolicyError, LazerApiKeyMissingError, OracleFeeSourceUnavailableError, OracleSourceNotImplementedError, PythCache, aggregateTicker, aggregateTickerWithConstant, aggregateTickerWithPyth, buildPythPriceUpdateCalls, fetchPriceFeedsUpdateData, refreshOraclePrices, updatePythPrices, } from "../oracle/index.js";
|
|
18
|
+
export { FetchPolicyError, LazerApiKeyMissingError, OracleFeeSourceUnavailableError, OracleSourceNotImplementedError, PythCache, aggregateTicker, aggregateTickerWithConstant, aggregateTickerWithPyth, ORACLE_SOURCES, buildPythPriceUpdateCalls, fetchPriceFeedsUpdateData, isOracleSource, parseOracleSourceList, pythCoreHermesEndpoint, pythProHermesEndpoint, refreshOraclePrices, resolveHermesReadEndpoint, updatePythPrices, waterxEnvelopeOf, waterxQuoteCenterEndpoint, } from "../oracle/index.js";
|
|
19
19
|
// ======== Wormhole / Wormholescan utilities (credit bridge) ========
|
|
20
20
|
export { fetchDepositVaa, fetchVaa, listBridgeWithdrawalVaas, listVaasByEmitter, padEvmEmitter, toWormholescanEmitter, vaaBase64ToBytes, vaaBase64ToHex, vaaBytesToBase64, waitForVaa, } from "../account/funding/wormhole.js";
|
|
21
21
|
// ======== Generated BCS types (sui-ts-codegen) ========
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { makeSenderRequest } from "../../account/account-request.js";
|
|
19
19
|
import * as staking from "../../generated/waterx_staking/waterx_staking.js";
|
|
20
|
+
import { ownEntry } from "../../utils/record.js";
|
|
20
21
|
import { toU64Arg } from "../../utils/validate.js";
|
|
21
22
|
function pool(client, stakeAlias) {
|
|
22
|
-
const id = client.config.packages.waterx_staking?.pools
|
|
23
|
+
const id = ownEntry(client.config.packages.waterx_staking?.pools, stakeAlias);
|
|
23
24
|
if (!id) {
|
|
24
25
|
throw new Error(`config.packages.waterx_staking.pools[${stakeAlias}] is not set — staking is not deployed for this stake type`);
|
|
25
26
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Exposes three namespaces over the two product-line sub-clients:
|
|
5
5
|
*
|
|
6
|
-
* const client = await WaterXClient.create({ network: "TESTNET" });
|
|
6
|
+
* const client = await WaterXClient.create({ network: "TESTNET", oracleSource: "pyth_rule" });
|
|
7
7
|
* client.account.createAccount(tx, { alias }); // -> shared waterx_account + funding
|
|
8
8
|
* client.perp.placeOrderRequest(tx, params); // -> perp builder
|
|
9
9
|
* client.predict.placeOrder(tx, params); // -> prediction builder
|
|
@@ -370,20 +370,25 @@ export interface ClientCreateOptions {
|
|
|
370
370
|
/**
|
|
371
371
|
* The perp line's oracle price-update source (perp-line only — the
|
|
372
372
|
* prediction line has no oracle leg), forwarded to `PerpClient.create`.
|
|
373
|
+
* REQUIRED — there is NO default source: every deployment names its source
|
|
374
|
+
* explicitly (wire it from your own env var, e.g. `ORACLE_SOURCE`).
|
|
373
375
|
* Source-neutral by design: a source need not be Pyth (see `'waterx_rule'`).
|
|
374
376
|
*
|
|
375
|
-
* - `'pyth_rule'`
|
|
377
|
+
* - `'pyth_rule'` — Pyth Core updates; infra in the source's own
|
|
378
|
+
* `PYTH_CORE_INFRA` table.
|
|
376
379
|
* - `'pyth_lazer_rule'` — Pyth Lazer signed updates (pair with `pythApiKey`
|
|
377
|
-
* and a config carrying `packages.pyth_lazer_rule`)
|
|
380
|
+
* and a config carrying `packages.pyth_lazer_rule`); infra in the
|
|
381
|
+
* source's own `LAZER_INFRA` table.
|
|
378
382
|
* - `'waterx_rule'` — the first-party WaterX quote-center (Nautilus-TEE,
|
|
379
|
-
* ed25519 signed batches; no credential, no per-update fee)
|
|
380
|
-
*
|
|
383
|
+
* ed25519 signed batches; no credential, no per-update fee); infra in the
|
|
384
|
+
* source's own `WATERX_INFRA` table. Pair with `waterxEndpoint` /
|
|
385
|
+
* `waterxFetch` when the browser needs a proxy.
|
|
381
386
|
*
|
|
382
387
|
* Each source is self-contained with no cross-source fallback; selecting a
|
|
383
388
|
* source whose feed for a ticker is absent fails at tx-build (not at init).
|
|
384
389
|
* See perp `CreateClientOptions.oracleSource` for the full note.
|
|
385
390
|
*/
|
|
386
|
-
oracleSource
|
|
391
|
+
oracleSource: OracleSource | OracleSource[];
|
|
387
392
|
/**
|
|
388
393
|
* Pyth Lazer access token, forwarded to the perp line. Required under
|
|
389
394
|
* `oracleSource: 'pyth_lazer_rule'`, unused by `'pyth_rule'`. A SECRET —
|
|
@@ -395,7 +400,7 @@ export interface ClientCreateOptions {
|
|
|
395
400
|
pythFetch?: PythFetchPolicy;
|
|
396
401
|
/**
|
|
397
402
|
* Quote-center base URL for `oracleSource: 'waterx_rule'`, forwarded to the
|
|
398
|
-
* perp line — overrides the per-network `
|
|
403
|
+
* perp line — overrides the source's own per-network `WATERX_INFRA` default.
|
|
399
404
|
*
|
|
400
405
|
* `waterx_rule` is the one source a BROWSER fetches itself, so it is bound by
|
|
401
406
|
* the quote-center deployment's CORS allowlist: a front end whose origin is
|
|
@@ -406,7 +411,7 @@ export interface ClientCreateOptions {
|
|
|
406
411
|
waterxEndpoint?: string;
|
|
407
412
|
/**
|
|
408
413
|
* Retry/timeout policy — and `fetchImpl` — for the perp line's quote-center
|
|
409
|
-
* fetch. Falls back to
|
|
414
|
+
* fetch. Falls back to the built-in defaults — never to `pythFetch`.
|
|
410
415
|
*/
|
|
411
416
|
waterxFetch?: FetchPolicy;
|
|
412
417
|
/** Perp-line overrides (network, grpcUrl, waterxConfigUrl, cache, …). */
|
|
@@ -448,6 +453,6 @@ export declare class WaterXClient {
|
|
|
448
453
|
* `waterx-config` JSON) and returns a ready client. Each line can target a
|
|
449
454
|
* different network via `opts.perp.network` / `opts.predict.network`.
|
|
450
455
|
*/
|
|
451
|
-
static create(opts
|
|
456
|
+
static create(opts: ClientCreateOptions): Promise<WaterXClient>;
|
|
452
457
|
}
|
|
453
458
|
export {};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Exposes three namespaces over the two product-line sub-clients:
|
|
5
5
|
*
|
|
6
|
-
* const client = await WaterXClient.create({ network: "TESTNET" });
|
|
6
|
+
* const client = await WaterXClient.create({ network: "TESTNET", oracleSource: "pyth_rule" });
|
|
7
7
|
* client.account.createAccount(tx, { alias }); // -> shared waterx_account + funding
|
|
8
8
|
* client.perp.placeOrderRequest(tx, params); // -> perp builder
|
|
9
9
|
* client.predict.placeOrder(tx, params); // -> prediction builder
|
|
@@ -150,7 +150,7 @@ export class WaterXClient {
|
|
|
150
150
|
* `waterx-config` JSON) and returns a ready client. Each line can target a
|
|
151
151
|
* different network via `opts.perp.network` / `opts.predict.network`.
|
|
152
152
|
*/
|
|
153
|
-
static async create(opts
|
|
153
|
+
static async create(opts) {
|
|
154
154
|
const baseNetwork = opts.network ?? "TESTNET";
|
|
155
155
|
const { network: perpNetwork, ...perpRest } = opts.perp ?? {};
|
|
156
156
|
const { network: predictNetwork, ...predictRest } = opts.predict ?? {};
|
package/dist/src/utils/config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ownEntry } from "./record.js";
|
|
1
2
|
/** Returns all registered market tickers (e.g. "BTCUSD") from waterx-config. */
|
|
2
3
|
export function getMarketTickers(config) {
|
|
3
4
|
return Object.keys(config.packages.waterx_perp.markets);
|
|
@@ -11,5 +12,5 @@ export function getMarketTickers(config) {
|
|
|
11
12
|
*/
|
|
12
13
|
export function getCollateralAssets(config) {
|
|
13
14
|
const feeds = config.packages.pyth_rule?.feeds ?? {};
|
|
14
|
-
return Object.keys(config.packages.wlp.pool_tokens).filter((t) => feeds
|
|
15
|
+
return Object.keys(config.packages.wlp.pool_tokens).filter((t) => ownEntry(feeds, t) !== undefined);
|
|
15
16
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Own-key record lookup. Ticker-keyed config records (`feeds`, `markets`,
|
|
3
|
+
* `aggregators`) are indexed with caller-supplied strings; a bare bracket
|
|
4
|
+
* read — like the `in` operator — walks the prototype chain, so a ticker
|
|
5
|
+
* named like an `Object.prototype` key ("toString", "constructor", …) reads
|
|
6
|
+
* as an inherited Function instead of "absent" and leaks into batches sent
|
|
7
|
+
* to the network. Every such lookup funnels through here so the answer is
|
|
8
|
+
* own-keys-only, everywhere, instead of per-site `Object.hasOwn` guards
|
|
9
|
+
* that drift.
|
|
10
|
+
*/
|
|
11
|
+
/** `record[key]` iff `key` is an OWN key — `undefined` for an absent record, an absent key, or a prototype-chain hit. */
|
|
12
|
+
export declare function ownEntry<T extends Record<string, unknown>>(record: T | undefined, key: string): T[string] | undefined;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Own-key record lookup. Ticker-keyed config records (`feeds`, `markets`,
|
|
3
|
+
* `aggregators`) are indexed with caller-supplied strings; a bare bracket
|
|
4
|
+
* read — like the `in` operator — walks the prototype chain, so a ticker
|
|
5
|
+
* named like an `Object.prototype` key ("toString", "constructor", …) reads
|
|
6
|
+
* as an inherited Function instead of "absent" and leaks into batches sent
|
|
7
|
+
* to the network. Every such lookup funnels through here so the answer is
|
|
8
|
+
* own-keys-only, everywhere, instead of per-site `Object.hasOwn` guards
|
|
9
|
+
* that drift.
|
|
10
|
+
*/
|
|
11
|
+
/** `record[key]` iff `key` is an OWN key — `undefined` for an absent record, an absent key, or a prototype-chain hit. */
|
|
12
|
+
export function ownEntry(record, key) {
|
|
13
|
+
// The `T extends Record<...>` form (rather than `Record<string, V>`) keeps
|
|
14
|
+
// union-typed records inferable; TS then resolves `record[key]` only to the
|
|
15
|
+
// constraint's `unknown`, so restate the definitionally-true index type.
|
|
16
|
+
return record !== undefined && Object.hasOwn(record, key)
|
|
17
|
+
? record[key]
|
|
18
|
+
: undefined;
|
|
19
|
+
}
|