@waterx/sdk 4.3.2 → 4.3.3
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/.claude/skills/waterx-sdk-integration/SKILL.md +219 -0
- package/README.md +177 -10
- package/SKILLS.md +34 -0
- package/dist/cjs/src/generated/waterx_rule/waterx_rule.d.ts +140 -7
- package/dist/cjs/src/generated/waterx_rule/waterx_rule.js +163 -8
- package/dist/cjs/src/oracle/aggregate.d.ts +4 -1
- package/dist/cjs/src/oracle/aggregate.js +70 -26
- package/dist/cjs/src/oracle/config.d.ts +3 -2
- package/dist/cjs/src/oracle/index.d.ts +2 -2
- package/dist/cjs/src/oracle/index.js +10 -5
- package/dist/cjs/src/oracle/rules/waterx-rule.d.ts +136 -47
- package/dist/cjs/src/oracle/rules/waterx-rule.js +450 -114
- package/dist/cjs/src/perp/client.d.ts +10 -8
- package/dist/cjs/src/perp/index.d.ts +2 -2
- package/dist/cjs/src/perp/index.js +10 -2
- package/dist/cjs/src/unified-client.d.ts +1 -1
- package/dist/src/generated/waterx_rule/waterx_rule.d.ts +140 -7
- package/dist/src/generated/waterx_rule/waterx_rule.js +151 -7
- package/dist/src/oracle/aggregate.d.ts +4 -1
- package/dist/src/oracle/aggregate.js +71 -27
- package/dist/src/oracle/config.d.ts +3 -2
- package/dist/src/oracle/index.d.ts +2 -2
- package/dist/src/oracle/index.js +8 -6
- package/dist/src/oracle/rules/waterx-rule.d.ts +136 -47
- package/dist/src/oracle/rules/waterx-rule.js +447 -114
- package/dist/src/perp/client.d.ts +10 -8
- package/dist/src/perp/index.d.ts +2 -2
- package/dist/src/perp/index.js +7 -1
- package/dist/src/unified-client.d.ts +1 -1
- package/package.json +8 -2
|
@@ -70,6 +70,11 @@ export declare const BatchPricePayload: MoveStruct<{
|
|
|
70
70
|
length: number;
|
|
71
71
|
}, string>;
|
|
72
72
|
}, "@waterx/rule::waterx_rule::BatchPricePayload">;
|
|
73
|
+
export declare const MerkleRoot: MoveStruct<{
|
|
74
|
+
root: import("@mysten/sui/bcs").BcsType<number[], Iterable<number> & {
|
|
75
|
+
length: number;
|
|
76
|
+
}, string>;
|
|
77
|
+
}, "@waterx/rule::waterx_rule::MerkleRoot">;
|
|
73
78
|
export declare const FeedConfig: MoveStruct<{
|
|
74
79
|
ticker: import("@mysten/sui/bcs").BcsType<string, string, "string">;
|
|
75
80
|
sources: import("@mysten/sui/bcs").BcsType<string[], Iterable<string | number | bigint> & {
|
|
@@ -214,17 +219,82 @@ export interface CollectBatchLatestOptions {
|
|
|
214
219
|
* and so aborts on any stale item, this path runs alongside Pyth/Supra. To let
|
|
215
220
|
* those cover a lagging TEE — the blast-radius bound in the GCP ADR — a
|
|
216
221
|
* _freshness_ miss ABSTAINS (records `none`, which `aggregator::remove_outliers`
|
|
217
|
-
* drops before the `weight_threshold` fail-closed check)
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
+
* drops before the `weight_threshold` fail-closed check), and so does a _replayed_
|
|
223
|
+
* signed timestamp (the chain already accepted that snapshot — the on-chain price
|
|
224
|
+
* is at least as fresh, and two concurrent keeper PTBs sharing one envelope must
|
|
225
|
+
* not kill each other). A _config/integrity_ mismatch (source / ticker / method /
|
|
226
|
+
* confidence / deviation) still ABORTS: an enclave whose signed payload disagrees
|
|
227
|
+
* with the on-chain feed config is a red flag, not a liveness blip. Bad signature,
|
|
228
|
+
* malformed batch, and a future timestamp always abort.
|
|
222
229
|
*
|
|
223
230
|
* Every gate is identical to `feed_batch_item_latest`; only the abort-vs-abstain
|
|
224
|
-
* disposition of the
|
|
225
|
-
* collector rather than a fresh single-rule one.
|
|
231
|
+
* disposition of the freshness + replay gates differs, and the sink is the
|
|
232
|
+
* caller's collector rather than a fresh single-rule one.
|
|
226
233
|
*/
|
|
227
234
|
export declare function collectBatchLatest(options: CollectBatchLatestOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
235
|
+
export interface FeedSingleWithProofArguments {
|
|
236
|
+
oracleObj: RawTransactionArgument<string>;
|
|
237
|
+
config: RawTransactionArgument<string>;
|
|
238
|
+
enclaveConfig: RawTransactionArgument<string>;
|
|
239
|
+
enclave: RawTransactionArgument<string>;
|
|
240
|
+
timestampMs: RawTransactionArgument<number | bigint>;
|
|
241
|
+
item: TransactionArgument;
|
|
242
|
+
proof: RawTransactionArgument<Array<Array<number>>>;
|
|
243
|
+
sig: RawTransactionArgument<Array<number>>;
|
|
244
|
+
}
|
|
245
|
+
export interface FeedSingleWithProofOptions {
|
|
246
|
+
package?: string;
|
|
247
|
+
arguments: FeedSingleWithProofArguments | [
|
|
248
|
+
oracleObj: RawTransactionArgument<string>,
|
|
249
|
+
config: RawTransactionArgument<string>,
|
|
250
|
+
enclaveConfig: RawTransactionArgument<string>,
|
|
251
|
+
enclave: RawTransactionArgument<string>,
|
|
252
|
+
timestampMs: RawTransactionArgument<number | bigint>,
|
|
253
|
+
item: TransactionArgument,
|
|
254
|
+
proof: RawTransactionArgument<Array<Array<number>>>,
|
|
255
|
+
sig: RawTransactionArgument<Array<number>>
|
|
256
|
+
];
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Streaming per-symbol sibling of `feed_batch_latest`. Verifies ONE enclave
|
|
260
|
+
* signature over a Merkle `root`, checks `item` is a leaf of that root via
|
|
261
|
+
* `proof`, then runs the identical per-item gates + `oracle::aggregate`. Use for a
|
|
262
|
+
* WaterxRule-only aggregator; for a Pyth-coexisting aggregator use
|
|
263
|
+
* `collect_single_with_proof`.
|
|
264
|
+
*/
|
|
265
|
+
export declare function feedSingleWithProof(options: FeedSingleWithProofOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
266
|
+
export interface CollectSingleWithProofArguments {
|
|
267
|
+
collector: TransactionArgument;
|
|
268
|
+
config: RawTransactionArgument<string>;
|
|
269
|
+
enclaveConfig: RawTransactionArgument<string>;
|
|
270
|
+
enclave: RawTransactionArgument<string>;
|
|
271
|
+
timestampMs: RawTransactionArgument<number | bigint>;
|
|
272
|
+
item: TransactionArgument;
|
|
273
|
+
proof: RawTransactionArgument<Array<Array<number>>>;
|
|
274
|
+
sig: RawTransactionArgument<Array<number>>;
|
|
275
|
+
}
|
|
276
|
+
export interface CollectSingleWithProofOptions {
|
|
277
|
+
package?: string;
|
|
278
|
+
arguments: CollectSingleWithProofArguments | [
|
|
279
|
+
collector: TransactionArgument,
|
|
280
|
+
config: RawTransactionArgument<string>,
|
|
281
|
+
enclaveConfig: RawTransactionArgument<string>,
|
|
282
|
+
enclave: RawTransactionArgument<string>,
|
|
283
|
+
timestampMs: RawTransactionArgument<number | bigint>,
|
|
284
|
+
item: TransactionArgument,
|
|
285
|
+
proof: RawTransactionArgument<Array<Array<number>>>,
|
|
286
|
+
sig: RawTransactionArgument<Array<number>>
|
|
287
|
+
];
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Collect-only sibling of `feed_single_with_proof` for the dual-rule latest path
|
|
291
|
+
* (WaterX alongside Pyth on one aggregator), mirroring `collect_batch_latest`:
|
|
292
|
+
* verifies root + proof, feeds the leaf into the caller's `PriceCollector` WITHOUT
|
|
293
|
+
* calling `oracle::aggregate`. Abort vs abstain matches `collect_batch_latest`
|
|
294
|
+
* exactly — a config/integrity mismatch aborts, a freshness miss abstains so Pyth
|
|
295
|
+
* can cover a lagging TEE.
|
|
296
|
+
*/
|
|
297
|
+
export declare function collectSingleWithProof(options: CollectSingleWithProofOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
228
298
|
export interface QuoteForTimestampArguments {
|
|
229
299
|
config: RawTransactionArgument<string>;
|
|
230
300
|
enclaveConfig: RawTransactionArgument<string>;
|
|
@@ -421,6 +491,27 @@ export interface BatchPriceIntentOptions {
|
|
|
421
491
|
];
|
|
422
492
|
}
|
|
423
493
|
export declare function batchPriceIntent(options?: BatchPriceIntentOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
494
|
+
export interface MerkleRootIntentOptions {
|
|
495
|
+
package?: string;
|
|
496
|
+
arguments?: [
|
|
497
|
+
];
|
|
498
|
+
}
|
|
499
|
+
export declare function merkleRootIntent(options?: MerkleRootIntentOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
500
|
+
export interface LeafHashOfArguments {
|
|
501
|
+
item: TransactionArgument;
|
|
502
|
+
}
|
|
503
|
+
export interface LeafHashOfOptions {
|
|
504
|
+
package?: string;
|
|
505
|
+
arguments: LeafHashOfArguments | [
|
|
506
|
+
item: TransactionArgument
|
|
507
|
+
];
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* The keccak256 leaf hash for `item` — `keccak256(0x00 || BCS(item))`. Exposed so
|
|
511
|
+
* the off-chain builder / SDK can be pinned against the on-chain encoding in a
|
|
512
|
+
* cross-implementation golden test.
|
|
513
|
+
*/
|
|
514
|
+
export declare function leafHashOf(options: LeafHashOfOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
424
515
|
export interface MaxBatchSizeOptions {
|
|
425
516
|
package?: string;
|
|
426
517
|
arguments?: [
|
|
@@ -717,6 +808,48 @@ export interface SourceGataUsdtPerpWsOptions {
|
|
|
717
808
|
];
|
|
718
809
|
}
|
|
719
810
|
export declare function sourceGataUsdtPerpWs(options?: SourceGataUsdtPerpWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
811
|
+
export interface SourceBybitSpotWsOptions {
|
|
812
|
+
package?: string;
|
|
813
|
+
arguments?: [
|
|
814
|
+
];
|
|
815
|
+
}
|
|
816
|
+
export declare function sourceBybitSpotWs(options?: SourceBybitSpotWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
817
|
+
export interface SourceXstockEquityRestOptions {
|
|
818
|
+
package?: string;
|
|
819
|
+
arguments?: [
|
|
820
|
+
];
|
|
821
|
+
}
|
|
822
|
+
export declare function sourceXstockEquityRest(options?: SourceXstockEquityRestOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
823
|
+
export interface SourceOkxSpotWsOptions {
|
|
824
|
+
package?: string;
|
|
825
|
+
arguments?: [
|
|
826
|
+
];
|
|
827
|
+
}
|
|
828
|
+
export declare function sourceOkxSpotWs(options?: SourceOkxSpotWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
829
|
+
export interface SourceHyperliquidPerpWsOptions {
|
|
830
|
+
package?: string;
|
|
831
|
+
arguments?: [
|
|
832
|
+
];
|
|
833
|
+
}
|
|
834
|
+
export declare function sourceHyperliquidPerpWs(options?: SourceHyperliquidPerpWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
835
|
+
export interface SourceGateioSpotWsOptions {
|
|
836
|
+
package?: string;
|
|
837
|
+
arguments?: [
|
|
838
|
+
];
|
|
839
|
+
}
|
|
840
|
+
export declare function sourceGateioSpotWs(options?: SourceGateioSpotWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
841
|
+
export interface SourceKrakenSpotWsOptions {
|
|
842
|
+
package?: string;
|
|
843
|
+
arguments?: [
|
|
844
|
+
];
|
|
845
|
+
}
|
|
846
|
+
export declare function sourceKrakenSpotWs(options?: SourceKrakenSpotWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
847
|
+
export interface SourcePythLazerWsOptions {
|
|
848
|
+
package?: string;
|
|
849
|
+
arguments?: [
|
|
850
|
+
];
|
|
851
|
+
}
|
|
852
|
+
export declare function sourcePythLazerWs(options?: SourcePythLazerWsOptions): (tx: Transaction) => import("@mysten/sui/transactions").TransactionResult;
|
|
720
853
|
export interface MethodDirectOptions {
|
|
721
854
|
package?: string;
|
|
722
855
|
arguments?: [
|
|
@@ -36,9 +36,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.BatchLatestUpdated = exports.HistoricalPriceVerified = exports.SignedTsHwmKey = exports.Config = exports.VerifiedPrice = exports.FeedConfig = exports.BatchPricePayload = exports.BatchPriceItem = exports.PricePayload = exports.WaterxRule = exports.WATERX_RULE = void 0;
|
|
39
|
+
exports.BatchLatestUpdated = exports.HistoricalPriceVerified = exports.SignedTsHwmKey = exports.Config = exports.VerifiedPrice = exports.FeedConfig = exports.MerkleRoot = exports.BatchPricePayload = exports.BatchPriceItem = exports.PricePayload = exports.WaterxRule = exports.WATERX_RULE = void 0;
|
|
40
40
|
exports.feedBatchLatest = feedBatchLatest;
|
|
41
41
|
exports.collectBatchLatest = collectBatchLatest;
|
|
42
|
+
exports.feedSingleWithProof = feedSingleWithProof;
|
|
43
|
+
exports.collectSingleWithProof = collectSingleWithProof;
|
|
42
44
|
exports.quoteForTimestamp = quoteForTimestamp;
|
|
43
45
|
exports.destroyVerifiedPrice = destroyVerifiedPrice;
|
|
44
46
|
exports.collectVerifiedPrice = collectVerifiedPrice;
|
|
@@ -50,6 +52,8 @@ exports.newBatchItem = newBatchItem;
|
|
|
50
52
|
exports.pushBatchItem = pushBatchItem;
|
|
51
53
|
exports.feedConfig = feedConfig;
|
|
52
54
|
exports.batchPriceIntent = batchPriceIntent;
|
|
55
|
+
exports.merkleRootIntent = merkleRootIntent;
|
|
56
|
+
exports.leafHashOf = leafHashOf;
|
|
53
57
|
exports.maxBatchSize = maxBatchSize;
|
|
54
58
|
exports.batchItems = batchItems;
|
|
55
59
|
exports.batchItemSymbol = batchItemSymbol;
|
|
@@ -82,6 +86,13 @@ exports.sourceBinanceUsdmPerpWs = sourceBinanceUsdmPerpWs;
|
|
|
82
86
|
exports.sourceBybitLinearPerpWs = sourceBybitLinearPerpWs;
|
|
83
87
|
exports.sourceGateioUsdtPerpWs = sourceGateioUsdtPerpWs;
|
|
84
88
|
exports.sourceGataUsdtPerpWs = sourceGataUsdtPerpWs;
|
|
89
|
+
exports.sourceBybitSpotWs = sourceBybitSpotWs;
|
|
90
|
+
exports.sourceXstockEquityRest = sourceXstockEquityRest;
|
|
91
|
+
exports.sourceOkxSpotWs = sourceOkxSpotWs;
|
|
92
|
+
exports.sourceHyperliquidPerpWs = sourceHyperliquidPerpWs;
|
|
93
|
+
exports.sourceGateioSpotWs = sourceGateioSpotWs;
|
|
94
|
+
exports.sourceKrakenSpotWs = sourceKrakenSpotWs;
|
|
95
|
+
exports.sourcePythLazerWs = sourcePythLazerWs;
|
|
85
96
|
exports.methodDirect = methodDirect;
|
|
86
97
|
exports.methodMedian = methodMedian;
|
|
87
98
|
exports.methodConfidence = methodConfidence;
|
|
@@ -132,6 +143,9 @@ exports.BatchPriceItem = new index_ts_1.MoveStruct({ name: `${$moduleName}::Batc
|
|
|
132
143
|
exports.BatchPricePayload = new index_ts_1.MoveStruct({ name: `${$moduleName}::BatchPricePayload`, fields: {
|
|
133
144
|
items: bcs_1.bcs.vector(exports.BatchPriceItem)
|
|
134
145
|
} });
|
|
146
|
+
exports.MerkleRoot = new index_ts_1.MoveStruct({ name: `${$moduleName}::MerkleRoot`, fields: {
|
|
147
|
+
root: bcs_1.bcs.vector(bcs_1.bcs.u8())
|
|
148
|
+
} });
|
|
135
149
|
exports.FeedConfig = new index_ts_1.MoveStruct({ name: `${$moduleName}::FeedConfig`, fields: {
|
|
136
150
|
ticker: bcs_1.bcs.string(),
|
|
137
151
|
sources: bcs_1.bcs.vector(bcs_1.bcs.u64()),
|
|
@@ -217,15 +231,17 @@ function feedBatchLatest(options) {
|
|
|
217
231
|
* and so aborts on any stale item, this path runs alongside Pyth/Supra. To let
|
|
218
232
|
* those cover a lagging TEE — the blast-radius bound in the GCP ADR — a
|
|
219
233
|
* _freshness_ miss ABSTAINS (records `none`, which `aggregator::remove_outliers`
|
|
220
|
-
* drops before the `weight_threshold` fail-closed check)
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
234
|
+
* drops before the `weight_threshold` fail-closed check), and so does a _replayed_
|
|
235
|
+
* signed timestamp (the chain already accepted that snapshot — the on-chain price
|
|
236
|
+
* is at least as fresh, and two concurrent keeper PTBs sharing one envelope must
|
|
237
|
+
* not kill each other). A _config/integrity_ mismatch (source / ticker / method /
|
|
238
|
+
* confidence / deviation) still ABORTS: an enclave whose signed payload disagrees
|
|
239
|
+
* with the on-chain feed config is a red flag, not a liveness blip. Bad signature,
|
|
240
|
+
* malformed batch, and a future timestamp always abort.
|
|
225
241
|
*
|
|
226
242
|
* Every gate is identical to `feed_batch_item_latest`; only the abort-vs-abstain
|
|
227
|
-
* disposition of the
|
|
228
|
-
* collector rather than a fresh single-rule one.
|
|
243
|
+
* disposition of the freshness + replay gates differs, and the sink is the
|
|
244
|
+
* caller's collector rather than a fresh single-rule one.
|
|
229
245
|
*/
|
|
230
246
|
function collectBatchLatest(options) {
|
|
231
247
|
const packageAddress = options.package ?? '@waterx/rule';
|
|
@@ -247,6 +263,63 @@ function collectBatchLatest(options) {
|
|
|
247
263
|
arguments: (0, index_ts_1.normalizeMoveArguments)(options.arguments, argumentsTypes, parameterNames),
|
|
248
264
|
});
|
|
249
265
|
}
|
|
266
|
+
/**
|
|
267
|
+
* Streaming per-symbol sibling of `feed_batch_latest`. Verifies ONE enclave
|
|
268
|
+
* signature over a Merkle `root`, checks `item` is a leaf of that root via
|
|
269
|
+
* `proof`, then runs the identical per-item gates + `oracle::aggregate`. Use for a
|
|
270
|
+
* WaterxRule-only aggregator; for a Pyth-coexisting aggregator use
|
|
271
|
+
* `collect_single_with_proof`.
|
|
272
|
+
*/
|
|
273
|
+
function feedSingleWithProof(options) {
|
|
274
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
275
|
+
const argumentsTypes = [
|
|
276
|
+
null,
|
|
277
|
+
null,
|
|
278
|
+
'0x2::clock::Clock',
|
|
279
|
+
null,
|
|
280
|
+
null,
|
|
281
|
+
'u64',
|
|
282
|
+
null,
|
|
283
|
+
'vector<vector<u8>>',
|
|
284
|
+
'vector<u8>'
|
|
285
|
+
];
|
|
286
|
+
const parameterNames = ["oracleObj", "config", "enclaveConfig", "enclave", "timestampMs", "item", "proof", "sig"];
|
|
287
|
+
return (tx) => tx.moveCall({
|
|
288
|
+
package: packageAddress,
|
|
289
|
+
module: 'waterx_rule',
|
|
290
|
+
function: 'feed_single_with_proof',
|
|
291
|
+
arguments: (0, index_ts_1.normalizeMoveArguments)(options.arguments, argumentsTypes, parameterNames),
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Collect-only sibling of `feed_single_with_proof` for the dual-rule latest path
|
|
296
|
+
* (WaterX alongside Pyth on one aggregator), mirroring `collect_batch_latest`:
|
|
297
|
+
* verifies root + proof, feeds the leaf into the caller's `PriceCollector` WITHOUT
|
|
298
|
+
* calling `oracle::aggregate`. Abort vs abstain matches `collect_batch_latest`
|
|
299
|
+
* exactly — a config/integrity mismatch aborts, a freshness miss abstains so Pyth
|
|
300
|
+
* can cover a lagging TEE.
|
|
301
|
+
*/
|
|
302
|
+
function collectSingleWithProof(options) {
|
|
303
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
304
|
+
const argumentsTypes = [
|
|
305
|
+
null,
|
|
306
|
+
null,
|
|
307
|
+
'0x2::clock::Clock',
|
|
308
|
+
null,
|
|
309
|
+
null,
|
|
310
|
+
'u64',
|
|
311
|
+
null,
|
|
312
|
+
'vector<vector<u8>>',
|
|
313
|
+
'vector<u8>'
|
|
314
|
+
];
|
|
315
|
+
const parameterNames = ["collector", "config", "enclaveConfig", "enclave", "timestampMs", "item", "proof", "sig"];
|
|
316
|
+
return (tx) => tx.moveCall({
|
|
317
|
+
package: packageAddress,
|
|
318
|
+
module: 'waterx_rule',
|
|
319
|
+
function: 'collect_single_with_proof',
|
|
320
|
+
arguments: (0, index_ts_1.normalizeMoveArguments)(options.arguments, argumentsTypes, parameterNames),
|
|
321
|
+
});
|
|
322
|
+
}
|
|
250
323
|
/**
|
|
251
324
|
* Verifies a historical quote without touching `waterx_oracle`.
|
|
252
325
|
*
|
|
@@ -438,6 +511,32 @@ function batchPriceIntent(options = {}) {
|
|
|
438
511
|
function: 'batch_price_intent',
|
|
439
512
|
});
|
|
440
513
|
}
|
|
514
|
+
function merkleRootIntent(options = {}) {
|
|
515
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
516
|
+
return (tx) => tx.moveCall({
|
|
517
|
+
package: packageAddress,
|
|
518
|
+
module: 'waterx_rule',
|
|
519
|
+
function: 'merkle_root_intent',
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* The keccak256 leaf hash for `item` — `keccak256(0x00 || BCS(item))`. Exposed so
|
|
524
|
+
* the off-chain builder / SDK can be pinned against the on-chain encoding in a
|
|
525
|
+
* cross-implementation golden test.
|
|
526
|
+
*/
|
|
527
|
+
function leafHashOf(options) {
|
|
528
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
529
|
+
const argumentsTypes = [
|
|
530
|
+
null
|
|
531
|
+
];
|
|
532
|
+
const parameterNames = ["item"];
|
|
533
|
+
return (tx) => tx.moveCall({
|
|
534
|
+
package: packageAddress,
|
|
535
|
+
module: 'waterx_rule',
|
|
536
|
+
function: 'leaf_hash_of',
|
|
537
|
+
arguments: (0, index_ts_1.normalizeMoveArguments)(options.arguments, argumentsTypes, parameterNames),
|
|
538
|
+
});
|
|
539
|
+
}
|
|
441
540
|
function maxBatchSize(options = {}) {
|
|
442
541
|
const packageAddress = options.package ?? '@waterx/rule';
|
|
443
542
|
return (tx) => tx.moveCall({
|
|
@@ -824,6 +923,62 @@ function sourceGataUsdtPerpWs(options = {}) {
|
|
|
824
923
|
function: 'source_gata_usdt_perp_ws',
|
|
825
924
|
});
|
|
826
925
|
}
|
|
926
|
+
function sourceBybitSpotWs(options = {}) {
|
|
927
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
928
|
+
return (tx) => tx.moveCall({
|
|
929
|
+
package: packageAddress,
|
|
930
|
+
module: 'waterx_rule',
|
|
931
|
+
function: 'source_bybit_spot_ws',
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
function sourceXstockEquityRest(options = {}) {
|
|
935
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
936
|
+
return (tx) => tx.moveCall({
|
|
937
|
+
package: packageAddress,
|
|
938
|
+
module: 'waterx_rule',
|
|
939
|
+
function: 'source_xstock_equity_rest',
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
function sourceOkxSpotWs(options = {}) {
|
|
943
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
944
|
+
return (tx) => tx.moveCall({
|
|
945
|
+
package: packageAddress,
|
|
946
|
+
module: 'waterx_rule',
|
|
947
|
+
function: 'source_okx_spot_ws',
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
function sourceHyperliquidPerpWs(options = {}) {
|
|
951
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
952
|
+
return (tx) => tx.moveCall({
|
|
953
|
+
package: packageAddress,
|
|
954
|
+
module: 'waterx_rule',
|
|
955
|
+
function: 'source_hyperliquid_perp_ws',
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
function sourceGateioSpotWs(options = {}) {
|
|
959
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
960
|
+
return (tx) => tx.moveCall({
|
|
961
|
+
package: packageAddress,
|
|
962
|
+
module: 'waterx_rule',
|
|
963
|
+
function: 'source_gateio_spot_ws',
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
function sourceKrakenSpotWs(options = {}) {
|
|
967
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
968
|
+
return (tx) => tx.moveCall({
|
|
969
|
+
package: packageAddress,
|
|
970
|
+
module: 'waterx_rule',
|
|
971
|
+
function: 'source_kraken_spot_ws',
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
function sourcePythLazerWs(options = {}) {
|
|
975
|
+
const packageAddress = options.package ?? '@waterx/rule';
|
|
976
|
+
return (tx) => tx.moveCall({
|
|
977
|
+
package: packageAddress,
|
|
978
|
+
module: 'waterx_rule',
|
|
979
|
+
function: 'source_pyth_lazer_ws',
|
|
980
|
+
});
|
|
981
|
+
}
|
|
827
982
|
function methodDirect(options = {}) {
|
|
828
983
|
const packageAddress = options.package ?? '@waterx/rule';
|
|
829
984
|
return (tx) => tx.moveCall({
|
|
@@ -26,7 +26,7 @@ import type { Transaction, TransactionArgument } from "@mysten/sui/transactions"
|
|
|
26
26
|
import type { OracleHost } from "./host.ts";
|
|
27
27
|
import type { OracleSource, PriceUpdateRule, UpdateDataProvider } from "./price-update-rule.ts";
|
|
28
28
|
import { type OracleFeeSource, type PythCache } from "./pyth.ts";
|
|
29
|
-
import { type WaterxSignedEnvelope } from "./rules/waterx-rule.ts";
|
|
29
|
+
import { type WaterxSignedEnvelope, type WaterxSignedLeaf } from "./rules/waterx-rule.ts";
|
|
30
30
|
/**
|
|
31
31
|
* Aggregate one ticker's price into the shared `Oracle`: build a collector, feed
|
|
32
32
|
* every rule the ticker is configured for, then `aggregate`.
|
|
@@ -57,6 +57,9 @@ export declare function aggregateTicker(tx: Transaction, host: OracleHost, args:
|
|
|
57
57
|
ticker: string;
|
|
58
58
|
priceInfoObjectId?: string;
|
|
59
59
|
lazerUpdate?: TransactionArgument;
|
|
60
|
+
/** This ticker's signed Merkle leaf — the default waterx shape. */
|
|
61
|
+
waterxLeaf?: WaterxSignedLeaf;
|
|
62
|
+
/** Batch envelope covering this ticker — the fallback waterx shape. */
|
|
60
63
|
waterxEnvelope?: WaterxSignedEnvelope;
|
|
61
64
|
}): void;
|
|
62
65
|
/**
|
|
@@ -120,17 +120,25 @@ function aggregateTicker(tx, host, args) {
|
|
|
120
120
|
(0, pyth_lazer_rule_ts_1.feedLazerRule)(tx, host, collector, args.lazerUpdate);
|
|
121
121
|
fed = true;
|
|
122
122
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
// header
|
|
123
|
+
// One waterx leg at most, and the leaf shape wins: both entries record the
|
|
124
|
+
// same per-symbol signed-timestamp high-water mark and feed the same rule
|
|
125
|
+
// witness into this collector, so emitting both would make the second one
|
|
126
|
+
// abstain on its own predecessor's mark for no gain. `refreshOraclePrices`
|
|
127
|
+
// only ever supplies one; a caller that passes both gets the cheaper leg.
|
|
128
|
+
if (args.waterxLeaf !== undefined) {
|
|
129
|
+
// waterx_rule::collect_single_with_proof re-derives the snapshot root from
|
|
130
|
+
// this leaf + its proof, verifies the enclave signature over that root, and
|
|
131
|
+
// feeds the price. If the ticker's aggregator does not (yet) weight
|
|
132
|
+
// `WaterxRule`, the contribution is silently dropped on-chain — feeding
|
|
133
|
+
// ahead of the weight migration is safe. See WaterxRule's module header for
|
|
134
|
+
// the abort-vs-abstain split.
|
|
135
|
+
(0, waterx_rule_ts_1.feedWaterxRuleWithProof)(tx, host, collector, args.waterxLeaf);
|
|
136
|
+
fed = true;
|
|
137
|
+
}
|
|
138
|
+
else if (args.waterxEnvelope !== undefined) {
|
|
139
|
+
// Fallback shape: collect_batch_latest re-verifies the WHOLE batch
|
|
140
|
+
// signature (every item rebuilt in-PTB) and feeds this collector's symbol
|
|
141
|
+
// out of it. Only reached against a quote-center with no leaf route.
|
|
134
142
|
(0, waterx_rule_ts_1.feedWaterxRule)(tx, host, collector, args.waterxEnvelope);
|
|
135
143
|
fed = true;
|
|
136
144
|
}
|
|
@@ -223,11 +231,11 @@ async function refreshOraclePrices(tx, host, tickers, opts = {}) {
|
|
|
223
231
|
if (tickers.length === 0)
|
|
224
232
|
return;
|
|
225
233
|
// Dedupe the caller's list (order-preserving): a repeated ticker would
|
|
226
|
-
// otherwise aggregate TWICE in this one PTB — wasted gas for every rule,
|
|
227
|
-
//
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
//
|
|
234
|
+
// otherwise aggregate TWICE in this one PTB — wasted gas for every rule, and
|
|
235
|
+
// under waterx the second collect would be dead weight on top of that: the
|
|
236
|
+
// on-chain per-symbol replay guard (F-014) sees its own predecessor's
|
|
237
|
+
// high-water mark from earlier in this same transaction and abstains, so the
|
|
238
|
+
// repeat pays full verification cost to contribute nothing.
|
|
231
239
|
tickers = [...new Set(tickers)];
|
|
232
240
|
// price_info_object lookup for every ticker with a pyth_rule.feeds entry —
|
|
233
241
|
// needed by aggregateTicker's (unchanged) Pyth feed step below regardless of
|
|
@@ -298,10 +306,12 @@ async function refreshOraclePrices(tx, host, tickers, opts = {}) {
|
|
|
298
306
|
// leg needs per-ticker data from its update leg must decide its carry here
|
|
299
307
|
// — falling through silently would starve its weighted tickers on-chain.
|
|
300
308
|
const lazerUpdateByTicker = new Map();
|
|
301
|
-
// Signed
|
|
302
|
-
//
|
|
303
|
-
//
|
|
304
|
-
//
|
|
309
|
+
// Signed waterx data per served ticker — a per-symbol Merkle leaf normally, a
|
|
310
|
+
// shared batch envelope on the fallback shape. Unlike Lazer's shared PTB
|
|
311
|
+
// handle, waterx's verify+feed is bundled into the per-ticker collect call, so
|
|
312
|
+
// its `buildUpdateCalls` emits nothing and the signed data is carried straight
|
|
313
|
+
// from the group's fetched data.
|
|
314
|
+
const waterxLeafByTicker = new Map();
|
|
305
315
|
const waterxEnvelopeByTicker = new Map();
|
|
306
316
|
for (const [i, group] of groups.entries()) {
|
|
307
317
|
const data = dataByGroup[i] ?? null;
|
|
@@ -325,12 +335,45 @@ async function refreshOraclePrices(tx, host, tickers, opts = {}) {
|
|
|
325
335
|
break;
|
|
326
336
|
case "waterx_rule": {
|
|
327
337
|
// waterx_rule emits no shared handle (verify+feed is bundled into the
|
|
328
|
-
// per-ticker
|
|
329
|
-
//
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
338
|
+
// per-ticker collect call), so the signed data is carried straight from
|
|
339
|
+
// this group's fetched data to the feed leg below. Leaves are per-symbol
|
|
340
|
+
// and indexed BY symbol — never fanned out across the group like the
|
|
341
|
+
// envelope, since each leaf only verifies for its own symbol
|
|
342
|
+
// (`ECollectorSymbolMismatch`). A leaf for a symbol outside this group is
|
|
343
|
+
// dropped rather than carried: the feed leg is keyed by ticker anyway.
|
|
344
|
+
const leaves = (0, waterx_rule_ts_1.waterxLeavesOf)(data);
|
|
345
|
+
// `length > 0` matters: `{ leaves: [] }` is shape-valid (`[].every(...)`
|
|
346
|
+
// is `true`), so a bare truthiness test would TAKE this branch, carry
|
|
347
|
+
// nothing, and `break` past the envelope branch below.
|
|
348
|
+
if (leaves && leaves.length > 0) {
|
|
349
|
+
const served = new Set(group.tickers);
|
|
350
|
+
for (const leaf of leaves) {
|
|
351
|
+
if (served.has(leaf.symbol))
|
|
352
|
+
waterxLeafByTicker.set(leaf.symbol, leaf);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
const envelope = (0, waterx_rule_ts_1.waterxEnvelopeOf)(data);
|
|
357
|
+
if (envelope) {
|
|
358
|
+
for (const ticker of group.tickers)
|
|
359
|
+
waterxEnvelopeByTicker.set(ticker, envelope);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// Fail the BUILD, not the chain. Both suppliers of `data` already
|
|
363
|
+
// guarantee full coverage — the live fetch through `assertCoverage`, a
|
|
364
|
+
// cached payload through `narrowUpdateData` (which returns `null`, i.e.
|
|
365
|
+
// "miss → live fetch", rather than a partial) — so reaching here with a
|
|
366
|
+
// ticker uncarried means one of those invariants broke. Left alone it
|
|
367
|
+
// emits a collector with no waterx leg, which surfaces MUCH later as an
|
|
368
|
+
// opaque on-chain `EMissingPriceSource` (or, if the rule is unweighted
|
|
369
|
+
// for that ticker, as a silently thinner weighted set). This names the
|
|
370
|
+
// tickers instead.
|
|
371
|
+
const uncarried = group.tickers.filter((t) => !waterxLeafByTicker.has(t) && !waterxEnvelopeByTicker.has(t));
|
|
372
|
+
if (uncarried.length > 0) {
|
|
373
|
+
throw new Error(`waterx_rule update data carries no signed price for ticker(s): ${uncarried.join(", ")}. ` +
|
|
374
|
+
"Expected one signed leaf per ticker (or a batch envelope covering all of " +
|
|
375
|
+
"them) — a payload that serves none of a group's tickers must be reported " +
|
|
376
|
+
"as a miss, not fed.");
|
|
334
377
|
}
|
|
335
378
|
break;
|
|
336
379
|
}
|
|
@@ -346,6 +389,7 @@ async function refreshOraclePrices(tx, host, tickers, opts = {}) {
|
|
|
346
389
|
ticker,
|
|
347
390
|
priceInfoObjectId: priceInfoByTicker.get(ticker),
|
|
348
391
|
lazerUpdate: lazerUpdateByTicker.get(ticker),
|
|
392
|
+
waterxLeaf: waterxLeafByTicker.get(ticker),
|
|
349
393
|
waterxEnvelope: waterxEnvelopeByTicker.get(ticker),
|
|
350
394
|
});
|
|
351
395
|
}
|
|
@@ -96,7 +96,8 @@ export interface WaterxRuleFeedEntry {
|
|
|
96
96
|
/**
|
|
97
97
|
* `waterx_rule` deployment entry — the first-party Nautilus-TEE oracle rule.
|
|
98
98
|
* Read by `WaterxRule` (`rules/waterx-rule.ts`): `feeds` for ticker support,
|
|
99
|
-
* `config`/`enclave_config`/`enclave` for the
|
|
99
|
+
* `config`/`enclave_config`/`enclave` for the collect call
|
|
100
|
+
* (`collect_single_with_proof`, or `collect_batch_latest` on the fallback shape),
|
|
100
101
|
* `published_at` for the package address. The off-chain signed price is pulled
|
|
101
102
|
* from the quote-center (endpoint from the rule-owned `WATERX_INFRA` table in
|
|
102
103
|
* `rules/waterx-rule.ts`), not this JSON.
|
|
@@ -201,7 +202,7 @@ export interface WaterxAccessConfig {
|
|
|
201
202
|
* Quote-center base URL override (`waterxEndpoint` create option). A base
|
|
202
203
|
* PATH is preserved — the rule appends via `joinEndpointPath`, so
|
|
203
204
|
* `https://app.example/api/quote-center` resolves to
|
|
204
|
-
* `…/api/quote-center/v1/quotes/
|
|
205
|
+
* `…/api/quote-center/v1/quotes/leaves` and a proxy route is not rewritten
|
|
205
206
|
* away. A trailing slash is trimmed.
|
|
206
207
|
*/
|
|
207
208
|
endpoint?: string;
|
|
@@ -29,8 +29,8 @@ export { PythCoreRule } from "./rules/pyth-core-rule.ts";
|
|
|
29
29
|
export type { PythCoreUpdatePayload } from "./rules/pyth-core-rule.ts";
|
|
30
30
|
export { PythLazerRule, LazerApiKeyMissingError } from "./rules/pyth-lazer-rule.ts";
|
|
31
31
|
export type { PythLazerUpdatePayload } from "./rules/pyth-lazer-rule.ts";
|
|
32
|
-
export { WaterxRule, parseSignedEnvelope, BATCH_PRICE_INTENT, WATERX_INFRA, waterxQuoteCenterEndpoint, waterxEnvelopeOf, } from "./rules/waterx-rule.ts";
|
|
33
|
-
export type { WaterxUpdatePayload, WaterxSignedEnvelope, WaterxBatchItem, } from "./rules/waterx-rule.ts";
|
|
32
|
+
export { WaterxRule, parseSignedEnvelope, parseSignedLeaves, BATCH_PRICE_INTENT, MERKLE_ROOT_INTENT, WATERX_INFRA, waterxQuoteCenterEndpoint, waterxLeavesOf, waterxEnvelopeOf, } from "./rules/waterx-rule.ts";
|
|
33
|
+
export type { WaterxUpdatePayload, WaterxLeafPayload, WaterxEnvelopePayload, WaterxSignedEnvelope, WaterxSignedLeaf, WaterxBatchItem, } from "./rules/waterx-rule.ts";
|
|
34
34
|
export { OracleSourceNotImplementedError, resolveOracleRule } from "./rule-registry.ts";
|
|
35
35
|
export { aggregateTicker, aggregateTickerWithPyth, aggregateTickerWithConstant, refreshOraclePrices, } from "./aggregate.ts";
|
|
36
36
|
export { openPythSponsorFund, reimbursePythSponsor } from "./rules/sponsor.ts";
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* rules that consume it are separate concerns.
|
|
18
18
|
*/
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.reimbursePythSponsor = exports.openPythSponsorFund = exports.refreshOraclePrices = exports.aggregateTickerWithConstant = exports.aggregateTickerWithPyth = exports.aggregateTicker = exports.resolveOracleRule = exports.OracleSourceNotImplementedError = exports.waterxEnvelopeOf = exports.waterxQuoteCenterEndpoint = exports.WATERX_INFRA = exports.BATCH_PRICE_INTENT = exports.parseSignedEnvelope = exports.WaterxRule = exports.LazerApiKeyMissingError = exports.PythLazerRule = exports.PythCoreRule = exports.resolveHermesReadEndpoint = exports.resolveOracleReadPlan = exports.parseOracleSourceList = exports.isOracleSource = exports.ORACLE_SOURCES = exports.OracleFeeSourceUnavailableError = exports.MISSING_FEED_MEMO_TTL_MS = exports.HermesEndpointRejectedAllFeedsError = exports.updatePythPrices = exports.PYTH_PRO_HERMES_ENDPOINT = exports.pythProHermesEndpoint = exports.pythCoreHermesEndpoint = exports.buildPythPriceUpdateCalls = exports.probeMissingFeeds = exports.endpointSupportedFeedIds = exports.fetchPriceFeedsUpdateData = exports.PythCache = exports.joinEndpointPath = exports.fetchWithPolicy = exports.FetchPolicyError = void 0;
|
|
20
|
+
exports.reimbursePythSponsor = exports.openPythSponsorFund = exports.refreshOraclePrices = exports.aggregateTickerWithConstant = exports.aggregateTickerWithPyth = exports.aggregateTicker = exports.resolveOracleRule = exports.OracleSourceNotImplementedError = exports.waterxEnvelopeOf = exports.waterxLeavesOf = exports.waterxQuoteCenterEndpoint = exports.WATERX_INFRA = exports.MERKLE_ROOT_INTENT = exports.BATCH_PRICE_INTENT = exports.parseSignedLeaves = exports.parseSignedEnvelope = exports.WaterxRule = exports.LazerApiKeyMissingError = exports.PythLazerRule = exports.PythCoreRule = exports.resolveHermesReadEndpoint = exports.resolveOracleReadPlan = exports.parseOracleSourceList = exports.isOracleSource = exports.ORACLE_SOURCES = exports.OracleFeeSourceUnavailableError = exports.MISSING_FEED_MEMO_TTL_MS = exports.HermesEndpointRejectedAllFeedsError = exports.updatePythPrices = exports.PYTH_PRO_HERMES_ENDPOINT = exports.pythProHermesEndpoint = exports.pythCoreHermesEndpoint = exports.buildPythPriceUpdateCalls = exports.probeMissingFeeds = exports.endpointSupportedFeedIds = exports.fetchPriceFeedsUpdateData = exports.PythCache = exports.joinEndpointPath = exports.fetchWithPolicy = exports.FetchPolicyError = void 0;
|
|
21
21
|
// Shared fetch resilience wrapper — `FetchPolicyError` is re-exported (not
|
|
22
22
|
// just the type) so a consumer (e.g. a BE prefetch cache) can `instanceof`
|
|
23
23
|
// it off the failure `fetchPriceFeedsUpdateData` / `PythLazerRule` /
|
|
@@ -85,16 +85,21 @@ Object.defineProperty(exports, "PythLazerRule", { enumerable: true, get: functio
|
|
|
85
85
|
Object.defineProperty(exports, "LazerApiKeyMissingError", { enumerable: true, get: function () { return pyth_lazer_rule_ts_1.LazerApiKeyMissingError; } });
|
|
86
86
|
// `WATERX_INFRA` / `waterxQuoteCenterEndpoint` are the source's own infra table +
|
|
87
87
|
// read-plane accessor (mirrors `pythCoreHermesEndpoint`).
|
|
88
|
-
// WaterX quote-center rule (first-party ed25519 signed
|
|
89
|
-
//
|
|
88
|
+
// WaterX quote-center rule (first-party ed25519 signed prices; the `feedWaterxRule*`
|
|
89
|
+
// legs stay internal to `aggregate.ts`). Both wire shapes are exported because a
|
|
90
|
+
// BE prefetch cache holds whichever one its quote-center serves: per-symbol
|
|
91
|
+
// Merkle leaves (default) or one indivisible batch envelope (fallback).
|
|
90
92
|
var waterx_rule_ts_1 = require("./rules/waterx-rule.js");
|
|
91
93
|
Object.defineProperty(exports, "WaterxRule", { enumerable: true, get: function () { return waterx_rule_ts_1.WaterxRule; } });
|
|
92
94
|
Object.defineProperty(exports, "parseSignedEnvelope", { enumerable: true, get: function () { return waterx_rule_ts_1.parseSignedEnvelope; } });
|
|
95
|
+
Object.defineProperty(exports, "parseSignedLeaves", { enumerable: true, get: function () { return waterx_rule_ts_1.parseSignedLeaves; } });
|
|
93
96
|
Object.defineProperty(exports, "BATCH_PRICE_INTENT", { enumerable: true, get: function () { return waterx_rule_ts_1.BATCH_PRICE_INTENT; } });
|
|
97
|
+
Object.defineProperty(exports, "MERKLE_ROOT_INTENT", { enumerable: true, get: function () { return waterx_rule_ts_1.MERKLE_ROOT_INTENT; } });
|
|
94
98
|
Object.defineProperty(exports, "WATERX_INFRA", { enumerable: true, get: function () { return waterx_rule_ts_1.WATERX_INFRA; } });
|
|
95
99
|
Object.defineProperty(exports, "waterxQuoteCenterEndpoint", { enumerable: true, get: function () { return waterx_rule_ts_1.waterxQuoteCenterEndpoint; } });
|
|
96
|
-
// Rule-owned payload
|
|
97
|
-
// hand-cast the payload shape.
|
|
100
|
+
// Rule-owned payload accessors (kind-check + unwrap in one place) — never
|
|
101
|
+
// hand-cast the payload shape, and never assume which variant it is.
|
|
102
|
+
Object.defineProperty(exports, "waterxLeavesOf", { enumerable: true, get: function () { return waterx_rule_ts_1.waterxLeavesOf; } });
|
|
98
103
|
Object.defineProperty(exports, "waterxEnvelopeOf", { enumerable: true, get: function () { return waterx_rule_ts_1.waterxEnvelopeOf; } });
|
|
99
104
|
// `resolveOracleRule` is the ONE source→rule registry — exported so external
|
|
100
105
|
// consumers (e.g. a BE prefetch cache that keys per source and needs each
|