UNPKG

@swaptoshi/dex-module

Version:

Klayr decentralized exchange (dex) on-chain module

170 lines 8.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.transform = transform; exports.initialize = initialize; exports.write = write; exports.grow = grow; exports.lte = lte; exports.binarySearch = binarySearch; exports.getSurroundingObservations = getSurroundingObservations; exports.observeSingle = observeSingle; exports.observe = observe; const observation_1 = require("../../observation"); const int_1 = require("../int"); function transform(last, blockTimestamp, tick, liquidity) { const delta = int_1.Uint32.from(blockTimestamp).sub(last.blockTimestamp); return { blockTimestamp, tickCumulative: int_1.Int56.from(last.tickCumulative).add(int_1.Int56.from(tick).mul(delta)).toString(), secondsPerLiquidityCumulativeX128: int_1.Uint160.from(last.secondsPerLiquidityCumulativeX128) .add(int_1.Uint160.from(delta) .shl(128) .div(int_1.Uint128.from(liquidity).gt(0) ? liquidity : 1)) .toString(), initialized: true, }; } async function initialize(observationStore, context, poolAddress, time, simulation = false) { if (!simulation) { await observationStore.set(context, observationStore.getKey(poolAddress, '0'), { blockTimestamp: time, tickCumulative: '0', secondsPerLiquidityCumulativeX128: '0', initialized: true, }); } const cardinality = '1'; const cardinalityNext = '1'; return [cardinality, cardinalityNext]; } async function write(observationStore, context, poolAddress, index, blockTimestamp, tick, liquidity, cardinality, cardinalityNext, simulation = false) { let indexUpdated = ''; let cardinalityUpdated = ''; const last = await observationStore.getOrDefault(context, observationStore.getKey(poolAddress, index)); if (last.blockTimestamp === blockTimestamp) return [index, cardinality]; if (int_1.Uint16.from(cardinalityNext).gt(cardinality) && int_1.Uint16.from(index).eq(int_1.Uint16.from(cardinality).sub(1))) { cardinalityUpdated = cardinalityNext; } else { cardinalityUpdated = cardinality; } indexUpdated = int_1.Uint16.from(index).add(1).mod(cardinalityUpdated).toString(); if (!simulation) { await observationStore.set(context, observationStore.getKey(poolAddress, indexUpdated), transform(last, blockTimestamp, tick, liquidity)); } return [indexUpdated, cardinalityUpdated]; } async function grow(observationStore, context, poolAddress, current, next, simulation = false) { if (int_1.Uint16.from(current).lte(0)) throw new Error('I'); if (int_1.Uint16.from(next).lte(current)) return current; for (let i = int_1.Uint16.from(current); i.lt(next); i = i.add(1)) { if (!(await observationStore.has(context, observationStore.getKey(poolAddress, i.toString())))) { if (!simulation) { await observationStore.set(context, observationStore.getKey(poolAddress, i.toString()), { ...observation_1.defaultObservation, blockTimestamp: '1', }); } } else { const observation = await observationStore.get(context, observationStore.getKey(poolAddress, i.toString())); if (!simulation) { await observationStore.set(context, observationStore.getKey(poolAddress, i.toString()), { ...observation, blockTimestamp: '1', }); } } } return next; } function lte(time, a, b) { if (int_1.Uint32.from(a).lte(time) && int_1.Uint32.from(b).lte(time)) return int_1.Uint32.from(a).lte(b); const aAdjusted = int_1.Uint256.from(int_1.Uint32.from(a).gt(time) ? a : int_1.Uint256.from(2).pow(32).add(a).toString()); const bAdjusted = int_1.Uint256.from(int_1.Uint32.from(b).gt(time) ? b : int_1.Uint256.from(2).pow(32).add(b).toString()); return aAdjusted.lte(bAdjusted); } async function binarySearch(observationStore, context, poolAddress, time, target, index, cardinality) { let beforeOrAt; let atOrAfter; let l = int_1.Uint256.from(index).add(1).mod(cardinality); let r = int_1.Uint256.from(l).add(cardinality).sub(1); let i; while (true) { i = l.add(r).div(2); beforeOrAt = await observationStore.getOrDefault(context, observationStore.getKey(poolAddress, i.mod(cardinality).toString())); if (!beforeOrAt.initialized) { l = i.add(1); continue; } atOrAfter = await observationStore.getOrDefault(context, observationStore.getKey(poolAddress, i.add(1).mod(cardinality).toString())); const targetAtOrAfter = lte(time, beforeOrAt.blockTimestamp, target); if (targetAtOrAfter && lte(time, target, atOrAfter.blockTimestamp)) break; if (!targetAtOrAfter) r = i.sub(1); else l = i.add(1); } return [beforeOrAt, atOrAfter]; } async function getSurroundingObservations(observationStore, context, poolAddress, time, target, tick, index, liquidity, cardinality) { let beforeOrAt; let atOrAfter; beforeOrAt = await observationStore.getOrDefault(context, observationStore.getKey(poolAddress, index)); if (lte(time, beforeOrAt.blockTimestamp, target)) { if (beforeOrAt.blockTimestamp === target) { atOrAfter = beforeOrAt; return [beforeOrAt, atOrAfter]; } return [beforeOrAt, transform(beforeOrAt, target, tick, liquidity)]; } beforeOrAt = await observationStore.getOrDefault(context, observationStore.getKey(poolAddress, int_1.Uint16.from(index).add(1).mod(cardinality).toString())); if (!beforeOrAt.initialized) beforeOrAt = await observationStore.getOrDefault(context, observationStore.getKey(poolAddress, '0')); if (!lte(time, beforeOrAt.blockTimestamp, target)) throw new Error('OLD'); return binarySearch(observationStore, context, poolAddress, time, target, index, cardinality); } async function observeSingle(observationStore, context, poolAddress, time, secondsAgo, tick, index, liquidity, cardinality) { if (int_1.Uint32.from(secondsAgo).eq(0)) { let last = await observationStore.getOrDefault(context, observationStore.getKey(poolAddress, index)); if (last.blockTimestamp !== time) last = transform(last, time, tick, liquidity); return [last.tickCumulative, last.secondsPerLiquidityCumulativeX128]; } const target = int_1.Uint32.from(time).sub(secondsAgo); const [beforeOrAt, atOrAfter] = await getSurroundingObservations(observationStore, context, poolAddress, time, target.toString(), tick, index, liquidity, cardinality); if (target.eq(beforeOrAt.blockTimestamp)) { return [beforeOrAt.tickCumulative, beforeOrAt.secondsPerLiquidityCumulativeX128]; } if (target.eq(atOrAfter.blockTimestamp)) { return [atOrAfter.tickCumulative, atOrAfter.secondsPerLiquidityCumulativeX128]; } const observationTimeDelta = int_1.Uint32.from(atOrAfter.blockTimestamp).sub(beforeOrAt.blockTimestamp); const targetDelta = target.sub(beforeOrAt.blockTimestamp); const tickCumulative = int_1.Int56.from(atOrAfter.tickCumulative).sub(beforeOrAt.tickCumulative).div(observationTimeDelta).mul(targetDelta).add(beforeOrAt.tickCumulative); const secondsPerLiquidityCumulativeX128 = int_1.Uint160.from(0) .add(int_1.Uint256.from(atOrAfter.secondsPerLiquidityCumulativeX128).sub(beforeOrAt.secondsPerLiquidityCumulativeX128).toString()) .mul(targetDelta) .div(observationTimeDelta) .add(beforeOrAt.secondsPerLiquidityCumulativeX128); return [tickCumulative.toString(), secondsPerLiquidityCumulativeX128.toString()]; } async function observe(observationStore, context, poolAddress, time, secondsAgo, tick, index, liquidity, cardinality) { if (int_1.Uint16.from(cardinality).lte(0)) throw new Error('I'); const tickCumulatives = []; const secondsPerLiquidityCumulativeX128s = []; for (let i = int_1.Uint256.from(0); i.lt(secondsAgo.length); i = i.add(1)) { const [tickCumulative, secondsPerLiquidityCumulativeX128] = await observeSingle(observationStore, context, poolAddress, time, secondsAgo[i.toNumber()], tick, index, liquidity, cardinality); tickCumulatives.push(tickCumulative); secondsPerLiquidityCumulativeX128s.push(secondsPerLiquidityCumulativeX128); } return { tickCumulatives, secondsPerLiquidityCumulativeX128s }; } //# sourceMappingURL=oracle.js.map