@waterx/sdk 2.4.1 → 3.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.
- package/README.md +25 -21
- package/dist/src/{utils → account}/account-request.d.ts +2 -2
- package/dist/src/{user → account}/account.d.ts +23 -21
- package/dist/src/{user → account}/account.js +5 -5
- package/dist/src/account/client.d.ts +42 -0
- package/dist/src/account/client.js +17 -0
- package/dist/src/account/config.d.ts +151 -0
- package/dist/src/account/config.js +8 -0
- package/dist/src/account/constants.d.ts +5 -0
- package/dist/src/account/constants.js +5 -0
- package/dist/src/account/fetch/referral.d.ts +15 -0
- package/dist/src/account/fetch/referral.js +51 -0
- package/dist/src/account/fetch/simulate.d.ts +34 -0
- package/dist/src/account/fetch/simulate.js +43 -0
- package/dist/src/{utils/consolidate-balance.d.ts → account/funding/balance.d.ts} +3 -8
- package/dist/src/{utils/consolidate-balance.js → account/funding/balance.js} +6 -1
- package/dist/src/account/funding/consolidate.d.ts +46 -0
- package/dist/src/account/funding/consolidate.js +137 -0
- package/dist/src/{user → account/funding}/credit.d.ts +10 -10
- package/dist/src/{user → account/funding}/credit.js +6 -6
- package/dist/src/{user → account/funding}/custody.d.ts +4 -4
- package/dist/src/{user → account/funding}/custody.js +2 -2
- package/dist/src/{utils → account/funding}/wormhole.d.ts +4 -4
- package/dist/src/{utils → account/funding}/wormhole.js +1 -1
- package/dist/src/account/index.d.ts +29 -0
- package/dist/src/account/index.js +29 -0
- package/dist/src/{user → account}/referral.d.ts +3 -3
- package/dist/src/{user → account}/referral.js +1 -1
- package/dist/src/base-client.d.ts +74 -0
- package/dist/src/base-client.js +97 -0
- package/dist/src/constants.d.ts +4 -46
- package/dist/src/constants.js +8 -52
- package/dist/src/generated/bucket_v2_framework/liability.d.ts +0 -26
- package/dist/src/generated/bucket_v2_framework/liability.js +0 -28
- package/dist/src/generated/waterx_account/account.d.ts +50 -15
- package/dist/src/generated/waterx_account/account.js +51 -15
- package/dist/src/generated/waterx_oracle/oracle.d.ts +7 -1
- package/dist/src/generated/waterx_oracle/oracle.js +7 -2
- package/dist/src/{prediction/generated → generated}/waterx_prediction/account_data.d.ts +19 -2
- package/dist/src/{prediction/generated → generated}/waterx_prediction/admin.d.ts +3 -1
- package/dist/src/{prediction/generated → generated}/waterx_prediction/deps/sui/balance.d.ts +3 -1
- package/dist/src/{prediction/generated/waterx_account → generated/waterx_prediction}/deps/sui/table.d.ts +6 -1
- package/dist/src/generated/waterx_prediction/events.d.ts +288 -0
- package/dist/src/{prediction/generated → generated}/waterx_prediction/events.js +39 -0
- package/dist/src/{prediction/generated → generated}/waterx_prediction/global_config.d.ts +6 -1
- package/dist/src/{prediction/generated → generated}/waterx_prediction/order.d.ts +34 -1
- package/dist/src/{prediction/generated → generated}/waterx_prediction/position.d.ts +16 -1
- package/dist/src/{prediction/generated → generated}/waterx_prediction/view.d.ts +69 -4
- package/dist/src/{prediction/generated → generated}/waterx_prediction/waterx_prediction.d.ts +162 -2
- package/dist/src/{prediction/generated → generated}/waterx_prediction/waterx_prediction.js +99 -0
- package/dist/src/generated/waterx_pyth_rule/pyth_rule.d.ts +102 -0
- package/dist/src/generated/waterx_pyth_rule/pyth_rule.js +99 -0
- package/dist/src/generated/waterx_supra_rule/supra_rule.d.ts +5 -5
- package/dist/src/generated/waterx_supra_rule/supra_rule.js +1 -2
- package/dist/src/generated/withdrawal_queue/withdrawal_queue.d.ts +23 -23
- package/dist/src/generated/withdrawal_queue/withdrawal_queue.js +3 -6
- package/dist/src/oracle/aggregate.d.ts +74 -0
- package/dist/src/oracle/aggregate.js +112 -0
- package/dist/src/oracle/config.d.ts +99 -0
- package/dist/src/oracle/config.js +23 -0
- package/dist/src/oracle/host.d.ts +32 -0
- package/dist/src/oracle/host.js +10 -0
- package/dist/src/oracle/index.d.ts +16 -0
- package/dist/src/oracle/index.js +18 -0
- package/dist/src/oracle/pyth.d.ts +52 -0
- package/dist/src/oracle/pyth.js +220 -0
- package/dist/src/oracle/rules/constant-rule.d.ts +9 -0
- package/dist/src/oracle/rules/constant-rule.js +14 -0
- package/dist/src/oracle/rules/pyth-rule.d.ts +11 -0
- package/dist/src/oracle/rules/pyth-rule.js +20 -0
- package/dist/src/oracle/rules/sponsor.d.ts +28 -0
- package/dist/src/oracle/rules/sponsor.js +48 -0
- package/dist/src/oracle/rules/supra-rule.d.ts +11 -0
- package/dist/src/oracle/rules/supra-rule.js +22 -0
- package/dist/src/perp/client.d.ts +78 -0
- package/dist/src/perp/client.js +108 -0
- package/dist/src/{client.d.ts → perp/config-view.d.ts} +15 -60
- package/dist/src/{client.js → perp/config-view.js} +23 -95
- package/dist/src/perp/config.d.ts +126 -0
- package/dist/src/{config.js → perp/config.js} +11 -12
- package/dist/src/perp/constants.d.ts +49 -0
- package/dist/src/perp/constants.js +61 -0
- package/dist/src/perp/fetch/account.d.ts +43 -0
- package/dist/src/perp/fetch/account.js +64 -0
- package/dist/src/perp/fetch/bridge.d.ts +90 -0
- package/dist/src/perp/fetch/bridge.js +127 -0
- package/dist/src/perp/fetch/custody.d.ts +32 -0
- package/dist/src/perp/fetch/custody.js +62 -0
- package/dist/src/perp/fetch/market.d.ts +30 -0
- package/dist/src/perp/fetch/market.js +68 -0
- package/dist/src/perp/fetch/positions.d.ts +70 -0
- package/dist/src/perp/fetch/positions.js +185 -0
- package/dist/src/perp/fetch/simulate.d.ts +12 -0
- package/dist/src/perp/fetch/simulate.js +13 -0
- package/dist/src/perp/fetch.d.ts +23 -0
- package/dist/src/perp/fetch.js +23 -0
- package/dist/src/{index.d.ts → perp/index.d.ts} +21 -21
- package/dist/src/{index.js → perp/index.js} +21 -21
- package/dist/src/perp/tx-builders/common.d.ts +83 -0
- package/dist/src/perp/tx-builders/common.js +70 -0
- package/dist/src/perp/tx-builders/credit.d.ts +65 -0
- package/dist/src/perp/tx-builders/credit.js +62 -0
- package/dist/src/perp/tx-builders/rewards.d.ts +30 -0
- package/dist/src/perp/tx-builders/rewards.js +34 -0
- package/dist/src/perp/tx-builders/trading.d.ts +51 -0
- package/dist/src/perp/tx-builders/trading.js +59 -0
- package/dist/src/perp/tx-builders/wlp.d.ts +90 -0
- package/dist/src/perp/tx-builders/wlp.js +120 -0
- package/dist/src/perp/tx-builders.d.ts +23 -0
- package/dist/src/perp/tx-builders.js +23 -0
- package/dist/src/perp/user/index.d.ts +8 -0
- package/dist/src/perp/user/index.js +8 -0
- package/dist/src/{user → perp/user}/order.d.ts +7 -7
- package/dist/src/{user → perp/user}/order.js +3 -3
- package/dist/src/{user → perp/user}/staking.d.ts +4 -4
- package/dist/src/{user → perp/user}/staking.js +2 -2
- package/dist/src/{user → perp/user}/trading.d.ts +13 -13
- package/dist/src/{user → perp/user}/trading.js +2 -2
- package/dist/src/{user → perp/user}/wlp.d.ts +7 -7
- package/dist/src/{user → perp/user}/wlp.js +3 -3
- package/dist/src/prediction/account.js +40 -76
- package/dist/src/prediction/client.d.ts +8 -38
- package/dist/src/prediction/client.js +11 -67
- package/dist/src/prediction/config.d.ts +16 -2
- package/dist/src/prediction/config.js +10 -4
- package/dist/src/prediction/index.d.ts +11 -11
- package/dist/src/prediction/index.js +10 -10
- package/dist/src/prediction/prediction.d.ts +45 -0
- package/dist/src/prediction/prediction.js +71 -0
- package/dist/src/prediction/tx-builders.d.ts +4 -4
- package/dist/src/prediction/tx-builders.js +2 -2
- package/dist/src/prediction/user/index.d.ts +2 -2
- package/dist/src/prediction/user/index.js +1 -1
- package/dist/src/prediction/user/position.d.ts +2 -2
- package/dist/src/prediction/user/position.js +1 -1
- package/dist/src/prediction/utils/bcs.d.ts +5 -0
- package/dist/src/prediction/utils/bcs.js +5 -0
- package/dist/src/prediction/utils/index.d.ts +7 -0
- package/dist/src/prediction/utils/index.js +7 -0
- package/dist/src/sdk.d.ts +10 -6
- package/dist/src/sdk.js +9 -5
- package/dist/src/unified-client.d.ts +140 -145
- package/dist/src/unified-client.js +98 -40
- package/dist/src/utils/config.d.ts +1 -1
- package/package.json +22 -5
- package/dist/src/config.d.ts +0 -292
- package/dist/src/fetch.d.ts +0 -254
- package/dist/src/fetch.js +0 -564
- package/dist/src/prediction/generated/bucket_v2_framework/account.d.ts +0 -100
- package/dist/src/prediction/generated/bucket_v2_framework/account.js +0 -129
- package/dist/src/prediction/generated/bucket_v2_framework/deps/std/type_name.d.ts +0 -6
- package/dist/src/prediction/generated/bucket_v2_framework/deps/std/type_name.js +0 -19
- package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/balance.d.ts +0 -10
- package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/vec_map.d.ts +0 -36
- package/dist/src/prediction/generated/bucket_v2_framework/deps/sui/vec_map.js +0 -27
- package/dist/src/prediction/generated/bucket_v2_framework/double.d.ts +0 -382
- package/dist/src/prediction/generated/bucket_v2_framework/double.js +0 -466
- package/dist/src/prediction/generated/bucket_v2_framework/float.d.ts +0 -362
- package/dist/src/prediction/generated/bucket_v2_framework/float.js +0 -440
- package/dist/src/prediction/generated/bucket_v2_framework/liability.d.ts +0 -193
- package/dist/src/prediction/generated/bucket_v2_framework/liability.js +0 -205
- package/dist/src/prediction/generated/bucket_v2_framework/linked_table.d.ts +0 -384
- package/dist/src/prediction/generated/bucket_v2_framework/linked_table.js +0 -382
- package/dist/src/prediction/generated/bucket_v2_framework/sheet.d.ts +0 -344
- package/dist/src/prediction/generated/bucket_v2_framework/sheet.js +0 -338
- package/dist/src/prediction/generated/utils/index.d.ts +0 -30
- package/dist/src/prediction/generated/utils/index.js +0 -160
- package/dist/src/prediction/generated/waterx_account/account.d.ts +0 -1589
- package/dist/src/prediction/generated/waterx_account/account.js +0 -1758
- package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/liability.d.ts +0 -7
- package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/liability.js +0 -13
- package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/sheet.d.ts +0 -7
- package/dist/src/prediction/generated/waterx_account/deps/bucket_v2_framework/sheet.js +0 -16
- package/dist/src/prediction/generated/waterx_account/deps/std/type_name.d.ts +0 -6
- package/dist/src/prediction/generated/waterx_account/deps/std/type_name.js +0 -19
- package/dist/src/prediction/generated/waterx_account/deps/sui/balance.d.ts +0 -10
- package/dist/src/prediction/generated/waterx_account/deps/sui/balance.js +0 -14
- package/dist/src/prediction/generated/waterx_account/deps/sui/object_table.d.ts +0 -12
- package/dist/src/prediction/generated/waterx_account/deps/sui/object_table.js +0 -19
- package/dist/src/prediction/generated/waterx_account/deps/sui/vec_map.d.ts +0 -36
- package/dist/src/prediction/generated/waterx_account/deps/sui/vec_map.js +0 -27
- package/dist/src/prediction/generated/waterx_account/deps/sui/vec_set.d.ts +0 -16
- package/dist/src/prediction/generated/waterx_account/deps/sui/vec_set.js +0 -19
- package/dist/src/prediction/generated/waterx_account/direct_rule.d.ts +0 -75
- package/dist/src/prediction/generated/waterx_account/direct_rule.js +0 -78
- package/dist/src/prediction/generated/waterx_account/events.d.ts +0 -33
- package/dist/src/prediction/generated/waterx_account/events.js +0 -137
- package/dist/src/prediction/generated/waterx_account/version.js +0 -8
- package/dist/src/prediction/generated/waterx_prediction/bet_sharing.d.ts +0 -60
- package/dist/src/prediction/generated/waterx_prediction/bet_sharing.js +0 -83
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/balance.js +0 -14
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/table.d.ts +0 -24
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/table.js +0 -31
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/vec_set.d.ts +0 -16
- package/dist/src/prediction/generated/waterx_prediction/deps/sui/vec_set.js +0 -19
- package/dist/src/prediction/generated/waterx_prediction/events.d.ts +0 -22
- package/dist/src/prediction/generated/waterx_prediction/version.d.ts +0 -10
- package/dist/src/tx-builders.d.ts +0 -296
- package/dist/src/tx-builders.js +0 -461
- package/dist/src/user/index.d.ts +0 -8
- package/dist/src/user/index.js +0 -8
- package/dist/src/utils/pyth.d.ts +0 -124
- package/dist/src/utils/pyth.js +0 -392
- /package/dist/src/{utils → account}/account-request.js +0 -0
- /package/dist/src/{core → account}/waterx-account.d.ts +0 -0
- /package/dist/src/{core → account}/waterx-account.js +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/account_data.js +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/admin.js +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/deps/bucket_v2_framework/linked_table.d.ts +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/deps/bucket_v2_framework/linked_table.js +0 -0
- /package/dist/src/{prediction/generated/bucket_v2_framework → generated/waterx_prediction}/deps/sui/balance.js +0 -0
- /package/dist/src/{prediction/generated/waterx_account → generated/waterx_prediction}/deps/sui/table.js +0 -0
- /package/dist/src/{prediction/generated/bucket_v2_framework → generated/waterx_prediction}/deps/sui/vec_set.d.ts +0 -0
- /package/dist/src/{prediction/generated/bucket_v2_framework → generated/waterx_prediction}/deps/sui/vec_set.js +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/global_config.js +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/order.js +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/outcome.d.ts +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/outcome.js +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/position.js +0 -0
- /package/dist/src/{prediction/generated/waterx_account → generated/waterx_prediction}/version.d.ts +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/version.js +0 -0
- /package/dist/src/{prediction/generated → generated}/waterx_prediction/view.js +0 -0
package/dist/src/utils/pyth.js
DELETED
|
@@ -1,392 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pyth price feed integration for the WaterX v3 oracle (ticker-based).
|
|
3
|
-
*
|
|
4
|
-
* Hermes REST fetches price update VAAs; on-chain a single PTB:
|
|
5
|
-
* 1. wormhole::vaa::parse_and_verify
|
|
6
|
-
* 2. pyth::create_authenticated_price_infos_using_accumulator
|
|
7
|
-
* 3. pyth::update_single_price_feed (one per feed)
|
|
8
|
-
* 4. for each ticker: oracle::new_collector(symbol) → pyth_rule::feed → oracle::aggregate
|
|
9
|
-
*
|
|
10
|
-
* No type parameters on `feed` / `aggregate` anymore — the oracle is one
|
|
11
|
-
* shared object keyed by ticker. `pyth_rule::feed` looks up the on-chain
|
|
12
|
-
* `PriceInfoObject` ID by ticker via the `pyth_rule::Config` identifier map.
|
|
13
|
-
*/
|
|
14
|
-
import { fromHex, toHex } from "@mysten/bcs";
|
|
15
|
-
import { bcs } from "@mysten/sui/bcs";
|
|
16
|
-
// ============================================================================
|
|
17
|
-
// Pyth-sponsor flow — pays Pyth update fees from a shared sponsor pool AND
|
|
18
|
-
// attaches the `PythSponsorRule` witness to a TradingRequest. Required when
|
|
19
|
-
// the market's `request_checklist` contains `PythSponsorRule`.
|
|
20
|
-
// ============================================================================
|
|
21
|
-
import { reimburse as sponsorReimburse, request as sponsorRequest, } from "../generated/pyth_sponsor_rule/pyth_sponsor_rule.js";
|
|
22
|
-
import { feed as constantRuleFeed } from "../generated/waterx_constant_rule/constant_rule.js";
|
|
23
|
-
import { aggregate as aggregateCall, newCollector } from "../generated/waterx_oracle/oracle.js";
|
|
24
|
-
import { feed as pythRuleFeed } from "../generated/waterx_pyth_rule/pyth_rule.js";
|
|
25
|
-
import { feed as supraRuleFeed } from "../generated/waterx_supra_rule/supra_rule.js";
|
|
26
|
-
export class PythCache {
|
|
27
|
-
pythStateInfo;
|
|
28
|
-
wormholePackageId;
|
|
29
|
-
priceTableInfo;
|
|
30
|
-
priceFeedObjectIdCache = new Map();
|
|
31
|
-
}
|
|
32
|
-
// ============================================================================
|
|
33
|
-
// Hermes REST
|
|
34
|
-
// ============================================================================
|
|
35
|
-
export async function fetchPriceFeedsUpdateData(endpoint, priceIds) {
|
|
36
|
-
if (priceIds.length === 0)
|
|
37
|
-
return [];
|
|
38
|
-
const url = new URL("/v2/updates/price/latest", endpoint);
|
|
39
|
-
priceIds.forEach((id) => url.searchParams.append("ids[]", id));
|
|
40
|
-
const res = await fetch(url.toString(), { signal: AbortSignal.timeout(15_000) });
|
|
41
|
-
if (!res.ok)
|
|
42
|
-
throw new Error(`Hermes price fetch failed: ${res.status} ${await res.text()}`);
|
|
43
|
-
const json = (await res.json());
|
|
44
|
-
const data = json.binary?.data;
|
|
45
|
-
if (!Array.isArray(data) || data.length === 0) {
|
|
46
|
-
throw new Error("Hermes returned no binary price data");
|
|
47
|
-
}
|
|
48
|
-
return data.map((hex) => fromHex(hex));
|
|
49
|
-
}
|
|
50
|
-
// ============================================================================
|
|
51
|
-
// On-chain helpers (cached)
|
|
52
|
-
// ============================================================================
|
|
53
|
-
function pkgFromUpgradeCap(json, objectId) {
|
|
54
|
-
const upgradeCap = json.upgrade_cap ??
|
|
55
|
-
json.fields?.upgrade_cap;
|
|
56
|
-
const nested = upgradeCap?.fields?.package;
|
|
57
|
-
const pkg = typeof upgradeCap?.package === "string"
|
|
58
|
-
? upgradeCap.package
|
|
59
|
-
: typeof nested === "string"
|
|
60
|
-
? nested
|
|
61
|
-
: undefined;
|
|
62
|
-
if (!pkg)
|
|
63
|
-
throw new Error(`Cannot resolve package id for object ${objectId}`);
|
|
64
|
-
return pkg;
|
|
65
|
-
}
|
|
66
|
-
async function getPythStateInfo(client, pythStateId, cache) {
|
|
67
|
-
if (cache?.pythStateInfo)
|
|
68
|
-
return cache.pythStateInfo;
|
|
69
|
-
const result = await client.getObject({ objectId: pythStateId, include: { json: true } });
|
|
70
|
-
const json = result.object?.json;
|
|
71
|
-
if (!json)
|
|
72
|
-
throw new Error("Unable to fetch pyth state");
|
|
73
|
-
const packageId = pkgFromUpgradeCap(json, pythStateId);
|
|
74
|
-
const fields = json.fields;
|
|
75
|
-
const fee = (fields?.base_update_fee ?? json.base_update_fee);
|
|
76
|
-
if (fee === undefined)
|
|
77
|
-
throw new Error("Unable to fetch pyth state base_update_fee");
|
|
78
|
-
const info = { packageId, baseUpdateFee: BigInt(fee) };
|
|
79
|
-
if (cache)
|
|
80
|
-
cache.pythStateInfo = info;
|
|
81
|
-
return info;
|
|
82
|
-
}
|
|
83
|
-
async function getWormholePackageId(client, wormholeStateId, cache) {
|
|
84
|
-
if (cache?.wormholePackageId)
|
|
85
|
-
return cache.wormholePackageId;
|
|
86
|
-
const result = await client.getObject({ objectId: wormholeStateId, include: { json: true } });
|
|
87
|
-
const json = result.object?.json;
|
|
88
|
-
if (!json)
|
|
89
|
-
throw new Error(`Cannot resolve wormhole package id from ${wormholeStateId}`);
|
|
90
|
-
const pkg = pkgFromUpgradeCap(json, wormholeStateId);
|
|
91
|
-
if (cache)
|
|
92
|
-
cache.wormholePackageId = pkg;
|
|
93
|
-
return pkg;
|
|
94
|
-
}
|
|
95
|
-
async function getPriceTableInfo(client, pythStateId, cache) {
|
|
96
|
-
if (cache?.priceTableInfo)
|
|
97
|
-
return cache.priceTableInfo;
|
|
98
|
-
const list = await client.listDynamicFields({ parentId: pythStateId });
|
|
99
|
-
const entry = list.dynamicFields.find((e) => {
|
|
100
|
-
const vt = e.valueType || e.objectType || "";
|
|
101
|
-
return vt.includes("PriceIdentifier") || vt.includes("price_info");
|
|
102
|
-
});
|
|
103
|
-
if (!entry)
|
|
104
|
-
throw new Error("Price table not found in Pyth state dynamic fields");
|
|
105
|
-
const childId = entry.childId ?? entry.objectId;
|
|
106
|
-
const typeStr = entry.valueType || entry.objectType || "";
|
|
107
|
-
if (!childId)
|
|
108
|
-
throw new Error("Price table missing childId");
|
|
109
|
-
const pkgMatch = typeStr.match(/(0x[a-fA-F0-9]+)::price_identifier::PriceIdentifier/);
|
|
110
|
-
if (!pkgMatch)
|
|
111
|
-
throw new Error(`Cannot extract package from price table type: ${typeStr}`);
|
|
112
|
-
const info = { id: childId, fieldType: pkgMatch[1] };
|
|
113
|
-
if (cache)
|
|
114
|
-
cache.priceTableInfo = info;
|
|
115
|
-
return info;
|
|
116
|
-
}
|
|
117
|
-
async function getPriceFeedObjectId(client, table, feedId, cache, pythStateId) {
|
|
118
|
-
const normalized = feedId.replace(/^0x/, "");
|
|
119
|
-
const cacheKey = pythStateId ? `${pythStateId}:${normalized}` : normalized;
|
|
120
|
-
if (cache?.priceFeedObjectIdCache.has(cacheKey)) {
|
|
121
|
-
return cache.priceFeedObjectIdCache.get(cacheKey);
|
|
122
|
-
}
|
|
123
|
-
const keyBytes = bcs
|
|
124
|
-
.struct("PriceIdentifier", { bytes: bcs.vector(bcs.u8()) })
|
|
125
|
-
.serialize({ bytes: fromHex(normalized) })
|
|
126
|
-
.toBytes();
|
|
127
|
-
const result = await client.getDynamicField({
|
|
128
|
-
parentId: table.id,
|
|
129
|
-
name: { type: `${table.fieldType}::price_identifier::PriceIdentifier`, bcs: keyBytes },
|
|
130
|
-
});
|
|
131
|
-
const value = result.dynamicField?.value;
|
|
132
|
-
const objectId = !value?.bcs || value.bcs.length < 32 ? undefined : "0x" + toHex(value.bcs);
|
|
133
|
-
if (cache)
|
|
134
|
-
cache.priceFeedObjectIdCache.set(cacheKey, objectId);
|
|
135
|
-
return objectId;
|
|
136
|
-
}
|
|
137
|
-
// ============================================================================
|
|
138
|
-
// Accumulator parsing
|
|
139
|
-
// ============================================================================
|
|
140
|
-
function extractVaaBytes(accumulatorMessage) {
|
|
141
|
-
const view = new DataView(accumulatorMessage.buffer, accumulatorMessage.byteOffset, accumulatorMessage.byteLength);
|
|
142
|
-
const trailingPayloadSize = view.getUint8(6);
|
|
143
|
-
const vaaSizeOffset = 7 + trailingPayloadSize + 1; // +1 for proof_type
|
|
144
|
-
const vaaSize = view.getUint16(vaaSizeOffset, false);
|
|
145
|
-
const vaaOffset = vaaSizeOffset + 2;
|
|
146
|
-
return accumulatorMessage.subarray(vaaOffset, vaaOffset + vaaSize);
|
|
147
|
-
}
|
|
148
|
-
// ============================================================================
|
|
149
|
-
// Pyth update calls
|
|
150
|
-
// ============================================================================
|
|
151
|
-
/**
|
|
152
|
-
* Append the on-chain Pyth update PTB block. Returns `PriceInfoObject` IDs
|
|
153
|
-
* (one per `feedIds`, same order). After this you can call
|
|
154
|
-
* `pyth_rule::feed` per ticker against the matching `PriceInfoObject`.
|
|
155
|
-
*
|
|
156
|
-
* If `sponsorFund` is provided, the per-feed update fee comes from the
|
|
157
|
-
* sponsor pool (`pyth_sponsor_rule::split`) instead of `tx.gas`.
|
|
158
|
-
*/
|
|
159
|
-
export async function buildPythPriceUpdateCalls(tx, client, updates, feedIds, cache, sponsorFund) {
|
|
160
|
-
if (updates.length === 0) {
|
|
161
|
-
throw new Error("No price update data provided; Hermes returned empty results");
|
|
162
|
-
}
|
|
163
|
-
if (updates.length > 1) {
|
|
164
|
-
throw new Error("Only a single accumulator message is supported per transaction");
|
|
165
|
-
}
|
|
166
|
-
const pyth = client.pyth;
|
|
167
|
-
const [stateInfo, wormholePackageId, table] = await Promise.all([
|
|
168
|
-
getPythStateInfo(client.grpcClient, pyth.state_id, cache),
|
|
169
|
-
getWormholePackageId(client.grpcClient, pyth.wormhole_state_id, cache),
|
|
170
|
-
getPriceTableInfo(client.grpcClient, pyth.state_id, cache),
|
|
171
|
-
]);
|
|
172
|
-
const priceInfoObjectIds = await Promise.all(feedIds.map((feedId) => getPriceFeedObjectId(client.grpcClient, table, feedId, cache, pyth.state_id)));
|
|
173
|
-
const { packageId: pythPackageId, baseUpdateFee } = stateInfo;
|
|
174
|
-
// 1. Verify VAA
|
|
175
|
-
const vaa = extractVaaBytes(updates[0]);
|
|
176
|
-
const [verifiedVaa] = tx.moveCall({
|
|
177
|
-
target: `${wormholePackageId}::vaa::parse_and_verify`,
|
|
178
|
-
arguments: [tx.object(pyth.wormhole_state_id), tx.pure.vector("u8", vaa), tx.object.clock()],
|
|
179
|
-
});
|
|
180
|
-
// 2. Authenticate price infos
|
|
181
|
-
const [hotPotato0] = tx.moveCall({
|
|
182
|
-
target: `${pythPackageId}::pyth::create_authenticated_price_infos_using_accumulator`,
|
|
183
|
-
arguments: [
|
|
184
|
-
tx.object(pyth.state_id),
|
|
185
|
-
tx.pure.vector("u8", updates[0]),
|
|
186
|
-
verifiedVaa,
|
|
187
|
-
tx.object.clock(),
|
|
188
|
-
],
|
|
189
|
-
});
|
|
190
|
-
// 3. Per-feed update
|
|
191
|
-
let hotPotato = hotPotato0;
|
|
192
|
-
for (let i = 0; i < feedIds.length; i++) {
|
|
193
|
-
const priceInfoObjectId = priceInfoObjectIds[i];
|
|
194
|
-
if (!priceInfoObjectId) {
|
|
195
|
-
throw new Error(`Pyth feed ${feedIds[i]} not registered on-chain in Pyth state`);
|
|
196
|
-
}
|
|
197
|
-
const feeCoin = sponsorFund
|
|
198
|
-
? tx.moveCall({
|
|
199
|
-
target: `${sponsorFund.packageId}::pyth_sponsor_rule::split`,
|
|
200
|
-
arguments: [sponsorFund.fund],
|
|
201
|
-
})[0]
|
|
202
|
-
: tx.splitCoins(tx.gas, [tx.pure.u64(baseUpdateFee)])[0];
|
|
203
|
-
[hotPotato] = tx.moveCall({
|
|
204
|
-
target: `${pythPackageId}::pyth::update_single_price_feed`,
|
|
205
|
-
arguments: [
|
|
206
|
-
tx.object(pyth.state_id),
|
|
207
|
-
hotPotato,
|
|
208
|
-
tx.object(priceInfoObjectId),
|
|
209
|
-
feeCoin,
|
|
210
|
-
tx.object.clock(),
|
|
211
|
-
],
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
// 4. Destroy hot potato
|
|
215
|
-
tx.moveCall({
|
|
216
|
-
target: `${pythPackageId}::hot_potato_vector::destroy`,
|
|
217
|
-
arguments: [hotPotato],
|
|
218
|
-
typeArguments: [`${pythPackageId}::price_info::PriceInfo`],
|
|
219
|
-
});
|
|
220
|
-
return priceInfoObjectIds;
|
|
221
|
-
}
|
|
222
|
-
/** All-in-one: fetch from Hermes, append update calls. Returns PriceInfoObject IDs. */
|
|
223
|
-
export async function updatePythPrices(tx, client, feedIds, cache, sponsorFund) {
|
|
224
|
-
const updates = await fetchPriceFeedsUpdateData(client.pyth.hermes_endpoint, feedIds);
|
|
225
|
-
return buildPythPriceUpdateCalls(tx, client, updates, feedIds, cache, sponsorFund);
|
|
226
|
-
}
|
|
227
|
-
// ============================================================================
|
|
228
|
-
// Per-ticker refresh: collector → pyth_rule::feed → oracle::aggregate
|
|
229
|
-
// ============================================================================
|
|
230
|
-
/**
|
|
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:
|
|
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.
|
|
248
|
-
*/
|
|
249
|
-
export function aggregateTicker(tx, client, args) {
|
|
250
|
-
const oraclePkg = client.config.packages.waterx_oracle.published_at;
|
|
251
|
-
const collector = newCollector({
|
|
252
|
-
package: oraclePkg,
|
|
253
|
-
arguments: { symbol: args.ticker },
|
|
254
|
-
})(tx);
|
|
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
|
-
}
|
|
281
|
-
aggregateCall({
|
|
282
|
-
package: oraclePkg,
|
|
283
|
-
arguments: {
|
|
284
|
-
oracle: tx.object(client.config.packages.waterx_oracle.oracle),
|
|
285
|
-
collector,
|
|
286
|
-
},
|
|
287
|
-
})(tx);
|
|
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
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Append a `supra_rule::feed` on `collector` when the deployment has supra
|
|
298
|
-
* enabled + wired (see {@link WaterXClient.getSupraRule}). No-op otherwise, so
|
|
299
|
-
* Pyth-only deployments are unchanged.
|
|
300
|
-
*/
|
|
301
|
-
function maybeFeedSupra(tx, client, collector) {
|
|
302
|
-
const supra = client.getSupraRule();
|
|
303
|
-
if (!supra)
|
|
304
|
-
return;
|
|
305
|
-
supraRuleFeed({
|
|
306
|
-
package: supra.published_at,
|
|
307
|
-
arguments: {
|
|
308
|
-
collector,
|
|
309
|
-
config: tx.object(supra.config),
|
|
310
|
-
oracleHolder: tx.object(supra.oracle_holder),
|
|
311
|
-
},
|
|
312
|
-
})(tx);
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* {@link aggregateTicker} for a **constant-only** ticker (no Pyth update needed —
|
|
316
|
-
* the price comes from the on-chain `constant_rule::Config`).
|
|
317
|
-
*
|
|
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.
|
|
323
|
-
*/
|
|
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`);
|
|
327
|
-
}
|
|
328
|
-
aggregateTicker(tx, client, { ticker: args.ticker });
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
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.
|
|
336
|
-
*/
|
|
337
|
-
export async function refreshOraclePrices(tx, client, tickers, opts = {}) {
|
|
338
|
-
if (tickers.length === 0)
|
|
339
|
-
return;
|
|
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));
|
|
348
|
-
}
|
|
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) });
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Opens a `Fund` hot potato from the shared PythSponsor pool. Pass the
|
|
356
|
-
* returned `{ fund, packageId }` straight to `refreshOraclePrices` as
|
|
357
|
-
* `sponsorFund`, then `reimbursePythSponsor` once the TradingRequest is
|
|
358
|
-
* built to attach the `PythSponsorRule` witness and return leftover
|
|
359
|
-
* balance.
|
|
360
|
-
*/
|
|
361
|
-
export function openPythSponsorFund(tx, client) {
|
|
362
|
-
const entry = client.config.packages.pyth_sponsor_rule;
|
|
363
|
-
if (!entry?.published_at || !entry.pyth_sponsor) {
|
|
364
|
-
throw new Error("pyth_sponsor_rule.{published_at,pyth_sponsor} missing — sponsor flow unavailable");
|
|
365
|
-
}
|
|
366
|
-
const [fund] = sponsorRequest({
|
|
367
|
-
package: entry.published_at,
|
|
368
|
-
arguments: { self: tx.object(entry.pyth_sponsor) },
|
|
369
|
-
})(tx);
|
|
370
|
-
return { fund: fund, packageId: entry.published_at };
|
|
371
|
-
}
|
|
372
|
-
/**
|
|
373
|
-
* Consumes the `Fund` hot potato from `openPythSponsorFund`, returns any
|
|
374
|
-
* leftover SUI to the sponsor pool, and attaches the `PythSponsorRule`
|
|
375
|
-
* witness to the given `TradingRequest<C_TOKEN>` so `trading::execute`
|
|
376
|
-
* can satisfy a checklist that includes `PythSponsorRule`.
|
|
377
|
-
*/
|
|
378
|
-
export function reimbursePythSponsor(tx, client, fund, tradingRequest, collateralType) {
|
|
379
|
-
const entry = client.config.packages.pyth_sponsor_rule;
|
|
380
|
-
if (!entry?.published_at || !entry.pyth_sponsor) {
|
|
381
|
-
throw new Error("pyth_sponsor_rule missing from config");
|
|
382
|
-
}
|
|
383
|
-
sponsorReimburse({
|
|
384
|
-
package: entry.published_at,
|
|
385
|
-
arguments: {
|
|
386
|
-
self: tx.object(entry.pyth_sponsor),
|
|
387
|
-
fund: fund,
|
|
388
|
-
tradingReq: tradingRequest,
|
|
389
|
-
},
|
|
390
|
-
typeArguments: [collateralType],
|
|
391
|
-
})(tx);
|
|
392
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/dist/src/{prediction/generated/waterx_account → generated/waterx_prediction}/version.d.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|