@waterx/sdk 2.3.1-dev.0 → 2.4.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/dist/src/client.d.ts +10 -22
- package/dist/src/client.js +12 -33
- package/dist/src/config.d.ts +24 -15
- package/dist/src/constants.d.ts +4 -0
- package/dist/src/constants.js +5 -0
- package/dist/src/index.d.ts +3 -3
- package/dist/src/index.js +2 -2
- package/dist/src/utils/pyth.d.ts +35 -32
- package/dist/src/utils/pyth.js +81 -136
- package/package.json +1 -1
package/dist/src/client.d.ts
CHANGED
|
@@ -70,35 +70,23 @@ export declare class WaterXClient {
|
|
|
70
70
|
price_info_object: string;
|
|
71
71
|
};
|
|
72
72
|
/**
|
|
73
|
-
* True when `ticker` is priced by `
|
|
73
|
+
* True when `ticker` is priced by `constant_rule` (a constant pin,
|
|
74
74
|
* e.g. `USDCUSD → $1`) rather than Pyth. Such tickers are fed via
|
|
75
75
|
* `constant_rule::feed` and need no Pyth update; see {@link refreshOraclePrices}.
|
|
76
76
|
*
|
|
77
77
|
* All-or-nothing, mirroring {@link getSupraRule} and the keeper: only routes a
|
|
78
78
|
* ticker to the constant rule when the rule is FULLY wired (`published_at` +
|
|
79
|
-
* `config` present). A half-populated block — `
|
|
80
|
-
* is deployed, a realistic mid-rollout state — would otherwise make this
|
|
81
|
-
* while {@link
|
|
82
|
-
*
|
|
79
|
+
* `config` present). A half-populated block — a `feeds` entry listed before the
|
|
80
|
+
* rule is deployed, a realistic mid-rollout state — would otherwise make this
|
|
81
|
+
* true while {@link aggregateTicker} throws, aborting the whole price-refresh PTB
|
|
82
|
+
* instead of safely falling back to Pyth.
|
|
83
|
+
*
|
|
84
|
+
* Whether a constant ticker is *also* Pyth-fed (the dual-feed transition state)
|
|
85
|
+
* or constant-only is not a separate flag — it falls out of whether the ticker
|
|
86
|
+
* still has a `pyth_rule.feeds` entry. {@link aggregateTicker} feeds each rule the
|
|
87
|
+
* ticker is configured for, so no `isDualFeed` / `isConstantOnly` predicate is needed.
|
|
83
88
|
*/
|
|
84
89
|
isConstantTicker(ticker: string): boolean;
|
|
85
|
-
/**
|
|
86
|
-
* True when `ticker` is mid-migration and must be fed by *both* Pyth and the
|
|
87
|
-
* constant rule into one collector — so the aggregator can hold the
|
|
88
|
-
* `{Pyth, Constant}` weight set without an `EMissingPriceSource` window while
|
|
89
|
-
* rule weights are flipped (on-chain `aggregator::remove_outliers` requires
|
|
90
|
-
* every weighted rule present in the collector). Listed in
|
|
91
|
-
* `waterx_constant_rule.dual_feed`; clamped to `prices` so a stray entry that
|
|
92
|
-
* isn't a real constant ticker can't double-feed against no weight. See
|
|
93
|
-
* {@link aggregateTickerWithDual} and the USDCUSD runbook in `waterx-contract`.
|
|
94
|
-
*/
|
|
95
|
-
isDualFeedTicker(ticker: string): boolean;
|
|
96
|
-
/**
|
|
97
|
-
* True when `ticker` is fed by the constant rule *alone* (steady state): no
|
|
98
|
-
* Pyth feed call, so it skips the Pyth update. Dual-feed tickers are constant
|
|
99
|
-
* *and* Pyth, so they are NOT constant-only.
|
|
100
|
-
*/
|
|
101
|
-
isConstantOnlyTicker(ticker: string): boolean;
|
|
102
90
|
/**
|
|
103
91
|
* The `supra_rule` config when it is deployed, enabled, and fully wired
|
|
104
92
|
* (`config` + `oracle_holder`), else `undefined`. When present, callers feed
|
package/dist/src/client.js
CHANGED
|
@@ -118,48 +118,27 @@ export class WaterXClient {
|
|
|
118
118
|
return f;
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
|
-
* True when `ticker` is priced by `
|
|
121
|
+
* True when `ticker` is priced by `constant_rule` (a constant pin,
|
|
122
122
|
* e.g. `USDCUSD → $1`) rather than Pyth. Such tickers are fed via
|
|
123
123
|
* `constant_rule::feed` and need no Pyth update; see {@link refreshOraclePrices}.
|
|
124
124
|
*
|
|
125
125
|
* All-or-nothing, mirroring {@link getSupraRule} and the keeper: only routes a
|
|
126
126
|
* ticker to the constant rule when the rule is FULLY wired (`published_at` +
|
|
127
|
-
* `config` present). A half-populated block — `
|
|
128
|
-
* is deployed, a realistic mid-rollout state — would otherwise make this
|
|
129
|
-
* while {@link
|
|
130
|
-
*
|
|
127
|
+
* `config` present). A half-populated block — a `feeds` entry listed before the
|
|
128
|
+
* rule is deployed, a realistic mid-rollout state — would otherwise make this
|
|
129
|
+
* true while {@link aggregateTicker} throws, aborting the whole price-refresh PTB
|
|
130
|
+
* instead of safely falling back to Pyth.
|
|
131
|
+
*
|
|
132
|
+
* Whether a constant ticker is *also* Pyth-fed (the dual-feed transition state)
|
|
133
|
+
* or constant-only is not a separate flag — it falls out of whether the ticker
|
|
134
|
+
* still has a `pyth_rule.feeds` entry. {@link aggregateTicker} feeds each rule the
|
|
135
|
+
* ticker is configured for, so no `isDualFeed` / `isConstantOnly` predicate is needed.
|
|
131
136
|
*/
|
|
132
137
|
isConstantTicker(ticker) {
|
|
133
|
-
const c = this.config.packages.
|
|
134
|
-
if (!c?.published_at || !c.config)
|
|
135
|
-
return false;
|
|
136
|
-
return c.prices?.[ticker] !== undefined;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* True when `ticker` is mid-migration and must be fed by *both* Pyth and the
|
|
140
|
-
* constant rule into one collector — so the aggregator can hold the
|
|
141
|
-
* `{Pyth, Constant}` weight set without an `EMissingPriceSource` window while
|
|
142
|
-
* rule weights are flipped (on-chain `aggregator::remove_outliers` requires
|
|
143
|
-
* every weighted rule present in the collector). Listed in
|
|
144
|
-
* `waterx_constant_rule.dual_feed`; clamped to `prices` so a stray entry that
|
|
145
|
-
* isn't a real constant ticker can't double-feed against no weight. See
|
|
146
|
-
* {@link aggregateTickerWithDual} and the USDCUSD runbook in `waterx-contract`.
|
|
147
|
-
*/
|
|
148
|
-
isDualFeedTicker(ticker) {
|
|
149
|
-
const c = this.config.packages.waterx_constant_rule;
|
|
138
|
+
const c = this.config.packages.constant_rule;
|
|
150
139
|
if (!c?.published_at || !c.config)
|
|
151
140
|
return false;
|
|
152
|
-
|
|
153
|
-
return false;
|
|
154
|
-
return c.dual_feed?.includes(ticker) ?? false;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* True when `ticker` is fed by the constant rule *alone* (steady state): no
|
|
158
|
-
* Pyth feed call, so it skips the Pyth update. Dual-feed tickers are constant
|
|
159
|
-
* *and* Pyth, so they are NOT constant-only.
|
|
160
|
-
*/
|
|
161
|
-
isConstantOnlyTicker(ticker) {
|
|
162
|
-
return this.isConstantTicker(ticker) && !this.isDualFeedTicker(ticker);
|
|
141
|
+
return c.feeds?.[ticker] !== undefined;
|
|
163
142
|
}
|
|
164
143
|
/**
|
|
165
144
|
* The `supra_rule` config when it is deployed, enabled, and fully wired
|
package/dist/src/config.d.ts
CHANGED
|
@@ -25,31 +25,40 @@ export interface PythRulePackage extends BasePackageEntry {
|
|
|
25
25
|
export interface PythSponsorRulePackage extends BasePackageEntry {
|
|
26
26
|
pyth_sponsor: string;
|
|
27
27
|
}
|
|
28
|
+
/** Per-ticker `constant_rule` feed entry (mirrors the `pyth_rule.feeds` shape). */
|
|
29
|
+
export interface ConstantFeedEntry {
|
|
30
|
+
/**
|
|
31
|
+
* Constant 1e9-scaled price (decimal string), mirroring the on-chain
|
|
32
|
+
* `Config.prices` value (e.g. `"1000000000"` for $1). Informational off-chain —
|
|
33
|
+
* the on-chain `constant_rule::feed` reads the price from `Config`; the SDK only
|
|
34
|
+
* keys routing off the presence of the entry.
|
|
35
|
+
*/
|
|
36
|
+
price: string;
|
|
37
|
+
}
|
|
28
38
|
export interface WaterxConstantRulePackage extends BasePackageEntry {
|
|
29
39
|
/** Shared `constant_rule::Config` holding the per-ticker constant prices. */
|
|
30
40
|
config: string;
|
|
31
41
|
/**
|
|
32
|
-
* Oracle ticker → constant
|
|
33
|
-
*
|
|
34
|
-
*
|
|
42
|
+
* Oracle ticker → constant feed entry, mirroring `pyth_rule.feeds`. A ticker
|
|
43
|
+
* present here is fed via `constant_rule::feed` instead of (steady state) or
|
|
44
|
+
* alongside (dual-feed) `pyth_rule::feed` (e.g. `USDCUSD → { price: "1000000000" }`).
|
|
35
45
|
*/
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
dual_feed?: string[];
|
|
46
|
+
feeds?: Record<string, ConstantFeedEntry>;
|
|
47
|
+
}
|
|
48
|
+
/** Per-ticker `supra_rule` feed entry (mirrors the `pyth_rule.feeds` shape). */
|
|
49
|
+
export interface SupraFeedEntry {
|
|
50
|
+
/** Supra pair id (mirrors the on-chain `Config`; informational off-chain). */
|
|
51
|
+
pair_id: number;
|
|
52
|
+
/** Optional per-ticker freshness tolerance override (ms). */
|
|
53
|
+
tolerance_ms?: number;
|
|
45
54
|
}
|
|
46
55
|
export interface SupraRulePackage extends BasePackageEntry {
|
|
47
56
|
/** Shared `supra_rule::Config` (per-symbol Supra pair_id + freshness tolerance). */
|
|
48
57
|
config: string;
|
|
49
58
|
/** Supra `OracleHolder` shared object id (network-specific). Required to feed. */
|
|
50
59
|
oracle_holder?: string;
|
|
51
|
-
/** Oracle ticker → Supra
|
|
52
|
-
|
|
60
|
+
/** Oracle ticker → Supra feed entry (mirrors the on-chain `Config`; informational). */
|
|
61
|
+
feeds?: Record<string, SupraFeedEntry>;
|
|
53
62
|
/**
|
|
54
63
|
* When true AND `config` + `oracle_holder` are set, `refreshOraclePrices`
|
|
55
64
|
* feeds `supra_rule` on the same `PriceCollector` as Pyth before `aggregate`
|
|
@@ -190,7 +199,7 @@ export interface WaterXPackages {
|
|
|
190
199
|
waterx_referral?: WaterxReferralPackage;
|
|
191
200
|
pyth_rule: PythRulePackage;
|
|
192
201
|
pyth_sponsor_rule?: PythSponsorRulePackage;
|
|
193
|
-
|
|
202
|
+
constant_rule?: WaterxConstantRulePackage;
|
|
194
203
|
supra_rule?: SupraRulePackage;
|
|
195
204
|
waterx_account: WxaAccountPackage;
|
|
196
205
|
waterx_oracle: WaterxOraclePackage;
|
package/dist/src/constants.d.ts
CHANGED
|
@@ -41,6 +41,10 @@ export declare const PERM_MINT_WLP = 256;
|
|
|
41
41
|
export declare const PERM_REDEEM_WLP = 512;
|
|
42
42
|
export declare const PERM_ALL_TRADING = 255;
|
|
43
43
|
export declare const PERM_ALL = 65535;
|
|
44
|
+
export declare const STAKING_PERM_DEPOSIT_STAKE: number;
|
|
45
|
+
export declare const STAKING_PERM_REDEEM_STAKE: number;
|
|
46
|
+
export declare const STAKING_PERM_CLAIM_REWARD: number;
|
|
47
|
+
export declare const STAKING_PERM_ALL: number;
|
|
44
48
|
export declare const ORDER_LIMIT_BUY = 0;
|
|
45
49
|
export declare const ORDER_LIMIT_SELL = 1;
|
|
46
50
|
export declare const ORDER_STOP_BUY = 2;
|
package/dist/src/constants.js
CHANGED
|
@@ -44,6 +44,11 @@ export const PERM_MINT_WLP = 256;
|
|
|
44
44
|
export const PERM_REDEEM_WLP = 512;
|
|
45
45
|
export const PERM_ALL_TRADING = 0xff;
|
|
46
46
|
export const PERM_ALL = 0xffff;
|
|
47
|
+
// ======== Staking Permission Bitmasks (matches waterx_staking.move) ========
|
|
48
|
+
export const STAKING_PERM_DEPOSIT_STAKE = 1 << 0;
|
|
49
|
+
export const STAKING_PERM_REDEEM_STAKE = 1 << 1;
|
|
50
|
+
export const STAKING_PERM_CLAIM_REWARD = 1 << 2;
|
|
51
|
+
export const STAKING_PERM_ALL = STAKING_PERM_DEPOSIT_STAKE | STAKING_PERM_REDEEM_STAKE | STAKING_PERM_CLAIM_REWARD;
|
|
47
52
|
// ======== Order Type Tags ========
|
|
48
53
|
export const ORDER_LIMIT_BUY = 0;
|
|
49
54
|
export const ORDER_LIMIT_SELL = 1;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
export { WaterXClient } from "./client.ts";
|
|
2
2
|
export type { CreateClientOptions } from "./client.ts";
|
|
3
3
|
export { PYTH_DEFAULTS, WORMHOLE_DEFAULTS, clearConfigCache, defaultConfigUrl, loadConfig, } from "./config.ts";
|
|
4
|
-
export type { BasePackageEntry, WaterxReferralPackage, LoadConfigOptions, NativeCustodyAsset, NativeCustodyPackage, PythInfraConfig, PythRulePackage, PythSponsorRulePackage, SupraRulePackage, TestnetFaucetPackage, TrustedEmitterRow, WaterXConfig, WaterXPackages, WaterxCreditPackage, WaterxOraclePackage, WaterxPerpMarketEntry, WaterxPerpPackage, WaterxStakingPackage, WithdrawalQueuePackage, WlpPackage, WormholeBridgePackage, WormholeInfraConfig, WxaAccountPackage, } from "./config.ts";
|
|
5
|
-
export { ACTION_ADD_PRE_ORDER, ACTION_CANCEL_ORDER, ACTION_CANCEL_PRE_ORDER, ACTION_CLOSE_POSITION, ACTION_DECREASE_POSITION, ACTION_DEPOSIT_COLLATERAL, ACTION_INCREASE_POSITION, ACTION_LIQUIDATE, ACTION_OPEN_POSITION, ACTION_PLACE_ORDER, ACTION_UPDATE_ORDER, ACTION_WITHDRAW_COLLATERAL, BPS_SCALE, CRYPTO_FEE_RATE, DOUBLE_SCALE, DRY_RUN_SENDER, FLOAT_SCALE, MAINTENANCE_MARGIN_RATE, ORDER_LIMIT_BUY, ORDER_LIMIT_SELL, ORDER_STOP_BUY, ORDER_STOP_SELL, ORDER_TAG_WILDCARD, PERM_ALL, PERM_ALL_TRADING, PERM_CANCEL_ORDER, PERM_CLOSE_POSITION, PERM_DECREASE_POSITION, PERM_DEPOSIT_COLLATERAL, PERM_INCREASE_POSITION, PERM_MINT_WLP, PERM_OPEN_POSITION, PERM_PLACE_ORDER, PERM_REDEEM_WLP, PERM_WITHDRAW_COLLATERAL, STOCK_FEE_RATE, MS_PER_YEAR, SUI_DECIMALS, WLP_DECIMALS, COLLATERAL_DECIMALS, TOKEN_DECIMALS, } from "./constants.ts";
|
|
4
|
+
export type { BasePackageEntry, ConstantFeedEntry, WaterxReferralPackage, LoadConfigOptions, NativeCustodyAsset, NativeCustodyPackage, PythInfraConfig, PythRulePackage, PythSponsorRulePackage, SupraFeedEntry, SupraRulePackage, TestnetFaucetPackage, TrustedEmitterRow, WaterXConfig, WaterXPackages, WaterxCreditPackage, WaterxOraclePackage, WaterxPerpMarketEntry, WaterxPerpPackage, WaterxStakingPackage, WithdrawalQueuePackage, WlpPackage, WormholeBridgePackage, WormholeInfraConfig, WxaAccountPackage, } from "./config.ts";
|
|
5
|
+
export { ACTION_ADD_PRE_ORDER, ACTION_CANCEL_ORDER, ACTION_CANCEL_PRE_ORDER, ACTION_CLOSE_POSITION, ACTION_DECREASE_POSITION, ACTION_DEPOSIT_COLLATERAL, ACTION_INCREASE_POSITION, ACTION_LIQUIDATE, ACTION_OPEN_POSITION, ACTION_PLACE_ORDER, ACTION_UPDATE_ORDER, ACTION_WITHDRAW_COLLATERAL, BPS_SCALE, CRYPTO_FEE_RATE, DOUBLE_SCALE, DRY_RUN_SENDER, FLOAT_SCALE, MAINTENANCE_MARGIN_RATE, ORDER_LIMIT_BUY, ORDER_LIMIT_SELL, ORDER_STOP_BUY, ORDER_STOP_SELL, ORDER_TAG_WILDCARD, PERM_ALL, PERM_ALL_TRADING, PERM_CANCEL_ORDER, PERM_CLOSE_POSITION, PERM_DECREASE_POSITION, PERM_DEPOSIT_COLLATERAL, PERM_INCREASE_POSITION, PERM_MINT_WLP, PERM_OPEN_POSITION, PERM_PLACE_ORDER, PERM_REDEEM_WLP, PERM_WITHDRAW_COLLATERAL, STAKING_PERM_DEPOSIT_STAKE, STAKING_PERM_REDEEM_STAKE, STAKING_PERM_CLAIM_REWARD, STAKING_PERM_ALL, STOCK_FEE_RATE, MS_PER_YEAR, SUI_DECIMALS, WLP_DECIMALS, COLLATERAL_DECIMALS, TOKEN_DECIMALS, } from "./constants.ts";
|
|
6
6
|
export type { Network } from "./constants.ts";
|
|
7
7
|
export { getMarketTickers, getCollateralAssets } from "./utils/config.ts";
|
|
8
8
|
export { annualizedApyFromRatio, annualizeFundingRate, calcBorrowRate, calcBorrowRateAccrual, calcDynamicFeeBps, calcEffectiveCollateralUsd, calcEstLiqPrice, calcFee, calcFundingFeeUsd, calcFundingRate, calcImpactFeeRate, calcLeverage, calcMaxReducibleCollateralUsd, calcNotional, calcPositionBorrowFee, calcTokenUtilizationBps, calcTotalTradingFeeRate, calcUnrealizedPnl, calcWlpIncentiveApy, calcWlpMintOut, calcWlpPrice, calcWlpRedeemOut, decodeFundingIndexDelta, rawPrice, } from "./utils/math.ts";
|
|
9
9
|
export * from "./user/index.ts";
|
|
10
10
|
export * from "./tx-builders.ts";
|
|
11
11
|
export * from "./fetch.ts";
|
|
12
|
-
export { PythCache,
|
|
12
|
+
export { PythCache, aggregateTicker, aggregateTickerWithConstant, aggregateTickerWithPyth, buildPythPriceUpdateCalls, fetchPriceFeedsUpdateData, refreshOraclePrices, updatePythPrices, } from "./utils/pyth.ts";
|
|
13
13
|
export { fetchDepositVaa, fetchVaa, listBridgeWithdrawalVaas, listVaasByEmitter, padEvmEmitter, toWormholescanEmitter, vaaBase64ToBytes, vaaBase64ToHex, vaaBytesToBase64, waitForVaa, } from "./utils/wormhole.ts";
|
|
14
14
|
export type { VaaListItem, VaaResponse, WormholescanOptions } from "./utils/wormhole.ts";
|
|
15
15
|
export { AccountData as AccountDataBcs, GlobalConfigData as GlobalConfigDataBcs, MarketData as MarketDataBcs, OrderData as OrderDataBcs, PoolData as PoolDataBcs, PositionData as PositionDataBcs, RedeemRequestData as RedeemRequestDataBcs, TokenPoolData as TokenPoolDataBcs, } from "./generated/waterx_perp_view/view.ts";
|
package/dist/src/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export { WaterXClient } from "./client.js";
|
|
3
3
|
export { PYTH_DEFAULTS, WORMHOLE_DEFAULTS, clearConfigCache, defaultConfigUrl, loadConfig, } from "./config.js";
|
|
4
4
|
// ======== Constants & enums ========
|
|
5
|
-
export { ACTION_ADD_PRE_ORDER, ACTION_CANCEL_ORDER, ACTION_CANCEL_PRE_ORDER, ACTION_CLOSE_POSITION, ACTION_DECREASE_POSITION, ACTION_DEPOSIT_COLLATERAL, ACTION_INCREASE_POSITION, ACTION_LIQUIDATE, ACTION_OPEN_POSITION, ACTION_PLACE_ORDER, ACTION_UPDATE_ORDER, ACTION_WITHDRAW_COLLATERAL, BPS_SCALE, CRYPTO_FEE_RATE, DOUBLE_SCALE, DRY_RUN_SENDER, FLOAT_SCALE, MAINTENANCE_MARGIN_RATE, ORDER_LIMIT_BUY, ORDER_LIMIT_SELL, ORDER_STOP_BUY, ORDER_STOP_SELL, ORDER_TAG_WILDCARD, PERM_ALL, PERM_ALL_TRADING, PERM_CANCEL_ORDER, PERM_CLOSE_POSITION, PERM_DECREASE_POSITION, PERM_DEPOSIT_COLLATERAL, PERM_INCREASE_POSITION, PERM_MINT_WLP, PERM_OPEN_POSITION, PERM_PLACE_ORDER, PERM_REDEEM_WLP, PERM_WITHDRAW_COLLATERAL, STOCK_FEE_RATE, MS_PER_YEAR, SUI_DECIMALS, WLP_DECIMALS, COLLATERAL_DECIMALS, TOKEN_DECIMALS, } from "./constants.js";
|
|
5
|
+
export { ACTION_ADD_PRE_ORDER, ACTION_CANCEL_ORDER, ACTION_CANCEL_PRE_ORDER, ACTION_CLOSE_POSITION, ACTION_DECREASE_POSITION, ACTION_DEPOSIT_COLLATERAL, ACTION_INCREASE_POSITION, ACTION_LIQUIDATE, ACTION_OPEN_POSITION, ACTION_PLACE_ORDER, ACTION_UPDATE_ORDER, ACTION_WITHDRAW_COLLATERAL, BPS_SCALE, CRYPTO_FEE_RATE, DOUBLE_SCALE, DRY_RUN_SENDER, FLOAT_SCALE, MAINTENANCE_MARGIN_RATE, ORDER_LIMIT_BUY, ORDER_LIMIT_SELL, ORDER_STOP_BUY, ORDER_STOP_SELL, ORDER_TAG_WILDCARD, PERM_ALL, PERM_ALL_TRADING, PERM_CANCEL_ORDER, PERM_CLOSE_POSITION, PERM_DECREASE_POSITION, PERM_DEPOSIT_COLLATERAL, PERM_INCREASE_POSITION, PERM_MINT_WLP, PERM_OPEN_POSITION, PERM_PLACE_ORDER, PERM_REDEEM_WLP, PERM_WITHDRAW_COLLATERAL, STAKING_PERM_DEPOSIT_STAKE, STAKING_PERM_REDEEM_STAKE, STAKING_PERM_CLAIM_REWARD, STAKING_PERM_ALL, STOCK_FEE_RATE, MS_PER_YEAR, SUI_DECIMALS, WLP_DECIMALS, COLLATERAL_DECIMALS, TOKEN_DECIMALS, } from "./constants.js";
|
|
6
6
|
// ======== Utilities ========
|
|
7
7
|
export { getMarketTickers, getCollateralAssets } from "./utils/config.js";
|
|
8
8
|
export { annualizedApyFromRatio, annualizeFundingRate, calcBorrowRate, calcBorrowRateAccrual, calcDynamicFeeBps, calcEffectiveCollateralUsd, calcEstLiqPrice, calcFee, calcFundingFeeUsd, calcFundingRate, calcImpactFeeRate, calcLeverage, calcMaxReducibleCollateralUsd, calcNotional, calcPositionBorrowFee, calcTokenUtilizationBps, calcTotalTradingFeeRate, calcUnrealizedPnl, calcWlpIncentiveApy, calcWlpMintOut, calcWlpPrice, calcWlpRedeemOut, decodeFundingIndexDelta, rawPrice, } from "./utils/math.js";
|
|
@@ -13,7 +13,7 @@ export * from "./tx-builders.js";
|
|
|
13
13
|
// ======== Read-only queries ========
|
|
14
14
|
export * from "./fetch.js";
|
|
15
15
|
// ======== Pyth oracle utilities ========
|
|
16
|
-
export { PythCache,
|
|
16
|
+
export { PythCache, aggregateTicker, aggregateTickerWithConstant, aggregateTickerWithPyth, buildPythPriceUpdateCalls, fetchPriceFeedsUpdateData, refreshOraclePrices, updatePythPrices, } from "./utils/pyth.js";
|
|
17
17
|
// ======== Wormhole / Wormholescan utilities (credit bridge) ========
|
|
18
18
|
export { fetchDepositVaa, fetchVaa, listBridgeWithdrawalVaas, listVaasByEmitter, padEvmEmitter, toWormholescanEmitter, vaaBase64ToBytes, vaaBase64ToHex, vaaBytesToBase64, waitForVaa, } from "./utils/wormhole.js";
|
|
19
19
|
// ======== Generated BCS types (sui-ts-codegen) ========
|
package/dist/src/utils/pyth.d.ts
CHANGED
|
@@ -46,52 +46,55 @@ export declare function updatePythPrices(tx: Transaction, client: WaterXClient,
|
|
|
46
46
|
packageId: string;
|
|
47
47
|
}): Promise<string[]>;
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
49
|
+
* Aggregate one ticker's price into the shared `Oracle`: build a collector, feed
|
|
50
|
+
* every rule the ticker is configured for, then `aggregate`. The fed rule set must
|
|
51
|
+
* match the on-chain weighted set for the ticker — `aggregator::remove_outliers`
|
|
52
|
+
* aborts `EMissingPriceSource` if a weighted rule is missing from the collector:
|
|
51
53
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
+
* - **Pyth** — fed when `priceInfoObjectId` is supplied (i.e. the ticker has a
|
|
55
|
+
* `pyth_rule.feeds` entry). Caller must run the Pyth update first so the
|
|
56
|
+
* `PriceInfoObject` is fresh.
|
|
57
|
+
* - **Supra** — fed alongside Pyth when supra is enabled + wired (abstains on-chain
|
|
58
|
+
* for symbols it has no pair for).
|
|
59
|
+
* - **Constant** — fed when the ticker is a constant ticker
|
|
60
|
+
* ({@link WaterXClient.isConstantTicker}).
|
|
61
|
+
*
|
|
62
|
+
* "Dual-feed" (Pyth + Constant) and "constant-only" are not special cases — they
|
|
63
|
+
* fall out of which rules the ticker is in: a constant ticker that also has a Pyth
|
|
64
|
+
* feed gets both; one with no Pyth feed (no `priceInfoObjectId`) gets constant only.
|
|
65
|
+
* Throws if no rule applies to the ticker.
|
|
54
66
|
*/
|
|
55
|
-
export declare function
|
|
67
|
+
export declare function aggregateTicker(tx: Transaction, client: WaterXClient, args: {
|
|
56
68
|
ticker: string;
|
|
57
|
-
priceInfoObjectId
|
|
69
|
+
priceInfoObjectId?: string;
|
|
58
70
|
}): void;
|
|
59
71
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* needed — the price comes from the on-chain `constant_rule::Config`.
|
|
72
|
+
* Thin wrapper over {@link aggregateTicker} for a Pyth-fed ticker. Kept for
|
|
73
|
+
* back-compat (e.g. WLP mint builds). Caller must run the Pyth update first.
|
|
63
74
|
*/
|
|
64
|
-
export declare function
|
|
75
|
+
export declare function aggregateTickerWithPyth(tx: Transaction, client: WaterXClient, args: {
|
|
65
76
|
ticker: string;
|
|
77
|
+
priceInfoObjectId: string;
|
|
66
78
|
}): void;
|
|
67
79
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* `constant_rule::feed`, then `aggregate`. Used while the aggregator carries the
|
|
71
|
-
* `{Pyth, Constant}` weight set so neither weighted rule is missing from the
|
|
72
|
-
* collector (`aggregator::remove_outliers` aborts `EMissingPriceSource`
|
|
73
|
-
* otherwise). Still needs a fresh Pyth `PriceInfoObject`, so the caller must
|
|
74
|
-
* have run the Pyth update for this ticker first.
|
|
80
|
+
* {@link aggregateTicker} for a **constant-only** ticker (no Pyth update needed —
|
|
81
|
+
* the price comes from the on-chain `constant_rule::Config`).
|
|
75
82
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* `
|
|
83
|
+
* Throws if the ticker ALSO has a `pyth_rule.feeds` entry (a dual-feed transition
|
|
84
|
+
* ticker): feeding only the constant leg would leave the still-weighted Pyth rule
|
|
85
|
+
* absent from the collector and abort `aggregate` with `EMissingPriceSource`. Such
|
|
86
|
+
* tickers must go through {@link aggregateTicker} with a `priceInfoObjectId` (or
|
|
87
|
+
* {@link refreshOraclePrices}), which feeds both.
|
|
80
88
|
*/
|
|
81
|
-
export declare function
|
|
89
|
+
export declare function aggregateTickerWithConstant(tx: Transaction, client: WaterXClient, args: {
|
|
82
90
|
ticker: string;
|
|
83
|
-
priceInfoObjectId: string;
|
|
84
91
|
}): void;
|
|
85
92
|
/**
|
|
86
|
-
* Refresh multiple tickers in one PTB.
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* - **Pyth** — the rest.
|
|
92
|
-
*
|
|
93
|
-
* Pyth-priced tickers (Pyth-only + dual) are updated on-chain via Pyth first
|
|
94
|
-
* (one accumulator), then each ticker runs its collector → feed → aggregate.
|
|
93
|
+
* Refresh multiple tickers in one PTB. For each ticker {@link aggregateTicker}
|
|
94
|
+
* feeds whichever rules it is configured for (Pyth if it has a `pyth_rule.feeds`
|
|
95
|
+
* entry, Supra when enabled, Constant when it's a constant ticker). Tickers with a
|
|
96
|
+
* Pyth feed are updated on-chain via one shared Pyth accumulator first; the rest
|
|
97
|
+
* (constant-only) skip Pyth entirely.
|
|
95
98
|
*/
|
|
96
99
|
export declare function refreshOraclePrices(tx: Transaction, client: WaterXClient, tickers: string[], opts?: {
|
|
97
100
|
cache?: PythCache;
|
package/dist/src/utils/pyth.js
CHANGED
|
@@ -228,39 +228,71 @@ export async function updatePythPrices(tx, client, feedIds, cache, sponsorFund)
|
|
|
228
228
|
// Per-ticker refresh: collector → pyth_rule::feed → oracle::aggregate
|
|
229
229
|
// ============================================================================
|
|
230
230
|
/**
|
|
231
|
-
*
|
|
232
|
-
*
|
|
231
|
+
* Aggregate one ticker's price into the shared `Oracle`: build a collector, feed
|
|
232
|
+
* every rule the ticker is configured for, then `aggregate`. The fed rule set must
|
|
233
|
+
* match the on-chain weighted set for the ticker — `aggregator::remove_outliers`
|
|
234
|
+
* aborts `EMissingPriceSource` if a weighted rule is missing from the collector:
|
|
233
235
|
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
+
* - **Pyth** — fed when `priceInfoObjectId` is supplied (i.e. the ticker has a
|
|
237
|
+
* `pyth_rule.feeds` entry). Caller must run the Pyth update first so the
|
|
238
|
+
* `PriceInfoObject` is fresh.
|
|
239
|
+
* - **Supra** — fed alongside Pyth when supra is enabled + wired (abstains on-chain
|
|
240
|
+
* for symbols it has no pair for).
|
|
241
|
+
* - **Constant** — fed when the ticker is a constant ticker
|
|
242
|
+
* ({@link WaterXClient.isConstantTicker}).
|
|
243
|
+
*
|
|
244
|
+
* "Dual-feed" (Pyth + Constant) and "constant-only" are not special cases — they
|
|
245
|
+
* fall out of which rules the ticker is in: a constant ticker that also has a Pyth
|
|
246
|
+
* feed gets both; one with no Pyth feed (no `priceInfoObjectId`) gets constant only.
|
|
247
|
+
* Throws if no rule applies to the ticker.
|
|
236
248
|
*/
|
|
237
|
-
export function
|
|
249
|
+
export function aggregateTicker(tx, client, args) {
|
|
250
|
+
const oraclePkg = client.config.packages.waterx_oracle.published_at;
|
|
238
251
|
const collector = newCollector({
|
|
239
|
-
package:
|
|
252
|
+
package: oraclePkg,
|
|
240
253
|
arguments: { symbol: args.ticker },
|
|
241
254
|
})(tx);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
let fed = false;
|
|
256
|
+
if (args.priceInfoObjectId) {
|
|
257
|
+
pythRuleFeed({
|
|
258
|
+
package: client.config.packages.pyth_rule.published_at,
|
|
259
|
+
arguments: {
|
|
260
|
+
collector,
|
|
261
|
+
config: tx.object(client.config.packages.pyth_rule.config),
|
|
262
|
+
pythState: tx.object(client.pyth.state_id),
|
|
263
|
+
pythPriceInfo: tx.object(args.priceInfoObjectId),
|
|
264
|
+
},
|
|
265
|
+
})(tx);
|
|
266
|
+
// Supra rides on the same collector when enabled (abstains on-chain otherwise).
|
|
267
|
+
maybeFeedSupra(tx, client, collector);
|
|
268
|
+
fed = true;
|
|
269
|
+
}
|
|
270
|
+
if (client.isConstantTicker(args.ticker)) {
|
|
271
|
+
const constant = client.config.packages.constant_rule;
|
|
272
|
+
constantRuleFeed({
|
|
273
|
+
package: constant.published_at,
|
|
274
|
+
arguments: { collector, config: tx.object(constant.config) },
|
|
275
|
+
})(tx);
|
|
276
|
+
fed = true;
|
|
277
|
+
}
|
|
278
|
+
if (!fed) {
|
|
279
|
+
throw new Error(`no oracle rule configured for ticker '${args.ticker}' (no pyth feed, not a constant ticker)`);
|
|
280
|
+
}
|
|
256
281
|
aggregateCall({
|
|
257
|
-
package:
|
|
282
|
+
package: oraclePkg,
|
|
258
283
|
arguments: {
|
|
259
284
|
oracle: tx.object(client.config.packages.waterx_oracle.oracle),
|
|
260
|
-
collector
|
|
285
|
+
collector,
|
|
261
286
|
},
|
|
262
287
|
})(tx);
|
|
263
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Thin wrapper over {@link aggregateTicker} for a Pyth-fed ticker. Kept for
|
|
291
|
+
* back-compat (e.g. WLP mint builds). Caller must run the Pyth update first.
|
|
292
|
+
*/
|
|
293
|
+
export function aggregateTickerWithPyth(tx, client, args) {
|
|
294
|
+
aggregateTicker(tx, client, args);
|
|
295
|
+
}
|
|
264
296
|
/**
|
|
265
297
|
* Append a `supra_rule::feed` on `collector` when the deployment has supra
|
|
266
298
|
* enabled + wired (see {@link WaterXClient.getSupraRule}). No-op otherwise, so
|
|
@@ -280,130 +312,43 @@ function maybeFeedSupra(tx, client, collector) {
|
|
|
280
312
|
})(tx);
|
|
281
313
|
}
|
|
282
314
|
/**
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
* needed — the price comes from the on-chain `constant_rule::Config`.
|
|
286
|
-
*/
|
|
287
|
-
export function aggregateTickerWithConstant(tx, client, args) {
|
|
288
|
-
const constant = client.config.packages.waterx_constant_rule;
|
|
289
|
-
if (!constant?.published_at || !constant.config) {
|
|
290
|
-
throw new Error(`waterx_constant_rule.{published_at,config} missing — cannot feed constant ticker '${args.ticker}'`);
|
|
291
|
-
}
|
|
292
|
-
const collector = newCollector({
|
|
293
|
-
package: client.config.packages.waterx_oracle.published_at,
|
|
294
|
-
arguments: { symbol: args.ticker },
|
|
295
|
-
})(tx);
|
|
296
|
-
constantRuleFeed({
|
|
297
|
-
package: constant.published_at,
|
|
298
|
-
arguments: {
|
|
299
|
-
collector: collector,
|
|
300
|
-
config: tx.object(constant.config),
|
|
301
|
-
},
|
|
302
|
-
})(tx);
|
|
303
|
-
aggregateCall({
|
|
304
|
-
package: client.config.packages.waterx_oracle.published_at,
|
|
305
|
-
arguments: {
|
|
306
|
-
oracle: tx.object(client.config.packages.waterx_oracle.oracle),
|
|
307
|
-
collector: collector,
|
|
308
|
-
},
|
|
309
|
-
})(tx);
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* For a dual-feed ticker mid-migration (e.g. `USDCUSD`), build one collector
|
|
313
|
-
* fed by *both* `pyth_rule::feed` (+ `supra_rule::feed` when enabled) *and*
|
|
314
|
-
* `constant_rule::feed`, then `aggregate`. Used while the aggregator carries the
|
|
315
|
-
* `{Pyth, Constant}` weight set so neither weighted rule is missing from the
|
|
316
|
-
* collector (`aggregator::remove_outliers` aborts `EMissingPriceSource`
|
|
317
|
-
* otherwise). Still needs a fresh Pyth `PriceInfoObject`, so the caller must
|
|
318
|
-
* have run the Pyth update for this ticker first.
|
|
315
|
+
* {@link aggregateTicker} for a **constant-only** ticker (no Pyth update needed —
|
|
316
|
+
* the price comes from the on-chain `constant_rule::Config`).
|
|
319
317
|
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
* `
|
|
318
|
+
* Throws if the ticker ALSO has a `pyth_rule.feeds` entry (a dual-feed transition
|
|
319
|
+
* ticker): feeding only the constant leg would leave the still-weighted Pyth rule
|
|
320
|
+
* absent from the collector and abort `aggregate` with `EMissingPriceSource`. Such
|
|
321
|
+
* tickers must go through {@link aggregateTicker} with a `priceInfoObjectId` (or
|
|
322
|
+
* {@link refreshOraclePrices}), which feeds both.
|
|
324
323
|
*/
|
|
325
|
-
export function
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
throw new Error(`waterx_constant_rule.{published_at,config} missing — cannot dual-feed ticker '${args.ticker}'`);
|
|
324
|
+
export function aggregateTickerWithConstant(tx, client, args) {
|
|
325
|
+
if (client.config.packages.pyth_rule?.feeds?.[args.ticker] !== undefined) {
|
|
326
|
+
throw new Error(`'${args.ticker}' is in pyth_rule.feeds (dual-feed) — feed both via aggregateTicker({ priceInfoObjectId }) / refreshOraclePrices, not aggregateTickerWithConstant`);
|
|
329
327
|
}
|
|
330
|
-
|
|
331
|
-
package: client.config.packages.waterx_oracle.published_at,
|
|
332
|
-
arguments: { symbol: args.ticker },
|
|
333
|
-
})(tx);
|
|
334
|
-
pythRuleFeed({
|
|
335
|
-
package: client.config.packages.pyth_rule.published_at,
|
|
336
|
-
arguments: {
|
|
337
|
-
collector: collector,
|
|
338
|
-
config: tx.object(client.config.packages.pyth_rule.config),
|
|
339
|
-
pythState: tx.object(client.pyth.state_id),
|
|
340
|
-
pythPriceInfo: tx.object(args.priceInfoObjectId),
|
|
341
|
-
},
|
|
342
|
-
})(tx);
|
|
343
|
-
// Second weighted rule (when enabled) on the same collector, matching the
|
|
344
|
-
// pure-Pyth path.
|
|
345
|
-
maybeFeedSupra(tx, client, collector);
|
|
346
|
-
// The constant rule — the leg that lets the aggregator carry a Constant weight.
|
|
347
|
-
constantRuleFeed({
|
|
348
|
-
package: constant.published_at,
|
|
349
|
-
arguments: {
|
|
350
|
-
collector: collector,
|
|
351
|
-
config: tx.object(constant.config),
|
|
352
|
-
},
|
|
353
|
-
})(tx);
|
|
354
|
-
aggregateCall({
|
|
355
|
-
package: client.config.packages.waterx_oracle.published_at,
|
|
356
|
-
arguments: {
|
|
357
|
-
oracle: tx.object(client.config.packages.waterx_oracle.oracle),
|
|
358
|
-
collector: collector,
|
|
359
|
-
},
|
|
360
|
-
})(tx);
|
|
328
|
+
aggregateTicker(tx, client, { ticker: args.ticker });
|
|
361
329
|
}
|
|
362
330
|
/**
|
|
363
|
-
* Refresh multiple tickers in one PTB.
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
* - **Pyth** — the rest.
|
|
369
|
-
*
|
|
370
|
-
* Pyth-priced tickers (Pyth-only + dual) are updated on-chain via Pyth first
|
|
371
|
-
* (one accumulator), then each ticker runs its collector → feed → aggregate.
|
|
331
|
+
* Refresh multiple tickers in one PTB. For each ticker {@link aggregateTicker}
|
|
332
|
+
* feeds whichever rules it is configured for (Pyth if it has a `pyth_rule.feeds`
|
|
333
|
+
* entry, Supra when enabled, Constant when it's a constant ticker). Tickers with a
|
|
334
|
+
* Pyth feed are updated on-chain via one shared Pyth accumulator first; the rest
|
|
335
|
+
* (constant-only) skip Pyth entirely.
|
|
372
336
|
*/
|
|
373
337
|
export async function refreshOraclePrices(tx, client, tickers, opts = {}) {
|
|
374
338
|
if (tickers.length === 0)
|
|
375
339
|
return;
|
|
376
|
-
//
|
|
377
|
-
//
|
|
378
|
-
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
if (pythUpdateTickers.length > 0) {
|
|
385
|
-
// Oracle tickers (e.g. "BTCUSD") → each one's pyth feed entry: feed_id
|
|
386
|
-
// (off-chain) drives the accumulator; price_info_object (on-chain) is
|
|
387
|
-
// consumed by the per-ticker aggregate cycle.
|
|
388
|
-
const entries = pythUpdateTickers.map((t) => client.getPythFeed(t));
|
|
389
|
-
const feedIds = entries.map((e) => e.feed_id);
|
|
390
|
-
await updatePythPrices(tx, client, feedIds, opts.cache, opts.sponsorFund);
|
|
391
|
-
pythTickers.forEach((ticker, i) => {
|
|
392
|
-
aggregateTickerWithPyth(tx, client, {
|
|
393
|
-
ticker,
|
|
394
|
-
priceInfoObjectId: entries[i].price_info_object,
|
|
395
|
-
});
|
|
396
|
-
});
|
|
397
|
-
dualTickers.forEach((ticker, i) => {
|
|
398
|
-
// dual entries are appended after the pyth-only ones.
|
|
399
|
-
aggregateTickerWithDual(tx, client, {
|
|
400
|
-
ticker,
|
|
401
|
-
priceInfoObjectId: entries[pythTickers.length + i].price_info_object,
|
|
402
|
-
});
|
|
403
|
-
});
|
|
340
|
+
// Every ticker with a pyth_rule.feeds entry needs the on-chain Pyth update
|
|
341
|
+
// first (one shared accumulator). Constant-only tickers (no pyth feed) skip it.
|
|
342
|
+
const pythTickers = tickers.filter((t) => client.config.packages.pyth_rule?.feeds?.[t] !== undefined);
|
|
343
|
+
const priceInfoByTicker = new Map();
|
|
344
|
+
if (pythTickers.length > 0) {
|
|
345
|
+
const entries = pythTickers.map((t) => client.getPythFeed(t));
|
|
346
|
+
await updatePythPrices(tx, client, entries.map((e) => e.feed_id), opts.cache, opts.sponsorFund);
|
|
347
|
+
pythTickers.forEach((t, i) => priceInfoByTicker.set(t, entries[i].price_info_object));
|
|
404
348
|
}
|
|
405
|
-
|
|
406
|
-
|
|
349
|
+
// Aggregate each ticker, feeding whichever rules it is configured for.
|
|
350
|
+
for (const ticker of tickers) {
|
|
351
|
+
aggregateTicker(tx, client, { ticker, priceInfoObjectId: priceInfoByTicker.get(ticker) });
|
|
407
352
|
}
|
|
408
353
|
}
|
|
409
354
|
/**
|