@oddmaki-protocol/sdk 1.8.0 → 1.10.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/dist/index.d.mts +200 -116
- package/dist/index.d.ts +200 -116
- package/dist/index.js +200 -155
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +200 -155
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -8,7 +8,7 @@ var CONTRACT_ADDRESSES = {
|
|
|
8
8
|
[baseSepolia.id]: {
|
|
9
9
|
diamond: "0x31a4126aec35b36d46dd371eb0f0d5b71e1c2292",
|
|
10
10
|
conditionalTokens: "0x7364747372Ac4a175B5326f5B2C9CB1C271d32e8",
|
|
11
|
-
usdc: "
|
|
11
|
+
usdc: "0x036cbd53842c5426634e7929541ec2318f3dcf7e",
|
|
12
12
|
subgraph: "https://api.studio.thegraph.com/query/1716020/oddmaki-base-sepolia/version/latest"
|
|
13
13
|
},
|
|
14
14
|
[base.id]: {
|
|
@@ -5213,6 +5213,11 @@ var PythResolutionFacet_default = [
|
|
|
5213
5213
|
type: "int64",
|
|
5214
5214
|
internalType: "int64"
|
|
5215
5215
|
},
|
|
5216
|
+
{
|
|
5217
|
+
name: "openTime",
|
|
5218
|
+
type: "uint256",
|
|
5219
|
+
internalType: "uint256"
|
|
5220
|
+
},
|
|
5216
5221
|
{
|
|
5217
5222
|
name: "closeTime",
|
|
5218
5223
|
type: "uint256",
|
|
@@ -5252,11 +5257,6 @@ var PythResolutionFacet_default = [
|
|
|
5252
5257
|
name: "resolutionWindow",
|
|
5253
5258
|
type: "uint256",
|
|
5254
5259
|
internalType: "uint256"
|
|
5255
|
-
},
|
|
5256
|
-
{
|
|
5257
|
-
name: "pythUpdateData",
|
|
5258
|
-
type: "bytes[]",
|
|
5259
|
-
internalType: "bytes[]"
|
|
5260
5260
|
}
|
|
5261
5261
|
],
|
|
5262
5262
|
outputs: [
|
|
@@ -5266,20 +5266,7 @@ var PythResolutionFacet_default = [
|
|
|
5266
5266
|
internalType: "uint256"
|
|
5267
5267
|
}
|
|
5268
5268
|
],
|
|
5269
|
-
stateMutability: "
|
|
5270
|
-
},
|
|
5271
|
-
{
|
|
5272
|
-
type: "function",
|
|
5273
|
-
name: "getOpenMaxStaleness",
|
|
5274
|
-
inputs: [],
|
|
5275
|
-
outputs: [
|
|
5276
|
-
{
|
|
5277
|
-
name: "",
|
|
5278
|
-
type: "uint256",
|
|
5279
|
-
internalType: "uint256"
|
|
5280
|
-
}
|
|
5281
|
-
],
|
|
5282
|
-
stateMutability: "view"
|
|
5269
|
+
stateMutability: "nonpayable"
|
|
5283
5270
|
},
|
|
5284
5271
|
{
|
|
5285
5272
|
type: "function",
|
|
@@ -5296,34 +5283,34 @@ var PythResolutionFacet_default = [
|
|
|
5296
5283
|
},
|
|
5297
5284
|
{
|
|
5298
5285
|
type: "function",
|
|
5299
|
-
name: "
|
|
5286
|
+
name: "markPriceMarketInvalid",
|
|
5300
5287
|
inputs: [
|
|
5301
5288
|
{
|
|
5302
5289
|
name: "marketId",
|
|
5303
5290
|
type: "uint256",
|
|
5304
5291
|
internalType: "uint256"
|
|
5305
|
-
},
|
|
5306
|
-
{
|
|
5307
|
-
name: "pythUpdateData",
|
|
5308
|
-
type: "bytes[]",
|
|
5309
|
-
internalType: "bytes[]"
|
|
5310
5292
|
}
|
|
5311
5293
|
],
|
|
5312
5294
|
outputs: [],
|
|
5313
|
-
stateMutability: "
|
|
5295
|
+
stateMutability: "nonpayable"
|
|
5314
5296
|
},
|
|
5315
5297
|
{
|
|
5316
5298
|
type: "function",
|
|
5317
|
-
name: "
|
|
5299
|
+
name: "resolvePriceMarketPyth",
|
|
5318
5300
|
inputs: [
|
|
5319
5301
|
{
|
|
5320
|
-
name: "
|
|
5302
|
+
name: "marketId",
|
|
5321
5303
|
type: "uint256",
|
|
5322
5304
|
internalType: "uint256"
|
|
5305
|
+
},
|
|
5306
|
+
{
|
|
5307
|
+
name: "pythUpdateData",
|
|
5308
|
+
type: "bytes[]",
|
|
5309
|
+
internalType: "bytes[]"
|
|
5323
5310
|
}
|
|
5324
5311
|
],
|
|
5325
5312
|
outputs: [],
|
|
5326
|
-
stateMutability: "
|
|
5313
|
+
stateMutability: "payable"
|
|
5327
5314
|
},
|
|
5328
5315
|
{
|
|
5329
5316
|
type: "function",
|
|
@@ -5461,19 +5448,6 @@ var PythResolutionFacet_default = [
|
|
|
5461
5448
|
],
|
|
5462
5449
|
anonymous: false
|
|
5463
5450
|
},
|
|
5464
|
-
{
|
|
5465
|
-
type: "event",
|
|
5466
|
-
name: "OpenMaxStalenessUpdated",
|
|
5467
|
-
inputs: [
|
|
5468
|
-
{
|
|
5469
|
-
name: "openMaxStaleness",
|
|
5470
|
-
type: "uint256",
|
|
5471
|
-
indexed: false,
|
|
5472
|
-
internalType: "uint256"
|
|
5473
|
-
}
|
|
5474
|
-
],
|
|
5475
|
-
anonymous: false
|
|
5476
|
-
},
|
|
5477
5451
|
{
|
|
5478
5452
|
type: "event",
|
|
5479
5453
|
name: "PriceMarketCreatedPyth",
|
|
@@ -5529,6 +5503,25 @@ var PythResolutionFacet_default = [
|
|
|
5529
5503
|
],
|
|
5530
5504
|
anonymous: false
|
|
5531
5505
|
},
|
|
5506
|
+
{
|
|
5507
|
+
type: "event",
|
|
5508
|
+
name: "PriceMarketInvalidated",
|
|
5509
|
+
inputs: [
|
|
5510
|
+
{
|
|
5511
|
+
name: "marketId",
|
|
5512
|
+
type: "uint256",
|
|
5513
|
+
indexed: true,
|
|
5514
|
+
internalType: "uint256"
|
|
5515
|
+
},
|
|
5516
|
+
{
|
|
5517
|
+
name: "caller",
|
|
5518
|
+
type: "address",
|
|
5519
|
+
indexed: true,
|
|
5520
|
+
internalType: "address"
|
|
5521
|
+
}
|
|
5522
|
+
],
|
|
5523
|
+
anonymous: false
|
|
5524
|
+
},
|
|
5532
5525
|
{
|
|
5533
5526
|
type: "event",
|
|
5534
5527
|
name: "PriceMarketResolvedPyth",
|
|
@@ -5551,6 +5544,12 @@ var PythResolutionFacet_default = [
|
|
|
5551
5544
|
indexed: false,
|
|
5552
5545
|
internalType: "int64"
|
|
5553
5546
|
},
|
|
5547
|
+
{
|
|
5548
|
+
name: "openPriceTime",
|
|
5549
|
+
type: "uint256",
|
|
5550
|
+
indexed: false,
|
|
5551
|
+
internalType: "uint256"
|
|
5552
|
+
},
|
|
5554
5553
|
{
|
|
5555
5554
|
name: "outcome",
|
|
5556
5555
|
type: "string",
|
|
@@ -5594,17 +5593,17 @@ var PythResolutionFacet_default = [
|
|
|
5594
5593
|
},
|
|
5595
5594
|
{
|
|
5596
5595
|
type: "error",
|
|
5597
|
-
name: "
|
|
5596
|
+
name: "AssertionInProgress",
|
|
5598
5597
|
inputs: []
|
|
5599
5598
|
},
|
|
5600
5599
|
{
|
|
5601
5600
|
type: "error",
|
|
5602
|
-
name: "
|
|
5601
|
+
name: "CloseTimeNotAfterOpenTime",
|
|
5603
5602
|
inputs: []
|
|
5604
5603
|
},
|
|
5605
5604
|
{
|
|
5606
5605
|
type: "error",
|
|
5607
|
-
name: "
|
|
5606
|
+
name: "CloseTimeNotReached",
|
|
5608
5607
|
inputs: []
|
|
5609
5608
|
},
|
|
5610
5609
|
{
|
|
@@ -5638,6 +5637,11 @@ var PythResolutionFacet_default = [
|
|
|
5638
5637
|
}
|
|
5639
5638
|
]
|
|
5640
5639
|
},
|
|
5640
|
+
{
|
|
5641
|
+
type: "error",
|
|
5642
|
+
name: "GracePeriodNotElapsed",
|
|
5643
|
+
inputs: []
|
|
5644
|
+
},
|
|
5641
5645
|
{
|
|
5642
5646
|
type: "error",
|
|
5643
5647
|
name: "InsufficientPythFee",
|
|
@@ -5663,6 +5667,11 @@ var PythResolutionFacet_default = [
|
|
|
5663
5667
|
name: "InvalidMarketId",
|
|
5664
5668
|
inputs: []
|
|
5665
5669
|
},
|
|
5670
|
+
{
|
|
5671
|
+
type: "error",
|
|
5672
|
+
name: "InvalidOpenTime",
|
|
5673
|
+
inputs: []
|
|
5674
|
+
},
|
|
5666
5675
|
{
|
|
5667
5676
|
type: "error",
|
|
5668
5677
|
name: "InvalidOutcomesLength",
|
|
@@ -5680,7 +5689,12 @@ var PythResolutionFacet_default = [
|
|
|
5680
5689
|
},
|
|
5681
5690
|
{
|
|
5682
5691
|
type: "error",
|
|
5683
|
-
name: "
|
|
5692
|
+
name: "NoClosePriceInWindow",
|
|
5693
|
+
inputs: []
|
|
5694
|
+
},
|
|
5695
|
+
{
|
|
5696
|
+
type: "error",
|
|
5697
|
+
name: "NoOpenPriceInWindow",
|
|
5684
5698
|
inputs: []
|
|
5685
5699
|
},
|
|
5686
5700
|
{
|
|
@@ -6707,6 +6721,24 @@ var ERC20_default = [
|
|
|
6707
6721
|
],
|
|
6708
6722
|
stateMutability: "view"
|
|
6709
6723
|
},
|
|
6724
|
+
{
|
|
6725
|
+
type: "function",
|
|
6726
|
+
name: "mint",
|
|
6727
|
+
inputs: [
|
|
6728
|
+
{
|
|
6729
|
+
name: "to",
|
|
6730
|
+
type: "address",
|
|
6731
|
+
internalType: "address"
|
|
6732
|
+
},
|
|
6733
|
+
{
|
|
6734
|
+
name: "amount",
|
|
6735
|
+
type: "uint256",
|
|
6736
|
+
internalType: "uint256"
|
|
6737
|
+
}
|
|
6738
|
+
],
|
|
6739
|
+
outputs: [],
|
|
6740
|
+
stateMutability: "nonpayable"
|
|
6741
|
+
},
|
|
6710
6742
|
{
|
|
6711
6743
|
type: "function",
|
|
6712
6744
|
name: "name",
|
|
@@ -6925,6 +6957,24 @@ var UmaOracle_default = [
|
|
|
6925
6957
|
],
|
|
6926
6958
|
stateMutability: "view"
|
|
6927
6959
|
},
|
|
6960
|
+
{
|
|
6961
|
+
type: "function",
|
|
6962
|
+
name: "disputeAssertion",
|
|
6963
|
+
inputs: [
|
|
6964
|
+
{
|
|
6965
|
+
name: "assertionId",
|
|
6966
|
+
type: "bytes32",
|
|
6967
|
+
internalType: "bytes32"
|
|
6968
|
+
},
|
|
6969
|
+
{
|
|
6970
|
+
name: "disputer",
|
|
6971
|
+
type: "address",
|
|
6972
|
+
internalType: "address"
|
|
6973
|
+
}
|
|
6974
|
+
],
|
|
6975
|
+
outputs: [],
|
|
6976
|
+
stateMutability: "nonpayable"
|
|
6977
|
+
},
|
|
6928
6978
|
{
|
|
6929
6979
|
type: "function",
|
|
6930
6980
|
name: "getAssertion",
|
|
@@ -7102,24 +7152,6 @@ var UmaOracle_default = [
|
|
|
7102
7152
|
],
|
|
7103
7153
|
outputs: [],
|
|
7104
7154
|
stateMutability: "nonpayable"
|
|
7105
|
-
},
|
|
7106
|
-
{
|
|
7107
|
-
type: "function",
|
|
7108
|
-
name: "disputeAssertion",
|
|
7109
|
-
inputs: [
|
|
7110
|
-
{
|
|
7111
|
-
name: "assertionId",
|
|
7112
|
-
type: "bytes32",
|
|
7113
|
-
internalType: "bytes32"
|
|
7114
|
-
},
|
|
7115
|
-
{
|
|
7116
|
-
name: "disputer",
|
|
7117
|
-
type: "address",
|
|
7118
|
-
internalType: "address"
|
|
7119
|
-
}
|
|
7120
|
-
],
|
|
7121
|
-
outputs: [],
|
|
7122
|
-
stateMutability: "nonpayable"
|
|
7123
7155
|
}
|
|
7124
7156
|
];
|
|
7125
7157
|
|
|
@@ -9914,7 +9946,7 @@ var GET_PRICE_MARKET_SERIES = gql`
|
|
|
9914
9946
|
venueId
|
|
9915
9947
|
name
|
|
9916
9948
|
}
|
|
9917
|
-
markets {
|
|
9949
|
+
markets(first: 1000, orderBy: marketId, orderDirection: asc) {
|
|
9918
9950
|
id
|
|
9919
9951
|
marketId
|
|
9920
9952
|
question
|
|
@@ -11457,41 +11489,45 @@ var DEFAULT_FRESH_MAX_AGE_SECONDS = 120;
|
|
|
11457
11489
|
var DEFAULT_FRESH_MAX_ATTEMPTS = 3;
|
|
11458
11490
|
var PriceMarketModule = class extends BaseModule {
|
|
11459
11491
|
/**
|
|
11460
|
-
* Create a Pyth-powered price market
|
|
11492
|
+
* Create a Pyth-powered price market. Three shapes via one entry point:
|
|
11461
11493
|
*
|
|
11462
|
-
*
|
|
11463
|
-
*
|
|
11464
|
-
*
|
|
11465
|
-
*
|
|
11494
|
+
* - **Immediate Up/Down** (`strikePrice = 0`, `openTime = 0` or omitted):
|
|
11495
|
+
* `openTime` is set to `block.timestamp` at creation; open price is
|
|
11496
|
+
* captured at resolution from the earliest Hermes VAA in
|
|
11497
|
+
* `[openTime, openTime + resolutionWindow]`.
|
|
11498
|
+
*
|
|
11499
|
+
* - **Scheduled Up/Down** (`strikePrice = 0`, `openTime > now`):
|
|
11500
|
+
* Market exists from creation and is tradable. At `openTime` the open
|
|
11501
|
+
* price window begins; capture happens at resolution as above.
|
|
11502
|
+
*
|
|
11503
|
+
* - **Explicit strike** (`strikePrice > 0`): Above/Below market resolved
|
|
11504
|
+
* against the caller-supplied target. `openTime` is ignored and stored
|
|
11505
|
+
* as `block.timestamp`; no open-price capture occurs at resolution.
|
|
11506
|
+
*
|
|
11507
|
+
* Creation never touches Pyth — no VAA submission, no Pyth fee. The
|
|
11508
|
+
* resolver pays Pyth fees later when calling {@link resolvePyth}.
|
|
11466
11509
|
*
|
|
11467
11510
|
* @param params.venueId - The venue to create the market in
|
|
11468
11511
|
* @param params.pythFeedId - Pyth price feed ID (e.g., ETH/USD)
|
|
11469
|
-
* @param params.strikePrice - Target price
|
|
11470
|
-
* @param params.
|
|
11512
|
+
* @param params.strikePrice - Target price (0 = capture open at resolution)
|
|
11513
|
+
* @param params.openTime - When the market opens (0 = immediate / now)
|
|
11514
|
+
* @param params.closeTime - Absolute close timestamp (must be > effective openTime)
|
|
11471
11515
|
* @param params.outcomes - Market outcome labels (e.g., ["Up", "Down"] or ["Above", "Below"])
|
|
11472
|
-
* @param params.tickSize - Price increment for the orderbook
|
|
11516
|
+
* @param params.tickSize - Price increment for the orderbook (1e15 or 1e16)
|
|
11473
11517
|
* @param params.collateralToken - ERC20 collateral token address
|
|
11474
|
-
* @param params.question - Market question for
|
|
11518
|
+
* @param params.question - Market question for ancillary data
|
|
11475
11519
|
* @param params.liveness - UMA challenge period in seconds (0 = default)
|
|
11476
11520
|
* @param params.tags - Optional tags for the market
|
|
11477
|
-
* @param params.resolutionWindow - Pyth timestamp tolerance in seconds (0 = default 60s)
|
|
11521
|
+
* @param params.resolutionWindow - Pyth timestamp tolerance in seconds (0 = default 60s, max 300s)
|
|
11478
11522
|
*/
|
|
11479
11523
|
async createPyth(params) {
|
|
11480
11524
|
const wallet = this.walletClient;
|
|
11481
11525
|
const account = await this.getSignerAccount();
|
|
11482
11526
|
const outcomes = params.outcomes ?? ["Up", "Down"];
|
|
11483
|
-
const isStrikeMarket = params.strikePrice && params.strikePrice > BigInt(0);
|
|
11484
11527
|
const { encodedTags, ancillaryData } = await this._prepareCreationCommon(params, await this.getSignerAddress());
|
|
11485
11528
|
if (!isValidTickSize(params.tickSize)) {
|
|
11486
11529
|
throw new Error("Invalid tickSize: must be 1e15 (0.1%) or 1e16 (1%)");
|
|
11487
11530
|
}
|
|
11488
|
-
let pythUpdateData = [];
|
|
11489
|
-
let valueSent = BigInt(0);
|
|
11490
|
-
if (!isStrikeMarket) {
|
|
11491
|
-
const pythResult = await this._preparePythUpdate(params.pythFeedId);
|
|
11492
|
-
pythUpdateData = pythResult.pythUpdateData;
|
|
11493
|
-
valueSent = pythResult.valueSent;
|
|
11494
|
-
}
|
|
11495
11531
|
const { request } = await this.publicClient.simulateContract({
|
|
11496
11532
|
address: this.config.diamondAddress,
|
|
11497
11533
|
abi: PythResolutionFacet_default,
|
|
@@ -11500,6 +11536,7 @@ var PriceMarketModule = class extends BaseModule {
|
|
|
11500
11536
|
params.venueId,
|
|
11501
11537
|
params.pythFeedId,
|
|
11502
11538
|
params.strikePrice ?? BigInt(0),
|
|
11539
|
+
params.openTime ?? BigInt(0),
|
|
11503
11540
|
params.closeTime,
|
|
11504
11541
|
outcomes,
|
|
11505
11542
|
params.tickSize,
|
|
@@ -11507,20 +11544,21 @@ var PriceMarketModule = class extends BaseModule {
|
|
|
11507
11544
|
ancillaryData,
|
|
11508
11545
|
params.liveness ?? BigInt(0),
|
|
11509
11546
|
encodedTags,
|
|
11510
|
-
params.resolutionWindow ?? BigInt(0)
|
|
11511
|
-
pythUpdateData
|
|
11547
|
+
params.resolutionWindow ?? BigInt(0)
|
|
11512
11548
|
],
|
|
11513
|
-
account
|
|
11514
|
-
value: valueSent
|
|
11549
|
+
account
|
|
11515
11550
|
});
|
|
11516
11551
|
return wallet.writeContract(request);
|
|
11517
11552
|
}
|
|
11518
11553
|
/**
|
|
11519
|
-
* Resolve a price market using Pyth
|
|
11554
|
+
* Resolve a price market using Pyth.
|
|
11520
11555
|
*
|
|
11521
|
-
* Anyone can call this after
|
|
11522
|
-
*
|
|
11523
|
-
*
|
|
11556
|
+
* Anyone can call this after `closeTime`. For deferred Up/Down markets
|
|
11557
|
+
* (`strikePrice == 0`), the SDK fetches **two** Hermes VAAs — one for the
|
|
11558
|
+
* open window, one for the close window — and submits them together so the
|
|
11559
|
+
* on-chain facet can capture the open price and compare against the close
|
|
11560
|
+
* in a single transaction. For explicit-strike markets only the close VAA
|
|
11561
|
+
* is fetched.
|
|
11524
11562
|
*/
|
|
11525
11563
|
async resolvePyth(marketId) {
|
|
11526
11564
|
const wallet = this.walletClient;
|
|
@@ -11535,10 +11573,21 @@ var PriceMarketModule = class extends BaseModule {
|
|
|
11535
11573
|
`Close time not reached. Current: ${now.toString()}, CloseTime: ${pm.closeTime.toString()}`
|
|
11536
11574
|
);
|
|
11537
11575
|
}
|
|
11538
|
-
const
|
|
11576
|
+
const isDeferred = pm.strikePrice === BigInt(0);
|
|
11577
|
+
const closeVAA = await this.fetchPythHistoricalData(
|
|
11539
11578
|
pm.feedId,
|
|
11540
11579
|
Number(pm.closeTime)
|
|
11541
11580
|
);
|
|
11581
|
+
let pythUpdateData;
|
|
11582
|
+
if (isDeferred) {
|
|
11583
|
+
const openVAA = await this.fetchPythHistoricalData(
|
|
11584
|
+
pm.feedId,
|
|
11585
|
+
Number(pm.openTime)
|
|
11586
|
+
);
|
|
11587
|
+
pythUpdateData = [...openVAA, ...closeVAA];
|
|
11588
|
+
} else {
|
|
11589
|
+
pythUpdateData = closeVAA;
|
|
11590
|
+
}
|
|
11542
11591
|
const pythAddress = await this.getPythContract();
|
|
11543
11592
|
const pythFee = await this.publicClient.readContract({
|
|
11544
11593
|
address: pythAddress,
|
|
@@ -11569,7 +11618,7 @@ var PriceMarketModule = class extends BaseModule {
|
|
|
11569
11618
|
});
|
|
11570
11619
|
}
|
|
11571
11620
|
/**
|
|
11572
|
-
* Check if a price market can be resolved
|
|
11621
|
+
* Check if a price market can be resolved (closeTime reached and not yet resolved).
|
|
11573
11622
|
*/
|
|
11574
11623
|
async canResolve(marketId) {
|
|
11575
11624
|
return await this.publicClient.readContract({
|
|
@@ -11627,36 +11676,6 @@ var PriceMarketModule = class extends BaseModule {
|
|
|
11627
11676
|
});
|
|
11628
11677
|
return wallet.writeContract(request);
|
|
11629
11678
|
}
|
|
11630
|
-
/**
|
|
11631
|
-
* Get the effective opening-price staleness window in seconds.
|
|
11632
|
-
*
|
|
11633
|
-
* A submitted VAA's `publishTime` must fall within
|
|
11634
|
-
* `[block.timestamp - openMaxStaleness, block.timestamp + OPEN_FUTURE_SKEW]`
|
|
11635
|
-
* at `createPriceMarketPyth` time. Defaults to 300s when unset on-chain.
|
|
11636
|
-
*/
|
|
11637
|
-
async getOpenMaxStaleness() {
|
|
11638
|
-
return await this.publicClient.readContract({
|
|
11639
|
-
address: this.config.diamondAddress,
|
|
11640
|
-
abi: PythResolutionFacet_default,
|
|
11641
|
-
functionName: "getOpenMaxStaleness"
|
|
11642
|
-
});
|
|
11643
|
-
}
|
|
11644
|
-
/**
|
|
11645
|
-
* Set the opening-price staleness window (seconds). Diamond owner only.
|
|
11646
|
-
* Pass 0 to fall back to the built-in default.
|
|
11647
|
-
*/
|
|
11648
|
-
async setOpenMaxStaleness(openMaxStaleness) {
|
|
11649
|
-
const wallet = this.walletClient;
|
|
11650
|
-
const account = await this.getSignerAccount();
|
|
11651
|
-
const { request } = await this.publicClient.simulateContract({
|
|
11652
|
-
address: this.config.diamondAddress,
|
|
11653
|
-
abi: PythResolutionFacet_default,
|
|
11654
|
-
functionName: "setOpenMaxStaleness",
|
|
11655
|
-
args: [openMaxStaleness],
|
|
11656
|
-
account
|
|
11657
|
-
});
|
|
11658
|
-
return wallet.writeContract(request);
|
|
11659
|
-
}
|
|
11660
11679
|
// ---- Private helpers ----
|
|
11661
11680
|
/**
|
|
11662
11681
|
* Shared pre-flight checks: creation fee allowance, ancillary data, tags
|
|
@@ -11688,33 +11707,18 @@ var PriceMarketModule = class extends BaseModule {
|
|
|
11688
11707
|
);
|
|
11689
11708
|
return { encodedTags, ancillaryData };
|
|
11690
11709
|
}
|
|
11691
|
-
/**
|
|
11692
|
-
* Fetch Pyth update data and compute the required ETH value (for Up/Down markets)
|
|
11693
|
-
*/
|
|
11694
|
-
async _preparePythUpdate(feedId) {
|
|
11695
|
-
const pythUpdateData = await this.fetchPythUpdateData(feedId);
|
|
11696
|
-
const pythAddress = await this.getPythContract();
|
|
11697
|
-
const pythFee = await this.publicClient.readContract({
|
|
11698
|
-
address: pythAddress,
|
|
11699
|
-
abi: PYTH_GET_UPDATE_FEE_ABI,
|
|
11700
|
-
functionName: "getUpdateFee",
|
|
11701
|
-
args: [pythUpdateData]
|
|
11702
|
-
});
|
|
11703
|
-
const valueSent = pythFee > BigInt(0) ? pythFee : BigInt(1e9);
|
|
11704
|
-
return { pythUpdateData, valueSent };
|
|
11705
|
-
}
|
|
11706
11710
|
formatAncillaryData(question) {
|
|
11707
11711
|
let data = `q:title:${question.title}`;
|
|
11708
11712
|
data += `,description:${question.description}`;
|
|
11709
11713
|
return stringToHex(data);
|
|
11710
11714
|
}
|
|
11711
11715
|
/**
|
|
11712
|
-
* Fetch latest Pyth price update from Hermes — bytes plus the
|
|
11716
|
+
* Fetch the latest Pyth price update from Hermes — the bytes plus the
|
|
11717
|
+
* VAA's publishTime.
|
|
11713
11718
|
*
|
|
11714
|
-
*
|
|
11715
|
-
*
|
|
11716
|
-
*
|
|
11717
|
-
* to sign, the VAA will be rejected.
|
|
11719
|
+
* Useful for UI projected-strike display: callers can render the current
|
|
11720
|
+
* Pyth price (and its publishTime) before a deferred market's open window
|
|
11721
|
+
* closes, then switch to the on-chain strike once resolution happens.
|
|
11718
11722
|
*/
|
|
11719
11723
|
async fetchPythLatestUpdate(feedId) {
|
|
11720
11724
|
const url = `${PYTH_HERMES_BASE}/v2/updates/price/latest?ids[]=${feedId}`;
|
|
@@ -11741,14 +11745,14 @@ var PriceMarketModule = class extends BaseModule {
|
|
|
11741
11745
|
};
|
|
11742
11746
|
}
|
|
11743
11747
|
/**
|
|
11744
|
-
* Return a Pyth update that is fresh enough
|
|
11748
|
+
* Return a Pyth update that is fresh enough for client-side projected-strike
|
|
11749
|
+
* display.
|
|
11745
11750
|
*
|
|
11746
|
-
* If `cached` is provided and still within `maxAgeSeconds`, it
|
|
11747
|
-
* Otherwise
|
|
11748
|
-
*
|
|
11751
|
+
* If `cached` is provided and still within `maxAgeSeconds`, returns it
|
|
11752
|
+
* unchanged. Otherwise re-queries Hermes; if the new VAA is also stale
|
|
11753
|
+
* (quiet feed), retries up to `maxAttempts`.
|
|
11749
11754
|
*
|
|
11750
|
-
* Defaults: `maxAgeSeconds = 120`
|
|
11751
|
-
* on-chain window), `maxAttempts = 3`.
|
|
11755
|
+
* Defaults: `maxAgeSeconds = 120`, `maxAttempts = 3`.
|
|
11752
11756
|
*/
|
|
11753
11757
|
async fetchFreshPythUpdate(feedId, options = {}) {
|
|
11754
11758
|
const maxAgeSeconds = options.maxAgeSeconds ?? DEFAULT_FRESH_MAX_AGE_SECONDS;
|
|
@@ -11771,14 +11775,55 @@ var PriceMarketModule = class extends BaseModule {
|
|
|
11771
11775
|
return latest;
|
|
11772
11776
|
}
|
|
11773
11777
|
/**
|
|
11774
|
-
*
|
|
11778
|
+
* Resolve the projected open price for a deferred Up/Down market — what the
|
|
11779
|
+
* UI should display as the "strike" between `openTime` and resolution.
|
|
11780
|
+
*
|
|
11781
|
+
* For deferred markets, the on-chain `strikePrice` is 0 until the resolver
|
|
11782
|
+
* fires {@link resolvePyth}. This helper replicates the same rule the
|
|
11783
|
+
* contract will use ("earliest in-window Hermes VAA in
|
|
11784
|
+
* `[openTime, openTime + resolutionWindow]`") by querying Hermes at
|
|
11785
|
+
* `openTime`, so the value rendered in the UI matches what the on-chain
|
|
11786
|
+
* strike will be once resolution lands.
|
|
11787
|
+
*
|
|
11788
|
+
* Returns `null` when the projection isn't applicable:
|
|
11789
|
+
* - The market is already resolved — caller should read `pm.strikePrice` directly.
|
|
11790
|
+
* - The market is explicit-strike (`pm.strikePrice > 0`) — same, read from chain.
|
|
11791
|
+
* - The market hasn't reached `openTime` yet — no VAA exists; UI should show
|
|
11792
|
+
* "strike set at HH:MM" or similar pending state.
|
|
11793
|
+
*
|
|
11794
|
+
* `result.canonical === true` means the open window has fully elapsed and the
|
|
11795
|
+
* value will not change. Before that, render the price with a "pending" hint.
|
|
11775
11796
|
*/
|
|
11776
|
-
async
|
|
11777
|
-
const
|
|
11778
|
-
return
|
|
11797
|
+
async fetchProjectedOpenPrice(marketId) {
|
|
11798
|
+
const pm = await this.get(marketId);
|
|
11799
|
+
if (pm.resolved) return null;
|
|
11800
|
+
if (pm.strikePrice !== BigInt(0)) return null;
|
|
11801
|
+
const now = BigInt(Math.floor(Date.now() / 1e3));
|
|
11802
|
+
if (now < pm.openTime) return null;
|
|
11803
|
+
const url = `${PYTH_HERMES_BASE}/v2/updates/price/${pm.openTime}?ids[]=${pm.feedId}`;
|
|
11804
|
+
const response = await fetch(url);
|
|
11805
|
+
if (!response.ok) {
|
|
11806
|
+
throw new Error(
|
|
11807
|
+
`Pyth Hermes API error: ${response.status} ${response.statusText}`
|
|
11808
|
+
);
|
|
11809
|
+
}
|
|
11810
|
+
const data = await response.json();
|
|
11811
|
+
const parsed = data.parsed?.[0];
|
|
11812
|
+
if (!parsed?.price) {
|
|
11813
|
+
throw new Error("Pyth Hermes response missing parsed.price for open VAA");
|
|
11814
|
+
}
|
|
11815
|
+
return {
|
|
11816
|
+
price: BigInt(parsed.price.price),
|
|
11817
|
+
publishTime: BigInt(parsed.price.publish_time),
|
|
11818
|
+
expo: Number(parsed.price.expo),
|
|
11819
|
+
canonical: now >= pm.openTime + pm.resolutionWindow,
|
|
11820
|
+
openTime: pm.openTime
|
|
11821
|
+
};
|
|
11779
11822
|
}
|
|
11780
11823
|
/**
|
|
11781
|
-
* Fetch historical Pyth price update data at a specific timestamp
|
|
11824
|
+
* Fetch historical Pyth price update data at a specific timestamp.
|
|
11825
|
+
* Used internally by {@link resolvePyth} to fetch open-window and
|
|
11826
|
+
* close-window VAAs.
|
|
11782
11827
|
*/
|
|
11783
11828
|
async fetchPythHistoricalData(feedId, publishTime) {
|
|
11784
11829
|
const url = `${PYTH_HERMES_BASE}/v2/updates/price/${publishTime}?ids[]=${feedId}`;
|