@waterx/sdk 3.1.1 → 4.0.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.
Files changed (76) hide show
  1. package/README.md +54 -18
  2. package/dist/cjs/src/account/config.d.ts +0 -16
  3. package/dist/cjs/src/oracle/aggregate.d.ts +96 -17
  4. package/dist/cjs/src/oracle/aggregate.js +179 -21
  5. package/dist/cjs/src/oracle/config.d.ts +85 -2
  6. package/dist/cjs/src/oracle/config.js +30 -1
  7. package/dist/cjs/src/oracle/host.d.ts +14 -1
  8. package/dist/cjs/src/oracle/index.d.ts +19 -5
  9. package/dist/cjs/src/oracle/index.js +54 -6
  10. package/dist/cjs/src/oracle/price-update-rule.d.ts +180 -0
  11. package/dist/cjs/src/oracle/price-update-rule.js +56 -0
  12. package/dist/cjs/src/oracle/pyth.d.ts +142 -11
  13. package/dist/cjs/src/oracle/pyth.js +408 -25
  14. package/dist/cjs/src/oracle/rule-registry.d.ts +41 -0
  15. package/dist/cjs/src/oracle/rule-registry.js +65 -0
  16. package/dist/cjs/src/oracle/rules/pyth-core-rule.d.ts +15 -0
  17. package/dist/cjs/src/oracle/rules/pyth-core-rule.js +99 -0
  18. package/dist/cjs/src/oracle/rules/pyth-lazer-rule.d.ts +41 -0
  19. package/dist/cjs/src/oracle/rules/pyth-lazer-rule.js +197 -0
  20. package/dist/cjs/src/oracle/rules/pyth-rule.js +5 -0
  21. package/dist/cjs/src/oracle/rules/sponsor.d.ts +11 -7
  22. package/dist/cjs/src/oracle/rules/sponsor.js +11 -7
  23. package/dist/cjs/src/oracle/update-fetch.d.ts +115 -0
  24. package/dist/cjs/src/oracle/update-fetch.js +285 -0
  25. package/dist/cjs/src/perp/client.d.ts +40 -5
  26. package/dist/cjs/src/perp/client.js +18 -3
  27. package/dist/cjs/src/perp/config.d.ts +10 -7
  28. package/dist/cjs/src/perp/config.js +77 -17
  29. package/dist/cjs/src/perp/index.d.ts +3 -2
  30. package/dist/cjs/src/perp/index.js +6 -2
  31. package/dist/cjs/src/perp/tx-builders/common.d.ts +52 -15
  32. package/dist/cjs/src/perp/tx-builders/common.js +39 -6
  33. package/dist/cjs/src/perp/tx-builders/wlp.d.ts +11 -3
  34. package/dist/cjs/src/perp/tx-builders/wlp.js +29 -3
  35. package/dist/cjs/src/perp/tx-builders.d.ts +3 -3
  36. package/dist/cjs/src/perp/tx-builders.js +3 -3
  37. package/dist/cjs/src/unified-client.d.ts +25 -0
  38. package/dist/cjs/src/unified-client.js +3 -0
  39. package/dist/src/account/config.d.ts +0 -16
  40. package/dist/src/oracle/aggregate.d.ts +96 -17
  41. package/dist/src/oracle/aggregate.js +180 -22
  42. package/dist/src/oracle/config.d.ts +85 -2
  43. package/dist/src/oracle/config.js +29 -0
  44. package/dist/src/oracle/host.d.ts +14 -1
  45. package/dist/src/oracle/index.d.ts +19 -5
  46. package/dist/src/oracle/index.js +42 -6
  47. package/dist/src/oracle/price-update-rule.d.ts +180 -0
  48. package/dist/src/oracle/price-update-rule.js +53 -0
  49. package/dist/src/oracle/pyth.d.ts +142 -11
  50. package/dist/src/oracle/pyth.js +402 -24
  51. package/dist/src/oracle/rule-registry.d.ts +41 -0
  52. package/dist/src/oracle/rule-registry.js +60 -0
  53. package/dist/src/oracle/rules/pyth-core-rule.d.ts +15 -0
  54. package/dist/src/oracle/rules/pyth-core-rule.js +96 -0
  55. package/dist/src/oracle/rules/pyth-lazer-rule.d.ts +41 -0
  56. package/dist/src/oracle/rules/pyth-lazer-rule.js +192 -0
  57. package/dist/src/oracle/rules/pyth-rule.js +5 -0
  58. package/dist/src/oracle/rules/sponsor.d.ts +11 -7
  59. package/dist/src/oracle/rules/sponsor.js +11 -7
  60. package/dist/src/oracle/update-fetch.d.ts +115 -0
  61. package/dist/src/oracle/update-fetch.js +277 -0
  62. package/dist/src/perp/client.d.ts +40 -5
  63. package/dist/src/perp/client.js +18 -3
  64. package/dist/src/perp/config.d.ts +10 -7
  65. package/dist/src/perp/config.js +77 -17
  66. package/dist/src/perp/index.d.ts +3 -2
  67. package/dist/src/perp/index.js +1 -1
  68. package/dist/src/perp/tx-builders/common.d.ts +52 -15
  69. package/dist/src/perp/tx-builders/common.js +39 -6
  70. package/dist/src/perp/tx-builders/wlp.d.ts +11 -3
  71. package/dist/src/perp/tx-builders/wlp.js +29 -3
  72. package/dist/src/perp/tx-builders.d.ts +3 -3
  73. package/dist/src/perp/tx-builders.js +3 -3
  74. package/dist/src/unified-client.d.ts +25 -0
  75. package/dist/src/unified-client.js +3 -0
  76. package/package.json +1 -1
@@ -4,7 +4,7 @@
4
4
  * and the request+execute envelope (optional Pyth-sponsor flow + pre-sweep).
5
5
  */
6
6
  import { Transaction, type TransactionArgument } from "@mysten/sui/transactions";
7
- import { PythCache } from "../../oracle/index.ts";
7
+ import { PythCache, type OracleFeeSource, type UpdateDataProvider } from "../../oracle/index.ts";
8
8
  import type { PerpClient } from "../client.ts";
9
9
  export interface CommonBuildOpts {
10
10
  /** Append to an existing PTB instead of creating a new one. */
@@ -14,16 +14,31 @@ export interface CommonBuildOpts {
14
14
  /** Share a `PythCache` across builders to avoid redundant pyth_state reads. */
15
15
  pythCache?: PythCache;
16
16
  /**
17
- * Wire the `pyth_sponsor_rule` flow:
18
- * - open a Fund via `pyth_sponsor_rule::request(sponsor)`
19
- * - pay Pyth update fees from the Fund (instead of `tx.gas`)
20
- * - reimburse leftover into the sponsor pool + attach
21
- * `PythSponsorRule` witness to the TradingRequest so markets
22
- * whose `request_checklist` contains `PythSponsorRule` accept it
23
- * Default: true (matches the testnet/mainnet checklist config).
24
- * Pass `false` only when the market checklist is empty.
17
+ * @deprecated No longer a fee-source decision. `wrapRequestAndExecute` now
18
+ * opens (and reimburses) the `pyth_sponsor_rule` Fund purely from config
19
+ * presence whenever `client.config.packages.pyth_sponsor_rule` is
20
+ * deployed, the fund is ALWAYS opened, regardless of this flag (see
21
+ * `OracleFeeSourceUnavailable` in `oracle/pyth.ts`). This closes the gap
22
+ * where a market whose checklist required `PythSponsorRule`, or a caller
23
+ * that mis-set this flag, silently drew from `tx.gas` and failed
24
+ * ON-CHAIN instead of at build time. Use `allowGasFee` for the
25
+ * non-sponsored case instead. Kept accepted (as a no-op) only so existing
26
+ * callers keep compiling; will be removed in a future major version.
25
27
  */
26
28
  useSponsor?: boolean;
29
+ /**
30
+ * Explicit opt-in to draw the Pyth update fee from `tx.gas` when this
31
+ * client's config has no `pyth_sponsor_rule` deployed. Ignored whenever a
32
+ * sponsor fund IS available — the sponsor pool always wins over `tx.gas`
33
+ * when one can be opened (see `useSponsor`'s deprecation note above).
34
+ * Required for flows with no `TradingRequest` to reimburse a sponsor fund
35
+ * against (e.g. `buildMintWlpTx` — see its doc comment). Building an
36
+ * oracle refresh with neither a sponsor fund nor this flag throws
37
+ * `OracleFeeSourceUnavailable` instead of silently drawing from `tx.gas`
38
+ * (Enoki-sponsored transactions reject any `tx.gas` draw). Default:
39
+ * `false`.
40
+ */
41
+ allowGasFee?: boolean;
27
42
  /**
28
43
  * Pre-sweep parked backing assets (USDC, USDsui, …) at the wxa account's
29
44
  * address into USD credit, plus any CREDIT coins/funds at the address into
@@ -42,6 +57,15 @@ export interface CommonBuildOpts {
42
57
  * {@link buildConsolidateToUsdTx} separately.
43
58
  */
44
59
  consolidateToUsd?: boolean;
60
+ /**
61
+ * BE prefetch-cache seam for the oracle update-data fetch — forwarded
62
+ * verbatim into `refreshOraclePrices`'s `updateDataProvider` opt (see
63
+ * `UpdateDataProvider` in `oracle/price-update-rule.ts`). Default: none
64
+ * (always a live fetch). A caller-supplied provider that misses or throws
65
+ * still falls back to a live fetch — this option can only make a refresh
66
+ * faster, never break it.
67
+ */
68
+ updateDataProvider?: UpdateDataProvider;
45
69
  }
46
70
  interface RequestParams {
47
71
  ticker: string;
@@ -57,20 +81,33 @@ export declare function newTx(opts?: CommonBuildOpts): Transaction;
57
81
  */
58
82
  export declare function refreshWlpPoolOracles(tx: Transaction, client: PerpClient, extraTickers: string[], opts: {
59
83
  cache?: PythCache;
60
- sponsorFund?: {
61
- fund: TransactionArgument;
62
- packageId: string;
63
- };
84
+ /** Forwarded to `refreshOraclePrices` — already resolved by the caller (see `OracleFeeSource`). */
85
+ feeSource?: OracleFeeSource;
64
86
  lpType?: string;
87
+ updateDataProvider?: UpdateDataProvider;
65
88
  }): Promise<void>;
66
89
  /**
67
- * Build the *Request + execute envelope with optional Pyth sponsor flow:
90
+ * Build the *Request + execute envelope with the config-driven Pyth sponsor flow:
68
91
  *
92
+ * [maybeConsolidate(tx)]
69
93
  * [fund = sponsor.request()]
70
- * refreshOraclePrices(..., sponsorFund?)
94
+ * refreshOraclePrices(..., feeSource?)
71
95
  * req = buildRequest()
72
96
  * [sponsor.reimburse(fund, req)]
73
97
  * trading::execute(req)
98
+ *
99
+ * Accepted ordering caveat: `maybeConsolidate` runs FIRST and can itself
100
+ * append PTB commands (the consolidation sweep) before the fee-source check
101
+ * inside `refreshOraclePrices` ever runs — so an `OracleFeeSourceUnavailable`
102
+ * throw here is NOT the "zero commands appended" guarantee
103
+ * `refreshOraclePrices` gives its own callers (see its docblock in
104
+ * `aggregate.ts`); `tx` can already carry the sweep. This is the same
105
+ * discard-tx-on-throw contract every `build*Tx` composer already has for
106
+ * mid-build on-chain-read failures — not a new hole. It matters only for a
107
+ * caller that passed in their OWN `opts.tx` (reusing one `Transaction`
108
+ * across builder calls, e.g. to compose several actions in one PTB); such a
109
+ * caller must discard the whole `tx` on any throw from this function, not
110
+ * just retry the failed step.
74
111
  */
75
112
  export declare function wrapRequestAndExecute(client: PerpClient, tx: Transaction, req: RequestParams & {
76
113
  accountId: string;
@@ -23,32 +23,65 @@ export async function refreshWlpPoolOracles(tx, client, extraTickers, opts) {
23
23
  const oracleTickers = Array.from(new Set([...extraTickers, ...poolTickers]));
24
24
  await refreshOraclePrices(tx, client, oracleTickers, {
25
25
  cache: opts.cache,
26
- sponsorFund: opts.sponsorFund,
26
+ feeSource: opts.feeSource,
27
+ updateDataProvider: opts.updateDataProvider,
27
28
  });
28
29
  for (const tokenType of Object.values(client.config.packages.wlp.pool_tokens)) {
29
30
  updateTokenValue(client, tx, { tokenType, lpType: opts.lpType });
30
31
  }
31
32
  }
32
33
  /**
33
- * Build the *Request + execute envelope with optional Pyth sponsor flow:
34
+ * Build the *Request + execute envelope with the config-driven Pyth sponsor flow:
34
35
  *
36
+ * [maybeConsolidate(tx)]
35
37
  * [fund = sponsor.request()]
36
- * refreshOraclePrices(..., sponsorFund?)
38
+ * refreshOraclePrices(..., feeSource?)
37
39
  * req = buildRequest()
38
40
  * [sponsor.reimburse(fund, req)]
39
41
  * trading::execute(req)
42
+ *
43
+ * Accepted ordering caveat: `maybeConsolidate` runs FIRST and can itself
44
+ * append PTB commands (the consolidation sweep) before the fee-source check
45
+ * inside `refreshOraclePrices` ever runs — so an `OracleFeeSourceUnavailable`
46
+ * throw here is NOT the "zero commands appended" guarantee
47
+ * `refreshOraclePrices` gives its own callers (see its docblock in
48
+ * `aggregate.ts`); `tx` can already carry the sweep. This is the same
49
+ * discard-tx-on-throw contract every `build*Tx` composer already has for
50
+ * mid-build on-chain-read failures — not a new hole. It matters only for a
51
+ * caller that passed in their OWN `opts.tx` (reusing one `Transaction`
52
+ * across builder calls, e.g. to compose several actions in one PTB); such a
53
+ * caller must discard the whole `tx` on any throw from this function, not
54
+ * just retry the failed step.
40
55
  */
41
56
  export async function wrapRequestAndExecute(client, tx, req, collateralTicker, opts, buildRequest) {
42
57
  await maybeConsolidate(client, tx, req.accountId, opts);
43
- const useSponsor = opts?.useSponsor ?? true;
58
+ // Fee source + witness attachment is config-driven, not a caller flag: the
59
+ // sponsor fund is opened (and later reimbursed) whenever this client's
60
+ // config has `pyth_sponsor_rule` deployed — regardless of the deprecated
61
+ // `useSponsor` flag (see its JSDoc). `allowGasFee` is the only caller lever
62
+ // left, and it only matters when config has NO sponsor rule to open (see
63
+ // `OracleFeeSourceUnavailable` in `oracle/pyth.ts`).
64
+ //
65
+ // `feeSource` is resolved HERE, once, from that same decision — sponsor
66
+ // beats gas structurally because this is the only branch that ever sees
67
+ // both candidates; everything downstream (`refreshWlpPoolOracles` →
68
+ // `refreshOraclePrices` → `BuildUpdateOpts` → `PythCoreRule` →
69
+ // `buildPythPriceUpdateCalls`) just carries the single resolved value.
44
70
  let sponsorFund;
45
- if (useSponsor)
71
+ if (client.config.packages.pyth_sponsor_rule) {
46
72
  sponsorFund = openPythSponsorFund(tx, client);
73
+ }
74
+ const feeSource = sponsorFund
75
+ ? { kind: "sponsor", ...sponsorFund }
76
+ : opts?.allowGasFee
77
+ ? { kind: "gas" }
78
+ : undefined;
47
79
  if (!opts?.skipOraclePriceRefresh) {
48
80
  await refreshWlpPoolOracles(tx, client, [req.ticker, collateralTicker], {
49
81
  cache: opts?.pythCache,
50
- sponsorFund,
82
+ feeSource,
51
83
  lpType: req.lpType,
84
+ updateDataProvider: opts?.updateDataProvider,
52
85
  });
53
86
  }
54
87
  const tradingReq = buildRequest(sponsorFund);
@@ -17,9 +17,15 @@ export interface BuildMintWlpParams extends MintWlpParams, CommonBuildOpts {
17
17
  * `last_price_refresh_timestamp` so `assert_prices_fresh` inside
18
18
  * `mint_wlp` passes.
19
19
  *
20
- * Does NOT use the pyth_sponsor flow — `mint_wlp` produces no
20
+ * Never uses the pyth_sponsor flow — `mint_wlp` produces no
21
21
  * `TradingRequest`, so there's nothing for the sponsor to attach its
22
- * witness to. Pyth update fees come from `tx.gas`.
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`).
23
29
  */
24
30
  export declare function buildMintWlpTx(client: PerpClient, params: BuildMintWlpParams): Promise<Transaction>;
25
31
  export interface BuildMintAndStakeWlpParams extends BuildMintWlpParams {
@@ -62,7 +68,9 @@ export interface BuildUnstakeAndRequestRedeemWlpParams extends Omit<RequestRedee
62
68
  * Refreshes every WLP pool-token oracle by default — `request_redeem` runs
63
69
  * `assert_prices_fresh` internally, so a stale oracle would abort the PTB.
64
70
  * Pass `skipOraclePriceRefresh: true` only when the caller is composing this
65
- * into a larger PTB that already pre-pumps prices.
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).
66
74
  */
67
75
  export declare function buildUnstakeAndRequestRedeemWlpTx(client: PerpClient, params: BuildUnstakeAndRequestRedeemWlpParams): Promise<Transaction>;
68
76
  export interface BuildCancelRedeemAndStakeWlpParams extends CancelRedeemWlpParams, CommonBuildOpts {
@@ -12,17 +12,29 @@ import { maybeConsolidate, newTx, refreshWlpPoolOracles } from "./common.js";
12
12
  * `last_price_refresh_timestamp` so `assert_prices_fresh` inside
13
13
  * `mint_wlp` passes.
14
14
  *
15
- * Does NOT use the pyth_sponsor flow — `mint_wlp` produces no
15
+ * Never uses the pyth_sponsor flow — `mint_wlp` produces no
16
16
  * `TradingRequest`, so there's nothing for the sponsor to attach its
17
- * witness to. Pyth update fees come from `tx.gas`.
17
+ * witness to, and `pyth_sponsor_rule::reimburse` cannot consume a Fund
18
+ * without one. So when `skipOraclePriceRefresh` is `false` (the refresh
19
+ * actually runs), the caller MUST pass `allowGasFee: true` — the Pyth
20
+ * update fee is drawn from `tx.gas`, which Enoki-sponsored transactions
21
+ * reject; a sponsored caller should keep `skipOraclePriceRefresh: true`
22
+ * instead and rely on freshness from other trade traffic (see
23
+ * `OracleFeeSourceUnavailable` in `oracle/pyth.ts`).
18
24
  */
19
25
  export async function buildMintWlpTx(client, params) {
20
26
  const tx = newTx(params);
21
27
  await maybeConsolidate(client, tx, params.accountId, params);
28
+ // `mint_wlp` has no sponsor flow to resolve against (see the doc comment
29
+ // above) — the only candidate source at this edge is the caller's
30
+ // ergonomic `allowGasFee` opt-in.
31
+ const feeSource = params.allowGasFee ? { kind: "gas" } : undefined;
22
32
  if (!params.skipOraclePriceRefresh) {
23
33
  await refreshWlpPoolOracles(tx, client, [params.depositTicker], {
24
34
  cache: params.pythCache,
25
35
  lpType: params.lpType,
36
+ feeSource,
37
+ updateDataProvider: params.updateDataProvider,
26
38
  });
27
39
  }
28
40
  mintWlp(client, tx, params);
@@ -40,10 +52,16 @@ export async function buildMintWlpTx(client, params) {
40
52
  export async function buildMintAndStakeWlpTx(client, params) {
41
53
  const tx = newTx(params);
42
54
  await maybeConsolidate(client, tx, params.accountId, params);
55
+ // `mint_wlp` has no sponsor flow to resolve against (see `buildMintWlpTx`'s
56
+ // doc comment) — the only candidate source at this edge is the caller's
57
+ // ergonomic `allowGasFee` opt-in.
58
+ const feeSource = params.allowGasFee ? { kind: "gas" } : undefined;
43
59
  if (!params.skipOraclePriceRefresh) {
44
60
  await refreshWlpPoolOracles(tx, client, [params.depositTicker], {
45
61
  cache: params.pythCache,
46
62
  lpType: params.lpType,
63
+ feeSource,
64
+ updateDataProvider: params.updateDataProvider,
47
65
  });
48
66
  }
49
67
  const stakeAlias = params.stakeAlias ?? "WLP";
@@ -65,16 +83,24 @@ export async function buildMintAndStakeWlpTx(client, params) {
65
83
  * Refreshes every WLP pool-token oracle by default — `request_redeem` runs
66
84
  * `assert_prices_fresh` internally, so a stale oracle would abort the PTB.
67
85
  * Pass `skipOraclePriceRefresh: true` only when the caller is composing this
68
- * into a larger PTB that already pre-pumps prices.
86
+ * into a larger PTB that already pre-pumps prices. Like `buildMintWlpTx`,
87
+ * `request_redeem` produces no `TradingRequest`, so a non-skipped refresh
88
+ * requires `allowGasFee: true` (see `buildMintWlpTx`'s doc comment).
69
89
  */
70
90
  export async function buildUnstakeAndRequestRedeemWlpTx(client, params) {
71
91
  const tx = newTx(params);
72
92
  const stakeAlias = params.stakeAlias ?? "WLP";
73
93
  await maybeConsolidate(client, tx, params.accountId, params);
94
+ // `request_redeem` has no sponsor flow to resolve against (see
95
+ // `buildMintWlpTx`'s doc comment) — the only candidate source at this edge
96
+ // is the caller's ergonomic `allowGasFee` opt-in.
97
+ const feeSource = params.allowGasFee ? { kind: "gas" } : undefined;
74
98
  if (!params.skipOraclePriceRefresh) {
75
99
  await refreshWlpPoolOracles(tx, client, [], {
76
100
  cache: params.pythCache,
77
101
  lpType: params.lpType,
102
+ feeSource,
103
+ updateDataProvider: params.updateDataProvider,
78
104
  });
79
105
  }
80
106
  unstake(client, tx, {
@@ -3,9 +3,9 @@
3
3
  *
4
4
  * Each `build*Tx` composer creates (or appends to) a `Transaction`, refreshes
5
5
  * the on-chain `Oracle` via Pyth, optionally pre-sweeps parked balances
6
- * (`consolidateToUsd`), wires the `pyth_sponsor_rule` flow when enabled, and
7
- * calls the matching `*_request` + `execute`. Implementations are split by
8
- * domain under `tx-builders/`:
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/`:
9
9
  *
10
10
  * common.ts CommonBuildOpts + request/execute envelope + oracle refresh
11
11
  * consolidate.ts parked-balance → wxUSD pre-sweep (appendConsolidate*)
@@ -3,9 +3,9 @@
3
3
  *
4
4
  * Each `build*Tx` composer creates (or appends to) a `Transaction`, refreshes
5
5
  * the on-chain `Oracle` via Pyth, optionally pre-sweeps parked balances
6
- * (`consolidateToUsd`), wires the `pyth_sponsor_rule` flow when enabled, and
7
- * calls the matching `*_request` + `execute`. Implementations are split by
8
- * domain under `tx-builders/`:
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/`:
9
9
  *
10
10
  * common.ts CommonBuildOpts + request/execute envelope + oracle refresh
11
11
  * consolidate.ts parked-balance → wxUSD pre-sweep (appendConsolidate*)
@@ -32,6 +32,8 @@ 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
+ import type { PythFetchPolicy } from "./oracle/config.ts";
36
+ import type { OracleSource } from "./oracle/price-update-rule.ts";
35
37
  import { PerpClient, type CreateClientOptions as PerpCreateOptions } from "./perp/client.ts";
36
38
  import * as perpFetch from "./perp/fetch.ts";
37
39
  import * as perpTx from "./perp/tx-builders.ts";
@@ -363,6 +365,29 @@ export interface ClientCreateOptions {
363
365
  waterxConfigUrl?: string;
364
366
  /** Memoize the fetched config JSON. */
365
367
  cache?: boolean;
368
+ /**
369
+ * The perp line's oracle price-update source (perp-line only — the
370
+ * prediction line has no oracle leg), forwarded to `PerpClient.create`.
371
+ * Source-neutral by design: a future source need not be Pyth.
372
+ *
373
+ * - `'pyth_rule'` (default) — Pyth Core updates on Core infra.
374
+ * - `'pyth_lazer_rule'` — Pyth Lazer signed updates (pair with `pythApiKey`
375
+ * and a config carrying `packages.pyth_lazer_rule`).
376
+ *
377
+ * Each source is self-contained with no cross-source fallback; selecting a
378
+ * source whose feed for a ticker is absent fails at tx-build (not at init).
379
+ * See perp `CreateClientOptions.oracleSource` for the full note.
380
+ */
381
+ oracleSource?: OracleSource;
382
+ /**
383
+ * Pyth Lazer access token, forwarded to the perp line. Required under
384
+ * `oracleSource: 'pyth_lazer_rule'`, unused by `'pyth_rule'`. A SECRET —
385
+ * pass it at init from your own env var; it is never read from the config
386
+ * JSON or `process.env`.
387
+ */
388
+ pythApiKey?: string;
389
+ /** Retry/timeout policy for the perp line's off-chain oracle fetches. */
390
+ pythFetch?: PythFetchPolicy;
366
391
  /** Perp-line overrides (network, grpcUrl, waterxConfigUrl, cache, …). */
367
392
  perp?: PerpLineOptions;
368
393
  /** Prediction-line overrides (network, grpcUrl, waterxConfigUrl, cache, settlement, …). */
@@ -168,6 +168,9 @@ export class WaterXClient {
168
168
  grpcUrl: opts.grpcUrl,
169
169
  waterxConfigUrl: opts.waterxConfigUrl,
170
170
  cache: opts.cache,
171
+ oracleSource: opts.oracleSource,
172
+ pythApiKey: opts.pythApiKey,
173
+ pythFetch: opts.pythFetch,
171
174
  ...perpRest,
172
175
  });
173
176
  const predictClient = await PredictClient.create(resolvedPredictNetwork, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@waterx/sdk",
3
- "version": "3.1.1",
3
+ "version": "4.0.1",
4
4
  "description": "WaterX SDK — perpetuals and prediction markets on Sui",
5
5
  "license": "MIT",
6
6
  "author": "WaterX",