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