@swaptoshi/dex-module
Version:
Klayr decentralized exchange (dex) on-chain module
170 lines • 8.66 kB
JavaScript
;
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