@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
@@ -2,57 +2,148 @@
2
2
  /**
3
3
  * Shared scaffolding for the high-level perp `build*Tx` composers:
4
4
  * `CommonBuildOpts`, the new-or-reuse PTB helper, the WLP pool-oracle refresh,
5
- * and the request+execute envelope (optional Pyth-sponsor flow + pre-sweep).
5
+ * and the request+execute envelope (optional pre-sweep).
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.newTx = newTx;
9
+ exports.assertTickersRefreshed = assertTickersRefreshed;
10
+ exports.assertWlpPoolRefreshed = assertWlpPoolRefreshed;
9
11
  exports.refreshWlpPoolOracles = refreshWlpPoolOracles;
10
12
  exports.wrapRequestAndExecute = wrapRequestAndExecute;
11
13
  exports.maybeConsolidate = maybeConsolidate;
12
14
  const transactions_1 = require("@mysten/sui/transactions");
13
15
  const consolidate_ts_1 = require("../../account/funding/consolidate.js");
14
16
  const index_ts_1 = require("../../oracle/index.js");
15
- const config_ts_1 = require("../../utils/config.js");
16
17
  const trading_ts_1 = require("../user/trading.js");
17
18
  const wlp_ts_1 = require("../user/wlp.js");
18
19
  function newTx(opts) {
19
20
  return opts?.tx ?? new transactions_1.Transaction();
20
21
  }
22
+ /**
23
+ * Fail the build when a ticker THIS action depends on went unrefreshed.
24
+ *
25
+ * The split of responsibility: `refreshOraclePrices` skips (it cannot know
26
+ * which of its tickers were load-bearing), the composer asserts (it does).
27
+ */
28
+ function assertTickersRefreshed(client, summary, required, opts,
29
+ /** Appended to the error, to say why THESE tickers were load-bearing. */
30
+ why) {
31
+ if (opts?.allowUnrefreshedPrices)
32
+ return;
33
+ const skipped = new Set(summary.skipped);
34
+ const unserved = [...new Set(required)].filter((ticker) => skipped.has(ticker));
35
+ if (unserved.length > 0) {
36
+ throw new index_ts_1.OracleTickerUnservedError(unserved, client.oracleSources, why);
37
+ }
38
+ }
39
+ /**
40
+ * Fail the build when ANY WLP pool asset went unpriced — stricter than
41
+ * {@link assertTickersRefreshed}, and deliberately so.
42
+ *
43
+ * `mint_wlp` / `settle_redeem` take `&WlpAum` and size the payout against the
44
+ * pool's WHOLE `tvl_usd`, so a stale price on any pool asset mis-values the
45
+ * trade — not just a stale price on the deposit ticker.
46
+ *
47
+ * Nothing on chain catches the gap. Two paths, neither of which fails:
48
+ * - the asset IS bumped: `update_token_value` calls `oracle::get_price`,
49
+ * which aborts `EStalePrice` unless this PTB aggregated it — loud, safe;
50
+ * - the asset is NOT bumped (it was skipped, so no leg was emitted): its
51
+ * `last_price_refresh_timestamp` keeps whatever a previous transaction
52
+ * left, and `assert_prices_fresh` only asks that it be within
53
+ * `price_refresh_threshold_ms`. A recent-enough stale price PASSES.
54
+ *
55
+ * So the silent case is exactly the skipped one, and the build is the only
56
+ * place it can be caught.
57
+ */
58
+ function assertWlpPoolRefreshed(client, summary, opts) {
59
+ // Every pool asset is required — that IS the WLP-specific part. The general
60
+ // assert does the rest; there is no second class of fault to detect, because
61
+ // `refreshWlpPoolOracles` requests the whole pool, so anything this client
62
+ // cannot price is necessarily in `summary.skipped` already.
63
+ assertTickersRefreshed(client, summary, Object.keys(client.config.packages.wlp?.pool_tokens ?? {}), opts, "They are WLP pool assets, and mint/redeem values the WHOLE pool. ");
64
+ }
21
65
  /**
22
66
  * Refresh every WLP pool-token oracle (+ caller-supplied extra tickers) and
23
67
  * bump each pool token's `last_price_refresh_timestamp` so the pool's
24
68
  * `assert_prices_fresh` passes when the next `mint_wlp` / `request_redeem` /
25
69
  * trading `execute` runs in the same PTB.
70
+ *
71
+ * Fails closed via {@link assertWlpPoolRefreshed} — see there for why a gap is
72
+ * otherwise silent rather than an on-chain abort.
26
73
  */
27
- async function refreshWlpPoolOracles(tx, client, extraTickers, opts) {
28
- const poolTickers = (0, config_ts_1.getCollateralAssets)(client.config);
29
- const oracleTickers = Array.from(new Set([...extraTickers, ...poolTickers]));
30
- await (0, index_ts_1.refreshOraclePrices)(tx, client, oracleTickers, {
31
- cache: opts.cache,
32
- feeSource: opts.feeSource,
74
+ async function refreshWlpPoolOracles(tx, client, extraTickers,
75
+ /** The build's options — `lpType`, plus `allowUnrefreshedPrices` / `updateDataProvider`. */
76
+ opts) {
77
+ // EVERY pool asset is requested, not a pre-filtered subset. Filtering here
78
+ // was the bug: a token the fed set cannot price was dropped from BOTH the
79
+ // refresh and the bump, so nothing on chain objected (see
80
+ // `assertWlpPoolRefreshed` for why `assert_prices_fresh` lets that through)
81
+ // and the mint was valued off a stale price. Ask for all of them, fail the
82
+ // build on any gap, then bump.
83
+ const poolTokens = client.config.packages.wlp?.pool_tokens ?? {};
84
+ // `refreshOraclePrices` dedupes its own input, so a plain concat is enough.
85
+ const oracleTickers = [...extraTickers, ...Object.keys(poolTokens)];
86
+ // Fail closed BEFORE the fetch, on EVERYTHING this build depends on.
87
+ //
88
+ // `refreshOraclePrices` no longer throws on an unservable ticker (it skips
89
+ // and reports), so nothing is gained by waiting for it — and waiting costs
90
+ // the full off-chain fetch plus every collector/aggregate moveCall appended
91
+ // to a caller-supplied `tx`, all discarded on the throw. The predicate is
92
+ // pure config, so the pre-flight answer is identical to the summary's, free.
93
+ //
94
+ // Two required sets, each with its own explanation: `extraTickers` are the
95
+ // caller's action-critical ones (the traded market + its collateral, or a
96
+ // WLP deposit ticker), and the pool is required wholesale because mint and
97
+ // redeem value the WHOLE pool.
98
+ const planned = plannedSummary(client, oracleTickers);
99
+ assertTickersRefreshed(client, planned, extraTickers, opts);
100
+ assertWlpPoolRefreshed(client, planned, opts);
101
+ const summary = await (0, index_ts_1.refreshOraclePrices)(tx, client, oracleTickers, {
33
102
  updateDataProvider: opts.updateDataProvider,
34
103
  });
35
- for (const tokenType of Object.values(client.config.packages.wlp.pool_tokens)) {
104
+ // Bump only what was actually AGGREGATED, not every pool entry.
105
+ //
106
+ // `update_token_value` calls `oracle::get_price`, which aborts `EStalePrice`
107
+ // unless this PTB aggregated that ticker. Normally the asserts above
108
+ // guarantee it — but `allowUnrefreshedPrices` skips them by design, and
109
+ // bumping a skipped asset then produced a transaction guaranteed to abort,
110
+ // which made the escape hatch unusable on exactly the deployments that need
111
+ // it. Driving the loop off the summary makes the opt-out mean what it says:
112
+ // build with whatever prices the chain already holds, and touch nothing else.
113
+ const aggregated = new Set(summary.refreshed);
114
+ for (const [ticker, tokenType] of Object.entries(poolTokens)) {
115
+ if (!aggregated.has(ticker))
116
+ continue;
36
117
  (0, wlp_ts_1.updateTokenValue)(client, tx, { tokenType, lpType: opts.lpType });
37
118
  }
119
+ return summary;
38
120
  }
39
121
  /**
40
- * Build the *Request + execute envelope with the config-driven Pyth sponsor flow:
122
+ * What {@link refreshOraclePrices} WOULD report for `tickers`, computed from
123
+ * config alone.
124
+ *
125
+ * Same predicate, same partition — so a pre-flight assert cannot disagree with
126
+ * the summary the refresh later returns, and a build destined to fail can fail
127
+ * before spending a network round trip or mutating the caller's transaction.
128
+ */
129
+ function plannedSummary(client, tickers) {
130
+ const { servable, unservable } = (0, index_ts_1.partitionServableTickers)(client, tickers);
131
+ return { refreshed: servable, skipped: unservable };
132
+ }
133
+ /**
134
+ * Build the *Request + execute envelope:
41
135
  *
42
136
  * [maybeConsolidate(tx)]
43
- * [fund = sponsor.request()]
44
- * refreshOraclePrices(..., feeSource?)
137
+ * refreshOraclePrices(...)
45
138
  * req = buildRequest()
46
- * [sponsor.reimburse(fund, req)]
47
139
  * trading::execute(req)
48
140
  *
49
141
  * Accepted ordering caveat: `maybeConsolidate` runs FIRST and can itself
50
- * append PTB commands (the consolidation sweep) before the fee-source check
51
- * inside `refreshOraclePrices` ever runs — so an `OracleFeeSourceUnavailable`
52
- * throw here is NOT the "zero commands appended" guarantee
53
- * `refreshOraclePrices` gives its own callers (see its docblock in
54
- * `aggregate.ts`); `tx` can already carry the sweep. This is the same
55
- * discard-tx-on-throw contract every `build*Tx` composer already has for
142
+ * append PTB commands (the consolidation sweep) before the refresh's own
143
+ * pre-checks run — so a throw out of `refreshOraclePrices` here is NOT the
144
+ * "zero commands appended" guarantee it gives its own callers (see its
145
+ * docblock in `aggregate.ts`); `tx` can already carry the sweep. This is the
146
+ * same discard-tx-on-throw contract every `build*Tx` composer already has for
56
147
  * mid-build on-chain-read failures — not a new hole. It matters only for a
57
148
  * caller that passed in their OWN `opts.tx` (reusing one `Transaction`
58
149
  * across builder calls, e.g. to compose several actions in one PTB); such a
@@ -61,39 +152,16 @@ async function refreshWlpPoolOracles(tx, client, extraTickers, opts) {
61
152
  */
62
153
  async function wrapRequestAndExecute(client, tx, req, collateralTicker, opts, buildRequest) {
63
154
  await maybeConsolidate(client, tx, req.accountId, opts);
64
- // Fee source + witness attachment is config-driven, not a caller flag: the
65
- // sponsor fund is opened (and later reimbursed) whenever this client's
66
- // config has `pyth_sponsor_rule` deployed — regardless of the deprecated
67
- // `useSponsor` flag (see its JSDoc). `allowGasFee` is the only caller lever
68
- // left, and it only matters when config has NO sponsor rule to open (see
69
- // `OracleFeeSourceUnavailable` in `oracle/pyth.ts`).
70
- //
71
- // `feeSource` is resolved HERE, once, from that same decision — sponsor
72
- // beats gas structurally because this is the only branch that ever sees
73
- // both candidates; everything downstream (`refreshWlpPoolOracles` →
74
- // `refreshOraclePrices` → `BuildUpdateOpts` → `PythCoreRule` →
75
- // `buildPythPriceUpdateCalls`) just carries the single resolved value.
76
- let sponsorFund;
77
- if (client.config.packages.pyth_sponsor_rule) {
78
- sponsorFund = (0, index_ts_1.openPythSponsorFund)(tx, client);
79
- }
80
- const feeSource = sponsorFund
81
- ? { kind: "sponsor", ...sponsorFund }
82
- : opts?.allowGasFee
83
- ? { kind: "gas" }
84
- : undefined;
85
155
  if (!opts?.skipOraclePriceRefresh) {
156
+ // The action-critical pair for a trade — the market being traded and the
157
+ // collateral it is margined in — is passed as the extras, which
158
+ // `refreshWlpPoolOracles` fails closed on before it fetches anything.
86
159
  await refreshWlpPoolOracles(tx, client, [req.ticker, collateralTicker], {
87
- cache: opts?.pythCache,
88
- feeSource,
160
+ ...opts,
89
161
  lpType: req.lpType,
90
- updateDataProvider: opts?.updateDataProvider,
91
162
  });
92
163
  }
93
- const tradingReq = buildRequest(sponsorFund);
94
- if (sponsorFund) {
95
- (0, index_ts_1.reimbursePythSponsor)(tx, client, sponsorFund.fund, tradingReq, req.collateralType);
96
- }
164
+ const tradingReq = buildRequest();
97
165
  (0, trading_ts_1.executeTrading)(client, tx, {
98
166
  ticker: req.ticker,
99
167
  collateralType: req.collateralType,
@@ -15,17 +15,8 @@ export interface BuildMintWlpParams extends MintWlpParams, CommonBuildOpts {
15
15
  * Mints WLP from a deposit asset already in the wxa account's stored
16
16
  * balance. Refreshes every pool-token oracle + bumps each pool token's
17
17
  * `last_price_refresh_timestamp` so `assert_prices_fresh` inside
18
- * `mint_wlp` passes.
19
- *
20
- * Never uses the pyth_sponsor flow — `mint_wlp` produces no
21
- * `TradingRequest`, so there's nothing for the sponsor to attach its
22
- * witness to, and `pyth_sponsor_rule::reimburse` cannot consume a Fund
23
- * without one. So when `skipOraclePriceRefresh` is `false` (the refresh
24
- * actually runs), the caller MUST pass `allowGasFee: true` — the Pyth
25
- * update fee is drawn from `tx.gas`, which Enoki-sponsored transactions
26
- * reject; a sponsored caller should keep `skipOraclePriceRefresh: true`
27
- * instead and rely on freshness from other trade traffic (see
28
- * `OracleFeeSourceUnavailable` in `oracle/pyth.ts`).
18
+ * `mint_wlp` passes. The refresh is fee-free (no update leg charges one),
19
+ * so this composes into Enoki-sponsored transactions as-is.
29
20
  */
30
21
  export declare function buildMintWlpTx(client: PerpClient, params: BuildMintWlpParams): Promise<Transaction>;
31
22
  export interface BuildMintAndStakeWlpParams extends BuildMintWlpParams {
@@ -68,9 +59,7 @@ export interface BuildUnstakeAndRequestRedeemWlpParams extends Omit<RequestRedee
68
59
  * Refreshes every WLP pool-token oracle by default — `request_redeem` runs
69
60
  * `assert_prices_fresh` internally, so a stale oracle would abort the PTB.
70
61
  * Pass `skipOraclePriceRefresh: true` only when the caller is composing this
71
- * into a larger PTB that already pre-pumps prices. Like `buildMintWlpTx`,
72
- * `request_redeem` produces no `TradingRequest`, so a non-skipped refresh
73
- * requires `allowGasFee: true` (see `buildMintWlpTx`'s doc comment).
62
+ * into a larger PTB that already pre-pumps prices.
74
63
  */
75
64
  export declare function buildUnstakeAndRequestRedeemWlpTx(client: PerpClient, params: BuildUnstakeAndRequestRedeemWlpParams): Promise<Transaction>;
76
65
  export interface BuildCancelRedeemAndStakeWlpParams extends CancelRedeemWlpParams, CommonBuildOpts {
@@ -16,31 +16,16 @@ const common_ts_1 = require("./common.js");
16
16
  * Mints WLP from a deposit asset already in the wxa account's stored
17
17
  * balance. Refreshes every pool-token oracle + bumps each pool token's
18
18
  * `last_price_refresh_timestamp` so `assert_prices_fresh` inside
19
- * `mint_wlp` passes.
20
- *
21
- * Never uses the pyth_sponsor flow — `mint_wlp` produces no
22
- * `TradingRequest`, so there's nothing for the sponsor to attach its
23
- * witness to, and `pyth_sponsor_rule::reimburse` cannot consume a Fund
24
- * without one. So when `skipOraclePriceRefresh` is `false` (the refresh
25
- * actually runs), the caller MUST pass `allowGasFee: true` — the Pyth
26
- * update fee is drawn from `tx.gas`, which Enoki-sponsored transactions
27
- * reject; a sponsored caller should keep `skipOraclePriceRefresh: true`
28
- * instead and rely on freshness from other trade traffic (see
29
- * `OracleFeeSourceUnavailable` in `oracle/pyth.ts`).
19
+ * `mint_wlp` passes. The refresh is fee-free (no update leg charges one),
20
+ * so this composes into Enoki-sponsored transactions as-is.
30
21
  */
31
22
  async function buildMintWlpTx(client, params) {
32
23
  const tx = (0, common_ts_1.newTx)(params);
33
24
  await (0, common_ts_1.maybeConsolidate)(client, tx, params.accountId, params);
34
- // `mint_wlp` has no sponsor flow to resolve against (see the doc comment
35
- // above) — the only candidate source at this edge is the caller's
36
- // ergonomic `allowGasFee` opt-in.
37
- const feeSource = params.allowGasFee ? { kind: "gas" } : undefined;
38
25
  if (!params.skipOraclePriceRefresh) {
39
26
  await (0, common_ts_1.refreshWlpPoolOracles)(tx, client, [params.depositTicker], {
40
- cache: params.pythCache,
27
+ ...params,
41
28
  lpType: params.lpType,
42
- feeSource,
43
- updateDataProvider: params.updateDataProvider,
44
29
  });
45
30
  }
46
31
  (0, wlp_ts_1.mintWlp)(client, tx, params);
@@ -58,16 +43,10 @@ async function buildMintWlpTx(client, params) {
58
43
  async function buildMintAndStakeWlpTx(client, params) {
59
44
  const tx = (0, common_ts_1.newTx)(params);
60
45
  await (0, common_ts_1.maybeConsolidate)(client, tx, params.accountId, params);
61
- // `mint_wlp` has no sponsor flow to resolve against (see `buildMintWlpTx`'s
62
- // doc comment) — the only candidate source at this edge is the caller's
63
- // ergonomic `allowGasFee` opt-in.
64
- const feeSource = params.allowGasFee ? { kind: "gas" } : undefined;
65
46
  if (!params.skipOraclePriceRefresh) {
66
47
  await (0, common_ts_1.refreshWlpPoolOracles)(tx, client, [params.depositTicker], {
67
- cache: params.pythCache,
48
+ ...params,
68
49
  lpType: params.lpType,
69
- feeSource,
70
- updateDataProvider: params.updateDataProvider,
71
50
  });
72
51
  }
73
52
  const stakeAlias = params.stakeAlias ?? "WLP";
@@ -89,24 +68,16 @@ async function buildMintAndStakeWlpTx(client, params) {
89
68
  * Refreshes every WLP pool-token oracle by default — `request_redeem` runs
90
69
  * `assert_prices_fresh` internally, so a stale oracle would abort the PTB.
91
70
  * Pass `skipOraclePriceRefresh: true` only when the caller is composing this
92
- * into a larger PTB that already pre-pumps prices. Like `buildMintWlpTx`,
93
- * `request_redeem` produces no `TradingRequest`, so a non-skipped refresh
94
- * requires `allowGasFee: true` (see `buildMintWlpTx`'s doc comment).
71
+ * into a larger PTB that already pre-pumps prices.
95
72
  */
96
73
  async function buildUnstakeAndRequestRedeemWlpTx(client, params) {
97
74
  const tx = (0, common_ts_1.newTx)(params);
98
75
  const stakeAlias = params.stakeAlias ?? "WLP";
99
76
  await (0, common_ts_1.maybeConsolidate)(client, tx, params.accountId, params);
100
- // `request_redeem` has no sponsor flow to resolve against (see
101
- // `buildMintWlpTx`'s doc comment) — the only candidate source at this edge
102
- // is the caller's ergonomic `allowGasFee` opt-in.
103
- const feeSource = params.allowGasFee ? { kind: "gas" } : undefined;
104
77
  if (!params.skipOraclePriceRefresh) {
105
78
  await (0, common_ts_1.refreshWlpPoolOracles)(tx, client, [], {
106
- cache: params.pythCache,
79
+ ...params,
107
80
  lpType: params.lpType,
108
- feeSource,
109
- updateDataProvider: params.updateDataProvider,
110
81
  });
111
82
  }
112
83
  (0, staking_ts_1.unstake)(client, tx, {
@@ -2,10 +2,10 @@
2
2
  * High-level perp transaction builders — barrel.
3
3
  *
4
4
  * Each `build*Tx` composer creates (or appends to) a `Transaction`, refreshes
5
- * the on-chain `Oracle` via Pyth, optionally pre-sweeps parked balances
6
- * (`consolidateToUsd`), wires the `pyth_sponsor_rule` flow when deployed in
7
- * config, and calls the matching `*_request` + `execute`. Implementations are
8
- * split by domain under `tx-builders/`:
5
+ * the on-chain `Oracle` via the client's derived fed set, optionally
6
+ * pre-sweeps parked balances (`consolidateToUsd`), and calls the matching
7
+ * `*_request` + `execute`. Implementations are split by domain under
8
+ * `tx-builders/`:
9
9
  *
10
10
  * common.ts CommonBuildOpts + request/execute envelope + oracle refresh
11
11
  * consolidate.ts parked-balance → wxUSD pre-sweep (appendConsolidate*)
@@ -20,4 +20,5 @@ export * from "./tx-builders/trading.ts";
20
20
  export * from "./tx-builders/wlp.ts";
21
21
  export * from "./tx-builders/rewards.ts";
22
22
  export * from "./tx-builders/credit.ts";
23
- export { openPythSponsorFund, PythCache, refreshOraclePrices, reimbursePythSponsor, updatePythPrices, } from "../oracle/index.ts";
23
+ export { refreshOraclePrices } from "../oracle/index.ts";
24
+ export { refreshWlpPoolOracles } from "./tx-builders/common.ts";
@@ -3,10 +3,10 @@
3
3
  * High-level perp transaction builders — barrel.
4
4
  *
5
5
  * Each `build*Tx` composer creates (or appends to) a `Transaction`, refreshes
6
- * the on-chain `Oracle` via Pyth, optionally pre-sweeps parked balances
7
- * (`consolidateToUsd`), wires the `pyth_sponsor_rule` flow when deployed in
8
- * config, and calls the matching `*_request` + `execute`. Implementations are
9
- * split by domain under `tx-builders/`:
6
+ * the on-chain `Oracle` via the client's derived fed set, optionally
7
+ * pre-sweeps parked balances (`consolidateToUsd`), and calls the matching
8
+ * `*_request` + `execute`. Implementations are split by domain under
9
+ * `tx-builders/`:
10
10
  *
11
11
  * common.ts CommonBuildOpts + request/execute envelope + oracle refresh
12
12
  * consolidate.ts parked-balance → wxUSD pre-sweep (appendConsolidate*)
@@ -30,16 +30,22 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
30
30
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
31
31
  };
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.updatePythPrices = exports.reimbursePythSponsor = exports.refreshOraclePrices = exports.PythCache = exports.openPythSponsorFund = void 0;
33
+ exports.refreshWlpPoolOracles = exports.refreshOraclePrices = void 0;
34
34
  __exportStar(require("../account/funding/consolidate.js"), exports);
35
35
  __exportStar(require("./tx-builders/trading.js"), exports);
36
36
  __exportStar(require("./tx-builders/wlp.js"), exports);
37
37
  __exportStar(require("./tx-builders/rewards.js"), exports);
38
38
  __exportStar(require("./tx-builders/credit.js"), exports);
39
- // Oracle helpers re-exported for callers composing custom PTBs.
39
+ // Oracle helpers re-exported for callers composing custom PTBs (the
40
+ // shared-refresh composition — see `CommonBuildOpts.skipOraclePriceRefresh`).
40
41
  var index_ts_1 = require("../oracle/index.js");
41
- Object.defineProperty(exports, "openPythSponsorFund", { enumerable: true, get: function () { return index_ts_1.openPythSponsorFund; } });
42
- Object.defineProperty(exports, "PythCache", { enumerable: true, get: function () { return index_ts_1.PythCache; } });
43
42
  Object.defineProperty(exports, "refreshOraclePrices", { enumerable: true, get: function () { return index_ts_1.refreshOraclePrices; } });
44
- Object.defineProperty(exports, "reimbursePythSponsor", { enumerable: true, get: function () { return index_ts_1.reimbursePythSponsor; } });
45
- Object.defineProperty(exports, "updatePythPrices", { enumerable: true, get: function () { return index_ts_1.updatePythPrices; } });
43
+ // The WLP pool-freshness leg. Public because any custom WLP PTB needs it and
44
+ // hand-rolling it is a trap: the refresh set and the `update_token_value` set
45
+ // must be IDENTICAL and must cover the WHOLE pool. Pre-filtering either one to
46
+ // what the fed set can price silently drops an asset from both halves, and
47
+ // nothing on chain objects — `assert_prices_fresh` only checks each token's
48
+ // timestamp against a threshold, so a recent-enough stale price passes and
49
+ // `mint_wlp` values the payout off it.
50
+ var common_ts_1 = require("./tx-builders/common.js");
51
+ Object.defineProperty(exports, "refreshWlpPoolOracles", { enumerable: true, get: function () { return common_ts_1.refreshWlpPoolOracles; } });
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Exposes three namespaces over the two product-line sub-clients:
5
5
  *
6
- * const client = await WaterXClient.create({ network: "TESTNET", oracleSource: "pyth_rule" });
6
+ * const client = await WaterXClient.create({ network: "TESTNET" });
7
7
  * client.account.createAccount(tx, { alias }); // -> shared waterx_account + funding
8
8
  * client.perp.placeOrderRequest(tx, params); // -> perp builder
9
9
  * client.predict.placeOrder(tx, params); // -> prediction builder
@@ -25,15 +25,14 @@
25
25
  *
26
26
  * Each namespace method forwards to the existing free-function builder with the
27
27
  * line's client pre-bound as the first argument; builders are build-only (they
28
- * return / mutate a `Transaction`), so frontend wallet flows and multi-step Pyth
29
- * injection keep working.
28
+ * return / mutate a `Transaction`), so frontend wallet flows and multi-step
29
+ * oracle injection keep working.
30
30
  */
31
31
  import { Transaction } from "@mysten/sui/transactions";
32
32
  import * as accountOps from "./account/index.ts";
33
33
  import * as perpReferral from "./account/referral.ts";
34
34
  import type { Network } from "./constants.ts";
35
35
  import type { PythFetchPolicy } from "./oracle/config.ts";
36
- import type { OracleSource } from "./oracle/price-update-rule.ts";
37
36
  import type { FetchPolicy } from "./oracle/update-fetch.ts";
38
37
  import { PerpClient, type CreateClientOptions as PerpCreateOptions } from "./perp/client.ts";
39
38
  import * as perpFetch from "./perp/fetch.ts";
@@ -151,11 +150,8 @@ declare const perpOps: {
151
150
  amount: bigint | number;
152
151
  creditType?: string;
153
152
  }): Promise<perpFetch.BridgeFeeView>;
154
- openPythSponsorFund: typeof perpTx.openPythSponsorFund;
155
- PythCache: typeof perpTx.PythCache;
156
153
  refreshOraclePrices: typeof perpTx.refreshOraclePrices;
157
- reimbursePythSponsor: typeof perpTx.reimbursePythSponsor;
158
- updatePythPrices: typeof perpTx.updatePythPrices;
154
+ refreshWlpPoolOracles: typeof perpTx.refreshWlpPoolOracles;
159
155
  appendConsolidateToUsd(client: import("./account/client.ts").AccountClientLike, tx: Transaction, accountId: string): Promise<number>;
160
156
  appendConsolidateAddressCredit(client: import("./account/client.ts").AccountClientLike, tx: Transaction, accountId: string): Promise<number>;
161
157
  appendConsolidateForSpend(client: import("./account/client.ts").AccountClientLike, tx: Transaction, accountId: string): Promise<number>;
@@ -368,30 +364,8 @@ export interface ClientCreateOptions {
368
364
  /** Memoize the fetched config JSON. */
369
365
  cache?: boolean;
370
366
  /**
371
- * The perp line's oracle price-update source (perp-line only the
372
- * prediction line has no oracle leg), forwarded to `PerpClient.create`.
373
- * REQUIRED — there is NO default source: every deployment names its source
374
- * explicitly (wire it from your own env var, e.g. `ORACLE_SOURCE`).
375
- * Source-neutral by design: a source need not be Pyth (see `'waterx_rule'`).
376
- *
377
- * - `'pyth_rule'` — Pyth Core updates; infra in the source's own
378
- * `PYTH_CORE_INFRA` table.
379
- * - `'pyth_lazer_rule'` — Pyth Lazer signed updates (pair with `pythApiKey`
380
- * and a config carrying `packages.pyth_lazer_rule`); infra in the
381
- * source's own `LAZER_INFRA` table.
382
- * - `'waterx_rule'` — the first-party WaterX quote-center (Nautilus-TEE,
383
- * ed25519 signed batches; no credential, no per-update fee); infra in the
384
- * source's own `WATERX_INFRA` table. Pair with `waterxEndpoint` /
385
- * `waterxFetch` when the browser needs a proxy.
386
- *
387
- * Each source is self-contained with no cross-source fallback; selecting a
388
- * source whose feed for a ticker is absent fails at tx-build (not at init).
389
- * See perp `CreateClientOptions.oracleSource` for the full note.
390
- */
391
- oracleSource: OracleSource | OracleSource[];
392
- /**
393
- * Pyth Lazer access token, forwarded to the perp line. Required under
394
- * `oracleSource: 'pyth_lazer_rule'`, unused by `'pyth_rule'`. A SECRET —
367
+ * Pyth Lazer access token, forwarded to the perp line. Required when the
368
+ * deployment's config wires `pyth_lazer_rule`, unused otherwise. A SECRET
395
369
  * pass it at init from your own env var; it is never read from the config
396
370
  * JSON or `process.env`.
397
371
  */
@@ -399,14 +373,14 @@ export interface ClientCreateOptions {
399
373
  /** Retry/timeout policy for the perp line's off-chain oracle fetches. */
400
374
  pythFetch?: PythFetchPolicy;
401
375
  /**
402
- * Quote-center base URL for `oracleSource: 'waterx_rule'`, forwarded to the
403
- * perp line — overrides the source's own per-network `WATERX_INFRA` default.
376
+ * Quote-center base URL for `waterx_rule`, forwarded to the perp line —
377
+ * overrides the source's own per-network `WATERX_INFRA` default.
404
378
  *
405
379
  * `waterx_rule` is the one source a BROWSER fetches itself, so it is bound by
406
380
  * the quote-center deployment's CORS allowlist: a front end whose origin is
407
381
  * not allowed points this at its own same-origin proxy. An absolute URL whose
408
382
  * base PATH is preserved — `https://app.example/api/quote-center` fetches
409
- * `…/api/quote-center/v1/quotes/update`. Unused by the Pyth sources.
383
+ * `…/api/quote-center/v1/quotes/leaves`. Unused by the Pyth sources.
410
384
  */
411
385
  waterxEndpoint?: string;
412
386
  /**
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Exposes three namespaces over the two product-line sub-clients:
6
6
  *
7
- * const client = await WaterXClient.create({ network: "TESTNET", oracleSource: "pyth_rule" });
7
+ * const client = await WaterXClient.create({ network: "TESTNET" });
8
8
  * client.account.createAccount(tx, { alias }); // -> shared waterx_account + funding
9
9
  * client.perp.placeOrderRequest(tx, params); // -> perp builder
10
10
  * client.predict.placeOrder(tx, params); // -> prediction builder
@@ -26,8 +26,8 @@
26
26
  *
27
27
  * Each namespace method forwards to the existing free-function builder with the
28
28
  * line's client pre-bound as the first argument; builders are build-only (they
29
- * return / mutate a `Transaction`), so frontend wallet flows and multi-step Pyth
30
- * injection keep working.
29
+ * return / mutate a `Transaction`), so frontend wallet flows and multi-step
30
+ * oracle injection keep working.
31
31
  */
32
32
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
33
33
  if (k2 === undefined) k2 = k;
@@ -204,7 +204,6 @@ class WaterXClient {
204
204
  grpcUrl: opts.grpcUrl,
205
205
  waterxConfigUrl: opts.waterxConfigUrl,
206
206
  cache: opts.cache,
207
- oracleSource: opts.oracleSource,
208
207
  pythApiKey: opts.pythApiKey,
209
208
  pythFetch: opts.pythFetch,
210
209
  waterxEndpoint: opts.waterxEndpoint,
@@ -1,11 +1,3 @@
1
1
  import type { WaterXConfig } from "../perp/config.ts";
2
2
  /** Returns all registered market tickers (e.g. "BTCUSD") from waterx-config. */
3
3
  export declare function getMarketTickers(config: WaterXConfig): string[];
4
- /**
5
- * Returns WLP pool-token tickers that also have a registered pyth_rule feed —
6
- * the canonical testnet config keys `pool_tokens` by coin symbol (e.g. `"USD"`)
7
- * while `pyth_rule.feeds` is keyed by oracle ticker (e.g. `"USDCUSD"`), so a
8
- * naive `Object.keys(pool_tokens)` blows up at `refreshOraclePrices` for any
9
- * key without a feed. Filter so the auto-refresh path stays tolerant.
10
- */
11
- export declare function getCollateralAssets(config: WaterXConfig): string[];
@@ -1,20 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getMarketTickers = getMarketTickers;
4
- exports.getCollateralAssets = getCollateralAssets;
5
- const record_ts_1 = require("./record.js");
6
4
  /** Returns all registered market tickers (e.g. "BTCUSD") from waterx-config. */
7
5
  function getMarketTickers(config) {
8
6
  return Object.keys(config.packages.waterx_perp.markets);
9
7
  }
10
- /**
11
- * Returns WLP pool-token tickers that also have a registered pyth_rule feed
12
- * the canonical testnet config keys `pool_tokens` by coin symbol (e.g. `"USD"`)
13
- * while `pyth_rule.feeds` is keyed by oracle ticker (e.g. `"USDCUSD"`), so a
14
- * naive `Object.keys(pool_tokens)` blows up at `refreshOraclePrices` for any
15
- * key without a feed. Filter so the auto-refresh path stays tolerant.
16
- */
17
- function getCollateralAssets(config) {
18
- const feeds = config.packages.pyth_rule?.feeds ?? {};
19
- return Object.keys(config.packages.wlp.pool_tokens).filter((t) => (0, record_ts_1.ownEntry)(feeds, t) !== undefined);
20
- }
8
+ // "Which WLP pool tokens can this deployment PRICE" is an oracle-coverage
9
+ // question, not a config read: it depends on the client's fed set, not just
10
+ // the JSON. It lives on `PerpClient.pricedPoolTickers()` (over
11
+ // `oracle/validate.ts`'s `servableTickers`) `utils/` is the shared base and
12
+ // must not import `oracle/`.
@@ -71,11 +71,9 @@ export interface WithdrawalQueuePackage {
71
71
  queue?: string;
72
72
  }
73
73
  /**
74
- * Wormhole infra for the cross-chain credit bridge. `state_id` is the same
75
- * shared Sui Wormhole `State` object Pyth uses (kept in sync with
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.
74
+ * Wormhole infra for the cross-chain credit bridge. `state_id` is the shared
75
+ * Sui Wormhole `State` object for the network. Override per-deployment via
76
+ * `WaterXConfig.wormhole` if a deployment ever points elsewhere.
79
77
  */
80
78
  export interface WormholeInfraConfig {
81
79
  /** Shared Sui Wormhole `State` object. */
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Wormhole / Wormholescan integration for the cross-chain credit bridge.
3
3
  *
4
- * Single source of truth for VAA discovery + (de)serialization mirrors
5
- * `oracle/pyth.ts`'s role for Pyth's Hermes endpoint. Two directions:
4
+ * Single source of truth for VAA discovery + (de)serialization. Two directions:
6
5
  *
7
6
  * - Mint (EVM → Sui): fetch the signed VAA for an EVM `Deposit` by
8
7
  * (emitter chain, emitter address, sequence); the raw bytes feed
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Wormhole / Wormholescan integration for the cross-chain credit bridge.
3
3
  *
4
- * Single source of truth for VAA discovery + (de)serialization mirrors
5
- * `oracle/pyth.ts`'s role for Pyth's Hermes endpoint. Two directions:
4
+ * Single source of truth for VAA discovery + (de)serialization. Two directions:
6
5
  *
7
6
  * - Mint (EVM → Sui): fetch the signed VAA for an EVM `Deposit` by
8
7
  * (emitter chain, emitter address, sequence); the raw bytes feed