@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
package/README.md
CHANGED
|
@@ -11,19 +11,21 @@ The perp and prediction lines expose builder functions with **colliding names**
|
|
|
11
11
|
```ts
|
|
12
12
|
import { WaterXClient } from "@waterx/sdk";
|
|
13
13
|
|
|
14
|
-
// waterxConfigUrl
|
|
14
|
+
// waterxConfigUrl and oracleSource are REQUIRED — the SDK has no built-in
|
|
15
|
+
// defaults and never reads env. oracleSource: see "Oracle sources" below.
|
|
15
16
|
const client = await WaterXClient.create({
|
|
16
17
|
network: "TESTNET",
|
|
17
18
|
waterxConfigUrl:
|
|
18
19
|
"https://raw.githubusercontent.com/WaterXProtocol/waterx-config/main/testnet.json",
|
|
20
|
+
oracleSource: "pyth_rule",
|
|
19
21
|
});
|
|
20
22
|
client.account.createAccount(tx, { alias }); // shared waterx_account + funding (credit/custody)
|
|
21
23
|
client.perp.buildPlaceOrderTx(params); // perpetuals
|
|
22
24
|
client.predict.placeOrder(tx, params); // prediction markets
|
|
23
25
|
// client.perp / client.predict ARE the line clients — sign/execute on them directly:
|
|
24
26
|
// await client.perp.signAndExecuteTransaction({ transaction: tx, signer })
|
|
25
|
-
// each line can target a different network + URL:
|
|
26
|
-
// WaterXClient.create({ perp: { network: "MAINNET", waterxConfigUrl: mainnetUrl }, predict: { network: "TESTNET", waterxConfigUrl: testnetUrl } })
|
|
27
|
+
// each line can target a different network + URL (oracleSource stays top-level):
|
|
28
|
+
// WaterXClient.create({ oracleSource: "pyth_rule", perp: { network: "MAINNET", waterxConfigUrl: mainnetUrl }, predict: { network: "TESTNET", waterxConfigUrl: testnetUrl } })
|
|
27
29
|
```
|
|
28
30
|
|
|
29
31
|
> `WaterXClient` is the umbrella entry point. `Client` is kept as a **deprecated alias** for one major cycle.
|
|
@@ -56,6 +58,7 @@ import { Transaction } from "@mysten/sui/transactions";
|
|
|
56
58
|
const client = await WaterXClient.create({
|
|
57
59
|
network: "TESTNET",
|
|
58
60
|
waterxConfigUrl: "https://raw.githubusercontent.com/WaterXProtocol/waterx-config/main/testnet.json",
|
|
61
|
+
oracleSource: "pyth_rule", // REQUIRED — single source or a list (the fed set); see "Oracle sources"
|
|
59
62
|
});
|
|
60
63
|
const signer = /* your Ed25519Keypair or wallet Signer */;
|
|
61
64
|
|
|
@@ -94,46 +97,53 @@ import { PredictClient } from "@waterx/sdk/prediction";
|
|
|
94
97
|
|
|
95
98
|
const waterxConfigUrl =
|
|
96
99
|
"https://raw.githubusercontent.com/WaterXProtocol/waterx-config/main/testnet.json";
|
|
97
|
-
const perp = await PerpClient.create("TESTNET", { waterxConfigUrl }); // or PerpClient.testnet({
|
|
98
|
-
const predict = await PredictClient.create("TESTNET", { waterxConfigUrl }); //
|
|
100
|
+
const perp = await PerpClient.create("TESTNET", { waterxConfigUrl, oracleSource: "pyth_rule" }); // or PerpClient.testnet({ ... })
|
|
101
|
+
const predict = await PredictClient.create("TESTNET", { waterxConfigUrl }); // predict line needs no oracle source
|
|
99
102
|
```
|
|
100
103
|
|
|
101
104
|
Read-only queries use gRPC `simulateTransaction` (no signer) — the `getX` view helpers, e.g. `await perp.simulate(tx)` or `getMarketData(perp, …)`.
|
|
102
105
|
|
|
103
106
|
## Oracle sources
|
|
104
107
|
|
|
105
|
-
ONE client create option, `oracleSource`,
|
|
108
|
+
ONE **required** client create option, `oracleSource`, names the price-update source(s) — a single value or a **list (the fed set)**. Each source is **self-contained** — it owns its own infra + config and does **not** back-stop any other source. There is **no default source**: a client that has not named its sources fails at creation. The name is source-neutral on purpose: a future source need not be Pyth. The SDK **never reads `process.env`** — each consumer wires it from its own env var, so every environment runs the **same SDK version** and differs only by env:
|
|
106
109
|
|
|
107
|
-
| Option | Values
|
|
108
|
-
| -------------- |
|
|
109
|
-
| `oracleSource` | `'pyth_rule'`
|
|
110
|
+
| Option | Values | What it selects |
|
|
111
|
+
| -------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
112
|
+
| `oracleSource` | `OracleSource \| OracleSource[]` of `'pyth_rule'` \| `'pyth_lazer_rule'` \| `'waterx_rule'` — REQUIRED, no default | The price-update source(s). `'pyth_rule'` = Pyth Core updates (Hermes VAA + per-feed update fees, keyless `hermes.pyth.network`). `'pyth_lazer_rule'` = Pyth Lazer signed updates (ONE `leEcdsa` verify per PTB, no per-feed fees); needs `packages.pyth_lazer_rule` feeds + a `pythApiKey`. `'waterx_rule'` = the first-party WaterX quote-center (Nautilus-TEE, ed25519-signed CEX prices): one signed batch envelope per build, no API key and no per-update fee; needs `packages.waterx_rule` feeds. |
|
|
110
113
|
|
|
111
|
-
**
|
|
114
|
+
**Multi-source fed sets.** With a list, ONE build fetches and feeds EVERY listed source's data in the same PTB; the chain's per-ticker aggregator **weight tables** decide which contributions count — feeding an unweighted rule's price is dropped on-chain, while starving a weighted rule aborts. That asymmetry is what makes weight migrations (Core→Pro, Pyth↔waterx coexistence) safe: keep the list a **superset** of every ticker's weighted rule set and flip weights per ticker at any time — an env edit, never an SDK release. (One caveat: waterx's feed call burns a per-symbol signed-timestamp high-water mark regardless of weights — see the replay note below.)
|
|
112
115
|
|
|
113
|
-
|
|
116
|
+
**No cross-source fallback, no feeds guard at init.** Construction rejects an empty/nullish `oracleSource` **and any value outside `ORACLE_SOURCES`** (a legacy `'core'` / `'pyth'` string fails at `create`), but a listed source whose feed for a requested ticker is absent is **not** an error at client creation — the build fails at **tx-build** only when **no** listed source serves the ticker (constant-only tickers, which need no price update, are exempt). A present-but-wrong feed id is not validated by the SDK; it aborts on-chain at dry-run.
|
|
117
|
+
|
|
118
|
+
Every source's external infra is a **rule-owned per-network table**, never deployment-overridable and never in the config JSON: `PYTH_CORE_INFRA` (`src/oracle/pyth.ts` — Pyth state ids + the keyless Core Hermes endpoint, read-plane accessor `pythCoreHermesEndpoint(network)`), `LAZER_INFRA` (`src/oracle/rules/pyth-lazer-rule.ts`), `WATERX_INFRA` (`src/oracle/rules/waterx-rule.ts` — testnet `quote-center-staging.waterx.app` / mainnet `quote-center.waterx.app`, accessor `waterxQuoteCenterEndpoint(network)`). For **price READS** under a fed set without `pyth_rule`, the documented Pyth Pro base (`pythProHermesEndpoint()` — identical for every subscriber, auth via the Bearer key) applies: resolve the read endpoint with `resolveHermesReadEndpoint(network, sources, override?)` instead of branching by hand, and pair it with `resolveOracleReadPlan` for the per-source served-sets/ids. `client.pyth` is the access-only `PythAccessConfig` — just the caller-supplied `pythApiKey` / `pythFetch` create options (a secret has no place in a public CDN JSON); `client.waterx` is likewise `WaterxAccessConfig` (`waterxEndpoint` / `waterxFetch` overrides only; fetch policy resolves **`waterxFetch` → built-in defaults** — deliberately no `pythFetch` fallback, sources never share config). See the browser/CORS note below.
|
|
114
119
|
|
|
115
120
|
```ts
|
|
116
|
-
// Per-environment wiring — the consumer owns the env var, not the SDK
|
|
121
|
+
// Per-environment wiring — the consumer owns the env var, not the SDK.
|
|
122
|
+
// parseOracleSourceList is THE canonical parser (trim, drop empty entries,
|
|
123
|
+
// validate every value, dedupe, throw operator-actionably) — never a bare
|
|
124
|
+
// split-and-cast, which would hand the strict constructor untrimmed junk.
|
|
125
|
+
import { parseOracleSourceList } from "@waterx/sdk/oracle";
|
|
126
|
+
|
|
117
127
|
const perp = await PerpClient.create(network, {
|
|
118
128
|
waterxConfigUrl,
|
|
119
|
-
oracleSource: process.env.ORACLE_SOURCE
|
|
120
|
-
pythApiKey: process.env.PYTH_API_KEY, // Lazer is auth-first
|
|
129
|
+
oracleSource: parseOracleSourceList(process.env.ORACLE_SOURCE), // REQUIRED; comma list = the fed set
|
|
130
|
+
pythApiKey: process.env.PYTH_API_KEY, // required iff 'pyth_lazer_rule' is listed (Lazer is auth-first)
|
|
121
131
|
});
|
|
122
132
|
```
|
|
123
133
|
|
|
124
|
-
This is the
|
|
134
|
+
This is the coexistence rollout pattern: staging lists every source under migration (`ORACLE_SOURCE=pyth_rule,pyth_lazer_rule,waterx_rule` + `PYTH_API_KEY`) while production stays single-value (`ORACLE_SOURCE=pyth_rule`) until its weight tables move — flipping an environment is an env-var change, never an SDK release.
|
|
125
135
|
|
|
126
136
|
### Adding an oracle source (runbook)
|
|
127
137
|
|
|
128
138
|
Every source plugs in the same way — routing is driven **only** by the client's `oracleSource` option (never a config `enabled` flag, never `process.env`):
|
|
129
139
|
|
|
130
140
|
1. **Implement `PriceUpdateRule`** in `src/oracle/rules/<name>-rule.ts` — all port fields (`src/oracle/price-update-rule.ts`): `kind`, `requiresFeeSource` (`true` iff the on-chain verify draws a per-update fee — gates the fail-fast fee-source check), `supportedTickers`, `fetchUpdateData`, `narrowUpdateData` (subset a cached whole-universe payload to one build's tickers — a divisible payload returns a per-feed subset, an indivisible one returns itself whole iff fully covered; uncovered ticker → `null` miss), `buildUpdateCalls`.
|
|
131
|
-
2. **Register it** in `src/oracle/rule-registry.ts` (`DEFAULT_RULES`) under a new `OracleSource` value
|
|
141
|
+
2. **Register it** in `src/oracle/rule-registry.ts` (`DEFAULT_RULES`) under a new `OracleSource` value — added to `ORACLE_SOURCES` in `price-update-rule.ts` (the union derives from that list; a registry test pins every listed value to a registered rule).
|
|
132
142
|
3. **Publish the on-chain rule package** — its config entry (package ids, per-ticker `feeds`) arrives via the normal `waterx-config` deploy pipeline; type it in `OraclePackages` (`src/oracle/config.ts`).
|
|
133
|
-
4. **Add SDK infra constants** if the source needs external infra that is not part of the config JSON (API endpoints, verifier packages, state objects) — a per-network
|
|
143
|
+
4. **Add SDK infra constants** if the source needs external infra that is not part of the config JSON (API endpoints, verifier packages, state objects) — a **rule-owned** per-network table inside the rule's own file, mirroring `LAZER_INFRA` / `WATERX_INFRA` (never on the shared client, never in `oracle/config.ts`). Wire its read-plane served-set/ids into `resolveOracleReadPlan` (`src/oracle/read-plane.ts`).
|
|
134
144
|
5. **Consumers flip `oracleSource`** per environment — no consumer code change, no SDK re-release.
|
|
135
145
|
|
|
136
|
-
The in-house `waterx_rule` (ed25519 enclave-signed CEX prices, `src/oracle/rules/waterx-rule.ts`) took exactly this path: it pulls one enclave-signed batch envelope covering the requested tickers from the quote-center (`GET /v1/quotes/update?symbols=…`, public read — no auth), then verifies **and** feeds in a single `waterx_rule::collect_batch_latest` call per collector, so it emits no shared verify step. On-chain a freshness miss
|
|
146
|
+
The in-house `waterx_rule` (ed25519 enclave-signed CEX prices, `src/oracle/rules/waterx-rule.ts`) took exactly this path: it pulls one enclave-signed batch envelope covering the requested tickers from the quote-center (`GET /v1/quotes/update?symbols=…`, public read — no auth), then verifies **and** feeds in a single `waterx_rule::collect_batch_latest` call per collector, so it emits no shared verify step. On-chain a **freshness** miss abstains (the other weighted rules cover); a config mismatch or bad signature aborts — and so does a **replayed** signed timestamp (`EReplayedSignature`, audit F-014: a signed tuple is single-use per symbol, weight-independent). Consequence: two PTBs carrying the same envelope for the same symbol cannot both land — never share one fetched envelope across concurrent builds for the same symbol.
|
|
137
147
|
|
|
138
148
|
> **Browser consumers:** this source fetches the quote-center directly from the page, so the quote-center deployment must return `Access-Control-Allow-Origin` for the app's origin. For an origin that is not on that allowlist, point the SDK at your own proxy instead of the default host — the endpoint and the transport are both overridable at client init:
|
|
139
149
|
>
|
|
@@ -148,7 +158,7 @@ The in-house `waterx_rule` (ed25519 enclave-signed CEX prices, `src/oracle/rules
|
|
|
148
158
|
> });
|
|
149
159
|
> ```
|
|
150
160
|
>
|
|
151
|
-
> Unset, `waterxEndpoint` falls back to `
|
|
161
|
+
> Unset, `waterxEndpoint` falls back to the rule-owned `WATERX_INFRA[network]` and `waterxFetch` to the built-in policy (15s timeout, 2 retries) — there is deliberately no `pythFetch` fallback. Both are inert under the Pyth sources. They are also top-level options on the umbrella `WaterXClient.create({ oracleSource, waterxEndpoint, waterxFetch, … })`, which forwards them to the perp line. Node/keeper consumers are unaffected by CORS either way.
|
|
152
162
|
|
|
153
163
|
## Recipes & full surface
|
|
154
164
|
|
|
@@ -73,8 +73,9 @@ export interface WithdrawalQueuePackage {
|
|
|
73
73
|
/**
|
|
74
74
|
* Wormhole infra for the cross-chain credit bridge. `state_id` is the same
|
|
75
75
|
* shared Sui Wormhole `State` object Pyth uses (kept in sync with
|
|
76
|
-
* `
|
|
77
|
-
* `WaterXConfig.wormhole` if a deployment ever points
|
|
76
|
+
* `PYTH_CORE_INFRA[*].wormhole_state_id` in `oracle/pyth.ts`). Override
|
|
77
|
+
* per-deployment via `WaterXConfig.wormhole` if a deployment ever points
|
|
78
|
+
* elsewhere.
|
|
78
79
|
*/
|
|
79
80
|
export interface WormholeInfraConfig {
|
|
80
81
|
/** Shared Sui Wormhole `State` object. */
|
|
@@ -70,11 +70,6 @@ export declare const BatchPricePayload: MoveStruct<{
|
|
|
70
70
|
length: number;
|
|
71
71
|
}, string>;
|
|
72
72
|
}, "@waterx/rule::waterx_rule::BatchPricePayload">;
|
|
73
|
-
export declare const MerkleRoot: MoveStruct<{
|
|
74
|
-
root: import("@mysten/sui/bcs").BcsType<number[], Iterable<number> & {
|
|
75
|
-
length: number;
|
|
76
|
-
}, string>;
|
|
77
|
-
}, "@waterx/rule::waterx_rule::MerkleRoot">;
|
|
78
73
|
export declare const FeedConfig: MoveStruct<{
|
|
79
74
|
ticker: import("@mysten/sui/bcs").BcsType<string, string, "string">;
|
|
80
75
|
sources: import("@mysten/sui/bcs").BcsType<string[], Iterable<string | number | bigint> & {
|
|
@@ -219,82 +214,17 @@ export interface CollectBatchLatestOptions {
|
|
|
219
214
|
* and so aborts on any stale item, this path runs alongside Pyth/Supra. To let
|
|
220
215
|
* those cover a lagging TEE — the blast-radius bound in the GCP ADR — a
|
|
221
216
|
* _freshness_ miss ABSTAINS (records `none`, which `aggregator::remove_outliers`
|
|
222
|
-
* drops before the `weight_threshold` fail-closed check)
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
* not
|
|
226
|
-
*
|
|
227
|
-
* with the on-chain feed config is a red flag, not a liveness blip. Bad signature,
|
|
228
|
-
* malformed batch, and a future timestamp always abort.
|
|
217
|
+
* drops before the `weight_threshold` fail-closed check). A _config/integrity_
|
|
218
|
+
* mismatch (source / ticker / method / confidence / deviation) still ABORTS: an
|
|
219
|
+
* enclave whose signed payload disagrees with the on-chain feed config is a red
|
|
220
|
+
* flag, not a liveness blip. Bad signature, malformed batch, a future timestamp,
|
|
221
|
+
* and replay always abort.
|
|
229
222
|
*
|
|
230
223
|
* Every gate is identical to `feed_batch_item_latest`; only the abort-vs-abstain
|
|
231
|
-
* disposition of the freshness
|
|
232
|
-
*
|
|
224
|
+
* disposition of the two freshness gates differs, and the sink is the caller's
|
|
225
|
+
* collector rather than a fresh single-rule one.
|
|
233
226
|
*/
|
|
234
227
|
export declare function collectBatchLatest(options: CollectBatchLatestOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
235
|
-
export interface FeedSingleWithProofArguments {
|
|
236
|
-
oracleObj: RawTransactionArgument<string>;
|
|
237
|
-
config: RawTransactionArgument<string>;
|
|
238
|
-
enclaveConfig: RawTransactionArgument<string>;
|
|
239
|
-
enclave: RawTransactionArgument<string>;
|
|
240
|
-
timestampMs: RawTransactionArgument<number | bigint>;
|
|
241
|
-
item: TransactionArgument;
|
|
242
|
-
proof: RawTransactionArgument<Array<Array<number>>>;
|
|
243
|
-
sig: RawTransactionArgument<Array<number>>;
|
|
244
|
-
}
|
|
245
|
-
export interface FeedSingleWithProofOptions {
|
|
246
|
-
package?: string;
|
|
247
|
-
arguments: FeedSingleWithProofArguments | [
|
|
248
|
-
oracleObj: RawTransactionArgument<string>,
|
|
249
|
-
config: RawTransactionArgument<string>,
|
|
250
|
-
enclaveConfig: RawTransactionArgument<string>,
|
|
251
|
-
enclave: RawTransactionArgument<string>,
|
|
252
|
-
timestampMs: RawTransactionArgument<number | bigint>,
|
|
253
|
-
item: TransactionArgument,
|
|
254
|
-
proof: RawTransactionArgument<Array<Array<number>>>,
|
|
255
|
-
sig: RawTransactionArgument<Array<number>>
|
|
256
|
-
];
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Streaming per-symbol sibling of `feed_batch_latest`. Verifies ONE enclave
|
|
260
|
-
* signature over a Merkle `root`, checks `item` is a leaf of that root via
|
|
261
|
-
* `proof`, then runs the identical per-item gates + `oracle::aggregate`. Use for a
|
|
262
|
-
* WaterxRule-only aggregator; for a Pyth-coexisting aggregator use
|
|
263
|
-
* `collect_single_with_proof`.
|
|
264
|
-
*/
|
|
265
|
-
export declare function feedSingleWithProof(options: FeedSingleWithProofOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
266
|
-
export interface CollectSingleWithProofArguments {
|
|
267
|
-
collector: TransactionArgument;
|
|
268
|
-
config: RawTransactionArgument<string>;
|
|
269
|
-
enclaveConfig: RawTransactionArgument<string>;
|
|
270
|
-
enclave: RawTransactionArgument<string>;
|
|
271
|
-
timestampMs: RawTransactionArgument<number | bigint>;
|
|
272
|
-
item: TransactionArgument;
|
|
273
|
-
proof: RawTransactionArgument<Array<Array<number>>>;
|
|
274
|
-
sig: RawTransactionArgument<Array<number>>;
|
|
275
|
-
}
|
|
276
|
-
export interface CollectSingleWithProofOptions {
|
|
277
|
-
package?: string;
|
|
278
|
-
arguments: CollectSingleWithProofArguments | [
|
|
279
|
-
collector: TransactionArgument,
|
|
280
|
-
config: RawTransactionArgument<string>,
|
|
281
|
-
enclaveConfig: RawTransactionArgument<string>,
|
|
282
|
-
enclave: RawTransactionArgument<string>,
|
|
283
|
-
timestampMs: RawTransactionArgument<number | bigint>,
|
|
284
|
-
item: TransactionArgument,
|
|
285
|
-
proof: RawTransactionArgument<Array<Array<number>>>,
|
|
286
|
-
sig: RawTransactionArgument<Array<number>>
|
|
287
|
-
];
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Collect-only sibling of `feed_single_with_proof` for the dual-rule latest path
|
|
291
|
-
* (WaterX alongside Pyth on one aggregator), mirroring `collect_batch_latest`:
|
|
292
|
-
* verifies root + proof, feeds the leaf into the caller's `PriceCollector` WITHOUT
|
|
293
|
-
* calling `oracle::aggregate`. Abort vs abstain matches `collect_batch_latest`
|
|
294
|
-
* exactly — a config/integrity mismatch aborts, a freshness miss abstains so Pyth
|
|
295
|
-
* can cover a lagging TEE.
|
|
296
|
-
*/
|
|
297
|
-
export declare function collectSingleWithProof(options: CollectSingleWithProofOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
298
228
|
export interface QuoteForTimestampArguments {
|
|
299
229
|
config: RawTransactionArgument<string>;
|
|
300
230
|
enclaveConfig: RawTransactionArgument<string>;
|
|
@@ -491,27 +421,6 @@ export interface BatchPriceIntentOptions {
|
|
|
491
421
|
];
|
|
492
422
|
}
|
|
493
423
|
export declare function batchPriceIntent(options?: BatchPriceIntentOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
494
|
-
export interface MerkleRootIntentOptions {
|
|
495
|
-
package?: string;
|
|
496
|
-
arguments?: [
|
|
497
|
-
];
|
|
498
|
-
}
|
|
499
|
-
export declare function merkleRootIntent(options?: MerkleRootIntentOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
500
|
-
export interface LeafHashOfArguments {
|
|
501
|
-
item: TransactionArgument;
|
|
502
|
-
}
|
|
503
|
-
export interface LeafHashOfOptions {
|
|
504
|
-
package?: string;
|
|
505
|
-
arguments: LeafHashOfArguments | [
|
|
506
|
-
item: TransactionArgument
|
|
507
|
-
];
|
|
508
|
-
}
|
|
509
|
-
/**
|
|
510
|
-
* The keccak256 leaf hash for `item` — `keccak256(0x00 || BCS(item))`. Exposed so
|
|
511
|
-
* the off-chain builder / SDK can be pinned against the on-chain encoding in a
|
|
512
|
-
* cross-implementation golden test.
|
|
513
|
-
*/
|
|
514
|
-
export declare function leafHashOf(options: LeafHashOfOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
515
424
|
export interface MaxBatchSizeOptions {
|
|
516
425
|
package?: string;
|
|
517
426
|
arguments?: [
|
|
@@ -808,42 +717,6 @@ export interface SourceGataUsdtPerpWsOptions {
|
|
|
808
717
|
];
|
|
809
718
|
}
|
|
810
719
|
export declare function sourceGataUsdtPerpWs(options?: SourceGataUsdtPerpWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
811
|
-
export interface SourceBybitSpotWsOptions {
|
|
812
|
-
package?: string;
|
|
813
|
-
arguments?: [
|
|
814
|
-
];
|
|
815
|
-
}
|
|
816
|
-
export declare function sourceBybitSpotWs(options?: SourceBybitSpotWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
817
|
-
export interface SourceXstockEquityRestOptions {
|
|
818
|
-
package?: string;
|
|
819
|
-
arguments?: [
|
|
820
|
-
];
|
|
821
|
-
}
|
|
822
|
-
export declare function sourceXstockEquityRest(options?: SourceXstockEquityRestOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
823
|
-
export interface SourceOkxSpotWsOptions {
|
|
824
|
-
package?: string;
|
|
825
|
-
arguments?: [
|
|
826
|
-
];
|
|
827
|
-
}
|
|
828
|
-
export declare function sourceOkxSpotWs(options?: SourceOkxSpotWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
829
|
-
export interface SourceHyperliquidPerpWsOptions {
|
|
830
|
-
package?: string;
|
|
831
|
-
arguments?: [
|
|
832
|
-
];
|
|
833
|
-
}
|
|
834
|
-
export declare function sourceHyperliquidPerpWs(options?: SourceHyperliquidPerpWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
835
|
-
export interface SourceGateioSpotWsOptions {
|
|
836
|
-
package?: string;
|
|
837
|
-
arguments?: [
|
|
838
|
-
];
|
|
839
|
-
}
|
|
840
|
-
export declare function sourceGateioSpotWs(options?: SourceGateioSpotWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
841
|
-
export interface SourceKrakenSpotWsOptions {
|
|
842
|
-
package?: string;
|
|
843
|
-
arguments?: [
|
|
844
|
-
];
|
|
845
|
-
}
|
|
846
|
-
export declare function sourceKrakenSpotWs(options?: SourceKrakenSpotWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
847
720
|
export interface MethodDirectOptions {
|
|
848
721
|
package?: string;
|
|
849
722
|
arguments?: [
|
|
@@ -36,11 +36,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.BatchLatestUpdated = exports.HistoricalPriceVerified = exports.SignedTsHwmKey = exports.Config = exports.VerifiedPrice = exports.FeedConfig = exports.
|
|
39
|
+
exports.BatchLatestUpdated = exports.HistoricalPriceVerified = exports.SignedTsHwmKey = exports.Config = exports.VerifiedPrice = exports.FeedConfig = exports.BatchPricePayload = exports.BatchPriceItem = exports.PricePayload = exports.WaterxRule = exports.WATERX_RULE = void 0;
|
|
40
40
|
exports.feedBatchLatest = feedBatchLatest;
|
|
41
41
|
exports.collectBatchLatest = collectBatchLatest;
|
|
42
|
-
exports.feedSingleWithProof = feedSingleWithProof;
|
|
43
|
-
exports.collectSingleWithProof = collectSingleWithProof;
|
|
44
42
|
exports.quoteForTimestamp = quoteForTimestamp;
|
|
45
43
|
exports.destroyVerifiedPrice = destroyVerifiedPrice;
|
|
46
44
|
exports.collectVerifiedPrice = collectVerifiedPrice;
|
|
@@ -52,8 +50,6 @@ exports.newBatchItem = newBatchItem;
|
|
|
52
50
|
exports.pushBatchItem = pushBatchItem;
|
|
53
51
|
exports.feedConfig = feedConfig;
|
|
54
52
|
exports.batchPriceIntent = batchPriceIntent;
|
|
55
|
-
exports.merkleRootIntent = merkleRootIntent;
|
|
56
|
-
exports.leafHashOf = leafHashOf;
|
|
57
53
|
exports.maxBatchSize = maxBatchSize;
|
|
58
54
|
exports.batchItems = batchItems;
|
|
59
55
|
exports.batchItemSymbol = batchItemSymbol;
|
|
@@ -86,12 +82,6 @@ exports.sourceBinanceUsdmPerpWs = sourceBinanceUsdmPerpWs;
|
|
|
86
82
|
exports.sourceBybitLinearPerpWs = sourceBybitLinearPerpWs;
|
|
87
83
|
exports.sourceGateioUsdtPerpWs = sourceGateioUsdtPerpWs;
|
|
88
84
|
exports.sourceGataUsdtPerpWs = sourceGataUsdtPerpWs;
|
|
89
|
-
exports.sourceBybitSpotWs = sourceBybitSpotWs;
|
|
90
|
-
exports.sourceXstockEquityRest = sourceXstockEquityRest;
|
|
91
|
-
exports.sourceOkxSpotWs = sourceOkxSpotWs;
|
|
92
|
-
exports.sourceHyperliquidPerpWs = sourceHyperliquidPerpWs;
|
|
93
|
-
exports.sourceGateioSpotWs = sourceGateioSpotWs;
|
|
94
|
-
exports.sourceKrakenSpotWs = sourceKrakenSpotWs;
|
|
95
85
|
exports.methodDirect = methodDirect;
|
|
96
86
|
exports.methodMedian = methodMedian;
|
|
97
87
|
exports.methodConfidence = methodConfidence;
|
|
@@ -142,9 +132,6 @@ exports.BatchPriceItem = new index_ts_1.MoveStruct({ name: `${$moduleName}::Batc
|
|
|
142
132
|
exports.BatchPricePayload = new index_ts_1.MoveStruct({ name: `${$moduleName}::BatchPricePayload`, fields: {
|
|
143
133
|
items: bcs_1.bcs.vector(exports.BatchPriceItem)
|
|
144
134
|
} });
|
|
145
|
-
exports.MerkleRoot = new index_ts_1.MoveStruct({ name: `${$moduleName}::MerkleRoot`, fields: {
|
|
146
|
-
root: bcs_1.bcs.vector(bcs_1.bcs.u8())
|
|
147
|
-
} });
|
|
148
135
|
exports.FeedConfig = new index_ts_1.MoveStruct({ name: `${$moduleName}::FeedConfig`, fields: {
|
|
149
136
|
ticker: bcs_1.bcs.string(),
|
|
150
137
|
sources: bcs_1.bcs.vector(bcs_1.bcs.u64()),
|
|
@@ -230,17 +217,15 @@ function feedBatchLatest(options) {
|
|
|
230
217
|
* and so aborts on any stale item, this path runs alongside Pyth/Supra. To let
|
|
231
218
|
* those cover a lagging TEE — the blast-radius bound in the GCP ADR — a
|
|
232
219
|
* _freshness_ miss ABSTAINS (records `none`, which `aggregator::remove_outliers`
|
|
233
|
-
* drops before the `weight_threshold` fail-closed check)
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* not
|
|
237
|
-
*
|
|
238
|
-
* with the on-chain feed config is a red flag, not a liveness blip. Bad signature,
|
|
239
|
-
* malformed batch, and a future timestamp always abort.
|
|
220
|
+
* drops before the `weight_threshold` fail-closed check). A _config/integrity_
|
|
221
|
+
* mismatch (source / ticker / method / confidence / deviation) still ABORTS: an
|
|
222
|
+
* enclave whose signed payload disagrees with the on-chain feed config is a red
|
|
223
|
+
* flag, not a liveness blip. Bad signature, malformed batch, a future timestamp,
|
|
224
|
+
* and replay always abort.
|
|
240
225
|
*
|
|
241
226
|
* Every gate is identical to `feed_batch_item_latest`; only the abort-vs-abstain
|
|
242
|
-
* disposition of the freshness
|
|
243
|
-
*
|
|
227
|
+
* disposition of the two freshness gates differs, and the sink is the caller's
|
|
228
|
+
* collector rather than a fresh single-rule one.
|
|
244
229
|
*/
|
|
245
230
|
function collectBatchLatest(options) {
|
|
246
231
|
const packageAddress = options.package ?? '@waterx/rule';
|
|
@@ -262,63 +247,6 @@ function collectBatchLatest(options) {
|
|
|
262
247
|
arguments: (0, index_ts_1.normalizeMoveArguments)(options.arguments, argumentsTypes, parameterNames),
|
|
263
248
|
});
|
|
264
249
|
}
|
|
265
|
-
/**
|
|
266
|
-
* Streaming per-symbol sibling of `feed_batch_latest`. Verifies ONE enclave
|
|
267
|
-
* signature over a Merkle `root`, checks `item` is a leaf of that root via
|
|
268
|
-
* `proof`, then runs the identical per-item gates + `oracle::aggregate`. Use for a
|
|
269
|
-
* WaterxRule-only aggregator; for a Pyth-coexisting aggregator use
|
|
270
|
-
* `collect_single_with_proof`.
|
|
271
|
-
*/
|
|
272
|
-
function feedSingleWithProof(options) {
|
|
273
|
-
const packageAddress = options.package ?? '@waterx/rule';
|
|
274
|
-
const argumentsTypes = [
|
|
275
|
-
null,
|
|
276
|
-
null,
|
|
277
|
-
'0x2::clock::Clock',
|
|
278
|
-
null,
|
|
279
|
-
null,
|
|
280
|
-
'u64',
|
|
281
|
-
null,
|
|
282
|
-
'vector<vector<u8>>',
|
|
283
|
-
'vector<u8>'
|
|
284
|
-
];
|
|
285
|
-
const parameterNames = ["oracleObj", "config", "enclaveConfig", "enclave", "timestampMs", "item", "proof", "sig"];
|
|
286
|
-
return (tx) => tx.moveCall({
|
|
287
|
-
package: packageAddress,
|
|
288
|
-
module: 'waterx_rule',
|
|
289
|
-
function: 'feed_single_with_proof',
|
|
290
|
-
arguments: (0, index_ts_1.normalizeMoveArguments)(options.arguments, argumentsTypes, parameterNames),
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Collect-only sibling of `feed_single_with_proof` for the dual-rule latest path
|
|
295
|
-
* (WaterX alongside Pyth on one aggregator), mirroring `collect_batch_latest`:
|
|
296
|
-
* verifies root + proof, feeds the leaf into the caller's `PriceCollector` WITHOUT
|
|
297
|
-
* calling `oracle::aggregate`. Abort vs abstain matches `collect_batch_latest`
|
|
298
|
-
* exactly — a config/integrity mismatch aborts, a freshness miss abstains so Pyth
|
|
299
|
-
* can cover a lagging TEE.
|
|
300
|
-
*/
|
|
301
|
-
function collectSingleWithProof(options) {
|
|
302
|
-
const packageAddress = options.package ?? '@waterx/rule';
|
|
303
|
-
const argumentsTypes = [
|
|
304
|
-
null,
|
|
305
|
-
null,
|
|
306
|
-
'0x2::clock::Clock',
|
|
307
|
-
null,
|
|
308
|
-
null,
|
|
309
|
-
'u64',
|
|
310
|
-
null,
|
|
311
|
-
'vector<vector<u8>>',
|
|
312
|
-
'vector<u8>'
|
|
313
|
-
];
|
|
314
|
-
const parameterNames = ["collector", "config", "enclaveConfig", "enclave", "timestampMs", "item", "proof", "sig"];
|
|
315
|
-
return (tx) => tx.moveCall({
|
|
316
|
-
package: packageAddress,
|
|
317
|
-
module: 'waterx_rule',
|
|
318
|
-
function: 'collect_single_with_proof',
|
|
319
|
-
arguments: (0, index_ts_1.normalizeMoveArguments)(options.arguments, argumentsTypes, parameterNames),
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
250
|
/**
|
|
323
251
|
* Verifies a historical quote without touching `waterx_oracle`.
|
|
324
252
|
*
|
|
@@ -510,32 +438,6 @@ function batchPriceIntent(options = {}) {
|
|
|
510
438
|
function: 'batch_price_intent',
|
|
511
439
|
});
|
|
512
440
|
}
|
|
513
|
-
function merkleRootIntent(options = {}) {
|
|
514
|
-
const packageAddress = options.package ?? '@waterx/rule';
|
|
515
|
-
return (tx) => tx.moveCall({
|
|
516
|
-
package: packageAddress,
|
|
517
|
-
module: 'waterx_rule',
|
|
518
|
-
function: 'merkle_root_intent',
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
/**
|
|
522
|
-
* The keccak256 leaf hash for `item` — `keccak256(0x00 || BCS(item))`. Exposed so
|
|
523
|
-
* the off-chain builder / SDK can be pinned against the on-chain encoding in a
|
|
524
|
-
* cross-implementation golden test.
|
|
525
|
-
*/
|
|
526
|
-
function leafHashOf(options) {
|
|
527
|
-
const packageAddress = options.package ?? '@waterx/rule';
|
|
528
|
-
const argumentsTypes = [
|
|
529
|
-
null
|
|
530
|
-
];
|
|
531
|
-
const parameterNames = ["item"];
|
|
532
|
-
return (tx) => tx.moveCall({
|
|
533
|
-
package: packageAddress,
|
|
534
|
-
module: 'waterx_rule',
|
|
535
|
-
function: 'leaf_hash_of',
|
|
536
|
-
arguments: (0, index_ts_1.normalizeMoveArguments)(options.arguments, argumentsTypes, parameterNames),
|
|
537
|
-
});
|
|
538
|
-
}
|
|
539
441
|
function maxBatchSize(options = {}) {
|
|
540
442
|
const packageAddress = options.package ?? '@waterx/rule';
|
|
541
443
|
return (tx) => tx.moveCall({
|
|
@@ -922,54 +824,6 @@ function sourceGataUsdtPerpWs(options = {}) {
|
|
|
922
824
|
function: 'source_gata_usdt_perp_ws',
|
|
923
825
|
});
|
|
924
826
|
}
|
|
925
|
-
function sourceBybitSpotWs(options = {}) {
|
|
926
|
-
const packageAddress = options.package ?? '@waterx/rule';
|
|
927
|
-
return (tx) => tx.moveCall({
|
|
928
|
-
package: packageAddress,
|
|
929
|
-
module: 'waterx_rule',
|
|
930
|
-
function: 'source_bybit_spot_ws',
|
|
931
|
-
});
|
|
932
|
-
}
|
|
933
|
-
function sourceXstockEquityRest(options = {}) {
|
|
934
|
-
const packageAddress = options.package ?? '@waterx/rule';
|
|
935
|
-
return (tx) => tx.moveCall({
|
|
936
|
-
package: packageAddress,
|
|
937
|
-
module: 'waterx_rule',
|
|
938
|
-
function: 'source_xstock_equity_rest',
|
|
939
|
-
});
|
|
940
|
-
}
|
|
941
|
-
function sourceOkxSpotWs(options = {}) {
|
|
942
|
-
const packageAddress = options.package ?? '@waterx/rule';
|
|
943
|
-
return (tx) => tx.moveCall({
|
|
944
|
-
package: packageAddress,
|
|
945
|
-
module: 'waterx_rule',
|
|
946
|
-
function: 'source_okx_spot_ws',
|
|
947
|
-
});
|
|
948
|
-
}
|
|
949
|
-
function sourceHyperliquidPerpWs(options = {}) {
|
|
950
|
-
const packageAddress = options.package ?? '@waterx/rule';
|
|
951
|
-
return (tx) => tx.moveCall({
|
|
952
|
-
package: packageAddress,
|
|
953
|
-
module: 'waterx_rule',
|
|
954
|
-
function: 'source_hyperliquid_perp_ws',
|
|
955
|
-
});
|
|
956
|
-
}
|
|
957
|
-
function sourceGateioSpotWs(options = {}) {
|
|
958
|
-
const packageAddress = options.package ?? '@waterx/rule';
|
|
959
|
-
return (tx) => tx.moveCall({
|
|
960
|
-
package: packageAddress,
|
|
961
|
-
module: 'waterx_rule',
|
|
962
|
-
function: 'source_gateio_spot_ws',
|
|
963
|
-
});
|
|
964
|
-
}
|
|
965
|
-
function sourceKrakenSpotWs(options = {}) {
|
|
966
|
-
const packageAddress = options.package ?? '@waterx/rule';
|
|
967
|
-
return (tx) => tx.moveCall({
|
|
968
|
-
package: packageAddress,
|
|
969
|
-
module: 'waterx_rule',
|
|
970
|
-
function: 'source_kraken_spot_ws',
|
|
971
|
-
});
|
|
972
|
-
}
|
|
973
827
|
function methodDirect(options = {}) {
|
|
974
828
|
const packageAddress = options.package ?? '@waterx/rule';
|
|
975
829
|
return (tx) => tx.moveCall({
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
*
|
|
20
20
|
* `refreshOraclePrices` additionally routes the on-chain price *update* leg
|
|
21
21
|
* (the fetch + verify/push step, before any of the above feeding) through the
|
|
22
|
-
* `PriceUpdateRule`
|
|
22
|
+
* `PriceUpdateRule` of EVERY source in the `host.oracleSources` fed set — see
|
|
23
|
+
* `rule-registry.ts`.
|
|
23
24
|
*/
|
|
24
25
|
import type { Transaction, TransactionArgument } from "@mysten/sui/transactions";
|
|
25
26
|
import type { OracleHost } from "./host.ts";
|
|
@@ -84,27 +85,26 @@ export declare function aggregateTickerWithConstant(tx: Transaction, host: Oracl
|
|
|
84
85
|
* entry, Lazer if the lazer update leg served it — see below — Supra when
|
|
85
86
|
* enabled, Constant when it's a constant ticker).
|
|
86
87
|
*
|
|
87
|
-
* Before that, the on-chain price *update* leg is routed by
|
|
88
|
-
* (see `rule-registry.ts`):
|
|
89
|
-
* `supportedTickers(host)
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
* dry-run, which is correct.
|
|
88
|
+
* Before that, the on-chain price *update* leg is routed by the
|
|
89
|
+
* `host.oracleSources` fed set (see `rule-registry.ts`): EVERY listed source
|
|
90
|
+
* updates the tickers its own `supportedTickers(host)` serves, all in this one
|
|
91
|
+
* PTB. There is **no cross-source fallback** — a requested ticker NO listed
|
|
92
|
+
* source serves, and that is not a constant-only ticker (which needs no
|
|
93
|
+
* price-update leg), fails the build immediately with a clear error naming
|
|
94
|
+
* the ticker and the list. That is the deliberate "fail the tx-build, don't
|
|
95
|
+
* silently reroute" contract: a wrong-but-present feed id is NOT validated
|
|
96
|
+
* here (it surfaces on-chain at dry-run); a ticker MISSING from every listed
|
|
97
|
+
* source's feeds is caught here.
|
|
98
98
|
*
|
|
99
|
-
*
|
|
100
|
-
* per-rule PTB atomicity. A fee-source pre-check runs first (
|
|
101
|
-
* `requiresFeeSource`) BEFORE any off-chain fetch or PTB mutation —
|
|
102
|
-
* fee-charging source with no `opts.feeSource` throws
|
|
99
|
+
* Each source's fetch + build runs against its own infra, guaranteeing
|
|
100
|
+
* per-rule PTB atomicity. A fee-source pre-check runs first (any listed
|
|
101
|
+
* source's `requiresFeeSource`) BEFORE any off-chain fetch or PTB mutation —
|
|
102
|
+
* so a fee-charging source with no `opts.feeSource` throws
|
|
103
103
|
* `OracleFeeSourceUnavailable` with zero wasted network calls and zero stray
|
|
104
|
-
* moveCalls. Only once that check passes
|
|
105
|
-
*
|
|
106
|
-
* can still fail mid-append for
|
|
107
|
-
* throw.
|
|
104
|
+
* moveCalls. Only once that check passes do the off-chain fetches run — in
|
|
105
|
+
* parallel across sources — and ALL settle before the first PTB mutation;
|
|
106
|
+
* on-chain reads inside `buildUpdateCalls` can still fail mid-append for
|
|
107
|
+
* other reasons — callers discard the tx on any throw.
|
|
108
108
|
*
|
|
109
109
|
* **Collector-feed leg is rule-aware:** a lazer-served group's
|
|
110
110
|
* `buildUpdateCalls` returns the verified `Update` PTB value
|
|
@@ -139,7 +139,7 @@ export declare function refreshOraclePrices(tx: Transaction, host: OracleHost, t
|
|
|
139
139
|
/**
|
|
140
140
|
* @internal Test-only: layer fake `PriceUpdateRule`s on top of the
|
|
141
141
|
* production registry (see `rule-registry.ts`'s `resolveOracleRule`).
|
|
142
|
-
* Production callers never set this — routing is by `host.
|
|
142
|
+
* Production callers never set this — routing is by `host.oracleSources`
|
|
143
143
|
* alone.
|
|
144
144
|
*/
|
|
145
145
|
ruleOverrides?: Partial<Record<OracleSource, PriceUpdateRule>>;
|