@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
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* rules that consume it are separate concerns.
|
|
18
18
|
*/
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.reimbursePythSponsor = exports.openPythSponsorFund = exports.refreshOraclePrices = exports.aggregateTickerWithConstant = exports.aggregateTickerWithPyth = exports.aggregateTicker = exports.OracleSourceNotImplementedError = exports.parseSignedEnvelope = exports.WaterxRule = exports.LazerApiKeyMissingError = exports.PythLazerRule = exports.PythCoreRule = exports.OracleFeeSourceUnavailableError = exports.MISSING_FEED_MEMO_TTL_MS = exports.HermesEndpointRejectedAllFeedsError = exports.updatePythPrices = exports.buildPythPriceUpdateCalls = exports.probeMissingFeeds = exports.endpointSupportedFeedIds = exports.fetchPriceFeedsUpdateData = exports.PythCache = exports.joinEndpointPath = exports.fetchWithPolicy = exports.FetchPolicyError = void 0;
|
|
20
|
+
exports.reimbursePythSponsor = exports.openPythSponsorFund = exports.refreshOraclePrices = exports.aggregateTickerWithConstant = exports.aggregateTickerWithPyth = exports.aggregateTicker = exports.resolveOracleRule = exports.OracleSourceNotImplementedError = exports.waterxEnvelopeOf = exports.waterxQuoteCenterEndpoint = exports.WATERX_INFRA = exports.BATCH_PRICE_INTENT = exports.parseSignedEnvelope = exports.WaterxRule = exports.LazerApiKeyMissingError = exports.PythLazerRule = exports.PythCoreRule = exports.resolveHermesReadEndpoint = exports.resolveOracleReadPlan = exports.parseOracleSourceList = exports.isOracleSource = exports.ORACLE_SOURCES = exports.OracleFeeSourceUnavailableError = exports.MISSING_FEED_MEMO_TTL_MS = exports.HermesEndpointRejectedAllFeedsError = exports.updatePythPrices = exports.PYTH_PRO_HERMES_ENDPOINT = exports.pythProHermesEndpoint = exports.pythCoreHermesEndpoint = exports.buildPythPriceUpdateCalls = exports.probeMissingFeeds = exports.endpointSupportedFeedIds = exports.fetchPriceFeedsUpdateData = exports.PythCache = exports.joinEndpointPath = exports.fetchWithPolicy = exports.FetchPolicyError = void 0;
|
|
21
21
|
// Shared fetch resilience wrapper — `FetchPolicyError` is re-exported (not
|
|
22
22
|
// just the type) so a consumer (e.g. a BE prefetch cache) can `instanceof`
|
|
23
23
|
// it off the failure `fetchPriceFeedsUpdateData` / `PythLazerRule` /
|
|
@@ -45,10 +45,35 @@ Object.defineProperty(exports, "fetchPriceFeedsUpdateData", { enumerable: true,
|
|
|
45
45
|
Object.defineProperty(exports, "endpointSupportedFeedIds", { enumerable: true, get: function () { return pyth_ts_1.endpointSupportedFeedIds; } });
|
|
46
46
|
Object.defineProperty(exports, "probeMissingFeeds", { enumerable: true, get: function () { return pyth_ts_1.probeMissingFeeds; } });
|
|
47
47
|
Object.defineProperty(exports, "buildPythPriceUpdateCalls", { enumerable: true, get: function () { return pyth_ts_1.buildPythPriceUpdateCalls; } });
|
|
48
|
+
// The pyth read-plane endpoint accessors — Core (keyless, per network) and
|
|
49
|
+
// Pro (the documented fixed base; auth via the caller's Bearer key). There
|
|
50
|
+
// is no client-level endpoint field: consumers pick via
|
|
51
|
+
// `resolveHermesReadEndpoint` (pyth_rule listed → Core, else override ??
|
|
52
|
+
// Pro) — never a hand-rolled branch, never a cross-source fallback.
|
|
53
|
+
Object.defineProperty(exports, "pythCoreHermesEndpoint", { enumerable: true, get: function () { return pyth_ts_1.pythCoreHermesEndpoint; } });
|
|
54
|
+
Object.defineProperty(exports, "pythProHermesEndpoint", { enumerable: true, get: function () { return pyth_ts_1.pythProHermesEndpoint; } });
|
|
55
|
+
Object.defineProperty(exports, "PYTH_PRO_HERMES_ENDPOINT", { enumerable: true, get: function () { return pyth_ts_1.PYTH_PRO_HERMES_ENDPOINT; } });
|
|
48
56
|
Object.defineProperty(exports, "updatePythPrices", { enumerable: true, get: function () { return pyth_ts_1.updatePythPrices; } });
|
|
49
57
|
Object.defineProperty(exports, "HermesEndpointRejectedAllFeedsError", { enumerable: true, get: function () { return pyth_ts_1.HermesEndpointRejectedAllFeedsError; } });
|
|
50
58
|
Object.defineProperty(exports, "MISSING_FEED_MEMO_TTL_MS", { enumerable: true, get: function () { return pyth_ts_1.MISSING_FEED_MEMO_TTL_MS; } });
|
|
51
59
|
Object.defineProperty(exports, "OracleFeeSourceUnavailableError", { enumerable: true, get: function () { return pyth_ts_1.OracleFeeSourceUnavailableError; } });
|
|
60
|
+
// Canonical OracleSource value list + THE env-string parser consumers fold
|
|
61
|
+
// onto — semantics and rationale in `source-list.ts`'s header.
|
|
62
|
+
var price_update_rule_ts_1 = require("./price-update-rule.js");
|
|
63
|
+
Object.defineProperty(exports, "ORACLE_SOURCES", { enumerable: true, get: function () { return price_update_rule_ts_1.ORACLE_SOURCES; } });
|
|
64
|
+
var source_list_ts_1 = require("./source-list.js");
|
|
65
|
+
Object.defineProperty(exports, "isOracleSource", { enumerable: true, get: function () { return source_list_ts_1.isOracleSource; } });
|
|
66
|
+
Object.defineProperty(exports, "parseOracleSourceList", { enumerable: true, get: function () { return source_list_ts_1.parseOracleSourceList; } });
|
|
67
|
+
// Per-source READ-plane resolution — which tickers a source can price
|
|
68
|
+
// off-chain and with which ids (`resolveOracleReadPlan`), and which
|
|
69
|
+
// Hermes-compatible base the hermes plans execute against
|
|
70
|
+
// (`resolveHermesReadEndpoint`: pyth_rule listed → Core, else override ??
|
|
71
|
+
// the documented Pyth Pro base). The one place the "lazer reads through
|
|
72
|
+
// `pyth_rule.feeds` hex ids" invariant lives; consumers resolve through
|
|
73
|
+
// this instead of hardcoding namespace sharing or endpoint branching.
|
|
74
|
+
var read_plane_ts_1 = require("./read-plane.js");
|
|
75
|
+
Object.defineProperty(exports, "resolveOracleReadPlan", { enumerable: true, get: function () { return read_plane_ts_1.resolveOracleReadPlan; } });
|
|
76
|
+
Object.defineProperty(exports, "resolveHermesReadEndpoint", { enumerable: true, get: function () { return read_plane_ts_1.resolveHermesReadEndpoint; } });
|
|
52
77
|
// Pyth Core rule (PriceUpdateRule wrapper over the Pyth source above)
|
|
53
78
|
var pyth_core_rule_ts_1 = require("./rules/pyth-core-rule.js");
|
|
54
79
|
Object.defineProperty(exports, "PythCoreRule", { enumerable: true, get: function () { return pyth_core_rule_ts_1.PythCoreRule; } });
|
|
@@ -58,20 +83,28 @@ Object.defineProperty(exports, "PythCoreRule", { enumerable: true, get: function
|
|
|
58
83
|
var pyth_lazer_rule_ts_1 = require("./rules/pyth-lazer-rule.js");
|
|
59
84
|
Object.defineProperty(exports, "PythLazerRule", { enumerable: true, get: function () { return pyth_lazer_rule_ts_1.PythLazerRule; } });
|
|
60
85
|
Object.defineProperty(exports, "LazerApiKeyMissingError", { enumerable: true, get: function () { return pyth_lazer_rule_ts_1.LazerApiKeyMissingError; } });
|
|
86
|
+
// `WATERX_INFRA` / `waterxQuoteCenterEndpoint` are the source's own infra table +
|
|
87
|
+
// read-plane accessor (mirrors `pythCoreHermesEndpoint`).
|
|
61
88
|
// WaterX quote-center rule (first-party ed25519 signed batches; `feedWaterxRule`
|
|
62
89
|
// stays internal to `aggregate.ts`).
|
|
63
90
|
var waterx_rule_ts_1 = require("./rules/waterx-rule.js");
|
|
64
91
|
Object.defineProperty(exports, "WaterxRule", { enumerable: true, get: function () { return waterx_rule_ts_1.WaterxRule; } });
|
|
65
92
|
Object.defineProperty(exports, "parseSignedEnvelope", { enumerable: true, get: function () { return waterx_rule_ts_1.parseSignedEnvelope; } });
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
// `resolveOracleRule`
|
|
93
|
+
Object.defineProperty(exports, "BATCH_PRICE_INTENT", { enumerable: true, get: function () { return waterx_rule_ts_1.BATCH_PRICE_INTENT; } });
|
|
94
|
+
Object.defineProperty(exports, "WATERX_INFRA", { enumerable: true, get: function () { return waterx_rule_ts_1.WATERX_INFRA; } });
|
|
95
|
+
Object.defineProperty(exports, "waterxQuoteCenterEndpoint", { enumerable: true, get: function () { return waterx_rule_ts_1.waterxQuoteCenterEndpoint; } });
|
|
96
|
+
// Rule-owned payload accessor (kind-check + unwrap in one place) — never
|
|
97
|
+
// hand-cast the payload shape.
|
|
98
|
+
Object.defineProperty(exports, "waterxEnvelopeOf", { enumerable: true, get: function () { return waterx_rule_ts_1.waterxEnvelopeOf; } });
|
|
99
|
+
// `resolveOracleRule` is the ONE source→rule registry — exported so external
|
|
100
|
+
// consumers (e.g. a BE prefetch cache that keys per source and needs each
|
|
101
|
+
// source's `supportedTickers`/`fetchUpdateData`) resolve through it instead of
|
|
102
|
+
// hand-mirroring the map and drifting. `OracleSourceNotImplementedError` is
|
|
103
|
+
// its `instanceof`-able failure (same reason as `OracleFeeSourceUnavailableError`
|
|
104
|
+
// above).
|
|
73
105
|
var rule_registry_ts_1 = require("./rule-registry.js");
|
|
74
106
|
Object.defineProperty(exports, "OracleSourceNotImplementedError", { enumerable: true, get: function () { return rule_registry_ts_1.OracleSourceNotImplementedError; } });
|
|
107
|
+
Object.defineProperty(exports, "resolveOracleRule", { enumerable: true, get: function () { return rule_registry_ts_1.resolveOracleRule; } });
|
|
75
108
|
// Aggregation orchestrator
|
|
76
109
|
var aggregate_ts_1 = require("./aggregate.js");
|
|
77
110
|
Object.defineProperty(exports, "aggregateTicker", { enumerable: true, get: function () { return aggregate_ts_1.aggregateTicker; } });
|
|
@@ -11,23 +11,37 @@
|
|
|
11
11
|
* remain plain collector-feed helpers wired directly into `aggregate.ts`.
|
|
12
12
|
*
|
|
13
13
|
* This file defines the port only — routing IS wired: `aggregate.ts`'s
|
|
14
|
-
* `refreshOraclePrices`
|
|
15
|
-
* `rule-registry.ts`, then drives fetch + `buildUpdateCalls`
|
|
16
|
-
* port; `aggregate.ts` stays the sole orchestrator.
|
|
14
|
+
* `refreshOraclePrices` resolves a concrete rule per `host.oracleSources`
|
|
15
|
+
* entry via `rule-registry.ts`, then drives fetch + `buildUpdateCalls`
|
|
16
|
+
* through this port; `aggregate.ts` stays the sole orchestrator.
|
|
17
17
|
*/
|
|
18
18
|
import type { Transaction, TransactionArgument } from "@mysten/sui/transactions";
|
|
19
19
|
import type { OracleHost } from "./host.ts";
|
|
20
20
|
import type { OracleFeeSource, PythCache } from "./pyth.ts";
|
|
21
21
|
export type PriceUpdateRuleKind = "pyth_rule" | "pyth_lazer_rule" | "supra_rule" | "constant_rule" | "waterx_rule";
|
|
22
22
|
/**
|
|
23
|
-
* The
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
23
|
+
* The canonical list of selectable oracle sources — the SINGLE authority the
|
|
24
|
+
* {@link OracleSource} union derives from (the value-list→union derive
|
|
25
|
+
* idiom of `unified-client.ts`'s `NON_CLIENT_FIRST`, plus `Object.freeze`
|
|
26
|
+
* so the immutability is RUNTIME truth: `as const` alone would let a JS
|
|
27
|
+
* consumer push into the array and desync the membership Set built from it
|
|
28
|
+
* in `source-list.ts`). Runtime membership checks and the `ORACLE_SOURCE`
|
|
29
|
+
* env parser live there, on `isOracleSource` / `parseOracleSourceList`.
|
|
30
|
+
* Only sources belong here: `supra_rule` and `constant_rule` are auxiliary
|
|
31
|
+
* rules fed alongside whichever sources are selected (see
|
|
32
|
+
* `aggregateTicker`), not sources themselves — the `satisfies` keeps
|
|
33
|
+
* entries inside `PriceUpdateRuleKind` but adding an auxiliary rule to this
|
|
34
|
+
* list is an (incorrect) editorial decision this comment exists to prevent.
|
|
29
35
|
*/
|
|
30
|
-
export
|
|
36
|
+
export declare const ORACLE_SOURCES: readonly ["pyth_rule", "pyth_lazer_rule", "waterx_rule"];
|
|
37
|
+
/**
|
|
38
|
+
* The kinds listable in a client's `oracleSource` create option (see
|
|
39
|
+
* `OracleHost.oracleSources`) — i.e. rules that can serve as the on-chain
|
|
40
|
+
* price *update* leg `refreshOraclePrices` runs before aggregating. Derived
|
|
41
|
+
* from {@link ORACLE_SOURCES}. The SDK never reads `process.env` — consumers
|
|
42
|
+
* resolve their own env var to this type.
|
|
43
|
+
*/
|
|
44
|
+
export type OracleSource = (typeof ORACLE_SOURCES)[number];
|
|
31
45
|
/**
|
|
32
46
|
* Off-chain payload fetched by a rule, tagged by `kind` so a caller holding
|
|
33
47
|
* several rules' results can tell them apart. `payload` is `unknown` here —
|
|
@@ -116,7 +130,14 @@ export interface UpdateDataProvider {
|
|
|
116
130
|
get(source: OracleSource, tickers: string[]): Promise<RuleUpdateData | null>;
|
|
117
131
|
}
|
|
118
132
|
export interface PriceUpdateRule {
|
|
119
|
-
|
|
133
|
+
/**
|
|
134
|
+
* `OracleSource`, not the wider `PriceUpdateRuleKind`: only selectable
|
|
135
|
+
* sources implement this port (`supra_rule`/`constant_rule` are plain
|
|
136
|
+
* collector-feed helpers), and the narrower type is what lets
|
|
137
|
+
* `refreshOraclePrices`'s per-source carry step switch exhaustively —
|
|
138
|
+
* adding a source without deciding its carry becomes a compile error.
|
|
139
|
+
*/
|
|
140
|
+
readonly kind: OracleSource;
|
|
120
141
|
/**
|
|
121
142
|
* `true` when this rule's on-chain update leg charges a per-update fee
|
|
122
143
|
* that must be paid from either a sponsor fund or `tx.gas` (Pyth Core:
|
|
@@ -12,12 +12,32 @@
|
|
|
12
12
|
* remain plain collector-feed helpers wired directly into `aggregate.ts`.
|
|
13
13
|
*
|
|
14
14
|
* This file defines the port only — routing IS wired: `aggregate.ts`'s
|
|
15
|
-
* `refreshOraclePrices`
|
|
16
|
-
* `rule-registry.ts`, then drives fetch + `buildUpdateCalls`
|
|
17
|
-
* port; `aggregate.ts` stays the sole orchestrator.
|
|
15
|
+
* `refreshOraclePrices` resolves a concrete rule per `host.oracleSources`
|
|
16
|
+
* entry via `rule-registry.ts`, then drives fetch + `buildUpdateCalls`
|
|
17
|
+
* through this port; `aggregate.ts` stays the sole orchestrator.
|
|
18
18
|
*/
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.ORACLE_SOURCES = void 0;
|
|
20
21
|
exports.assertRuleUpdateData = assertRuleUpdateData;
|
|
22
|
+
/**
|
|
23
|
+
* The canonical list of selectable oracle sources — the SINGLE authority the
|
|
24
|
+
* {@link OracleSource} union derives from (the value-list→union derive
|
|
25
|
+
* idiom of `unified-client.ts`'s `NON_CLIENT_FIRST`, plus `Object.freeze`
|
|
26
|
+
* so the immutability is RUNTIME truth: `as const` alone would let a JS
|
|
27
|
+
* consumer push into the array and desync the membership Set built from it
|
|
28
|
+
* in `source-list.ts`). Runtime membership checks and the `ORACLE_SOURCE`
|
|
29
|
+
* env parser live there, on `isOracleSource` / `parseOracleSourceList`.
|
|
30
|
+
* Only sources belong here: `supra_rule` and `constant_rule` are auxiliary
|
|
31
|
+
* rules fed alongside whichever sources are selected (see
|
|
32
|
+
* `aggregateTicker`), not sources themselves — the `satisfies` keeps
|
|
33
|
+
* entries inside `PriceUpdateRuleKind` but adding an auxiliary rule to this
|
|
34
|
+
* list is an (incorrect) editorial decision this comment exists to prevent.
|
|
35
|
+
*/
|
|
36
|
+
exports.ORACLE_SOURCES = Object.freeze([
|
|
37
|
+
"pyth_rule",
|
|
38
|
+
"pyth_lazer_rule",
|
|
39
|
+
"waterx_rule",
|
|
40
|
+
]);
|
|
21
41
|
/**
|
|
22
42
|
* Shared null → kind → shape guard ladder for a `PriceUpdateRule.buildUpdateCalls`
|
|
23
43
|
* payload — every rule's `buildUpdateCalls` needs the exact same three checks,
|
|
@@ -14,8 +14,52 @@
|
|
|
14
14
|
* 4. hot_potato_vector::destroy
|
|
15
15
|
*/
|
|
16
16
|
import type { Transaction, TransactionArgument } from "@mysten/sui/transactions";
|
|
17
|
+
import type { Network } from "../constants.ts";
|
|
17
18
|
import type { PythFetchPolicy } from "./config.ts";
|
|
18
19
|
import type { OracleHost } from "./host.ts";
|
|
20
|
+
/**
|
|
21
|
+
* Everything the Core source needs that is not in the canonical
|
|
22
|
+
* `waterx-config` JSON lives HERE, in the source that consumes it —
|
|
23
|
+
* `client.pyth` carries only the caller's credential/fetch policy
|
|
24
|
+
* (see `PythAccessConfig`). No other oracle source reads this table:
|
|
25
|
+
* selecting `pyth_lazer_rule` (or any future source) must never touch a Core
|
|
26
|
+
* endpoint or Core state object, so nothing Core-shaped stays on the shared
|
|
27
|
+
* client to leak across sources.
|
|
28
|
+
*
|
|
29
|
+
* - `state_id` / `wormhole_state_id` — the Core Pyth + Wormhole state objects
|
|
30
|
+
* the on-chain update PTB reads (below).
|
|
31
|
+
* - `hermes_endpoint` — the Core Hermes REST base for
|
|
32
|
+
* `fetchPriceFeedsUpdateData`. Keyless today; auth-first after the Pyth Pro
|
|
33
|
+
* migration (post-2026-08-18) via `client.pyth.api_key`.
|
|
34
|
+
*/
|
|
35
|
+
export interface PythCoreInfra {
|
|
36
|
+
state_id: string;
|
|
37
|
+
wormhole_state_id: string;
|
|
38
|
+
hermes_endpoint: string;
|
|
39
|
+
}
|
|
40
|
+
export declare const PYTH_CORE_INFRA: Record<Network, PythCoreInfra>;
|
|
41
|
+
/**
|
|
42
|
+
* The Core source's Hermes REST base for `network` — for consumers (BE/FE
|
|
43
|
+
* read planes) whose `ORACLE_SOURCE` fed set includes `'pyth_rule'`. A fed
|
|
44
|
+
* set WITHOUT `pyth_rule` reads the keyed Pyth Pro base instead — resolve
|
|
45
|
+
* through `resolveHermesReadEndpoint` (`oracle/read-plane.ts`) rather than
|
|
46
|
+
* branching by hand.
|
|
47
|
+
*/
|
|
48
|
+
export declare function pythCoreHermesEndpoint(network: Network): string;
|
|
49
|
+
/**
|
|
50
|
+
* The Pyth Pro Hermes-compatible REST base — the documented drop-in
|
|
51
|
+
* replacement for the Core endpoint (`https://pyth.dourolabs.app/hermes/…`),
|
|
52
|
+
* IDENTICAL for every subscriber: only the `Authorization: Bearer` key
|
|
53
|
+
* (`client.pyth.api_key` / the `pythApiKey` create option) is
|
|
54
|
+
* account-specific, so the URL is SDK infra, not deployment config. One base
|
|
55
|
+
* for both networks — Pro has no testnet variant (Pyth feed ids are
|
|
56
|
+
* chain-agnostic; `hermes-beta` is a Core-testnet concern). Consumers with a
|
|
57
|
+
* proxy/self-hosted mirror override it per deployment via
|
|
58
|
+
* `resolveHermesReadEndpoint`'s `override` param.
|
|
59
|
+
*/
|
|
60
|
+
export declare const PYTH_PRO_HERMES_ENDPOINT = "https://pyth.dourolabs.app/hermes";
|
|
61
|
+
/** Accessor mirror of {@link pythCoreHermesEndpoint} for the Pro base. */
|
|
62
|
+
export declare function pythProHermesEndpoint(): string;
|
|
19
63
|
type PriceTableInfo = {
|
|
20
64
|
id: string;
|
|
21
65
|
fieldType: string;
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
* 4. hot_potato_vector::destroy
|
|
16
16
|
*/
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.OracleFeeSourceUnavailableError = exports.HermesEndpointRejectedAllFeedsError = exports.MISSING_FEED_MEMO_TTL_MS = exports.PythCache = void 0;
|
|
18
|
+
exports.OracleFeeSourceUnavailableError = exports.HermesEndpointRejectedAllFeedsError = exports.MISSING_FEED_MEMO_TTL_MS = exports.PythCache = exports.PYTH_PRO_HERMES_ENDPOINT = exports.PYTH_CORE_INFRA = void 0;
|
|
19
|
+
exports.pythCoreHermesEndpoint = pythCoreHermesEndpoint;
|
|
20
|
+
exports.pythProHermesEndpoint = pythProHermesEndpoint;
|
|
19
21
|
exports.endpointSupportedFeedIds = endpointSupportedFeedIds;
|
|
20
22
|
exports.__resetMissingFeedCacheForTest = __resetMissingFeedCacheForTest;
|
|
21
23
|
exports.probeMissingFeeds = probeMissingFeeds;
|
|
@@ -25,6 +27,44 @@ exports.updatePythPrices = updatePythPrices;
|
|
|
25
27
|
const bcs_1 = require("@mysten/bcs");
|
|
26
28
|
const bcs_2 = require("@mysten/sui/bcs");
|
|
27
29
|
const update_fetch_ts_1 = require("./update-fetch.js");
|
|
30
|
+
exports.PYTH_CORE_INFRA = {
|
|
31
|
+
MAINNET: {
|
|
32
|
+
state_id: "0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8",
|
|
33
|
+
wormhole_state_id: "0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c",
|
|
34
|
+
hermes_endpoint: "https://hermes.pyth.network",
|
|
35
|
+
},
|
|
36
|
+
TESTNET: {
|
|
37
|
+
state_id: "0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c",
|
|
38
|
+
wormhole_state_id: "0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790",
|
|
39
|
+
hermes_endpoint: "https://hermes-beta.pyth.network",
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The Core source's Hermes REST base for `network` — for consumers (BE/FE
|
|
44
|
+
* read planes) whose `ORACLE_SOURCE` fed set includes `'pyth_rule'`. A fed
|
|
45
|
+
* set WITHOUT `pyth_rule` reads the keyed Pyth Pro base instead — resolve
|
|
46
|
+
* through `resolveHermesReadEndpoint` (`oracle/read-plane.ts`) rather than
|
|
47
|
+
* branching by hand.
|
|
48
|
+
*/
|
|
49
|
+
function pythCoreHermesEndpoint(network) {
|
|
50
|
+
return exports.PYTH_CORE_INFRA[network].hermes_endpoint;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The Pyth Pro Hermes-compatible REST base — the documented drop-in
|
|
54
|
+
* replacement for the Core endpoint (`https://pyth.dourolabs.app/hermes/…`),
|
|
55
|
+
* IDENTICAL for every subscriber: only the `Authorization: Bearer` key
|
|
56
|
+
* (`client.pyth.api_key` / the `pythApiKey` create option) is
|
|
57
|
+
* account-specific, so the URL is SDK infra, not deployment config. One base
|
|
58
|
+
* for both networks — Pro has no testnet variant (Pyth feed ids are
|
|
59
|
+
* chain-agnostic; `hermes-beta` is a Core-testnet concern). Consumers with a
|
|
60
|
+
* proxy/self-hosted mirror override it per deployment via
|
|
61
|
+
* `resolveHermesReadEndpoint`'s `override` param.
|
|
62
|
+
*/
|
|
63
|
+
exports.PYTH_PRO_HERMES_ENDPOINT = "https://pyth.dourolabs.app/hermes";
|
|
64
|
+
/** Accessor mirror of {@link pythCoreHermesEndpoint} for the Pro base. */
|
|
65
|
+
function pythProHermesEndpoint() {
|
|
66
|
+
return exports.PYTH_PRO_HERMES_ENDPOINT;
|
|
67
|
+
}
|
|
28
68
|
class PythCache {
|
|
29
69
|
pythStateInfo;
|
|
30
70
|
wormholePackageId;
|
|
@@ -439,7 +479,7 @@ async function getPriceTableInfo(client, pythStateId, cache) {
|
|
|
439
479
|
}
|
|
440
480
|
async function getPriceFeedObjectId(client, table, feedId, cache, pythStateId) {
|
|
441
481
|
const normalized = feedId.replace(/^0x/, "");
|
|
442
|
-
const cacheKey =
|
|
482
|
+
const cacheKey = `${pythStateId}:${normalized}`;
|
|
443
483
|
if (cache?.priceFeedObjectIdCache.has(cacheKey)) {
|
|
444
484
|
return cache.priceFeedObjectIdCache.get(cacheKey);
|
|
445
485
|
}
|
|
@@ -535,7 +575,9 @@ async function buildPythPriceUpdateCalls(tx, host, updates, feedIds, opts) {
|
|
|
535
575
|
throw new OracleFeeSourceUnavailableError();
|
|
536
576
|
}
|
|
537
577
|
const cache = opts?.cache;
|
|
538
|
-
|
|
578
|
+
// Core on-chain infra is the `pyth_rule` source's own table, keyed by the
|
|
579
|
+
// host's network — `client.pyth` carries only the caller's credential/policy.
|
|
580
|
+
const pyth = exports.PYTH_CORE_INFRA[host.network];
|
|
539
581
|
const [stateInfo, wormholePackageId, table] = await Promise.all([
|
|
540
582
|
getPythStateInfo(host.grpcClient, pyth.state_id, cache),
|
|
541
583
|
getWormholePackageId(host.grpcClient, pyth.wormhole_state_id, cache),
|
|
@@ -593,9 +635,9 @@ async function buildPythPriceUpdateCalls(tx, host, updates, feedIds, opts) {
|
|
|
593
635
|
}
|
|
594
636
|
/** All-in-one: fetch from Hermes, append update calls. Returns PriceInfoObject IDs. */
|
|
595
637
|
async function updatePythPrices(tx, host, feedIds, opts) {
|
|
596
|
-
//
|
|
597
|
-
//
|
|
598
|
-
const endpoint = host.
|
|
638
|
+
// The Core source's own Hermes endpoint (per-network, rule-owned table);
|
|
639
|
+
// credential + fetch policy are the caller-supplied `client.pyth` slice.
|
|
640
|
+
const endpoint = exports.PYTH_CORE_INFRA[host.network].hermes_endpoint;
|
|
599
641
|
const updates = await fetchPriceFeedsUpdateData(endpoint, feedIds, {
|
|
600
642
|
apiKey: host.pyth.api_key,
|
|
601
643
|
fetch: host.pyth.fetch,
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `read-plane.ts` — per-source READ-plane resolution: which of a caller's
|
|
3
|
+
* tickers a source can PRICE off-chain, and with which ids. The write plane
|
|
4
|
+
* (`PriceUpdateRule` + each source's `feeds` block) and the read plane are
|
|
5
|
+
* DIFFERENT namespaces for the pyth sources: Lazer WRITES with the integer
|
|
6
|
+
* ids in `pyth_lazer_rule.feeds`, but every Hermes-compatible price READ is
|
|
7
|
+
* keyed by the hex ids only `pyth_rule.feeds` carries. That cross-block
|
|
8
|
+
* dependency is a config invariant ("a lazer-fed ticker must also carry a
|
|
9
|
+
* Core hex entry to be read-visible"), and it lives HERE, once — consumers
|
|
10
|
+
* (FE/BE price facades) resolve through this instead of hardcoding which
|
|
11
|
+
* sources share which feeds namespace.
|
|
12
|
+
*/
|
|
13
|
+
import type { Network } from "../constants.ts";
|
|
14
|
+
import type { OracleHost } from "./host.ts";
|
|
15
|
+
import type { OracleSource } from "./price-update-rule.ts";
|
|
16
|
+
/**
|
|
17
|
+
* One source's read plan for a requested ticker set.
|
|
18
|
+
*
|
|
19
|
+
* - `plane: "hermes"` (pyth sources) — price via a Hermes-compatible REST
|
|
20
|
+
* endpoint, one entry per servable ticker mapped to its HEX feed id. The
|
|
21
|
+
* endpoint to execute against is {@link resolveHermesReadEndpoint} — the
|
|
22
|
+
* plan (ids) plus that resolver (host) is the complete read contract.
|
|
23
|
+
* - `plane: "quote_center"` (waterx) — price via the quote-center symbols
|
|
24
|
+
* api, keyed by ticker; served set = the `waterx_rule.feeds` block. An
|
|
25
|
+
* ABSENT block (source listed, package missing from the loaded config)
|
|
26
|
+
* serves NOTHING: claiming tickers would silently reroute reads to the
|
|
27
|
+
* quote-center — it happily serves symbols regardless of on-chain config —
|
|
28
|
+
* and swallow tickers a later-listed source could price. The
|
|
29
|
+
* misconfiguration is caught loudly by the consumer's feeds assert at
|
|
30
|
+
* client creation instead.
|
|
31
|
+
* - `unreadable` — requested tickers this source WRITES on-chain (its update
|
|
32
|
+
* leg serves them) but its read plane cannot price: the silent-invisibility
|
|
33
|
+
* trap (e.g. a lazer-fed ticker with no `pyth_rule.feeds` hex entry).
|
|
34
|
+
* Callers should surface these loudly; empty for sources whose write and
|
|
35
|
+
* read namespaces coincide.
|
|
36
|
+
*/
|
|
37
|
+
export type OracleReadPlan = {
|
|
38
|
+
unreadable: string[];
|
|
39
|
+
} & ({
|
|
40
|
+
plane: "hermes";
|
|
41
|
+
feedIdByTicker: Map<string, string>;
|
|
42
|
+
} | {
|
|
43
|
+
plane: "quote_center";
|
|
44
|
+
tickers: string[];
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Resolve `source`'s read plan for `tickers`. Pure config lookup — no
|
|
48
|
+
* network, no endpoint resolution (endpoints come from
|
|
49
|
+
* `pythCoreHermesEndpoint` / `waterxQuoteCenterEndpoint` / the deployment's
|
|
50
|
+
* own env). A ticker absent from the returned plan is simply not servable by
|
|
51
|
+
* THIS source's read plane — callers decide how to degrade (typically: ask
|
|
52
|
+
* the next source in their `ORACLE_SOURCE` list, then omit).
|
|
53
|
+
*/
|
|
54
|
+
/**
|
|
55
|
+
* The Hermes-compatible REST base a deployment's hermes-plane read plans
|
|
56
|
+
* execute against — the endpoint half of the read contract
|
|
57
|
+
* ({@link resolveOracleReadPlan} is the ids half):
|
|
58
|
+
*
|
|
59
|
+
* - `pyth_rule` in the fed set → the Core source's own keyless endpoint
|
|
60
|
+
* (`pythCoreHermesEndpoint(network)`).
|
|
61
|
+
* - otherwise → `override` when the deployment set one (a proxy or
|
|
62
|
+
* self-hosted mirror), else the documented Pyth Pro base
|
|
63
|
+
* (`pythProHermesEndpoint()` — identical for every subscriber; auth is the
|
|
64
|
+
* caller's `pythApiKey` Bearer, not a per-deployment URL).
|
|
65
|
+
*
|
|
66
|
+
* Total — never throws, never falls back Core-ward: a fed set without
|
|
67
|
+
* `pyth_rule` reads Pro (or the override), full stop.
|
|
68
|
+
*/
|
|
69
|
+
export declare function resolveHermesReadEndpoint(network: Network, sources: readonly OracleSource[], override?: string): string;
|
|
70
|
+
export declare function resolveOracleReadPlan(host: OracleHost, source: OracleSource, tickers: string[]): OracleReadPlan;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `read-plane.ts` — per-source READ-plane resolution: which of a caller's
|
|
4
|
+
* tickers a source can PRICE off-chain, and with which ids. The write plane
|
|
5
|
+
* (`PriceUpdateRule` + each source's `feeds` block) and the read plane are
|
|
6
|
+
* DIFFERENT namespaces for the pyth sources: Lazer WRITES with the integer
|
|
7
|
+
* ids in `pyth_lazer_rule.feeds`, but every Hermes-compatible price READ is
|
|
8
|
+
* keyed by the hex ids only `pyth_rule.feeds` carries. That cross-block
|
|
9
|
+
* dependency is a config invariant ("a lazer-fed ticker must also carry a
|
|
10
|
+
* Core hex entry to be read-visible"), and it lives HERE, once — consumers
|
|
11
|
+
* (FE/BE price facades) resolve through this instead of hardcoding which
|
|
12
|
+
* sources share which feeds namespace.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.resolveHermesReadEndpoint = resolveHermesReadEndpoint;
|
|
16
|
+
exports.resolveOracleReadPlan = resolveOracleReadPlan;
|
|
17
|
+
const record_ts_1 = require("../utils/record.js");
|
|
18
|
+
const pyth_ts_1 = require("./pyth.js");
|
|
19
|
+
/**
|
|
20
|
+
* Resolve `source`'s read plan for `tickers`. Pure config lookup — no
|
|
21
|
+
* network, no endpoint resolution (endpoints come from
|
|
22
|
+
* `pythCoreHermesEndpoint` / `waterxQuoteCenterEndpoint` / the deployment's
|
|
23
|
+
* own env). A ticker absent from the returned plan is simply not servable by
|
|
24
|
+
* THIS source's read plane — callers decide how to degrade (typically: ask
|
|
25
|
+
* the next source in their `ORACLE_SOURCE` list, then omit).
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* The Hermes-compatible REST base a deployment's hermes-plane read plans
|
|
29
|
+
* execute against — the endpoint half of the read contract
|
|
30
|
+
* ({@link resolveOracleReadPlan} is the ids half):
|
|
31
|
+
*
|
|
32
|
+
* - `pyth_rule` in the fed set → the Core source's own keyless endpoint
|
|
33
|
+
* (`pythCoreHermesEndpoint(network)`).
|
|
34
|
+
* - otherwise → `override` when the deployment set one (a proxy or
|
|
35
|
+
* self-hosted mirror), else the documented Pyth Pro base
|
|
36
|
+
* (`pythProHermesEndpoint()` — identical for every subscriber; auth is the
|
|
37
|
+
* caller's `pythApiKey` Bearer, not a per-deployment URL).
|
|
38
|
+
*
|
|
39
|
+
* Total — never throws, never falls back Core-ward: a fed set without
|
|
40
|
+
* `pyth_rule` reads Pro (or the override), full stop.
|
|
41
|
+
*/
|
|
42
|
+
function resolveHermesReadEndpoint(network, sources, override) {
|
|
43
|
+
if (sources.includes("pyth_rule"))
|
|
44
|
+
return (0, pyth_ts_1.pythCoreHermesEndpoint)(network);
|
|
45
|
+
return override ?? (0, pyth_ts_1.pythProHermesEndpoint)();
|
|
46
|
+
}
|
|
47
|
+
function resolveOracleReadPlan(host, source, tickers) {
|
|
48
|
+
switch (source) {
|
|
49
|
+
case "pyth_rule":
|
|
50
|
+
case "pyth_lazer_rule": {
|
|
51
|
+
// All ticker lookups go through `ownEntry` (own-keys-only): a ticker
|
|
52
|
+
// named like an Object.prototype key ("toString", "constructor", …)
|
|
53
|
+
// must read as not-listed, not as an inherited Function.
|
|
54
|
+
const hexFeeds = host.config.packages.pyth_rule?.feeds;
|
|
55
|
+
const feedIdByTicker = new Map();
|
|
56
|
+
for (const ticker of tickers) {
|
|
57
|
+
const feedId = (0, record_ts_1.ownEntry)(hexFeeds, ticker)?.feed_id;
|
|
58
|
+
if (feedId !== undefined)
|
|
59
|
+
feedIdByTicker.set(ticker, feedId);
|
|
60
|
+
}
|
|
61
|
+
// For pyth_rule the write and read namespaces coincide, so `unreadable`
|
|
62
|
+
// is always empty; for lazer it is exactly the hex-entry gap.
|
|
63
|
+
const writeFeeds = source === "pyth_lazer_rule" ? host.config.packages.pyth_lazer_rule?.feeds : hexFeeds;
|
|
64
|
+
const unreadable = tickers.filter((ticker) => (0, record_ts_1.ownEntry)(writeFeeds, ticker) !== undefined && !feedIdByTicker.has(ticker));
|
|
65
|
+
return { plane: "hermes", feedIdByTicker, unreadable };
|
|
66
|
+
}
|
|
67
|
+
case "waterx_rule": {
|
|
68
|
+
// Absent feeds block ⇒ serves nothing (see the OracleReadPlan doc) —
|
|
69
|
+
// never claim tickers the config doesn't name. `ownEntry` (own-keys-
|
|
70
|
+
// only, never the `in` operator or a bare bracket read) so a
|
|
71
|
+
// prototype-key ticker can't count as feeds-listed and poison the
|
|
72
|
+
// quote-center batch (which 404s whole batches on unknown symbols).
|
|
73
|
+
const feeds = host.config.packages.waterx_rule?.feeds;
|
|
74
|
+
return {
|
|
75
|
+
plane: "quote_center",
|
|
76
|
+
tickers: tickers.filter((ticker) => (0, record_ts_1.ownEntry)(feeds, ticker) !== undefined),
|
|
77
|
+
unreadable: [],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
default: {
|
|
81
|
+
const exhausted = source;
|
|
82
|
+
throw new Error(`resolveOracleReadPlan: unhandled OracleSource '${String(exhausted)}'`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `rule-registry.ts` — maps a client-selected `OracleSource` to its concrete
|
|
3
|
-
* `PriceUpdateRule` implementation
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* `PriceUpdateRule` implementation; the ONE place `OracleSource` values are
|
|
4
|
+
* wired to a rule instance. `refreshOraclePrices` (`aggregate.ts`) resolves
|
|
5
|
+
* every `host.oracleSources` entry through it, and consumers (e.g. a BE
|
|
6
|
+
* prefetch cache keying per source) import `resolveOracleRule` rather than
|
|
7
|
+
* hand-mirroring this map. Selection is driven purely by the value passed in
|
|
8
|
+
* (ultimately `OracleHost.oracleSources`, the `oracleSource` client create
|
|
7
9
|
* option) — never by a config JSON `enabled` flag and never by `process.env`.
|
|
8
10
|
*
|
|
9
11
|
* Each source is self-contained: it owns its own infra + config and does NOT
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* `rule-registry.ts` — maps a client-selected `OracleSource` to its concrete
|
|
4
|
-
* `PriceUpdateRule` implementation
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* `PriceUpdateRule` implementation; the ONE place `OracleSource` values are
|
|
5
|
+
* wired to a rule instance. `refreshOraclePrices` (`aggregate.ts`) resolves
|
|
6
|
+
* every `host.oracleSources` entry through it, and consumers (e.g. a BE
|
|
7
|
+
* prefetch cache keying per source) import `resolveOracleRule` rather than
|
|
8
|
+
* hand-mirroring this map. Selection is driven purely by the value passed in
|
|
9
|
+
* (ultimately `OracleHost.oracleSources`, the `oracleSource` client create
|
|
8
10
|
* option) — never by a config JSON `enabled` flag and never by `process.env`.
|
|
9
11
|
*
|
|
10
12
|
* Each source is self-contained: it owns its own infra + config and does NOT
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
exports.PythCoreRule = void 0;
|
|
12
|
+
const record_ts_1 = require("../../utils/record.js");
|
|
12
13
|
const price_update_rule_ts_1 = require("../price-update-rule.js");
|
|
13
14
|
const pyth_ts_1 = require("../pyth.js");
|
|
14
15
|
/**
|
|
@@ -36,10 +37,10 @@ exports.PythCoreRule = {
|
|
|
36
37
|
async fetchUpdateData(host, tickers) {
|
|
37
38
|
if (tickers.length === 0)
|
|
38
39
|
return null;
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
const endpoint = host.
|
|
40
|
+
// Endpoint is this source's own per-network infra (`PYTH_CORE_INFRA`);
|
|
41
|
+
// credential + retry/timeout policy are the caller-supplied `client.pyth`
|
|
42
|
+
// access slice.
|
|
43
|
+
const endpoint = (0, pyth_ts_1.pythCoreHermesEndpoint)(host.network);
|
|
43
44
|
const feedIds = tickers.map((ticker) => host.getPythFeed(ticker).feed_id);
|
|
44
45
|
const updates = await (0, pyth_ts_1.fetchPriceFeedsUpdateData)(endpoint, feedIds, {
|
|
45
46
|
apiKey: host.pyth.api_key,
|
|
@@ -79,7 +80,7 @@ exports.PythCoreRule = {
|
|
|
79
80
|
for (const ticker of tickers) {
|
|
80
81
|
// Same lookup as `host.getPythFeed(ticker)` minus its throw — an
|
|
81
82
|
// unlisted ticker is a miss here, not an error.
|
|
82
|
-
const feedId = host.config.packages.pyth_rule?.feeds
|
|
83
|
+
const feedId = (0, record_ts_1.ownEntry)(host.config.packages.pyth_rule?.feeds, ticker)?.feed_id;
|
|
83
84
|
if (feedId === undefined || !packedFeedIds.has(feedId))
|
|
84
85
|
return null;
|
|
85
86
|
feedIds.push(feedId);
|
|
@@ -8,8 +8,29 @@
|
|
|
8
8
|
* `Update` PTB value back through a `RuleUpdateHandle` for the feed calls.
|
|
9
9
|
*/
|
|
10
10
|
import type { Transaction, TransactionArgument } from "@mysten/sui/transactions";
|
|
11
|
+
import type { Network } from "../../constants.ts";
|
|
11
12
|
import type { OracleHost } from "../host.ts";
|
|
12
13
|
import { type PriceUpdateRule } from "../price-update-rule.ts";
|
|
14
|
+
/**
|
|
15
|
+
* Pyth Lazer (Pyth Pro) external infra — owned by THIS source, by network.
|
|
16
|
+
* Per-network constants for infrastructure Pyth operates (not part of the
|
|
17
|
+
* `waterx-config` JSON), co-located with the only rule that reads them —
|
|
18
|
+
* no other oracle source ever touches a Lazer endpoint or verifier.
|
|
19
|
+
*
|
|
20
|
+
* - `endpoint` — Lazer HTTP API base; signed updates come from
|
|
21
|
+
* `POST /v1/latest_price` (Bearer-authenticated). The service is
|
|
22
|
+
* network-agnostic (one signed payload verifies on any chain that trusts the
|
|
23
|
+
* Lazer signers), so both networks share the production host.
|
|
24
|
+
* - `verifier_package` — the Sui package carrying
|
|
25
|
+
* `pyth_lazer::parse_and_verify_le_ecdsa_update`. Per-network: testnet is
|
|
26
|
+
* still the original v1 publish; mainnet is the v2-upgraded package (which
|
|
27
|
+
* still exposes the v1 entry `pyth_lazer_rule` binds). Values mirror the
|
|
28
|
+
* contract repo's `pyth_lazer_rule/Move.toml` published-at pins.
|
|
29
|
+
*/
|
|
30
|
+
export declare const LAZER_INFRA: Record<Network, {
|
|
31
|
+
endpoint: string;
|
|
32
|
+
verifier_package: string;
|
|
33
|
+
}>;
|
|
13
34
|
/** `pyth_lazer_rule`'s narrowed `RuleUpdateData.payload` shape. */
|
|
14
35
|
export interface PythLazerUpdatePayload {
|
|
15
36
|
/** One signed `leEcdsa` message carrying every requested feed. */
|