Skip to content

Commit

Permalink
Merge pull request #304 from invariant-labs/add-validate-state-script
Browse files Browse the repository at this point in the history
add validate-state-script
  • Loading branch information
none00y authored Oct 9, 2024
2 parents b609ba7 + cfa24c0 commit 5c38274
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 6 deletions.
4 changes: 2 additions & 2 deletions scripts/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"setup-localnet": "npx tsc && node --experimental-wasm-modules target/setup-localnet.js",
"setup-testnet": "npx tsc && node --experimental-wasm-modules target/setup-testnet.js",
"setup-mainnet": "npx tsc && node --experimental-wasm-modules target/setup-mainnet.js",
"validate-state": "npx tsc && node --experimental-wasm-modules target/validate-state.js",
"change-admin": "npx tsc && node --experimental-wasm-modules target/change-admin.js"
},
"keywords": [],
Expand Down
131 changes: 131 additions & 0 deletions scripts/src/validate-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import {
Invariant,
LiquidityTick,
Network,
Pool,
PoolKey,
PSP22,
calculateAmountDelta
} from '@invariant-labs/a0-sdk'
import { INVARIANT_ADDRESS } from '@invariant-labs/a0-sdk/target/consts.js'
import { assert, initPolkadotApi } from '@invariant-labs/a0-sdk/target/utils.js'

const main = async () => {
const network = Network.Testnet
const api = await initPolkadotApi(network)

const psp22 = await PSP22.load(api, network)

const invariantAddress = INVARIANT_ADDRESS[network]
const invariant = await Invariant.load(api, network, invariantAddress)

const poolKeys = await invariant.getAllPoolKeys()

const poolPromises: Promise<[PoolKey, Pool, LiquidityTick[]]>[] = []
for (const poolKey of poolKeys) {
poolPromises.push(
new Promise(async resolve => {
const pool = await invariant.getPool(poolKey.tokenX, poolKey.tokenY, poolKey.feeTier)
const tickmap = await invariant.getFullTickmap(poolKey)
const liquidityTicks = await invariant.getAllLiquidityTicks(poolKey, tickmap)

resolve([poolKey, pool, liquidityTicks])
})
)
}

const poolsWithTicks = await Promise.all(poolPromises)

const balances = new Map<string, bigint>()

for (const [poolKey, pool, liquidityTicks] of poolsWithTicks) {
const { liquidityX, liquidityY } = getPairLiquidityValues(pool, liquidityTicks)

const newBalanceX = (balances.get(poolKey.tokenX) ?? 0n) + liquidityX
const newBalanceY = (balances.get(poolKey.tokenY) ?? 0n) + liquidityY

balances.set(poolKey.tokenX, newBalanceX)
balances.set(poolKey.tokenY, newBalanceY)
}

const tokens: string[] = []
balances.forEach((v, k) => tokens.push(k))

const onchainBalances = await psp22.getAllBalances(tokens, invariantAddress)
let failed = false

for (const [token, balance] of balances) {
const onchainBalance = onchainBalances.get(token)
if (onchainBalance === undefined || onchainBalance === null) {
console.error('Failed to fetch balance for', token)
continue
}

const diff = onchainBalance - balance

if (diff < 0) {
failed = true
console.error('Invalid balance', token, balance, onchainBalance, diff)
}
}

process.exit(failed ? 1 : 0)
}

const getPairLiquidityValues = (pool: Pool, liquidityTicks: LiquidityTick[]) => {
let liquidityX = 0n
let liquidityY = 0n
liquidityTicks.sort((a, b) => Number(a.index - b.index))
const visitedTicks: LiquidityTick[] = []
for (let i = 0; i < liquidityTicks.length; i++) {
let curr = liquidityTicks[i]

if (visitedTicks.length === 0 || curr.sign) {
visitedTicks.push(curr)
continue
}

for (let j = visitedTicks.length - 1; j >= 0; j--) {
let prev = visitedTicks[j]

if (!prev.sign) {
throw new Error('Prev tick must have positive liquidity')
}

let liquidityLower = prev.liquidityChange
let liquidityUpper = curr.liquidityChange

let liquidityDelta
let lowerTickIndex = prev.index
let upperTickIndex = curr.index

if (liquidityUpper >= liquidityLower) {
liquidityDelta = liquidityLower

curr.liquidityChange = liquidityUpper - liquidityLower
visitedTicks.pop()
} else {
liquidityDelta = liquidityUpper
prev.liquidityChange = liquidityLower - liquidityUpper
}

const [xVal, yVal] = calculateAmountDelta(
pool.currentTickIndex,
pool.sqrtPrice,
liquidityDelta,
false,
upperTickIndex,
lowerTickIndex
)

liquidityX = liquidityX + xVal
liquidityY = liquidityY + yVal
}
}

assert(visitedTicks.length === 0, 'Ticks were not emptied')

return { liquidityX, liquidityY }
}

main()
4 changes: 2 additions & 2 deletions sdk/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@invariant-labs/a0-sdk",
"version": "0.2.30",
"version": "0.2.31",
"collaborators": [
"Invariant Labs"
],
Expand Down
3 changes: 2 additions & 1 deletion sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export {
toPrice,
toSecondsPerLiquidity,
toSqrtPrice,
toTokenAmount
toTokenAmount,
calculateAmountDelta
} from '@invariant-labs/a0-sdk-wasm/invariant_a0_wasm.js'
export type {
CreatePositionEvent,
Expand Down

0 comments on commit 5c38274

Please sign in to comment.