@waterx/sdk 4.3.2 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/.claude/skills/waterx-sdk-integration/SKILL.md +225 -0
  2. package/README.md +216 -45
  3. package/SKILLS.md +34 -0
  4. package/dist/cjs/src/account/config.d.ts +3 -5
  5. package/dist/cjs/src/account/funding/wormhole.d.ts +1 -2
  6. package/dist/cjs/src/account/funding/wormhole.js +1 -2
  7. package/dist/cjs/src/generated/waterx_rule/waterx_rule.d.ts +140 -7
  8. package/dist/cjs/src/generated/waterx_rule/waterx_rule.js +163 -8
  9. package/dist/cjs/src/oracle/aggregate.d.ts +49 -62
  10. package/dist/cjs/src/oracle/aggregate.js +208 -164
  11. package/dist/cjs/src/oracle/config.d.ts +38 -51
  12. package/dist/cjs/src/oracle/config.js +1 -1
  13. package/dist/cjs/src/oracle/host.d.ts +14 -19
  14. package/dist/cjs/src/oracle/host.js +3 -3
  15. package/dist/cjs/src/oracle/index.d.ts +25 -16
  16. package/dist/cjs/src/oracle/index.js +87 -69
  17. package/dist/cjs/src/oracle/price-update-rule.d.ts +104 -66
  18. package/dist/cjs/src/oracle/price-update-rule.js +24 -16
  19. package/dist/cjs/src/oracle/pyth-pro-history.d.ts +36 -0
  20. package/dist/cjs/src/oracle/pyth-pro-history.js +41 -0
  21. package/dist/cjs/src/oracle/read-plane.d.ts +35 -53
  22. package/dist/cjs/src/oracle/read-plane.js +26 -48
  23. package/dist/cjs/src/oracle/read-prices.d.ts +105 -0
  24. package/dist/cjs/src/oracle/read-prices.js +162 -0
  25. package/dist/cjs/src/oracle/rule-registry.d.ts +12 -12
  26. package/dist/cjs/src/oracle/rule-registry.js +12 -14
  27. package/dist/cjs/src/oracle/rules/pyth-lazer-rule.d.ts +24 -3
  28. package/dist/cjs/src/oracle/rules/pyth-lazer-rule.js +40 -20
  29. package/dist/cjs/src/oracle/rules/waterx-rule.d.ts +271 -57
  30. package/dist/cjs/src/oracle/rules/waterx-rule.js +743 -144
  31. package/dist/cjs/src/oracle/schedule.d.ts +109 -0
  32. package/dist/cjs/src/oracle/schedule.js +991 -0
  33. package/dist/cjs/src/oracle/source-list.d.ts +31 -27
  34. package/dist/cjs/src/oracle/source-list.js +43 -45
  35. package/dist/cjs/src/oracle/symbol-catalog.d.ts +54 -0
  36. package/dist/cjs/src/oracle/symbol-catalog.js +69 -0
  37. package/dist/cjs/src/oracle/update-fetch.d.ts +11 -15
  38. package/dist/cjs/src/oracle/update-fetch.js +12 -19
  39. package/dist/cjs/src/oracle/validate.d.ts +105 -0
  40. package/dist/cjs/src/oracle/validate.js +185 -0
  41. package/dist/cjs/src/oracle/weight-coverage.d.ts +79 -0
  42. package/dist/cjs/src/oracle/weight-coverage.js +173 -0
  43. package/dist/cjs/src/perp/client.d.ts +40 -55
  44. package/dist/cjs/src/perp/client.js +44 -17
  45. package/dist/cjs/src/perp/config-view.d.ts +5 -14
  46. package/dist/cjs/src/perp/config-view.js +5 -16
  47. package/dist/cjs/src/perp/config.d.ts +3 -3
  48. package/dist/cjs/src/perp/config.js +11 -13
  49. package/dist/cjs/src/perp/index.d.ts +4 -6
  50. package/dist/cjs/src/perp/index.js +43 -18
  51. package/dist/cjs/src/perp/tx-builders/common.d.ts +86 -48
  52. package/dist/cjs/src/perp/tx-builders/common.js +115 -47
  53. package/dist/cjs/src/perp/tx-builders/wlp.d.ts +3 -14
  54. package/dist/cjs/src/perp/tx-builders/wlp.js +6 -35
  55. package/dist/cjs/src/perp/tx-builders.d.ts +6 -5
  56. package/dist/cjs/src/perp/tx-builders.js +16 -10
  57. package/dist/cjs/src/unified-client.d.ts +9 -35
  58. package/dist/cjs/src/unified-client.js +3 -4
  59. package/dist/cjs/src/utils/config.d.ts +0 -8
  60. package/dist/cjs/src/utils/config.js +5 -13
  61. package/dist/src/account/config.d.ts +3 -5
  62. package/dist/src/account/funding/wormhole.d.ts +1 -2
  63. package/dist/src/account/funding/wormhole.js +1 -2
  64. package/dist/src/generated/waterx_rule/waterx_rule.d.ts +140 -7
  65. package/dist/src/generated/waterx_rule/waterx_rule.js +151 -7
  66. package/dist/src/oracle/aggregate.d.ts +49 -62
  67. package/dist/src/oracle/aggregate.js +209 -164
  68. package/dist/src/oracle/config.d.ts +38 -51
  69. package/dist/src/oracle/config.js +1 -1
  70. package/dist/src/oracle/host.d.ts +14 -19
  71. package/dist/src/oracle/host.js +3 -3
  72. package/dist/src/oracle/index.d.ts +25 -16
  73. package/dist/src/oracle/index.js +61 -54
  74. package/dist/src/oracle/price-update-rule.d.ts +104 -66
  75. package/dist/src/oracle/price-update-rule.js +23 -16
  76. package/dist/src/oracle/pyth-pro-history.d.ts +36 -0
  77. package/dist/src/oracle/pyth-pro-history.js +38 -0
  78. package/dist/src/oracle/read-plane.d.ts +35 -53
  79. package/dist/src/oracle/read-plane.js +25 -47
  80. package/dist/src/oracle/read-prices.d.ts +105 -0
  81. package/dist/src/oracle/read-prices.js +156 -0
  82. package/dist/src/oracle/rule-registry.d.ts +12 -12
  83. package/dist/src/oracle/rule-registry.js +12 -14
  84. package/dist/src/oracle/rules/pyth-lazer-rule.d.ts +24 -3
  85. package/dist/src/oracle/rules/pyth-lazer-rule.js +39 -20
  86. package/dist/src/oracle/rules/waterx-rule.d.ts +271 -57
  87. package/dist/src/oracle/rules/waterx-rule.js +735 -144
  88. package/dist/src/oracle/schedule.d.ts +109 -0
  89. package/dist/src/oracle/schedule.js +985 -0
  90. package/dist/src/oracle/source-list.d.ts +31 -27
  91. package/dist/src/oracle/source-list.js +42 -43
  92. package/dist/src/oracle/symbol-catalog.d.ts +54 -0
  93. package/dist/src/oracle/symbol-catalog.js +65 -0
  94. package/dist/src/oracle/update-fetch.d.ts +11 -15
  95. package/dist/src/oracle/update-fetch.js +12 -18
  96. package/dist/src/oracle/validate.d.ts +105 -0
  97. package/dist/src/oracle/validate.js +177 -0
  98. package/dist/src/oracle/weight-coverage.d.ts +79 -0
  99. package/dist/src/oracle/weight-coverage.js +166 -0
  100. package/dist/src/perp/client.d.ts +40 -55
  101. package/dist/src/perp/client.js +45 -18
  102. package/dist/src/perp/config-view.d.ts +5 -14
  103. package/dist/src/perp/config-view.js +5 -16
  104. package/dist/src/perp/config.d.ts +3 -3
  105. package/dist/src/perp/config.js +11 -13
  106. package/dist/src/perp/index.d.ts +4 -6
  107. package/dist/src/perp/index.js +17 -5
  108. package/dist/src/perp/tx-builders/common.d.ts +86 -48
  109. package/dist/src/perp/tx-builders/common.js +114 -48
  110. package/dist/src/perp/tx-builders/wlp.d.ts +3 -14
  111. package/dist/src/perp/tx-builders/wlp.js +6 -35
  112. package/dist/src/perp/tx-builders.d.ts +6 -5
  113. package/dist/src/perp/tx-builders.js +15 -6
  114. package/dist/src/unified-client.d.ts +9 -35
  115. package/dist/src/unified-client.js +3 -4
  116. package/dist/src/utils/config.d.ts +0 -8
  117. package/dist/src/utils/config.js +5 -12
  118. package/package.json +8 -2
  119. package/dist/cjs/src/generated/pyth_sponsor_rule/deps/sui/balance.d.ts +0 -12
  120. package/dist/cjs/src/generated/pyth_sponsor_rule/deps/sui/balance.js +0 -17
  121. package/dist/cjs/src/generated/pyth_sponsor_rule/pyth_sponsor_rule.d.ts +0 -68
  122. package/dist/cjs/src/generated/pyth_sponsor_rule/pyth_sponsor_rule.js +0 -113
  123. package/dist/cjs/src/generated/waterx_pyth_rule/deps/sui/vec_map.d.ts +0 -36
  124. package/dist/cjs/src/generated/waterx_pyth_rule/deps/sui/vec_map.js +0 -31
  125. package/dist/cjs/src/generated/waterx_pyth_rule/pyth_rule.d.ts +0 -192
  126. package/dist/cjs/src/generated/waterx_pyth_rule/pyth_rule.js +0 -214
  127. package/dist/cjs/src/oracle/pyth.d.ts +0 -227
  128. package/dist/cjs/src/oracle/pyth.js +0 -652
  129. package/dist/cjs/src/oracle/rules/pyth-core-rule.d.ts +0 -15
  130. package/dist/cjs/src/oracle/rules/pyth-core-rule.js +0 -100
  131. package/dist/cjs/src/oracle/rules/pyth-rule.d.ts +0 -11
  132. package/dist/cjs/src/oracle/rules/pyth-rule.js +0 -29
  133. package/dist/cjs/src/oracle/rules/sponsor.d.ts +0 -32
  134. package/dist/cjs/src/oracle/rules/sponsor.js +0 -56
  135. package/dist/src/generated/pyth_sponsor_rule/deps/sui/balance.d.ts +0 -12
  136. package/dist/src/generated/pyth_sponsor_rule/deps/sui/balance.js +0 -14
  137. package/dist/src/generated/pyth_sponsor_rule/pyth_sponsor_rule.d.ts +0 -68
  138. package/dist/src/generated/pyth_sponsor_rule/pyth_sponsor_rule.js +0 -73
  139. package/dist/src/generated/waterx_pyth_rule/deps/sui/vec_map.d.ts +0 -36
  140. package/dist/src/generated/waterx_pyth_rule/deps/sui/vec_map.js +0 -27
  141. package/dist/src/generated/waterx_pyth_rule/pyth_rule.d.ts +0 -192
  142. package/dist/src/generated/waterx_pyth_rule/pyth_rule.js +0 -170
  143. package/dist/src/oracle/pyth.d.ts +0 -227
  144. package/dist/src/oracle/pyth.js +0 -638
  145. package/dist/src/oracle/rules/pyth-core-rule.d.ts +0 -15
  146. package/dist/src/oracle/rules/pyth-core-rule.js +0 -97
  147. package/dist/src/oracle/rules/pyth-rule.d.ts +0 -11
  148. package/dist/src/oracle/rules/pyth-rule.js +0 -26
  149. package/dist/src/oracle/rules/sponsor.d.ts +0 -32
  150. package/dist/src/oracle/rules/sponsor.js +0 -52
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Oracle-layer config schema — the package entries + config slice the shared
3
- * oracle layer (Pyth source + oracle rules + aggregate) reads. This is shared
3
+ * oracle layer (oracle rules + aggregate) reads. This is shared
4
4
  * infra, **not** the perp line: `perp/config.ts` imports these and
5
5
  * `WaterXPackages extends OraclePackages`; nothing here imports `perp/` or
6
6
  * `prediction/`. Snake_case mirrors the canonical `waterx-config` JSON 1:1.
@@ -12,35 +12,26 @@
12
12
  import type { BasePackageEntry } from "../account/config.ts";
13
13
  import type { BaseLineConfig } from "../base-client.ts";
14
14
  import type { FetchPolicy } from "./update-fetch.ts";
15
- export interface PythRulePackage extends BasePackageEntry {
16
- config: string;
17
- feeds: Record<string, {
18
- feed_id: string;
19
- price_info_object: string;
20
- }>;
21
- }
22
- export interface PythSponsorRulePackage extends BasePackageEntry {
23
- pyth_sponsor: string;
24
- }
25
15
  /**
26
16
  * `pyth_lazer_rule` deployment entry — present in the deployed testnet
27
17
  * `waterx-config` JSON. Read by `PythLazerRule` (`rules/pyth-lazer-rule.ts`):
28
18
  * `feeds` for ticker support + integer feed-id resolution, `state` for the
29
19
  * verify call, `published_at`/`config` for the per-ticker feed call.
30
20
  *
31
- * `enabled` mirrors the JSON field verbatim but MUST NOT be read for routing —
32
- * which rule prices a ticker is decided solely by the client's `oracleSource`
33
- * create option (see `OracleHost.oracleSources`), never by this flag or any
34
- * other config value.
21
+ * `enabled` switches the source off for this deployment: `deriveOracleSources`
22
+ * skips a block explicitly set to `false`. Absent means ON every live config
23
+ * omits it, and a published block with feeds is a wired source. Which rule
24
+ * prices a given TICKER is still decided by the feeds maps alone, never by a
25
+ * per-ticker flag.
35
26
  */
36
27
  export interface PythLazerRulePackage extends BasePackageEntry {
37
28
  config: string;
38
29
  state: string;
39
30
  enabled?: boolean;
40
- /** Oracle ticker → integer Pyth Lazer feed id (distinct id scheme from `pyth_rule`'s hex `feed_id`). */
31
+ /** Oracle ticker → integer Pyth Lazer feed id (distinct from the legacy Hermes hex id scheme). */
41
32
  feeds: Record<string, number>;
42
33
  }
43
- /** Per-ticker `constant_rule` feed entry (mirrors the `pyth_rule.feeds` shape). */
34
+ /** Per-ticker `constant_rule` feed entry (per-ticker map keyed by oracle ticker). */
44
35
  export interface ConstantFeedEntry {
45
36
  /**
46
37
  * Constant 1e9-scaled price (decimal string), mirroring the on-chain
@@ -54,13 +45,13 @@ export interface WaterxConstantRulePackage extends BasePackageEntry {
54
45
  /** Shared `constant_rule::Config` holding the per-ticker constant prices. */
55
46
  config: string;
56
47
  /**
57
- * Oracle ticker → constant feed entry, mirroring `pyth_rule.feeds`. A ticker
58
- * present here is fed via `constant_rule::feed` instead of (steady state) or
59
- * alongside (dual-feed) `pyth_rule::feed` (e.g. `USDCUSD → { price: "1000000000" }`).
48
+ * Oracle ticker → constant feed entry. A ticker present here is fed via
49
+ * `constant_rule::feed`, alone (constant-only) or alongside the live
50
+ * sources (e.g. `USDCUSD → { price: "1000000000" }`).
60
51
  */
61
52
  feeds?: Record<string, ConstantFeedEntry>;
62
53
  }
63
- /** Per-ticker `supra_rule` feed entry (mirrors the `pyth_rule.feeds` shape). */
54
+ /** Per-ticker `supra_rule` feed entry (per-ticker map keyed by oracle ticker). */
64
55
  export interface SupraFeedEntry {
65
56
  /** Supra pair id (mirrors the on-chain `Config`; informational off-chain). */
66
57
  pair_id: number;
@@ -84,8 +75,8 @@ export interface SupraRulePackage extends BasePackageEntry {
84
75
  }
85
76
  /**
86
77
  * Per-ticker `waterx_rule` feed entry. Keyed in `feeds` by the oracle **ticker**
87
- * (e.g. `"SUIUSD"`, the same key `pyth_rule.feeds` uses), so
88
- * `Object.keys(feeds)` is the SDK's supported-ticker set. The fields are
78
+ * (e.g. `"SUIUSD"`), so `Object.keys(feeds)` is the SDK's supported-ticker
79
+ * set. The fields are
89
80
  * informational off-chain — the SDK keys routing/support off the entry's
90
81
  * presence and pushes the enclave-signed price verbatim, never re-deriving it.
91
82
  */
@@ -96,14 +87,15 @@ export interface WaterxRuleFeedEntry {
96
87
  /**
97
88
  * `waterx_rule` deployment entry — the first-party Nautilus-TEE oracle rule.
98
89
  * Read by `WaterxRule` (`rules/waterx-rule.ts`): `feeds` for ticker support,
99
- * `config`/`enclave_config`/`enclave` for the `collect_batch_latest` call,
90
+ * `config`/`enclave_config`/`enclave` for the collect call
91
+ * (`collect_single_with_proof`, or `collect_batch_latest` on the fallback shape),
100
92
  * `published_at` for the package address. The off-chain signed price is pulled
101
93
  * from the quote-center (endpoint from the rule-owned `WATERX_INFRA` table in
102
94
  * `rules/waterx-rule.ts`), not this JSON.
103
95
  *
104
96
  * `enabled` mirrors the JSON field verbatim but MUST NOT be read for routing —
105
- * which rule prices a ticker is decided solely by the client's `oracleSource`
106
- * create option (see `OracleHost.oracleSources`), mirroring `pyth_lazer_rule`.
97
+ * which rule prices a ticker is decided solely by the client's derived fed set
98
+ * (see `OracleHost.oracleSources`), mirroring `pyth_lazer_rule`.
107
99
  */
108
100
  export interface WaterxRulePackage extends BasePackageEntry {
109
101
  /** Shared `waterx_rule::Config` (per-symbol on-chain feed_config). */
@@ -127,23 +119,21 @@ export interface WaterxOraclePackage extends BasePackageEntry {
127
119
  * structurally an oracle config.
128
120
  */
129
121
  export interface OraclePackages {
130
- pyth_rule: PythRulePackage;
131
- pyth_sponsor_rule?: PythSponsorRulePackage;
132
122
  /** See {@link PythLazerRulePackage} — typed only, not read for routing. */
133
123
  pyth_lazer_rule?: PythLazerRulePackage;
134
124
  constant_rule?: WaterxConstantRulePackage;
135
125
  supra_rule?: SupraRulePackage;
136
- /** See {@link WaterxRulePackage} — read by `WaterxRule` when `oracleSource` selects it. */
126
+ /** See {@link WaterxRulePackage} — read by `WaterxRule` when the config wires it. */
137
127
  waterx_rule?: WaterxRulePackage;
138
128
  waterx_oracle: WaterxOraclePackage;
139
129
  }
140
130
  /**
141
131
  * The caller-tunable subset of `fetchWithPolicy`'s policy exposed on the
142
132
  * `pythFetch` create option and `client.pyth.fetch` — the retry/timeout budget
143
- * for the off-chain Hermes (`fetchPriceFeedsUpdateData`) and Lazer
144
- * (`PythLazerRule`) update fetches. Deliberately narrower than the internal
145
- * `FetchPolicy` (no `retryDelayMs` / `apiKey` / `fetchImpl`). Both fetches fall
146
- * back to `fetchWithPolicy`'s defaults (15s timeout, 2 retries) when unset.
133
+ * for the off-chain Lazer (`PythLazerRule`) update fetch and the Lazer read
134
+ * executor (`readLazerPrices`). Deliberately narrower than the internal
135
+ * `FetchPolicy` (no `retryDelayMs` / `apiKey` / `fetchImpl`). Falls back to
136
+ * `fetchWithPolicy`'s defaults (15s timeout, 2 retries) when unset.
147
137
  */
148
138
  export type PythFetchPolicy = {
149
139
  timeoutMs?: number;
@@ -151,10 +141,9 @@ export type PythFetchPolicy = {
151
141
  };
152
142
  /**
153
143
  * `client.pyth` — ONLY the caller-supplied Pyth credential + fetch policy,
154
- * shared by the Pyth-family rules (`pyth_rule`, `pyth_lazer_rule`). It carries
155
- * NO endpoints and NO on-chain object ids: every oracle source owns its own
156
- * infra, co-located with its rule (`PYTH_CORE_INFRA` in `oracle/pyth.ts`;
157
- * the Lazer constants inside `rules/pyth-lazer-rule.ts`). A non-Pyth source
144
+ * read by `PythLazerRule`. It carries NO endpoints and NO on-chain object
145
+ * ids: every oracle source owns its own infra, co-located with its rule (the
146
+ * Lazer constants inside `rules/pyth-lazer-rule.ts`). A non-Pyth source
158
147
  * never reads this slice.
159
148
  * Nothing here is sourced from the canonical `waterx-config` JSON — a Bearer
160
149
  * secret has no place in a public CDN document.
@@ -163,22 +152,20 @@ export interface PythAccessConfig {
163
152
  /**
164
153
  * Pyth access token (`Authorization: Bearer …`). Required by
165
154
  * `PythLazerRule`'s signed-update fetch — Lazer is auth-first, so there is
166
- * no keyless default; absent when a lazer-routed fetch runs →
167
- * `LazerApiKeyMissing` is thrown at fetch time. Supplied via the
168
- * `pythApiKey` create option (the SDK never reads `process.env` or the
169
- * config JSON). As of the Pyth Pro migration (post-2026-08-18, per
170
- * https://docs.pyth.network/price-feeds/core/upgrade) this is ALSO required
171
- * for `pyth_rule`'s Hermes fetch (`fetchPriceFeedsUpdateData`) — see
172
- * `fetch` below.
155
+ * no keyless default; absent when a lazer-routed build runs →
156
+ * `LazerApiKeyMissing` is thrown by `refreshOraclePrices`'s credential
157
+ * pre-check (before any fetch) or by the rule's own fetch. Supplied via
158
+ * the `pythApiKey` create option (the SDK never reads `process.env` or the
159
+ * config JSON). The same key authenticates the Pyth Pro read/history
160
+ * surfaces (`readLazerPrices`, `fetchPythProHistory`).
173
161
  */
174
162
  api_key?: string;
175
163
  /**
176
- * Retry/timeout policy for the Hermes (`fetchPriceFeedsUpdateData`) and
177
- * Lazer (`PythLazerRule`) off-chain update fetches see `fetchWithPolicy`
178
- * (`./update-fetch.ts`) for the full policy (backoff, which statuses retry,
179
- * Bearer attachment). Supplied via the `pythFetch` create option. Optional:
180
- * both fetches default to `fetchWithPolicy`'s built-in defaults (15s
181
- * timeout, 2 retries) when unset.
164
+ * Retry/timeout policy for the Lazer (`PythLazerRule`) off-chain update
165
+ * fetch — see `fetchWithPolicy` (`./update-fetch.ts`) for the full policy
166
+ * (backoff, which statuses retry, Bearer attachment). Supplied via the
167
+ * `pythFetch` create option. Optional: defaults to `fetchWithPolicy`'s
168
+ * built-in defaults (15s timeout, 2 retries) when unset.
182
169
  */
183
170
  fetch?: PythFetchPolicy;
184
171
  }
@@ -201,7 +188,7 @@ export interface WaterxAccessConfig {
201
188
  * Quote-center base URL override (`waterxEndpoint` create option). A base
202
189
  * PATH is preserved — the rule appends via `joinEndpointPath`, so
203
190
  * `https://app.example/api/quote-center` resolves to
204
- * `…/api/quote-center/v1/quotes/update` and a proxy route is not rewritten
191
+ * `…/api/quote-center/v1/quotes/leaves` and a proxy route is not rewritten
205
192
  * away. A trailing slash is trimmed.
206
193
  */
207
194
  endpoint?: string;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Oracle-layer config schema — the package entries + config slice the shared
3
- * oracle layer (Pyth source + oracle rules + aggregate) reads. This is shared
3
+ * oracle layer (oracle rules + aggregate) reads. This is shared
4
4
  * infra, **not** the perp line: `perp/config.ts` imports these and
5
5
  * `WaterXPackages extends OraclePackages`; nothing here imports `perp/` or
6
6
  * `prediction/`. Snake_case mirrors the canonical `waterx-config` JSON 1:1.
@@ -3,16 +3,16 @@
3
3
  *
4
4
  * The oracle/refresh code used to take a concrete `PerpClient`, which fused the
5
5
  * shared oracle layer to the perp line. It only ever needs config-schema
6
- * lookups, the Pyth infra block, and a gRPC client — so it depends on this
7
- * structural interface instead. `PerpClient` satisfies it without any `implements`
8
- * clause, and a future `PredictClient` (or a test double) can too.
6
+ * lookups, the caller-supplied access slices, and a gRPC client — so it depends
7
+ * on this structural interface instead. `PerpClient` satisfies it without any
8
+ * `implements` clause, and a future `PredictClient` (or a test double) can too.
9
9
  */
10
10
  import type { SuiGrpcClient } from "@mysten/sui/grpc";
11
11
  import type { Network } from "../constants.ts";
12
12
  import type { OracleConfig, PythAccessConfig, WaterxAccessConfig } from "./config.ts";
13
13
  import type { OracleSource } from "./price-update-rule.ts";
14
14
  export interface OracleHost {
15
- /** Sui network this client targets — each rule keys its OWN infra table by it (`PYTH_CORE_INFRA`, `LAZER_INFRA`). */
15
+ /** Sui network this client targets — each rule keys its OWN infra table by it (`LAZER_INFRA`, `WATERX_INFRA`). */
16
16
  readonly network: Network;
17
17
  /** Oracle slice of the canonical `waterx-config` JSON (rule packages + per-ticker feeds). */
18
18
  readonly config: OracleConfig;
@@ -29,19 +29,19 @@ export interface OracleHost {
29
29
  * by the quote-center's CORS allowlist.
30
30
  */
31
31
  readonly waterx?: WaterxAccessConfig;
32
- /** gRPC client for the on-chain reads the Pyth update path needs. */
32
+ /** gRPC client for any on-chain reads an update path needs. */
33
33
  readonly grpcClient: SuiGrpcClient;
34
34
  /**
35
- * The FED SET for `refreshOraclePrices`'s update legs the REQUIRED
36
- * `oracleSource` create option normalized to a non-empty, deduped list.
37
- * Every listed source's data is fetched and fed in one build; the chain's
35
+ * The FED SET for `refreshOraclePrices`'s update legs, derived from the
36
+ * deployment config (`deriveOracleSources`) never a create option and
37
+ * never an env var.
38
+ *
39
+ * Every derived source's data is fetched and fed in one build; the chain's
38
40
  * per-ticker weight tables decide which contributions count (feeding an
39
- * unweighted rule is dropped on-chain; starving a weighted one aborts), so
40
- * during weight migrations the list stays a SUPERSET of every ticker's
41
- * weighted set. Routing is driven by this value ALONE: never by a config
42
- * JSON `enabled` flag and never by `process.env` — the SDK never reads it;
43
- * consumers (BE/FE) wire this option from their own env var
44
- * (`ORACLE_SOURCE`, comma-separated).
41
+ * unweighted rule is dropped on-chain; starving a weighted one aborts).
42
+ * Deriving the maximal wired set is therefore the fail-safe direction, and
43
+ * it keeps the fed set a SUPERSET of every ticker's weighted set through a
44
+ * weight migration for free.
45
45
  */
46
46
  readonly oracleSources: readonly OracleSource[];
47
47
  /** True when `ticker` is priced by `constant_rule`. */
@@ -52,9 +52,4 @@ export interface OracleHost {
52
52
  config: string;
53
53
  oracle_holder: string;
54
54
  } | undefined;
55
- /** The `pyth_rule.feeds` entry for `ticker` (`{ feed_id, price_info_object }`); throws if absent. */
56
- getPythFeed(ticker: string): {
57
- feed_id: string;
58
- price_info_object: string;
59
- };
60
55
  }
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * The oracle/refresh code used to take a concrete `PerpClient`, which fused the
5
5
  * shared oracle layer to the perp line. It only ever needs config-schema
6
- * lookups, the Pyth infra block, and a gRPC client — so it depends on this
7
- * structural interface instead. `PerpClient` satisfies it without any `implements`
8
- * clause, and a future `PredictClient` (or a test double) can too.
6
+ * lookups, the caller-supplied access slices, and a gRPC client — so it depends
7
+ * on this structural interface instead. `PerpClient` satisfies it without any
8
+ * `implements` clause, and a future `PredictClient` (or a test double) can too.
9
9
  */
10
10
  export {};
@@ -5,32 +5,41 @@
5
5
  * - `host.ts` — `OracleHost`, the narrow client slice this module reads.
6
6
  * - `update-fetch.ts` — `fetchWithPolicy`, the shared retry/timeout/Bearer resilience
7
7
  * wrapper every off-chain oracle (and config) fetch goes through.
8
- * - `pyth.ts` — Pyth as a price source: Hermes REST + on-chain update PTB.
9
8
  * - `price-update-rule.ts`— `PriceUpdateRule`, the fetch/build strategy port a rule
10
9
  * implements; `rule-registry.ts` + `aggregate.ts` wire
11
10
  * routing across rules.
12
- * - `rules/*` — one file per oracle rule (pyth / supra / constant / sponsor).
11
+ * - `rules/*` — one file per oracle rule (lazer / waterx / supra / constant).
13
12
  * - `aggregate.ts` — the orchestrator that feeds rules into a collector + aggregates.
14
- *
15
- * `pyth.ts` deliberately imports NO rule package — Pyth-the-source and the
16
- * rules that consume it are separate concerns.
13
+ * - `read-plane.ts` / `read-prices.ts` — per-source READ plans + their executors.
14
+ * - `validate.ts` consumers' boot-time coverage/credential asserts.
15
+ * - `schedule.ts` / `symbol-catalog.ts` / `pyth-pro-history.ts` market hours
16
+ * (parser + status walker), the Pyth Pro symbol catalog,
17
+ * and Pro chart history.
17
18
  */
18
19
  export type { OracleHost } from "./host.ts";
19
20
  export { FetchPolicyError, fetchWithPolicy, joinEndpointPath } from "./update-fetch.ts";
20
21
  export type { FetchPolicy } from "./update-fetch.ts";
21
- export { PythCache, fetchPriceFeedsUpdateData, endpointSupportedFeedIds, probeMissingFeeds, buildPythPriceUpdateCalls, pythCoreHermesEndpoint, pythProHermesEndpoint, PYTH_PRO_HERMES_ENDPOINT, updatePythPrices, HermesEndpointRejectedAllFeedsError, MISSING_FEED_MEMO_TTL_MS, OracleFeeSourceUnavailableError, } from "./pyth.ts";
22
- export type { OracleFeeSource } from "./pyth.ts";
23
- export type { PriceUpdateRule, PriceUpdateRuleKind, RuleUpdateData, RuleUpdateHandle, BuildUpdateOpts, OracleSource, UpdateDataProvider, } from "./price-update-rule.ts";
22
+ export type { PriceUpdateRule, PriceUpdateRuleKind, RuleUpdateData, RuleUpdateHandle, OracleCredentialRequirement, OracleCredentials, OracleSource, UpdateDataProvider, } from "./price-update-rule.ts";
23
+ export { oracleCredentialsFromHost } from "./price-update-rule.ts";
24
24
  export { ORACLE_SOURCES } from "./price-update-rule.ts";
25
- export { isOracleSource, parseOracleSourceList } from "./source-list.ts";
26
- export { resolveOracleReadPlan, resolveHermesReadEndpoint } from "./read-plane.ts";
25
+ export { deriveOracleSources } from "./source-list.ts";
26
+ export { resolveOracleReadPlan, readPlanTickers } from "./read-plane.ts";
27
27
  export type { OracleReadPlan } from "./read-plane.ts";
28
- export { PythCoreRule } from "./rules/pyth-core-rule.ts";
29
- export type { PythCoreUpdatePayload } from "./rules/pyth-core-rule.ts";
28
+ export { LazerNotEntitledError, readLazerPrices, readQuoteCenterPrices } from "./read-prices.ts";
29
+ export type { OraclePriceEntry } from "./read-prices.ts";
30
+ export { OracleTickerUnservedError, assertOracleWriteCoverage, missingOracleCredentials, partitionServableTickers, servableTickers, } from "./validate.ts";
31
+ export type { OracleCredentialKind } from "./validate.ts";
32
+ export { assertOracleWeightCoverage, readOracleWeightCoverage, OracleWeightCoverageError, OracleWeightUnreadableError, } from "./weight-coverage.ts";
33
+ export type { TickerWeightCoverage } from "./weight-coverage.ts";
30
34
  export { PythLazerRule, LazerApiKeyMissingError } from "./rules/pyth-lazer-rule.ts";
31
35
  export type { PythLazerUpdatePayload } from "./rules/pyth-lazer-rule.ts";
32
- export { WaterxRule, parseSignedEnvelope, BATCH_PRICE_INTENT, WATERX_INFRA, waterxQuoteCenterEndpoint, waterxEnvelopeOf, } from "./rules/waterx-rule.ts";
33
- export type { WaterxUpdatePayload, WaterxSignedEnvelope, WaterxBatchItem, } from "./rules/waterx-rule.ts";
36
+ export { WaterxRule, parseSignedEnvelope, parseSignedLeaves, BATCH_PRICE_INTENT, MERKLE_ROOT_INTENT, WATERX_INFRA, waterxQuoteCenterEndpoint, fetchWaterxSignedUpdate, fetchWaterxSignedLeaves, fetchWaterxUpdateData, pullWaterxQuotes, WATERX_MAX_PRICE_AGE_MS, isFreshWaterxEntry, waterxLeavesOf, waterxEnvelopeOf, } from "./rules/waterx-rule.ts";
37
+ export type { WaterxUpdatePayload, WaterxLeafPayload, WaterxEnvelopePayload, WaterxSignedEnvelope, WaterxSignedLeaf, WaterxBatchItem, LeafPull, } from "./rules/waterx-rule.ts";
34
38
  export { OracleSourceNotImplementedError, resolveOracleRule } from "./rule-registry.ts";
35
- export { aggregateTicker, aggregateTickerWithPyth, aggregateTickerWithConstant, refreshOraclePrices, } from "./aggregate.ts";
36
- export { openPythSponsorFund, reimbursePythSponsor } from "./rules/sponsor.ts";
39
+ export { aggregateTicker, aggregateTickerWithConstant, refreshOraclePrices } from "./aggregate.ts";
40
+ export type { OracleRefreshSummary } from "./aggregate.ts";
41
+ export { PythScheduleParseError, parsePythSchedule, getMarketStatus } from "./schedule.ts";
42
+ export type { HolidayDate, MarketStatusResult, ParsedPythSchedule, TradingHours, TradingSession, } from "./schedule.ts";
43
+ export { fetchPythSymbolCatalog } from "./symbol-catalog.ts";
44
+ export type { PythSymbolRecord } from "./symbol-catalog.ts";
45
+ export { fetchPythProHistory } from "./pyth-pro-history.ts";
@@ -5,75 +5,82 @@
5
5
  * - `host.ts` — `OracleHost`, the narrow client slice this module reads.
6
6
  * - `update-fetch.ts` — `fetchWithPolicy`, the shared retry/timeout/Bearer resilience
7
7
  * wrapper every off-chain oracle (and config) fetch goes through.
8
- * - `pyth.ts` — Pyth as a price source: Hermes REST + on-chain update PTB.
9
8
  * - `price-update-rule.ts`— `PriceUpdateRule`, the fetch/build strategy port a rule
10
9
  * implements; `rule-registry.ts` + `aggregate.ts` wire
11
10
  * routing across rules.
12
- * - `rules/*` — one file per oracle rule (pyth / supra / constant / sponsor).
11
+ * - `rules/*` — one file per oracle rule (lazer / waterx / supra / constant).
13
12
  * - `aggregate.ts` — the orchestrator that feeds rules into a collector + aggregates.
14
- *
15
- * `pyth.ts` deliberately imports NO rule package — Pyth-the-source and the
16
- * rules that consume it are separate concerns.
13
+ * - `read-plane.ts` / `read-prices.ts` — per-source READ plans + their executors.
14
+ * - `validate.ts` consumers' boot-time coverage/credential asserts.
15
+ * - `schedule.ts` / `symbol-catalog.ts` / `pyth-pro-history.ts` market hours
16
+ * (parser + status walker), the Pyth Pro symbol catalog,
17
+ * and Pro chart history.
17
18
  */
18
19
  // Shared fetch resilience wrapper — `FetchPolicyError` is re-exported (not
19
20
  // just the type) so a consumer (e.g. a BE prefetch cache) can `instanceof`
20
- // it off the failure `fetchPriceFeedsUpdateData` / `PythLazerRule` /
21
- // `loadConfig` surface, without a deep import of `./update-fetch.ts`.
22
- // `fetchWithPolicy` + `joinEndpointPath` are exported for consumers that hit
23
- // Hermes-compatible endpoints THEMSELVES (e.g. the BE's parsed latest-price
24
- // bootstrap and Pyth schedule readers): one shared Bearer/timeout/retry
25
- // policy and one base-path-safe URL join, instead of each caller re-rolling
26
- // them (the hand-rolled copies were how the Pro `/hermes` base path got
27
- // dropped and the Bearer went missing on sibling fetches).
21
+ // it off a failed rule fetch / `loadConfig` surface, without a deep import
22
+ // of `./update-fetch.ts`. `fetchWithPolicy` + `joinEndpointPath` are exported
23
+ // for consumers that hit oracle-adjacent endpoints THEMSELVES: one shared
24
+ // Bearer/timeout/retry policy and one base-path-safe URL join, instead of
25
+ // each caller re-rolling them (the hand-rolled copies were how base paths
26
+ // got dropped and Bearers went missing on sibling fetches).
28
27
  export { FetchPolicyError, fetchWithPolicy, joinEndpointPath } from "./update-fetch.js";
29
- // Pyth source `OracleFeeSourceUnavailableError` and
30
- // `HermesEndpointRejectedAllFeedsError` are re-exported (not just the types)
31
- // for the same `instanceof` reason as `FetchPolicyError` above: a consumer of
32
- // `buildPythPriceUpdateCalls` / `updatePythPrices` / `refreshOraclePrices` can
33
- // branch on the fee-source failure directly, and a consumer of
34
- // `fetchPriceFeedsUpdateData` / `probeMissingFeeds` can tell a misconfigured
35
- // or unentitled endpoint apart from feeds that endpoint genuinely lacks.
36
- export { PythCache, fetchPriceFeedsUpdateData, endpointSupportedFeedIds, probeMissingFeeds, buildPythPriceUpdateCalls,
37
- // The pyth read-plane endpoint accessors — Core (keyless, per network) and
38
- // Pro (the documented fixed base; auth via the caller's Bearer key). There
39
- // is no client-level endpoint field: consumers pick via
40
- // `resolveHermesReadEndpoint` (pyth_rule listed → Core, else override ??
41
- // Pro) — never a hand-rolled branch, never a cross-source fallback.
42
- pythCoreHermesEndpoint, pythProHermesEndpoint, PYTH_PRO_HERMES_ENDPOINT, updatePythPrices, HermesEndpointRejectedAllFeedsError, MISSING_FEED_MEMO_TTL_MS, OracleFeeSourceUnavailableError, } from "./pyth.js";
43
- // Canonical OracleSource value list + THE env-string parser consumers fold
44
- // onto — semantics and rationale in `source-list.ts`'s header.
28
+ export { oracleCredentialsFromHost } from "./price-update-rule.js";
29
+ // Canonical OracleSource value list + THE fed-set derivation (config in,
30
+ // sources out) semantics and rationale in `source-list.ts`'s header. There
31
+ // is no `oracleSource` option and no `ORACLE_SOURCE` env var to parse.
45
32
  export { ORACLE_SOURCES } from "./price-update-rule.js";
46
- export { isOracleSource, parseOracleSourceList } from "./source-list.js";
33
+ export { deriveOracleSources } from "./source-list.js";
47
34
  // Per-source READ-plane resolution — which tickers a source can price
48
- // off-chain and with which ids (`resolveOracleReadPlan`), and which
49
- // Hermes-compatible base the hermes plans execute against
50
- // (`resolveHermesReadEndpoint`: pyth_rule listed Core, else override ??
51
- // the documented Pyth Pro base). The one place the "lazer reads through
52
- // `pyth_rule.feeds` hex ids" invariant lives; consumers resolve through
53
- // this instead of hardcoding namespace sharing or endpoint branching.
54
- export { resolveOracleReadPlan, resolveHermesReadEndpoint } from "./read-plane.js";
55
- // Pyth Core rule (PriceUpdateRule wrapper over the Pyth source above)
56
- export { PythCoreRule } from "./rules/pyth-core-rule.js";
35
+ // off-chain and with which ids (`resolveOracleReadPlan`; every source reads
36
+ // its OWN feeds namespace, so write set == read set), plus the executors that
37
+ // run a plan (`readLazerPrices` / `readQuoteCenterPrices`) and decode each
38
+ // source's wire scaling in ONE place. `LazerNotEntitledError` is re-exported
39
+ // (not just the type) for the same `instanceof` reason as `FetchPolicyError`
40
+ // above: a consumer drops unentitled feeds and retries.
41
+ export { resolveOracleReadPlan, readPlanTickers } from "./read-plane.js";
42
+ export { LazerNotEntitledError, readLazerPrices, readQuoteCenterPrices } from "./read-prices.js";
43
+ // Boot-time deployment asserts consumers fold onto (`OracleTickerUnservedError`
44
+ // is `instanceof`-able, same rationale as above — and is the SAME type the
45
+ // per-build composers raise). Deliberately NOT called at client creation —
46
+ // see `validate.ts`'s header.
47
+ export { OracleTickerUnservedError, assertOracleWriteCoverage, missingOracleCredentials, partitionServableTickers, servableTickers, } from "./validate.js";
48
+ // The ON-CHAIN half of the same question. `validate.ts` reasons from config
49
+ // alone (necessary, not sufficient); this reads the aggregator weights, which
50
+ // is the only way to catch a ticker that is servable by config yet weighted to
51
+ // a rule the fed set cannot supply — the shape that aborts a WHOLE PTB.
52
+ export { assertOracleWeightCoverage, readOracleWeightCoverage, OracleWeightCoverageError, OracleWeightUnreadableError, } from "./weight-coverage.js";
57
53
  // Pyth Lazer rule (signed-update generation; `feedLazerRule` stays internal to `aggregate.ts`)
58
54
  // `LazerApiKeyMissingError` is re-exported (not just the type) for the same
59
- // `instanceof` reason as `OracleFeeSourceUnavailableError` above.
55
+ // `instanceof` reason as `FetchPolicyError` above.
60
56
  export { PythLazerRule, LazerApiKeyMissingError } from "./rules/pyth-lazer-rule.js";
61
57
  // `WATERX_INFRA` / `waterxQuoteCenterEndpoint` are the source's own infra table +
62
- // read-plane accessor (mirrors `pythCoreHermesEndpoint`).
63
- // WaterX quote-center rule (first-party ed25519 signed batches; `feedWaterxRule`
64
- // stays internal to `aggregate.ts`).
65
- export { WaterxRule, parseSignedEnvelope, BATCH_PRICE_INTENT, WATERX_INFRA, waterxQuoteCenterEndpoint,
66
- // Rule-owned payload accessor (kind-check + unwrap in one place) — never
67
- // hand-cast the payload shape.
68
- waterxEnvelopeOf, } from "./rules/waterx-rule.js";
58
+ // read-plane accessor.
59
+ // WaterX quote-center rule (first-party ed25519 signed prices; the `feedWaterxRule*`
60
+ // legs stay internal to `aggregate.ts`). Both wire shapes are exported because a
61
+ // BE prefetch cache holds whichever one its quote-center serves: per-symbol
62
+ // Merkle leaves (default) or one indivisible batch envelope (fallback). The
63
+ // WL-2345 seams: the raw fetchers (`fetchWaterxSignedUpdate` /
64
+ // `fetchWaterxSignedLeaves`), the coverage-policy fetch
65
+ // (`fetchWaterxUpdateData`), and the freshness contract
66
+ // (`WATERX_MAX_PRICE_AGE_MS` / `isFreshWaterxEntry`).
67
+ export { WaterxRule, parseSignedEnvelope, parseSignedLeaves, BATCH_PRICE_INTENT, MERKLE_ROOT_INTENT, WATERX_INFRA, waterxQuoteCenterEndpoint, fetchWaterxSignedUpdate, fetchWaterxSignedLeaves, fetchWaterxUpdateData, pullWaterxQuotes, WATERX_MAX_PRICE_AGE_MS, isFreshWaterxEntry,
68
+ // Rule-owned payload accessors (kind-check + unwrap in one place) — never
69
+ // hand-cast the payload shape, and never assume which variant it is.
70
+ waterxLeavesOf, waterxEnvelopeOf, } from "./rules/waterx-rule.js";
69
71
  // `resolveOracleRule` is the ONE source→rule registry — exported so external
70
72
  // consumers (e.g. a BE prefetch cache that keys per source and needs each
71
- // source's `supportedTickers`/`fetchUpdateData`) resolve through it instead of
72
- // hand-mirroring the map and drifting. `OracleSourceNotImplementedError` is
73
- // its `instanceof`-able failure (same reason as `OracleFeeSourceUnavailableError`
74
- // above).
73
+ // source's `supportedTickers`/`fetchUpdateData`/`updateIdentityBySymbol`)
74
+ // resolve through it instead of hand-mirroring the map and drifting.
75
+ // `OracleSourceNotImplementedError` is its `instanceof`-able failure (same
76
+ // reason as `FetchPolicyError` above).
75
77
  export { OracleSourceNotImplementedError, resolveOracleRule } from "./rule-registry.js";
76
78
  // Aggregation orchestrator
77
- export { aggregateTicker, aggregateTickerWithPyth, aggregateTickerWithConstant, refreshOraclePrices, } from "./aggregate.js";
78
- // Sponsor rule (fund open / reimburse + witness attach)
79
- export { openPythSponsorFund, reimbursePythSponsor } from "./rules/sponsor.js";
79
+ export { aggregateTicker, aggregateTickerWithConstant, refreshOraclePrices } from "./aggregate.js";
80
+ // Market hours: the Pyth schedule-grammar parser + the pure market-status
81
+ // walker (the one cross-repo implementation — see `schedule.ts`'s header).
82
+ export { PythScheduleParseError, parsePythSchedule, getMarketStatus } from "./schedule.js";
83
+ // Pyth Pro symbol catalog (keyless; schedule strings + hex↔integer id map)
84
+ // and Bearer-keyed chart history.
85
+ export { fetchPythSymbolCatalog } from "./symbol-catalog.js";
86
+ export { fetchPythProHistory } from "./pyth-pro-history.js";