Skip to content

Commit

Permalink
Merge pull request #285 from oraichain/feat/oraiswap-v3
Browse files Browse the repository at this point in the history
Feat/oraiswap v3
  • Loading branch information
vuonghuuhung authored Jul 10, 2024
2 parents 5c71178 + 8c25b25 commit 16614b7
Show file tree
Hide file tree
Showing 15 changed files with 1,156 additions and 1 deletion.
10 changes: 10 additions & 0 deletions .github/workflows/publish_package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,15 @@ jobs:
env:
CI: false
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Publish Universal-swap
id: publish-universal-swap
continue-on-error: true
run: yarn deploy packages/universal-swap
env:
CI: false
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Publish Oraidex contracts-sdk
id: publish-oraidex-contracts-sdk
continue-on-error: true
Expand All @@ -79,6 +81,14 @@ jobs:
CI: false
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Publish Oraidex oraiswap-v3
id: publish-oraiswap-v3
continue-on-error: true
run: yarn deploy packages/oraiswap-v3
env:
CI: false
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: send result via discord
uses: appleboy/discord-action@master
with:
Expand Down
18 changes: 18 additions & 0 deletions packages/oraiswap-v3/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@oraichain/oraiswap-v3",
"version": "0.1.0",
"main": "build/index.js",
"files": [
"build/"
],
"scripts": {
"build": "tsc -p tsconfig.json"
},
"license": "MIT",
"dependencies": {
"@cosmjs/cosmwasm-stargate": "^0.31.0",
"@oraichain/oraidex-contracts-sdk": "^1.0.43",
"@oraichain/oraiswap-v3-wasm": "^0.1.0",
"@oraichain/oraidex-common": "latest"
}
}
41 changes: 41 additions & 0 deletions packages/oraiswap-v3/src/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export const ORAISWAP_V3_CONTRACT = "orai10s0c75gw5y5eftms5ncfknw6lzmx0dyhedn75uz793m8zwz4g8zq4d9x9a";

export const DENOMINATOR = 10n ** 12n;
export const LIQUIDITY_DENOMINATOR = 10n ** 6n;
export const PRICE_DENOMINATOR = 10n ** 24n;
export const MAX_TICKMAP_QUERY_SIZE = (16 * 1024 * 8) / (16 + 64);
export const CHUNK_SIZE = 64;
export const LIQUIDITY_TICKS_LIMIT = (16 * 1024 * 8) / (32 + 128 + 8);

export const MAINNET_TOKENS = [
{
address: "orai",
symbol: "ORAI",
coingeckoId: "oraichain-token",
decimals: 6
},
{
address: "orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge",
symbol: "ORAIX",
coingeckoId: "oraidex",
decimals: 6
},
{
address: "orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q",
symbol: "OCH",
coingeckoId: "och",
decimals: 6
},
{
address: "orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd",
symbol: "USDC",
coingeckoId: "usd-coin",
decimals: 6
},
{
address: "orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh",
symbol: "USDT",
coingeckoId: "tether",
decimals: 6
}
];
143 changes: 143 additions & 0 deletions packages/oraiswap-v3/src/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { OraiswapV3QueryClient } from "@oraichain/oraidex-contracts-sdk";
import {
ArrayOfTupleOfUint16AndUint64,
PoolWithPoolKey
} from "@oraichain/oraidex-contracts-sdk/build/OraiswapV3.types";
import { LiquidityTick, PoolKey, Tickmap, getMaxTick, getMinTick, positionToTick } from "@oraichain/oraiswap-v3-wasm";
import { CHUNK_SIZE, LIQUIDITY_TICKS_LIMIT, MAX_TICKMAP_QUERY_SIZE, ORAISWAP_V3_CONTRACT } from "./const";
import { calculateLiquidityForPair, calculateLiquidityForRanges, parse } from "./helpers";
import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import { PositionLiquidInfo, VirtualRange } from "./types";

// TODO!: add docs

export class OraiswapV3Handler {
private _client: OraiswapV3QueryClient;

constructor(client: CosmWasmClient, address: string = ORAISWAP_V3_CONTRACT) {
this._client = new OraiswapV3QueryClient(client, address);
}

public async getPoolList(): Promise<PoolWithPoolKey[]> {
return await this._client.pools({});
}

public async getProtocolFee(): Promise<number> {
return await this._client.protocolFee();
}

public async getRawTickmap(
poolKey: PoolKey,
lowerTick: number,
upperTick: number,
xToY: boolean
): Promise<ArrayOfTupleOfUint16AndUint64> {
const tickmaps = await this._client.tickMap({
lowerTickIndex: lowerTick,
upperTickIndex: upperTick,
xToY,
poolKey
});
return tickmaps;
}

public async getFullTickmap(poolKey: PoolKey): Promise<Tickmap> {
const maxTick = getMaxTick(poolKey.fee_tier.tick_spacing);
let lowerTick = getMinTick(poolKey.fee_tier.tick_spacing);

const xToY = false;

const promises = [];
const tickSpacing = poolKey.fee_tier.tick_spacing;

const jump = (MAX_TICKMAP_QUERY_SIZE - 3) * CHUNK_SIZE;

while (lowerTick <= maxTick) {
let nextTick = lowerTick + jump;
const remainder = nextTick % tickSpacing;

if (remainder > 0) {
nextTick += tickSpacing - remainder;
} else if (remainder < 0) {
nextTick -= remainder;
}

let upperTick = nextTick;

if (upperTick > maxTick) {
upperTick = maxTick;
}

const result = this.getRawTickmap(poolKey, lowerTick, upperTick, xToY).then(
(tickmap) => tickmap.map(([a, b]) => [BigInt(a), BigInt(b)]) as [bigint, bigint][]
);
promises.push(result);

lowerTick = upperTick + tickSpacing;
}

const fullResult = (await Promise.all(promises)).flat(1);

const storedTickmap = new Map<bigint, bigint>(fullResult);

return { bitmap: storedTickmap };
}

public async getAllLiquidityTicks(poolKey: PoolKey, tickmap: Tickmap): Promise<LiquidityTick[]> {
const tickIndexes: number[] = [];
for (const [chunkIndex, chunk] of tickmap.bitmap.entries()) {
for (let bit = 0; bit < CHUNK_SIZE; bit++) {
const checkedBit = chunk & (1n << BigInt(bit));
if (checkedBit) {
const tickIndex = positionToTick(Number(chunkIndex), bit, poolKey.fee_tier.tick_spacing);
tickIndexes.push(tickIndex);
}
}
}
const tickLimit = LIQUIDITY_TICKS_LIMIT;
const promises: Promise<LiquidityTick[]>[] = [];
for (let i = 0; i < tickIndexes.length; i += tickLimit) {
promises.push(
this._client
.liquidityTicks({
poolKey,
tickIndexes: tickIndexes.slice(i, i + tickLimit).map(Number)
})
.then(parse)
);
}

const tickResults = await Promise.all(promises);
return tickResults.flat(1);
}

public async getPairLiquidityValues(pool: PoolWithPoolKey): Promise<{ liquidityX: bigint; liquidityY: bigint }> {
const tickmap = await this.getFullTickmap(pool.pool_key);

const liquidityTicks = await this.getAllLiquidityTicks(pool.pool_key, tickmap);

const tickIndexes: number[] = [];
for (const [chunkIndex, chunk] of tickmap.bitmap.entries()) {
for (let bit = 0; bit < CHUNK_SIZE; bit++) {
const checkedBit = chunk & (1n << BigInt(bit));
if (checkedBit) {
const tickIndex = positionToTick(Number(chunkIndex), bit, pool.pool_key.fee_tier.tick_spacing);
tickIndexes.push(tickIndex);
}
}
}

const tickArray: VirtualRange[] = [];

for (let i = 0; i < tickIndexes.length - 1; i++) {
tickArray.push({
lowerTick: tickIndexes[i],
upperTick: tickIndexes[i + 1]
});
}

const pos: PositionLiquidInfo[] = calculateLiquidityForRanges(liquidityTicks, tickArray);

return await calculateLiquidityForPair(pos, BigInt(pool.pool.sqrt_price));
}
}
Loading

0 comments on commit 16614b7

Please sign in to comment.