@kehtus/proportion-sdk 0.5.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/abi/challengeAccount.d.ts +1855 -0
  2. package/dist/abi/challengeAccount.d.ts.map +1 -0
  3. package/dist/abi/challengeAccount.js +2365 -0
  4. package/dist/abi/challengeAccount.js.map +1 -0
  5. package/dist/abi/challengeFactory.d.ts +1351 -0
  6. package/dist/abi/challengeFactory.d.ts.map +1 -0
  7. package/dist/abi/challengeFactory.js +1727 -0
  8. package/dist/abi/challengeFactory.js.map +1 -0
  9. package/dist/abi/challengeVault.d.ts +1392 -0
  10. package/dist/abi/challengeVault.d.ts.map +1 -0
  11. package/dist/abi/challengeVault.js +1793 -0
  12. package/dist/abi/challengeVault.js.map +1 -0
  13. package/dist/abi/factory.d.ts +4 -0
  14. package/dist/abi/factory.d.ts.map +1 -1
  15. package/dist/abi/factory.js +5 -0
  16. package/dist/abi/factory.js.map +1 -1
  17. package/dist/abi/fundedAccount.d.ts +49 -10
  18. package/dist/abi/fundedAccount.d.ts.map +1 -1
  19. package/dist/abi/fundedAccount.js +62 -13
  20. package/dist/abi/fundedAccount.js.map +1 -1
  21. package/dist/abi/mainVault.d.ts +409 -20
  22. package/dist/abi/mainVault.d.ts.map +1 -1
  23. package/dist/abi/mainVault.js +523 -20
  24. package/dist/abi/mainVault.js.map +1 -1
  25. package/dist/abi/priceOracle.d.ts +497 -0
  26. package/dist/abi/priceOracle.d.ts.map +1 -0
  27. package/dist/abi/priceOracle.js +644 -0
  28. package/dist/abi/priceOracle.js.map +1 -0
  29. package/dist/account.d.ts.map +1 -1
  30. package/dist/account.js +6 -0
  31. package/dist/account.js.map +1 -1
  32. package/dist/challenge/account.d.ts +95 -0
  33. package/dist/challenge/account.d.ts.map +1 -0
  34. package/dist/challenge/account.js +375 -0
  35. package/dist/challenge/account.js.map +1 -0
  36. package/dist/challenge/api.d.ts +49 -0
  37. package/dist/challenge/api.d.ts.map +1 -0
  38. package/dist/challenge/api.js +173 -0
  39. package/dist/challenge/api.js.map +1 -0
  40. package/dist/challenge/factory.d.ts +165 -0
  41. package/dist/challenge/factory.d.ts.map +1 -0
  42. package/dist/challenge/factory.js +392 -0
  43. package/dist/challenge/factory.js.map +1 -0
  44. package/dist/challenge/intents.d.ts +137 -0
  45. package/dist/challenge/intents.d.ts.map +1 -0
  46. package/dist/challenge/intents.js +218 -0
  47. package/dist/challenge/intents.js.map +1 -0
  48. package/dist/challenge/oracle.d.ts +50 -0
  49. package/dist/challenge/oracle.d.ts.map +1 -0
  50. package/dist/challenge/oracle.js +117 -0
  51. package/dist/challenge/oracle.js.map +1 -0
  52. package/dist/challenge/types.d.ts +652 -0
  53. package/dist/challenge/types.d.ts.map +1 -0
  54. package/dist/challenge/types.js +64 -0
  55. package/dist/challenge/types.js.map +1 -0
  56. package/dist/challenge/vault.d.ts +87 -0
  57. package/dist/challenge/vault.d.ts.map +1 -0
  58. package/dist/challenge/vault.js +299 -0
  59. package/dist/challenge/vault.js.map +1 -0
  60. package/dist/constants.d.ts +7 -3
  61. package/dist/constants.d.ts.map +1 -1
  62. package/dist/constants.js +21 -3
  63. package/dist/constants.js.map +1 -1
  64. package/dist/factory.d.ts +1 -1
  65. package/dist/factory.d.ts.map +1 -1
  66. package/dist/factory.js +12 -0
  67. package/dist/factory.js.map +1 -1
  68. package/dist/forwarder.d.ts +58 -0
  69. package/dist/forwarder.d.ts.map +1 -0
  70. package/dist/forwarder.js +145 -0
  71. package/dist/forwarder.js.map +1 -0
  72. package/dist/index.d.ts +13 -0
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +14 -0
  75. package/dist/index.js.map +1 -1
  76. package/dist/indexer.d.ts +52 -0
  77. package/dist/indexer.d.ts.map +1 -1
  78. package/dist/indexer.js +219 -4
  79. package/dist/indexer.js.map +1 -1
  80. package/dist/sdk.d.ts +23 -1
  81. package/dist/sdk.d.ts.map +1 -1
  82. package/dist/sdk.js +122 -35
  83. package/dist/sdk.js.map +1 -1
  84. package/dist/types.d.ts +50 -0
  85. package/dist/types.d.ts.map +1 -1
  86. package/dist/types.js.map +1 -1
  87. package/dist/utils.d.ts +35 -2
  88. package/dist/utils.d.ts.map +1 -1
  89. package/dist/utils.js +86 -7
  90. package/dist/utils.js.map +1 -1
  91. package/dist/vault.d.ts +44 -4
  92. package/dist/vault.d.ts.map +1 -1
  93. package/dist/vault.js +143 -9
  94. package/dist/vault.js.map +1 -1
  95. package/package.json +42 -42
@@ -0,0 +1,218 @@
1
+ import { hashTypedData, recoverTypedDataAddress, } from "viem";
2
+ import { challengeAccountAbi } from "../abi/challengeAccount.js";
3
+ // EIP-712 types mirroring ChallengeAccount's typehashes:
4
+ // OpenIntent(address owner,address account,uint32 market,bool isLong,uint96 margin,
5
+ // uint96 notional,uint64 maxPrice,uint64 minPrice,uint256 nonce,uint64 deadline)
6
+ // CloseIntent(address owner,address account,uint64 positionId,uint64 maxPrice,
7
+ // uint64 minPrice,uint256 nonce,uint64 deadline)
8
+ export const OPEN_INTENT_TYPES = {
9
+ OpenIntent: [
10
+ { name: "owner", type: "address" },
11
+ { name: "account", type: "address" },
12
+ { name: "market", type: "uint32" },
13
+ { name: "isLong", type: "bool" },
14
+ { name: "margin", type: "uint96" },
15
+ { name: "notional", type: "uint96" },
16
+ { name: "maxPrice", type: "uint64" },
17
+ { name: "minPrice", type: "uint64" },
18
+ { name: "nonce", type: "uint256" },
19
+ { name: "deadline", type: "uint64" },
20
+ ],
21
+ };
22
+ export const CLOSE_INTENT_TYPES = {
23
+ CloseIntent: [
24
+ { name: "owner", type: "address" },
25
+ { name: "account", type: "address" },
26
+ { name: "positionId", type: "uint64" },
27
+ { name: "maxPrice", type: "uint64" },
28
+ { name: "minPrice", type: "uint64" },
29
+ { name: "nonce", type: "uint256" },
30
+ { name: "deadline", type: "uint64" },
31
+ ],
32
+ };
33
+ /** SessionKeyLib permission bits (bitmask for registerSessionKey / SessionKey.permissions). */
34
+ export const SESSION_PERMISSION_OPEN = 1n << 0n;
35
+ export const SESSION_PERMISSION_CLOSE = 1n << 1n;
36
+ const DEFAULT_INTENT_TTL_SECONDS = 600;
37
+ /**
38
+ * EIP-712 domain of a ChallengeAccount clone. The domain is bound to the clone address,
39
+ * so intents can never replay across accounts or chains.
40
+ */
41
+ export function challengeAccountDomain(account, chainId) {
42
+ return {
43
+ name: "ProportionChallengeAccount",
44
+ version: "1",
45
+ chainId,
46
+ verifyingContract: account,
47
+ };
48
+ }
49
+ /** Local EIP-712 digest of an open intent (matches ChallengeAccount's on-chain digest). */
50
+ export function hashOpenIntent(intent, chainId) {
51
+ return hashTypedData({
52
+ domain: challengeAccountDomain(intent.account, chainId),
53
+ types: OPEN_INTENT_TYPES,
54
+ primaryType: "OpenIntent",
55
+ message: intent,
56
+ });
57
+ }
58
+ /** Local EIP-712 digest of a close intent (matches ChallengeAccount's on-chain digest). */
59
+ export function hashCloseIntent(intent, chainId) {
60
+ return hashTypedData({
61
+ domain: challengeAccountDomain(intent.account, chainId),
62
+ types: CLOSE_INTENT_TYPES,
63
+ primaryType: "CloseIntent",
64
+ message: intent,
65
+ });
66
+ }
67
+ /**
68
+ * Symmetric slippage bounds around an oracle price for intent maxPrice/minPrice.
69
+ * The contract checks the fill against both bounds, so setting both is safe for
70
+ * either side. Prices are raw HyperCore uint64 units.
71
+ */
72
+ export function priceBounds(price, slippageBps) {
73
+ if (slippageBps < 0 || slippageBps > 10_000)
74
+ throw new Error("slippageBps out of range [0, 10000]");
75
+ const bps = BigInt(slippageBps);
76
+ return {
77
+ maxPrice: (price * (10000n + bps)) / 10000n,
78
+ minPrice: (price * (10000n - bps)) / 10000n,
79
+ };
80
+ }
81
+ /**
82
+ * Session-key market whitelist: bit `market` set = allowed. Markets must be < 256.
83
+ *
84
+ * CAUTION: on-chain a mask of 0 means ALL markets allowed (SessionKeyLib treats 0 as
85
+ * "no restriction"), which is the opposite of an empty whitelist — so an empty input
86
+ * throws instead of silently producing the most permissive value. To deliberately allow
87
+ * all markets, pass 0n to registerSessionKey directly.
88
+ */
89
+ export function marketsToMask(markets) {
90
+ if (markets.length === 0) {
91
+ throw new Error("empty market list; on-chain mask 0 = ALL markets — pass 0n explicitly to allow all");
92
+ }
93
+ let mask = 0n;
94
+ for (const market of markets) {
95
+ if (!Number.isInteger(market) || market < 0 || market > 255) {
96
+ throw new Error(`market ${market} out of mask range [0, 255]`);
97
+ }
98
+ mask |= 1n << BigInt(market);
99
+ }
100
+ return mask;
101
+ }
102
+ export function maskToMarkets(mask) {
103
+ const markets = [];
104
+ for (let i = 0; i < 256; i++) {
105
+ if ((mask >> BigInt(i)) & 1n)
106
+ markets.push(i);
107
+ }
108
+ return markets;
109
+ }
110
+ /**
111
+ * Builds and signs ChallengeAccount trade intents (EIP-712). This is the canonical gasless
112
+ * trading path: the owner or a registered session key signs the intent locally and the
113
+ * challenge-service relayer submits it via openPositionBySig/closePositionBySig
114
+ * (see ChallengeApiClient.submitOpenIntent / submitCloseIntent).
115
+ */
116
+ export class ChallengeIntentsModule {
117
+ publicClient;
118
+ walletClient;
119
+ chain;
120
+ constructor(publicClient, walletClient, chain) {
121
+ this.publicClient = publicClient;
122
+ this.walletClient = walletClient;
123
+ this.chain = chain;
124
+ }
125
+ requireWallet() {
126
+ if (!this.walletClient)
127
+ throw new Error("WalletClient required for signing");
128
+ const walletChainId = this.walletClient.chain?.id;
129
+ if (walletChainId !== undefined && walletChainId !== this.chain.id) {
130
+ throw new Error(`WalletClient chain mismatch: expected ${this.chain.id}, got ${walletChainId}`);
131
+ }
132
+ return this.walletClient;
133
+ }
134
+ /** Next intent nonce of an account (monotonic; consumed by every bySig call). */
135
+ async getNonce(account) {
136
+ return this.publicClient.readContract({
137
+ address: account,
138
+ abi: challengeAccountAbi,
139
+ functionName: "nextNonce",
140
+ });
141
+ }
142
+ /**
143
+ * Sign an open intent. `owner` must be the account owner; it defaults to the signer,
144
+ * which is only correct when the owner (not a session key) signs. Session keys must
145
+ * pass the owner explicitly. `nonce` is fetched from the account when omitted.
146
+ */
147
+ async signOpenIntent(p) {
148
+ const wallet = this.requireWallet();
149
+ const signer = wallet.account;
150
+ if (!signer)
151
+ throw new Error("WalletClient has no account");
152
+ const intent = {
153
+ owner: p.owner ?? signer.address,
154
+ account: p.account,
155
+ market: p.market,
156
+ isLong: p.isLong,
157
+ margin: p.margin,
158
+ notional: p.notional,
159
+ maxPrice: p.maxPrice,
160
+ minPrice: p.minPrice,
161
+ nonce: p.nonce ?? (await this.getNonce(p.account)),
162
+ deadline: BigInt(p.deadlineSeconds ?? Math.floor(Date.now() / 1000) + DEFAULT_INTENT_TTL_SECONDS),
163
+ };
164
+ const signature = await wallet.signTypedData({
165
+ account: signer,
166
+ domain: challengeAccountDomain(p.account, this.chain.id),
167
+ types: OPEN_INTENT_TYPES,
168
+ primaryType: "OpenIntent",
169
+ message: intent,
170
+ });
171
+ return { intent, signature };
172
+ }
173
+ /** Sign a close intent. Same owner/nonce semantics as signOpenIntent. */
174
+ async signCloseIntent(p) {
175
+ const wallet = this.requireWallet();
176
+ const signer = wallet.account;
177
+ if (!signer)
178
+ throw new Error("WalletClient has no account");
179
+ const intent = {
180
+ owner: p.owner ?? signer.address,
181
+ account: p.account,
182
+ positionId: p.positionId,
183
+ maxPrice: p.maxPrice,
184
+ minPrice: p.minPrice,
185
+ nonce: p.nonce ?? (await this.getNonce(p.account)),
186
+ deadline: BigInt(p.deadlineSeconds ?? Math.floor(Date.now() / 1000) + DEFAULT_INTENT_TTL_SECONDS),
187
+ };
188
+ const signature = await wallet.signTypedData({
189
+ account: signer,
190
+ domain: challengeAccountDomain(p.account, this.chain.id),
191
+ types: CLOSE_INTENT_TYPES,
192
+ primaryType: "CloseIntent",
193
+ message: intent,
194
+ });
195
+ return { intent, signature };
196
+ }
197
+ /** Recover the signer of a signed open intent (owner or session key). */
198
+ async recoverOpenIntentSigner(signed) {
199
+ return recoverTypedDataAddress({
200
+ domain: challengeAccountDomain(signed.intent.account, this.chain.id),
201
+ types: OPEN_INTENT_TYPES,
202
+ primaryType: "OpenIntent",
203
+ message: signed.intent,
204
+ signature: signed.signature,
205
+ });
206
+ }
207
+ /** Recover the signer of a signed close intent (owner or session key). */
208
+ async recoverCloseIntentSigner(signed) {
209
+ return recoverTypedDataAddress({
210
+ domain: challengeAccountDomain(signed.intent.account, this.chain.id),
211
+ types: CLOSE_INTENT_TYPES,
212
+ primaryType: "CloseIntent",
213
+ message: signed.intent,
214
+ signature: signed.signature,
215
+ });
216
+ }
217
+ }
218
+ //# sourceMappingURL=intents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intents.js","sourceRoot":"","sources":["../../src/challenge/intents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ import type { Address, PublicClient } from "viem";
2
+ import type { OracleMarketState } from "./types.js";
3
+ type AddressResolver = Address | (() => Promise<Address>);
4
+ /**
5
+ * Read-only PriceOracle module (HyperCore BBO/mark). Used by frontends for price display
6
+ * and for deriving intent maxPrice/minPrice bounds (see priceBounds in intents.ts).
7
+ * All prices are raw HyperCore uint64 units.
8
+ *
9
+ * Owner controls (freeze/settle/pause/config) are multisig territory; refreshMarket is a
10
+ * keeper duty of the challenge-service — both intentionally not covered.
11
+ */
12
+ export declare class ChallengePricesModule {
13
+ private publicClient;
14
+ private addressResolver;
15
+ private addressPromise;
16
+ constructor(publicClient: PublicClient, addressResolver: AddressResolver);
17
+ /**
18
+ * Resolved PriceOracle address (lazy when constructed with a resolver). The in-flight
19
+ * promise is shared by concurrent callers (one RPC lookup); failures clear it for retry.
20
+ */
21
+ getAddress(): Promise<Address>;
22
+ /** Live best bid/offer for a market. */
23
+ getBbo(market: number): Promise<{
24
+ bid: bigint;
25
+ ask: bigint;
26
+ }>;
27
+ /**
28
+ * Taker-side execution price. isOpen=true uses the live BBO and reverts on
29
+ * disabled/paused/settled/frozen/stale markets; isOpen=false (close) is always allowed
30
+ * and clamped conservatively.
31
+ */
32
+ getExecutionPrice(market: number, isLong: boolean, isOpen: boolean): Promise<bigint>;
33
+ /** Conservative mark price used for valuation/liquidation (never trader-favorable). */
34
+ getRiskPrice(market: number, isLong: boolean): Promise<bigint>;
35
+ /** Batch price read for many markets (risk=true → risk prices, else mid/mark path). */
36
+ getPrices(markets: number[], risk: boolean): Promise<bigint[]>;
37
+ /** Per-market oracle cache/override state (frozen book, settled price, lastGoodMark age). */
38
+ getMarketState(market: number): Promise<OracleMarketState>;
39
+ /** Global oracle guard-rails (spread/deviation/staleness bounds) + pause flag. */
40
+ getConfig(): Promise<{
41
+ maxSpreadBps: number;
42
+ maxMarkDeviationBps: number;
43
+ fallbackSpreadBps: number;
44
+ maxStaleness: number;
45
+ paused: boolean;
46
+ owner: Address;
47
+ }>;
48
+ }
49
+ export {};
50
+ //# sourceMappingURL=oracle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oracle.d.ts","sourceRoot":"","sources":["../../src/challenge/oracle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAGlD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,KAAK,eAAe,GAAG,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;AAE1D;;;;;;;GAOG;AACH,qBAAa,qBAAqB;IAI9B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,eAAe;IAJzB,OAAO,CAAC,cAAc,CAA+B;gBAG3C,YAAY,EAAE,YAAY,EAC1B,eAAe,EAAE,eAAe;IAK1C;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAWpC,wCAAwC;IAClC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAWnE;;;;OAIG;IACG,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAU1F,uFAAuF;IACjF,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAUpE,uFAAuF;IACjF,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAWpE,6FAA6F;IACvF,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAYhE,kFAAkF;IAC5E,SAAS,IAAI,OAAO,CAAC;QACzB,YAAY,EAAE,MAAM,CAAC;QACrB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,OAAO,CAAC;QAChB,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;CAuBH"}
@@ -0,0 +1,117 @@
1
+ import { priceOracleAbi } from "../abi/priceOracle.js";
2
+ import { assertAllSuccess } from "../utils.js";
3
+ /**
4
+ * Read-only PriceOracle module (HyperCore BBO/mark). Used by frontends for price display
5
+ * and for deriving intent maxPrice/minPrice bounds (see priceBounds in intents.ts).
6
+ * All prices are raw HyperCore uint64 units.
7
+ *
8
+ * Owner controls (freeze/settle/pause/config) are multisig territory; refreshMarket is a
9
+ * keeper duty of the challenge-service — both intentionally not covered.
10
+ */
11
+ export class ChallengePricesModule {
12
+ publicClient;
13
+ addressResolver;
14
+ addressPromise;
15
+ constructor(publicClient, addressResolver) {
16
+ this.publicClient = publicClient;
17
+ this.addressResolver = addressResolver;
18
+ if (typeof addressResolver === "string")
19
+ this.addressPromise = Promise.resolve(addressResolver);
20
+ }
21
+ /**
22
+ * Resolved PriceOracle address (lazy when constructed with a resolver). The in-flight
23
+ * promise is shared by concurrent callers (one RPC lookup); failures clear it for retry.
24
+ */
25
+ async getAddress() {
26
+ if (!this.addressPromise) {
27
+ const resolver = this.addressResolver;
28
+ this.addressPromise = resolver().catch((err) => {
29
+ this.addressPromise = undefined;
30
+ throw err;
31
+ });
32
+ }
33
+ return this.addressPromise;
34
+ }
35
+ /** Live best bid/offer for a market. */
36
+ async getBbo(market) {
37
+ const address = await this.getAddress();
38
+ const [bid, ask] = await this.publicClient.readContract({
39
+ address,
40
+ abi: priceOracleAbi,
41
+ functionName: "getBbo",
42
+ args: [market],
43
+ });
44
+ return { bid, ask };
45
+ }
46
+ /**
47
+ * Taker-side execution price. isOpen=true uses the live BBO and reverts on
48
+ * disabled/paused/settled/frozen/stale markets; isOpen=false (close) is always allowed
49
+ * and clamped conservatively.
50
+ */
51
+ async getExecutionPrice(market, isLong, isOpen) {
52
+ const address = await this.getAddress();
53
+ return this.publicClient.readContract({
54
+ address,
55
+ abi: priceOracleAbi,
56
+ functionName: "getExecutionPrice",
57
+ args: [market, isLong, isOpen],
58
+ });
59
+ }
60
+ /** Conservative mark price used for valuation/liquidation (never trader-favorable). */
61
+ async getRiskPrice(market, isLong) {
62
+ const address = await this.getAddress();
63
+ return this.publicClient.readContract({
64
+ address,
65
+ abi: priceOracleAbi,
66
+ functionName: "getRiskPrice",
67
+ args: [market, isLong],
68
+ });
69
+ }
70
+ /** Batch price read for many markets (risk=true → risk prices, else mid/mark path). */
71
+ async getPrices(markets, risk) {
72
+ const address = await this.getAddress();
73
+ const prices = await this.publicClient.readContract({
74
+ address,
75
+ abi: priceOracleAbi,
76
+ functionName: "getPrices",
77
+ args: [markets, risk],
78
+ });
79
+ return [...prices];
80
+ }
81
+ /** Per-market oracle cache/override state (frozen book, settled price, lastGoodMark age). */
82
+ async getMarketState(market) {
83
+ const address = await this.getAddress();
84
+ const [lastGoodMark, lastGoodAt, frozenBid, frozenAsk, settledPrice, frozen, settled] = await this.publicClient.readContract({
85
+ address,
86
+ abi: priceOracleAbi,
87
+ functionName: "markets",
88
+ args: [market],
89
+ });
90
+ return { lastGoodMark, lastGoodAt, frozenBid, frozenAsk, settledPrice, frozen, settled };
91
+ }
92
+ /** Global oracle guard-rails (spread/deviation/staleness bounds) + pause flag. */
93
+ async getConfig() {
94
+ const address = await this.getAddress();
95
+ const contract = { address, abi: priceOracleAbi };
96
+ const results = await this.publicClient.multicall({
97
+ contracts: [
98
+ { ...contract, functionName: "maxSpreadBps" },
99
+ { ...contract, functionName: "maxMarkDeviationBps" },
100
+ { ...contract, functionName: "fallbackSpreadBps" },
101
+ { ...contract, functionName: "maxStaleness" },
102
+ { ...contract, functionName: "paused" },
103
+ { ...contract, functionName: "owner" },
104
+ ],
105
+ });
106
+ const r = assertAllSuccess(results);
107
+ return {
108
+ maxSpreadBps: r[0],
109
+ maxMarkDeviationBps: r[1],
110
+ fallbackSpreadBps: r[2],
111
+ maxStaleness: r[3],
112
+ paused: r[4],
113
+ owner: r[5],
114
+ };
115
+ }
116
+ }
117
+ //# sourceMappingURL=oracle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oracle.js","sourceRoot":"","sources":["../../src/challenge/oracle.ts"],"names":[],"mappings":"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"}