diff --git a/sdk/.npmignore b/sdk/.npmignore index d5ebedc..6663412 100644 --- a/sdk/.npmignore +++ b/sdk/.npmignore @@ -1,6 +1,7 @@ node_modules src/**/* tests/**/* +target/test-utils.* !src/wasm/pkg # build scripts build.sh @@ -11,4 +12,6 @@ package-wasm.sh .eslintrc .nvmrc mocharc.json -tsconfig.json \ No newline at end of file +tsconfig.json +# idls +contracts/**/*.idl \ No newline at end of file diff --git a/sdk/src/erc20.ts b/sdk/src/erc20.ts index 1f00d71..b9e1782 100644 --- a/sdk/src/erc20.ts +++ b/sdk/src/erc20.ts @@ -3,22 +3,12 @@ import { KeyringPair } from '@polkadot/keyring/types' import { Erc20Token } from './erc20-token.js' import { ActorId, Signer, getWasm, integerSafeCast } from './utils.js' import { FUNGIBLE_TOKEN_GAS_LIMIT, DEFAULT_ADDRESS } from './consts.js' -export type BalanceEntry = [Uint8Array, number] -export type AllowanceEntry = [Uint8Array, BalanceEntry] -export type FungibleTokenState = { - name: string - symbol: string - totalSupply: number - balances: Array - allowances: Array - decimals: number -} export class FungibleToken { private constructor( private readonly gasLimit: bigint, private readonly erc20: Erc20Token, - private readonly admin?: KeyringPair + private admin?: KeyringPair ) {} static async deploy( @@ -57,11 +47,15 @@ export class FungibleToken { const { response } = await grantMinterRoleTx.signAndSend() response() } - return new FungibleToken(gasLimit, erc20, deployer) + if (!erc20.programId) { + throw new Error('Failed to initialize FungibleToken program') + } + + return erc20.programId } - static async load(api: GearApi, programId: HexString, gasLimit: bigint = FUNGIBLE_TOKEN_GAS_LIMIT) { - const erc20 = new Erc20Token(api, programId) + static async load(api: GearApi, gasLimit: bigint = FUNGIBLE_TOKEN_GAS_LIMIT) { + const erc20 = new Erc20Token(api) return new FungibleToken(gasLimit, erc20) } @@ -75,69 +69,93 @@ export class FungibleToken { return id } - async allowance(owner: ActorId, spender: ActorId): Promise { + setAdmin(admin: KeyringPair) { + this.admin = admin + } + + async allowance(owner: ActorId, spender: ActorId, tokenAddress: HexString): Promise { + this.erc20.programId = tokenAddress + return this.erc20.erc20.allowance(owner as any, spender as any, DEFAULT_ADDRESS) } - async balanceOf(owner: ActorId): Promise { + async balanceOf(owner: ActorId, tokenAddress: HexString): Promise { + this.erc20.programId = tokenAddress + return this.erc20.erc20.balanceOf(owner as any, DEFAULT_ADDRESS) } - async decimals(): Promise { + async decimals(tokenAddress: HexString): Promise { + this.erc20.programId = tokenAddress + return BigInt(await this.erc20.erc20.decimals(DEFAULT_ADDRESS)) } - async name(): Promise { + async name(tokenAddress: HexString): Promise { + this.erc20.programId = tokenAddress + return this.erc20.erc20.name(DEFAULT_ADDRESS) } - async symbol(): Promise { + async symbol(tokenAddress: HexString): Promise { + this.erc20.programId = tokenAddress + return this.erc20.erc20.symbol(DEFAULT_ADDRESS) } - async totalSupply(): Promise { + async totalSupply(tokenAddress: HexString): Promise { + this.erc20.programId = tokenAddress + return this.erc20.erc20.totalSupply(DEFAULT_ADDRESS) } - async approveTx(spender: ActorId, amount: bigint) { + async approveTx(spender: ActorId, amount: bigint, tokenAddress: HexString) { + this.erc20.programId = tokenAddress + return this.erc20.erc20.approve(spender as any, amount as any).withGas(this.gasLimit) } - async approve(owner: Signer, spender: ActorId, amount: bigint): Promise { - const tx = await this.approveTx(spender, amount) + async approve(owner: Signer, spender: ActorId, amount: bigint, tokenAddress: HexString): Promise { + const tx = await this.approveTx(spender, amount, tokenAddress) const { response } = await tx.withAccount(owner).signAndSend() return response() } - async burnTx(account: ActorId, amount: bigint) { + async burnTx(account: ActorId, amount: bigint, tokenAddress: HexString) { + this.erc20.programId = tokenAddress + return this.erc20.admin.burn(account as any, amount as any).withGas(this.gasLimit) } - async burn(account: ActorId, amount: bigint) { + async burn(account: ActorId, amount: bigint, tokenAddress: HexString) { if (!this.admin) { throw new Error('Admin account is required to burn tokens') } - const tx = await this.burnTx(account, amount) + const tx = await this.burnTx(account, amount, tokenAddress) const { response } = await tx.withAccount(this.admin).signAndSend() return response() } - async mintTx(account: ActorId, amount: bigint) { + async mintTx(account: ActorId, amount: bigint, tokenAddress: HexString) { + this.erc20.programId = tokenAddress + return this.erc20.admin.mint(account as any, amount as any).withGas(this.gasLimit) } - async mint(account: ActorId, amount: bigint) { + async mint(account: ActorId, amount: bigint, tokenAddress: HexString) { if (!this.admin) { throw new Error('Admin account is required to mint tokens') } - const tx = await this.mintTx(account, amount) + const tx = await this.mintTx(account, amount, tokenAddress) const { response } = await tx.withAccount(this.admin).signAndSend() return response() } - async setTransferFail(flag: boolean) { + async setTransferFail(flag: boolean, tokenAddress: HexString) { + this.erc20.programId = tokenAddress + if (!this.admin) { throw new Error('Admin account is required to set transfer failure') } @@ -147,24 +165,28 @@ export class FungibleToken { return response() } - async transferTx(to: ActorId, amount: bigint) { + async transferTx(to: ActorId, amount: bigint, tokenAddress: HexString) { + this.erc20.programId = tokenAddress + return this.erc20.erc20.transfer(to as any, amount as any).withGas(this.gasLimit) } - async transfer(signer: Signer, to: ActorId, amount: bigint) { - const tx = await this.transferTx(to, amount) + async transfer(signer: Signer, to: ActorId, amount: bigint, tokenAddress: HexString) { + const tx = await this.transferTx(to, amount, tokenAddress) const { response } = await tx.withAccount(signer).signAndSend() return response() } - async transferFromTx(from: ActorId, to: ActorId, amount: bigint) { + async transferFromTx(from: ActorId, to: ActorId, amount: bigint, tokenAddress: HexString) { + this.erc20.programId = tokenAddress + return this.erc20.erc20 .transferFrom(from as any, to as any, amount as any) .withGas(this.gasLimit) } - async transferFrom(signer: Signer, from: ActorId, to: ActorId, amount: bigint) { - const tx = await this.transferFromTx(from, to, amount) + async transferFrom(signer: Signer, from: ActorId, to: ActorId, amount: bigint, tokenAddress: HexString) { + const tx = await this.transferFromTx(from, to, amount, tokenAddress) const { response } = await tx.withAccount(signer).signAndSend() return response() } diff --git a/sdk/src/test-utils.ts b/sdk/src/test-utils.ts index 82c2216..05e76ff 100644 --- a/sdk/src/test-utils.ts +++ b/sdk/src/test-utils.ts @@ -1,6 +1,6 @@ import { assert } from 'chai' -import { FungibleToken } from './erc20' import { isTokenX } from 'invariant-vara-wasm' +import { HexString } from '@gear-js/api' export const objectEquals = ( object: { [key: string]: any }, @@ -14,8 +14,8 @@ export const objectEquals = ( } } -export const sortTokens = (tokenX: FungibleToken, tokenY: FungibleToken) => { - return isTokenX(tokenX.programId(), tokenY.programId()) +export const sortTokens = (tokenX: HexString, tokenY: HexString) => { + return isTokenX(tokenX, tokenY) ? [tokenX, tokenY] : [tokenY, tokenX] } diff --git a/sdk/tests/deposits.test.ts b/sdk/tests/deposits.test.ts index d22b506..2db7b93 100644 --- a/sdk/tests/deposits.test.ts +++ b/sdk/tests/deposits.test.ts @@ -1,46 +1,49 @@ import 'mocha' import { initGearApi, newFeeTier, newPoolKey, subscribeToNewHeads } from '../src/utils.js' -import { GearKeyring } from '@gear-js/api' +import { GearKeyring, HexString } from '@gear-js/api' import { Network } from '../src/consts' import { Invariant } from '../src/invariant' import { assert } from 'chai' -import { FungibleToken } from '../src/erc20' +import { FungibleToken } from '../src/erc20.js' import { assertThrowsAsync, sortTokens } from '../src/test-utils.js' const api = await initGearApi({ providerAddress: Network.Local }) const admin = await GearKeyring.fromSuri('//Alice') let unsub: Promise | null = null -let tokenX: FungibleToken = null as any -let tokenY: FungibleToken = null as any +const GRC20: FungibleToken = await FungibleToken.load(api) +GRC20.setAdmin(admin) +let token0Address: HexString = null as any +let token1Address: HexString = null as any let invariant: Invariant = null as any + const feeTier = newFeeTier(10000000000n, 1n) const assertBalanceChange = async (changeX: bigint, changeY: bigint, callback: () => any) => { const userBalancesBefore = await invariant.getUserBalances(admin.addressRaw) - const balanceXBefore = await tokenX.balanceOf(admin.addressRaw) - const balanceYBefore = await tokenY.balanceOf(admin.addressRaw) - const invariantBalanceXBefore = await tokenX.balanceOf(invariant.programId()) - const invariantBalanceYBefore = await tokenY.balanceOf(invariant.programId()) + const balanceXBefore = await GRC20.balanceOf(admin.addressRaw, token0Address) + const balanceYBefore = await GRC20.balanceOf(admin.addressRaw, token1Address) + const invariantBalanceXBefore = await GRC20.balanceOf(invariant.programId(), token0Address) + const invariantBalanceYBefore = await GRC20.balanceOf(invariant.programId(), token1Address) await callback() const userBalancesAfter = await invariant.getUserBalances(admin.addressRaw) assert.deepEqual( - userBalancesAfter.get(tokenX.programId()) || 0n, - (userBalancesBefore.get(tokenX.programId()) || 0n) - changeX, + userBalancesAfter.get(token0Address) || 0n, + (userBalancesBefore.get(token0Address) || 0n) - changeX, 'tokenX, user balance mismatch' ) assert.deepEqual( - userBalancesAfter.get(tokenY.programId()) || 0n, - (userBalancesBefore.get(tokenY.programId()) || 0n) - changeY, + userBalancesAfter.get(token1Address) || 0n, + (userBalancesBefore.get(token1Address) || 0n) - changeY, 'tokenY, user balance mismatch' ) - const balanceXAfter = await tokenX.balanceOf(admin.addressRaw) - const balanceYAfter = await tokenY.balanceOf(admin.addressRaw) - const invariantBalanceXAfter = await tokenX.balanceOf(invariant.programId()) - const invariantBalanceYAfter = await tokenY.balanceOf(invariant.programId()) + const balanceXAfter = await GRC20.balanceOf(admin.addressRaw, token0Address) + const balanceYAfter = await GRC20.balanceOf(admin.addressRaw, token1Address) + const invariantBalanceXAfter = await GRC20.balanceOf(invariant.programId(), token0Address) + const invariantBalanceYAfter = await GRC20.balanceOf(invariant.programId(), token1Address) assert.deepEqual(balanceXAfter, balanceXBefore + changeX, 'tokenX, balance mismatch') assert.deepEqual(balanceYAfter, balanceYBefore + changeY, 'tokenY, balance mismatch') @@ -63,60 +66,42 @@ describe('deposits', async function () { beforeEach(async function () { this.timeout(200000) invariant = await Invariant.deploy(api, admin, 10000000000n) - tokenX = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) - tokenY = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) - ;[tokenX, tokenY] = sortTokens(tokenX, tokenY) + token0Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) + token1Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) + ;[token0Address, token1Address] = sortTokens(token0Address, token1Address) await invariant.addFeeTier(admin, feeTier) - const poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + const poolKey = newPoolKey(token0Address, token1Address, feeTier) await invariant.createPool(admin, poolKey, 1000000000000000000000000n) - await tokenX.mint(admin.addressRaw, 100000000000000n) - await tokenY.mint(admin.addressRaw, 100000000000000n) + await GRC20.mint(admin.addressRaw, 100000000000000n, token0Address) + await GRC20.mint(admin.addressRaw, 100000000000000n, token1Address) - await tokenX.approve(admin, invariant.programId(), 100000000000000n) - await tokenY.approve(admin, invariant.programId(), 100000000000000n) + await GRC20.approve(admin, invariant.programId(), 100000000000000n, token0Address) + await GRC20.approve(admin, invariant.programId(), 100000000000000n, token1Address) }) it('single deposit and withdraw', async function () { this.timeout(200000) const amount = 10000000000000n await assertBalanceChange(-amount, -amount, async () => { - assert.deepEqual( - await invariant.depositSingleToken(admin, tokenX.programId(), amount), - amount - ) - assert.deepEqual( - await invariant.depositSingleToken(admin, tokenY.programId(), amount), - amount - ) + assert.deepEqual(await invariant.depositSingleToken(admin, token0Address, amount), amount) + assert.deepEqual(await invariant.depositSingleToken(admin, token1Address, amount), amount) }) await assertBalanceChange(amount, amount, async () => { - assert.deepEqual( - await invariant.withdrawSingleToken(admin, tokenX.programId(), amount), - amount - ) - assert.deepEqual( - await invariant.withdrawSingleToken(admin, tokenY.programId(), amount), - amount - ) + assert.deepEqual(await invariant.withdrawSingleToken(admin, token0Address, amount), amount) + assert.deepEqual(await invariant.withdrawSingleToken(admin, token1Address, amount), amount) }) await assertBalanceChange(-amount, -amount, async () => { - assert.deepEqual( - await invariant.depositSingleToken(admin, tokenX.programId(), amount), - amount - ) - assert.deepEqual( - await invariant.depositSingleToken(admin, tokenY.programId(), amount), - amount - ) + assert.deepEqual(await invariant.depositSingleToken(admin, token0Address, amount), amount) + assert.deepEqual(await invariant.depositSingleToken(admin, token1Address, amount), amount) }) await assertBalanceChange(amount, amount, async () => { - assert.deepEqual(await invariant.withdrawSingleToken(admin, tokenX.programId(), null), amount) - assert.deepEqual(await invariant.withdrawSingleToken(admin, tokenY.programId(), null), amount) + assert.deepEqual(await invariant.withdrawSingleToken(admin, token0Address, null), amount) + assert.deepEqual(await invariant.withdrawSingleToken(admin, token1Address, null), amount) }) }) @@ -126,28 +111,28 @@ describe('deposits', async function () { await assertBalanceChange(0n, 0n, async () => { await assertThrowsAsync( - invariant.withdrawSingleToken(admin, tokenX.programId(), amount), + invariant.withdrawSingleToken(admin, token0Address, amount), "Panic occurred: panicked with 'InvariantError: NoBalanceForTheToken'" ) }) - await tokenX.setTransferFail(true) + await GRC20.setTransferFail(true, token0Address) await assertBalanceChange(0n, 0n, async () => { await assertThrowsAsync( - invariant.depositSingleToken(admin, tokenX.programId(), amount), + invariant.depositSingleToken(admin, token0Address, amount), "Panic occurred: panicked with 'InvariantError: UnrecoverableTransferError'" ) }) - await tokenX.setTransferFail(false) + await GRC20.setTransferFail(false, token0Address) await assertBalanceChange(-amount, 0n, async () => { - await invariant.depositSingleToken(admin, tokenX.programId(), amount) + await invariant.depositSingleToken(admin, token0Address, amount) }) - await tokenX.setTransferFail(true) + await GRC20.setTransferFail(true, token0Address) await assertBalanceChange(0n, 0n, async () => { await assertThrowsAsync( - invariant.withdrawSingleToken(admin, tokenX.programId(), amount), + invariant.withdrawSingleToken(admin, token0Address, amount), "Panic occurred: panicked with 'InvariantError: RecoverableTransferError'" ) }) @@ -158,59 +143,39 @@ describe('deposits', async function () { const amount = 10000000000000n await assertBalanceChange(-amount, -amount, async () => { assert.deepEqual( - await invariant.depositTokenPair( - admin, - [tokenX.programId(), amount], - [tokenY.programId(), amount] - ), + await invariant.depositTokenPair(admin, [token0Address, amount], [token1Address, amount]), [amount, amount] ) }) await assertBalanceChange(amount, amount, async () => { assert.deepEqual( - await invariant.withdrawTokenPair( - admin, - [tokenX.programId(), amount], - [tokenY.programId(), amount] - ), + await invariant.withdrawTokenPair(admin, [token0Address, amount], [token1Address, amount]), [amount, amount] ) }) await assertBalanceChange(-amount, -amount, async () => { - await invariant.depositTokenPair( - admin, - [tokenX.programId(), amount], - [tokenY.programId(), amount] - ) + await invariant.depositTokenPair(admin, [token0Address, amount], [token1Address, amount]) }) await assertBalanceChange(amount, amount, async () => { assert.deepEqual( - await invariant.withdrawTokenPair( - admin, - [tokenX.programId(), null], - [tokenY.programId(), null] - ), + await invariant.withdrawTokenPair(admin, [token0Address, null], [token1Address, null]), [amount, amount] ) }) await assertBalanceChange(-1n, -2n, async () => { assert.deepEqual( - await invariant.depositTokenPair(admin, [tokenX.programId(), 1n], [tokenY.programId(), 2n]), + await invariant.depositTokenPair(admin, [token0Address, 1n], [token1Address, 2n]), [1n, 2n] ) }) await assertBalanceChange(1n, 2n, async () => { assert.deepEqual( - await invariant.withdrawTokenPair( - admin, - [tokenX.programId(), 1n], - [tokenY.programId(), 2n] - ), + await invariant.withdrawTokenPair(admin, [token0Address, 1n], [token1Address, 2n]), [1n, 2n] ) }) @@ -223,38 +188,38 @@ describe('deposits', async function () { assert.deepEqual( await invariant.depositTokenPair( admin, - [tokenX.programId(), 100n], - [tokenY.programId(), 100n] + [token0Address, 100n], + [token1Address, 100n] ), [100n, 100n] ) }) - await tokenY.setTransferFail(true) + await GRC20.setTransferFail(true, token1Address) await assertBalanceChange(1n, 0n, async () => { await assertThrowsAsync( - invariant.withdrawTokenPair(admin, [tokenX.programId(), 1n], [tokenY.programId(), 1n]), + invariant.withdrawTokenPair(admin, [token0Address, 1n], [token1Address, 1n]), "Panic occurred: panicked with 'InvariantError: RecoverableTransferError'" ) }) - await tokenX.setTransferFail(true) - await tokenY.setTransferFail(false) + await GRC20.setTransferFail(true, token0Address) + await GRC20.setTransferFail(false, token1Address) await assertBalanceChange(0n, 1n, async () => { await assertThrowsAsync( - invariant.withdrawTokenPair(admin, [tokenX.programId(), 1n], [tokenY.programId(), 1n]), + invariant.withdrawTokenPair(admin, [token0Address, 1n], [token1Address, 1n]), "Panic occurred: panicked with 'InvariantError: RecoverableTransferError'" ) }) - await tokenX.setTransferFail(true) - await tokenY.setTransferFail(true) + await GRC20.setTransferFail(true, token0Address) + await GRC20.setTransferFail(true, token1Address) await assertBalanceChange(0n, 0n, async () => { await assertThrowsAsync( - invariant.withdrawTokenPair(admin, [tokenX.programId(), 1n], [tokenY.programId(), 1n]), + invariant.withdrawTokenPair(admin, [token0Address, 1n], [token1Address, 1n]), "Panic occurred: panicked with 'InvariantError: RecoverableTransferError'" ) }) @@ -262,31 +227,31 @@ describe('deposits', async function () { it('deposit token pair errors', async function () { this.timeout(200000) - await tokenX.setTransferFail(true) - await tokenY.setTransferFail(true) + await GRC20.setTransferFail(true, token0Address) + await GRC20.setTransferFail(true, token1Address) await assertBalanceChange(0n, 0n, async () => { await assertThrowsAsync( - invariant.depositTokenPair(admin, [tokenX.programId(), 1n], [tokenY.programId(), 1n]), + invariant.depositTokenPair(admin, [token0Address, 1n], [token1Address, 1n]), "Panic occurred: panicked with 'InvariantError: UnrecoverableTransferError'" ) }) - await tokenY.setTransferFail(false) + await GRC20.setTransferFail(false, token1Address) await assertBalanceChange(0n, -1n, async () => { await assertThrowsAsync( - invariant.depositTokenPair(admin, [tokenX.programId(), 1n], [tokenY.programId(), 1n]), + invariant.depositTokenPair(admin, [token0Address, 1n], [token1Address, 1n]), "Panic occurred: panicked with 'InvariantError: RecoverableTransferError'" ) }) - await tokenX.setTransferFail(false) - await tokenY.setTransferFail(true) + await GRC20.setTransferFail(false, token0Address) + await GRC20.setTransferFail(true, token1Address) await assertBalanceChange(-1n, 0n, async () => { await assertThrowsAsync( - invariant.depositTokenPair(admin, [tokenX.programId(), 1n], [tokenY.programId(), 1n]), + invariant.depositTokenPair(admin, [token0Address, 1n], [token1Address, 1n]), "Panic occurred: panicked with 'InvariantError: RecoverableTransferError'" ) }) diff --git a/sdk/tests/events.test.ts b/sdk/tests/events.test.ts index dc0ea11..0ffab34 100644 --- a/sdk/tests/events.test.ts +++ b/sdk/tests/events.test.ts @@ -1,10 +1,10 @@ import 'mocha' import { initGearApi, newFeeTier, newPoolKey, subscribeToNewHeads } from '../src/utils.js' -import { GearKeyring } from '@gear-js/api' +import { GearKeyring, HexString } from '@gear-js/api' import { Network } from '../src/consts' import { Invariant } from '../src/invariant' import { assert } from 'chai' -import { FungibleToken } from '../src/erc20' +import { FungibleToken } from '../src/erc20.js' import { objectEquals } from '../src/test-utils.js' import { PoolKey, @@ -21,8 +21,10 @@ const api = await initGearApi({ providerAddress: Network.Local }) const admin = await GearKeyring.fromSuri('//Alice') let unsub: Promise | null = null -let tokenX: FungibleToken = null as any -let tokenY: FungibleToken = null as any +const GRC20: FungibleToken = await FungibleToken.load(api) +GRC20.setAdmin(admin) +let token0Address: HexString = null as any +let token1Address: HexString = null as any let invariant: Invariant = null as any const feeTier = newFeeTier(10000000000n, 1n) let poolKey: PoolKey = null as any @@ -37,19 +39,19 @@ describe('events', async function () { this.timeout(80000) invariant = await Invariant.deploy(api, admin, toPercentage(1n, 2n)) - tokenX = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) - tokenY = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) - poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + token0Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) + token1Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) + poolKey = newPoolKey(token0Address, token1Address, feeTier) await invariant.addFeeTier(admin, feeTier) await invariant.createPool(admin, poolKey, toSqrtPrice(1n, 0n)) - await tokenX.mint(admin.addressRaw, 1000000000000n) - await tokenY.mint(admin.addressRaw, 1000000000000n) - await tokenX.approve(admin, invariant.programId(), 1000000000000n) - await tokenY.approve(admin, invariant.programId(), 1000000000000n) - await invariant.depositSingleToken(admin, tokenX.programId(), 1000000000000n) - await invariant.depositSingleToken(admin, tokenY.programId(), 1000000000000n) + await GRC20.mint(admin.addressRaw, 1000000000000n, token0Address) + await GRC20.mint(admin.addressRaw, 1000000000000n, token1Address) + await GRC20.approve(admin, invariant.programId(), 1000000000000n, token0Address) + await GRC20.approve(admin, invariant.programId(), 1000000000000n, token1Address) + await invariant.depositSingleToken(admin, token0Address, 1000000000000n) + await invariant.depositSingleToken(admin, token1Address, 1000000000000n) }) it('create position event', async function () { diff --git a/sdk/tests/example.test.ts b/sdk/tests/example.test.ts index 041baf9..23238e1 100644 --- a/sdk/tests/example.test.ts +++ b/sdk/tests/example.test.ts @@ -12,30 +12,29 @@ import { GearKeyring, HexString } from '@gear-js/api' import { Network } from '../src/consts' import { Invariant } from '../src/invariant' import { assert } from 'chai' -import { FungibleToken } from '../src/erc20' +import { FungibleToken } from '../src/erc20.js' import { Pool, Tick, Position } from '../src/schema' import { getLiquidityByY, toPercentage, toPrice } from 'invariant-vara-wasm' +import { sortTokens } from '../src/test-utils.js' const api = await initGearApi({ providerAddress: Network.Local }) const admin = await GearKeyring.fromSuri('//Alice') - +const GRC20 = await FungibleToken.load(api) +GRC20.setAdmin(admin) let token0Address: HexString = null as any let token1Address: HexString = null as any -{ - const token0 = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 12n) - const token1 = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 12n) - await token0.mint(admin.addressRaw, 1000000000000000000000000000000n) - await token1.mint(admin.addressRaw, 1000000000000000000000000000000n) - token0Address = token0.programId() - token1Address = token1.programId() -} - const INVARIANT_ADDRESS = (await Invariant.deploy(api, admin, 0n)).programId() let unsub: Promise = null as any describe('sdk guide snippets', async function () { this.timeout(80000) - + this.beforeEach(async function () { + token0Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 12n) + token1Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 12n) + ;[token0Address, token1Address] = sortTokens(token0Address, token1Address) + await GRC20.mint(admin.addressRaw, 1000000000000000000000000000000n, token0Address) + await GRC20.mint(admin.addressRaw, 1000000000000000000000000000000n, token1Address) + }) this.beforeAll(async function () { unsub = subscribeToNewHeads(api) }) @@ -83,13 +82,9 @@ describe('sdk guide snippets', async function () { // print amount of token x and y we need to give to create position based on parameters we passed console.log(tokenXAmount, tokenYAmount) - // load token contracts - const tokenX = await FungibleToken.load(api, poolKey.tokenX) - const tokenY = await FungibleToken.load(api, poolKey.tokenY) - // approve transfers of both tokens - await tokenX.approve(admin, invariant.programId(), tokenXAmount) - await tokenY.approve(admin, invariant.programId(), tokenYAmount) + await GRC20.approve(admin, invariant.programId(), tokenXAmount, poolKey.tokenX) + await GRC20.approve(admin, invariant.programId(), tokenYAmount, poolKey.tokenY) // deposit tokens in the contract await invariant.depositTokenPair( @@ -98,6 +93,10 @@ describe('sdk guide snippets', async function () { [poolKey.tokenY, tokenYAmount] ) + // check user balances + const userBalances = await invariant.getUserBalances(admin.addressRaw) + console.log(userBalances) + // create position const createPositionResult = await invariant.createPosition( admin, @@ -125,7 +124,7 @@ describe('sdk guide snippets', async function () { const amount = 6n * 10n ** 12n // approve token x transfer - await tokenX.approve(admin, invariant.programId(), amount) + await GRC20.approve(admin, invariant.programId(), amount, poolKey.tokenX) // deposit tokenX await invariant.depositSingleToken(admin, poolKey.tokenX, amount) @@ -162,7 +161,7 @@ describe('sdk guide snippets', async function () { console.log(fees) // get balance of a specific token before claiming position fees and print it - const adminBalanceBeforeClaim = await tokenX.balanceOf(admin.addressRaw) + const adminBalanceBeforeClaim = await GRC20.balanceOf(admin.addressRaw, token0Address) console.log(adminBalanceBeforeClaim) // specify position id @@ -175,7 +174,7 @@ describe('sdk guide snippets', async function () { console.log(withdrawResult) // get balance of a specific token after claiming position fees and print it - const adminBalanceAfterClaim = await tokenX.balanceOf(admin.addressRaw) + const adminBalanceAfterClaim = await GRC20.balanceOf(admin.addressRaw, token0Address) console.log(adminBalanceAfterClaim) const receiver = await GearKeyring.fromSuri('//Bob') @@ -183,7 +182,10 @@ describe('sdk guide snippets', async function () { const positionToTransfer = await invariant.getPosition(admin.addressRaw, 0n) // Transfer position from admin (signer) to receiver await invariant.transferPosition(admin, 0n, receiver.addressRaw) + // load received position const receiverPosition = await invariant.getPosition(receiver.addressRaw, 0n) + + // ensure that the position are equal assert.deepEqual(positionToTransfer, receiverPosition) console.log(receiverPosition) @@ -192,8 +194,8 @@ describe('sdk guide snippets', async function () { // ### // fetch user balances before removal - const adminToken0BalanceBeforeRemove = await tokenX.balanceOf(admin.addressRaw) - const adminToken1BalanceBeforeRemove = await tokenY.balanceOf(admin.addressRaw) + const adminToken0BalanceBeforeRemove = await GRC20.balanceOf(admin.addressRaw, token0Address) + const adminToken1BalanceBeforeRemove = await GRC20.balanceOf(admin.addressRaw, token1Address) console.log(adminToken0BalanceBeforeRemove, adminToken1BalanceBeforeRemove) // remove position @@ -203,8 +205,8 @@ describe('sdk guide snippets', async function () { await invariant.withdrawTokenPair(admin, [poolKey.tokenX, null], [poolKey.tokenY, null]) // get balance of a specific token after removing position - const adminToken0BalanceAfterRemove = await tokenX.balanceOf(admin.addressRaw) - const adminToken1BalanceAfterRemove = await tokenY.balanceOf(admin.addressRaw) + const adminToken0BalanceAfterRemove = await GRC20.balanceOf(admin.addressRaw, token0Address) + const adminToken1BalanceAfterRemove = await GRC20.balanceOf(admin.addressRaw, token1Address) // print balances console.log(adminToken0BalanceAfterRemove, adminToken1BalanceAfterRemove) @@ -212,39 +214,38 @@ describe('sdk guide snippets', async function () { it('sdk guide - using grc20', async function () { this.timeout(80000) - // deploy token, it will return token object - const token0 = await FungibleToken.deploy(api, admin, 'CoinA', 'ACOIN', 12n) - // token address can be accessed by calling programId method - const token1Address = ( - await FungibleToken.deploy(api, admin, 'CoinB', 'BCOIN', 12n) - ).programId() + // deploy token, it will return token address + const token0Address = await FungibleToken.deploy(api, admin, 'CoinA', 'ACOIN', 12n) + const token1Address = await FungibleToken.deploy(api, admin, 'CoinB', 'BCOIN', 12n) - // load token by passing its address (you can use existing one), it allows you to interact with it - // eslint disable-next-line - const token1 = await FungibleToken.load(api, token1Address) + // loading token class, allows you to interact with token contracts + const GRC20 = await FungibleToken.load(api) + // set admin account if you want to mint or burn tokens + // by default admin is set to the deployer of the contract + GRC20.setAdmin(admin) // interact with token 0 - const admin0Balance = await token0.balanceOf(admin.addressRaw) + const admin0Balance = await GRC20.balanceOf(admin.addressRaw, token0Address) console.log(admin0Balance) // if you want to interact with different token, // simply pass different contract address as an argument - const admin1Balance = await token1.balanceOf(admin.addressRaw) + const admin1Balance = await GRC20.balanceOf(admin.addressRaw, token1Address) console.log(admin1Balance) // fetch token metadata for previously deployed token0 - const token0Name = await token0.name() - const token0Symbol = await token0.symbol() - const token0Decimals = await token0.decimals() + const token0Name = await GRC20.name(token0Address) + const token0Symbol = await GRC20.symbol(token0Address) + const token0Decimals = await GRC20.decimals(token0Address) console.log(token0Name, token0Symbol, token0Decimals) // load diffrent token and load its metadata - const token1Name = await token1.name() - const token1Symbol = await token1.symbol() - const token1Decimals = await token1.decimals() + const token1Name = await GRC20.name(token1Address) + const token1Symbol = await GRC20.symbol(token1Address) + const token1Decimals = await GRC20.decimals(token1Address) console.log(token1Name, token1Symbol, token1Decimals) }) this.afterAll(async function () { - await unsub.then((unsub) => unsub()) + await unsub.then(unsub => unsub()) }) }) diff --git a/sdk/tests/fungible-token.test.ts b/sdk/tests/fungible-token.test.ts index c3c5689..f0d1ef4 100644 --- a/sdk/tests/fungible-token.test.ts +++ b/sdk/tests/fungible-token.test.ts @@ -9,7 +9,9 @@ const api = await initGearApi({ providerAddress: Network.Local }) const account0 = await GearKeyring.fromSuri('//Alice') const account1 = await GearKeyring.fromSuri('//Bob') let unsub: Promise | null = null -let token: FungibleToken = null as any +const GRC20: FungibleToken = await FungibleToken.load(api) +GRC20.setAdmin(account0) +let tokenAddress = null as any describe('FungibleToken', function () { before(function () { unsub = subscribeToNewHeads(api) @@ -17,56 +19,56 @@ describe('FungibleToken', function () { this.timeout(200000) beforeEach(async function () { - token = await FungibleToken.deploy(api, account0, 'Coin', 'COIN', 12n) + tokenAddress = await FungibleToken.deploy(api, account0, 'Coin', 'COIN', 12n) }) it('mint and burn', async function () { - const resMint = await token.mint(account0.addressRaw, 100n) + const resMint = await GRC20.mint(account0.addressRaw, 100n, tokenAddress) assert.strictEqual(resMint, true) - await token.balanceOf(account0.addressRaw).then(balance => { + await GRC20.balanceOf(account0.addressRaw, tokenAddress).then(balance => { assert.deepStrictEqual(balance, 100n) }) - const resBurn = await token.burn(account0.addressRaw, 100n) + const resBurn = await GRC20.burn(account0.addressRaw, 100n, tokenAddress) assert.strictEqual(resBurn, true) - await token.balanceOf(account0.addressRaw).then(balance => { + await GRC20.balanceOf(account0.addressRaw, tokenAddress).then(balance => { assert.deepStrictEqual(balance, 0n) }) }) it('mint and burn tx', async function () { { - const { response } = await (await token.mintTx(account0.addressRaw, 100n)) + const { response } = await (await GRC20.mintTx(account0.addressRaw, 100n, tokenAddress)) .withAccount(account0) .signAndSend() assert.strictEqual(await response(), true) } - await token.balanceOf(account0.addressRaw).then(balance => { + await GRC20.balanceOf(account0.addressRaw, tokenAddress).then(balance => { assert.deepStrictEqual(balance, 100n) }) { - const { response } = await (await token.burnTx(account0.addressRaw, 100n)) + const { response } = await (await GRC20.burnTx(account0.addressRaw, 100n, tokenAddress)) .withAccount(account0) .signAndSend() assert.strictEqual(await response(), true) } - await token.balanceOf(account0.addressRaw).then(balance => { + await GRC20.balanceOf(account0.addressRaw, tokenAddress).then(balance => { assert.deepStrictEqual(balance, 0n) }) }) it('approve and transfer', async () => { { - const res = await token.mint(account1.addressRaw, 100n) + const res = await GRC20.mint(account1.addressRaw, 100n, tokenAddress) assert.strictEqual(res, true) } { - const res = await token.approve(account1, account0.addressRaw, 100n) + const res = await GRC20.approve(account1, account0.addressRaw, 100n, tokenAddress) assert.strictEqual(res, true) } { - const allowance = token.allowance(account1.addressRaw, account0.addressRaw) - const balance0 = token.balanceOf(account0.addressRaw) - const balance1 = token.balanceOf(account1.addressRaw) - const totalSupply = token.totalSupply() - const decimals = token.decimals() + const allowance = GRC20.allowance(account1.addressRaw, account0.addressRaw, tokenAddress) + const balance0 = GRC20.balanceOf(account0.addressRaw, tokenAddress) + const balance1 = GRC20.balanceOf(account1.addressRaw, tokenAddress) + const totalSupply = GRC20.totalSupply(tokenAddress) + const decimals = GRC20.decimals(tokenAddress) assert.deepStrictEqual(await allowance, 100n, 'allowance mismatch') assert.deepStrictEqual(await balance0, 0n, 'balance0 mismatch') assert.deepStrictEqual(await balance1, 100n, 'balance1 mismatch') @@ -74,26 +76,32 @@ describe('FungibleToken', function () { assert.deepStrictEqual(await decimals, 12n, 'decimals mismatch') } { - const res = await token.mint(account1.addressRaw, 300n) + const res = await GRC20.mint(account1.addressRaw, 300n, tokenAddress) assert.strictEqual(res, true) } await assertThrowsAsync( - token.transferFrom(account0, account1.addressRaw, account0.addressRaw, 300n), + GRC20.transferFrom(account0, account1.addressRaw, account0.addressRaw, 300n, tokenAddress), 'Error: Panic occurred: InsufficientAllowance' ) { - const res = await token.approve(account1, account0.addressRaw, 300n) + const res = await GRC20.approve(account1, account0.addressRaw, 300n, tokenAddress) expect(res).to.equal(true) } { - const res = await token.transferFrom(account0, account1.addressRaw, account0.addressRaw, 300n) + const res = await GRC20.transferFrom( + account0, + account1.addressRaw, + account0.addressRaw, + 300n, + tokenAddress + ) expect(res).to.equal(true) } { - const allowance = token.allowance(account1.addressRaw, account0.addressRaw) - const balance0 = token.balanceOf(account0.addressRaw) - const balance1 = token.balanceOf(account1.addressRaw) - const totalSupply = token.totalSupply() + const allowance = GRC20.allowance(account1.addressRaw, account0.addressRaw, tokenAddress) + const balance0 = GRC20.balanceOf(account0.addressRaw, tokenAddress) + const balance1 = GRC20.balanceOf(account1.addressRaw, tokenAddress) + const totalSupply = GRC20.totalSupply(tokenAddress) expect(await allowance).to.equal(0n) expect(await balance0).to.equal(300n) expect(await balance1).to.equal(100n) @@ -102,23 +110,23 @@ describe('FungibleToken', function () { }) it('approve and transfer tx', async () => { { - const { response } = await (await token.mintTx(account1.addressRaw, 100n)) + const { response } = await (await GRC20.mintTx(account1.addressRaw, 100n, tokenAddress)) .withAccount(account0) .signAndSend() assert.strictEqual(await response(), true) } { - const { response } = await (await token.approveTx(account0.addressRaw, 100n)) + const { response } = await (await GRC20.approveTx(account0.addressRaw, 100n, tokenAddress)) .withAccount(account1) .signAndSend() assert.strictEqual(await response(), true) } { - const allowance = token.allowance(account1.addressRaw, account0.addressRaw) - const balance0 = token.balanceOf(account0.addressRaw) - const balance1 = token.balanceOf(account1.addressRaw) - const totalSupply = token.totalSupply() - const decimals = token.decimals() + const allowance = GRC20.allowance(account1.addressRaw, account0.addressRaw, tokenAddress) + const balance0 = GRC20.balanceOf(account0.addressRaw, tokenAddress) + const balance1 = GRC20.balanceOf(account1.addressRaw, tokenAddress) + const totalSupply = GRC20.totalSupply(tokenAddress) + const decimals = GRC20.decimals(tokenAddress) assert.deepStrictEqual(await allowance, 100n, 'allowance mismatch') assert.deepStrictEqual(await balance0, 0n, 'balance0 mismatch') assert.deepStrictEqual(await balance1, 100n, 'balance1 mismatch') @@ -126,7 +134,7 @@ describe('FungibleToken', function () { assert.deepStrictEqual(await decimals, 12n, 'decimals mismatch') } { - const { response } = await (await token.mintTx(account1.addressRaw, 300n)) + const { response } = await (await GRC20.mintTx(account1.addressRaw, 300n, tokenAddress)) .withAccount(account0) .signAndSend() assert.strictEqual(await response(), true) @@ -134,7 +142,7 @@ describe('FungibleToken', function () { await assertThrowsAsync( (async () => { const { response } = await ( - await token.transferFromTx(account1.addressRaw, account0.addressRaw, 300n) + await GRC20.transferFromTx(account1.addressRaw, account0.addressRaw, 300n, tokenAddress) ) .withAccount(account0) .signAndSend() @@ -143,24 +151,24 @@ describe('FungibleToken', function () { 'Error: Panic occurred: InsufficientAllowance' ) { - const { response } = await (await token.approveTx(account0.addressRaw, 300n)) + const { response } = await (await GRC20.approveTx(account0.addressRaw, 300n, tokenAddress)) .withAccount(account1) .signAndSend() assert.strictEqual(await response(), true) } { const { response } = await ( - await token.transferFromTx(account1.addressRaw, account0.addressRaw, 300n) + await GRC20.transferFromTx(account1.addressRaw, account0.addressRaw, 300n, tokenAddress) ) .withAccount(account0) .signAndSend() assert.strictEqual(await response(), true) } { - const allowance = token.allowance(account1.addressRaw, account0.addressRaw) - const balance0 = token.balanceOf(account0.addressRaw) - const balance1 = token.balanceOf(account1.addressRaw) - const totalSupply = token.totalSupply() + const allowance = GRC20.allowance(account1.addressRaw, account0.addressRaw, tokenAddress) + const balance0 = GRC20.balanceOf(account0.addressRaw, tokenAddress) + const balance1 = GRC20.balanceOf(account1.addressRaw, tokenAddress) + const totalSupply = GRC20.totalSupply(tokenAddress) expect(await allowance).to.equal(0n) expect(await balance0).to.equal(300n) expect(await balance1).to.equal(100n) diff --git a/sdk/tests/invariant.test.ts b/sdk/tests/invariant.test.ts index ebd735b..4f8f52c 100644 --- a/sdk/tests/invariant.test.ts +++ b/sdk/tests/invariant.test.ts @@ -1,10 +1,10 @@ import 'mocha' import { initGearApi, newFeeTier, newPoolKey, subscribeToNewHeads } from '../src/utils.js' -import { GearKeyring } from '@gear-js/api' +import { GearKeyring, HexString } from '@gear-js/api' import { Network } from '../src/consts' import { Invariant } from '../src/invariant' import { assert } from 'chai' -import { FungibleToken } from '../src/erc20' +import { FungibleToken } from '../src/erc20.js' import { assertThrowsAsync } from '../src/test-utils.js' import { SqrtPrice, Tick } from '../src/schema' @@ -13,8 +13,10 @@ const admin = await GearKeyring.fromSuri('//Alice') const user = await GearKeyring.fromSuri('//Bob') let unsub: Promise | null = null -let tokenX: FungibleToken = null as any -let tokenY: FungibleToken = null as any +const GRC20: FungibleToken = await FungibleToken.load(api) +GRC20.setAdmin(admin) +let token0Address: HexString = null as any +let token1Address: HexString = null as any let invariant: Invariant = null as any const MAXu64 = 18_446_744_073_709_551_615n const initProtocolFee = 10000000000n @@ -31,10 +33,10 @@ describe('Invariant', async function () { this.beforeEach(async function () { this.timeout(40000) invariant = await Invariant.deploy(api, admin, initProtocolFee) - tokenX = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 12n) - tokenY = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 12n) - await tokenX.mint(user.addressRaw, 1000000000n) - await tokenY.mint(user.addressRaw, 1000000000n) + token0Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 12n) + token1Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 12n) + await GRC20.mint(user.addressRaw, 1000000000n, token0Address) + await GRC20.mint(user.addressRaw, 1000000000n, token1Address) }) it('should set and change protocol fee', async function () { @@ -108,17 +110,17 @@ describe('Invariant', async function () { it('should get tick and check if it is initialized', async () => { await invariant.addFeeTier(admin, feeTier) - const poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + const poolKey = newPoolKey(token0Address, token1Address, feeTier) await invariant.createPool(user, poolKey, 1000000000000000000000000n) - await tokenX.approve(user, invariant.programId(), 1000000000n) - await tokenY.approve(user, invariant.programId(), 1000000000n) + await GRC20.approve(user, invariant.programId(), 1000000000n, token0Address) + await GRC20.approve(user, invariant.programId(), 1000000000n, token1Address) - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(token0Address, token1Address, feeTier) - await invariant.depositSingleToken(user, tokenX.programId(), 1000000n) - await invariant.depositSingleToken(user, tokenY.programId(), 1000000n) + await invariant.depositSingleToken(user, token0Address, 1000000n) + await invariant.depositSingleToken(user, token1Address, 1000000n) await invariant.createPosition( user, @@ -171,12 +173,12 @@ describe('Invariant', async function () { const initSqrtPrice: SqrtPrice = 1000000000000000000000000n - const poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + const poolKey = newPoolKey(token0Address, token1Address, feeTier) await invariant.createPool(user, poolKey, initSqrtPrice) const pools = await invariant.getPools(1n, 0n) assert.deepEqual(pools.length, 1) - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(token0Address, token1Address, feeTier) assert.deepEqual(pool, { liquidity: 0n, sqrtPrice: 1000000000000000000000000n, @@ -197,7 +199,7 @@ describe('Invariant', async function () { const initSqrtPrice: SqrtPrice = 1000175003749000000000000n - const poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + const poolKey = newPoolKey(token0Address, token1Address, feeTier) assertThrowsAsync(invariant.createPool(user, poolKey, initSqrtPrice), 'Error: InvalidInitTick') }) @@ -210,13 +212,13 @@ describe('Invariant', async function () { const initSqrtPrice: SqrtPrice = 1000000000000000000000000n { - const poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + const poolKey = newPoolKey(token0Address, token1Address, feeTier) await invariant.createPool(user, poolKey, initSqrtPrice) const pools = await invariant.getPools(1n, 0n) assert.deepEqual(pools.length, 1) - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(token0Address, token1Address, feeTier) assert.deepEqual(pool, { liquidity: 0n, sqrtPrice: 1000000000000000000000000n, @@ -231,7 +233,7 @@ describe('Invariant', async function () { }) } { - const poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + const poolKey = newPoolKey(token0Address, token1Address, feeTier) await assertThrowsAsync(invariant.createPool(user, poolKey, initSqrtPrice)) } diff --git a/sdk/tests/math.test.ts b/sdk/tests/math.test.ts index eab01ec..1840a11 100644 --- a/sdk/tests/math.test.ts +++ b/sdk/tests/math.test.ts @@ -1,10 +1,10 @@ import 'mocha' import { initGearApi, newFeeTier, newPoolKey, subscribeToNewHeads } from '../src/utils.js' -import { GearKeyring } from '@gear-js/api' +import { GearKeyring, HexString } from '@gear-js/api' import { Network } from '../src/consts' import { Invariant } from '../src/invariant' import { assert } from 'chai' -import { FungibleToken } from '../src/erc20' +import { FungibleToken } from '../src/erc20.js' import { objectEquals, sortTokens } from '../src/test-utils.js' import { PoolKey, SqrtPrice } from '../src/schema' import { Position, getLiquidityByX, getLiquidityByY } from 'invariant-vara-wasm' @@ -14,8 +14,10 @@ const admin = await GearKeyring.fromSuri('//Alice') const user = await GearKeyring.fromSuri('//Bob') let unsub: Promise | null = null -let tokenX: FungibleToken = null as any -let tokenY: FungibleToken = null as any +let token0Address: HexString = null as any +let token1Address: HexString = null as any +const GRC20: FungibleToken = await FungibleToken.load(api) +GRC20.setAdmin(admin) let invariant: Invariant = null as any let poolKey: PoolKey = null as any const positionOwner = user @@ -33,23 +35,23 @@ describe('math', async function () { this.timeout(80000) invariant = await Invariant.deploy(api, admin, 10000000000n) - tokenX = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) - tokenY = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) - ;[tokenX, tokenY] = sortTokens(tokenX, tokenY) + token0Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) + token1Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) + ;[token0Address, token1Address] = sortTokens(token0Address, token1Address) - poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + poolKey = newPoolKey(token0Address, token1Address, feeTier) await invariant.addFeeTier(admin, feeTier) const initSqrtPrice: SqrtPrice = 1005012269622000000000000n await invariant.createPool(admin, poolKey, initSqrtPrice) - await tokenX.mint(admin.addressRaw, 10000000000n) - await tokenY.mint(admin.addressRaw, 10000000000n) - await tokenX.approve(admin, invariant.programId(), 10000000000n) - await tokenY.approve(admin, invariant.programId(), 10000000000n) - await invariant.depositSingleToken(admin, tokenX.programId(), 10000000000n) - await invariant.depositSingleToken(admin, tokenY.programId(), 10000000000n) + await GRC20.mint(admin.addressRaw, 10000000000n, token0Address) + await GRC20.mint(admin.addressRaw, 10000000000n, token1Address) + await GRC20.approve(admin, invariant.programId(), 10000000000n, token0Address) + await GRC20.approve(admin, invariant.programId(), 10000000000n, token1Address) + await invariant.depositSingleToken(admin, token0Address, 10000000000n) + await invariant.depositSingleToken(admin, token1Address, 10000000000n) }) it('check get liquidity by x', async function () { this.timeout(200000) @@ -58,7 +60,7 @@ describe('math', async function () { const lowerTickIndex = 80n const upperTickIndex = 120n - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(token0Address, token1Address, feeTier) getLiquidityByX(providedAmount, lowerTickIndex, upperTickIndex, pool.sqrtPrice, true) } @@ -67,7 +69,7 @@ describe('math', async function () { const lowerTickIndex = 80n const upperTickIndex = 120n - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(token0Address, token1Address, feeTier) const { l, amount } = getLiquidityByX( providedAmount, @@ -77,12 +79,12 @@ describe('math', async function () { true ) - await tokenX.mint(positionOwner.addressRaw, providedAmount) - await tokenX.approve(positionOwner, invariant.programId(), providedAmount) - await tokenY.mint(positionOwner.addressRaw, amount) - await tokenY.approve(positionOwner, invariant.programId(), amount) - await invariant.depositSingleToken(positionOwner, tokenX.programId(), providedAmount) - await invariant.depositSingleToken(positionOwner, tokenY.programId(), amount) + await GRC20.mint(positionOwner.addressRaw, providedAmount, token0Address) + await GRC20.approve(positionOwner, invariant.programId(), providedAmount, token0Address) + await GRC20.mint(positionOwner.addressRaw, amount, token1Address) + await GRC20.approve(positionOwner, invariant.programId(), amount, token1Address) + await invariant.depositSingleToken(positionOwner, token0Address, providedAmount) + await invariant.depositSingleToken(positionOwner, token1Address, amount) await invariant.createPosition( positionOwner, @@ -114,7 +116,7 @@ describe('math', async function () { const lowerTickIndex = 150n const upperTickIndex = 800n - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(token0Address, token1Address, feeTier) const { l, amount } = getLiquidityByX( providedAmount, @@ -126,9 +128,9 @@ describe('math', async function () { assert.deepEqual(amount, 0n) - await tokenX.mint(positionOwner.addressRaw, providedAmount) - await tokenX.approve(positionOwner, invariant.programId(), providedAmount) - await invariant.depositSingleToken(positionOwner, tokenX.programId(), providedAmount) + await GRC20.mint(positionOwner.addressRaw, providedAmount, token0Address) + await GRC20.approve(positionOwner, invariant.programId(), providedAmount, token0Address) + await invariant.depositSingleToken(positionOwner, token0Address, providedAmount) await invariant.createPosition( positionOwner, @@ -163,26 +165,26 @@ describe('math', async function () { const providedAmount = 47600000000n const feeTier = newFeeTier(6000000000n, 10n) - let poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + let poolKey = newPoolKey(token0Address, token1Address, feeTier) beforeEach(async function () { invariant = await Invariant.deploy(api, admin, 10000000000n) - tokenX = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) - tokenY = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) + token0Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) + token1Address = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) - poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + poolKey = newPoolKey(token0Address, token1Address, feeTier) await invariant.addFeeTier(admin, feeTier) const initSqrtPrice: SqrtPrice = 367897834491000000000000n await invariant.createPool(admin, poolKey, initSqrtPrice) - await tokenX.mint(admin.addressRaw, 10000000000n) - await tokenY.mint(admin.addressRaw, 10000000000n) - await tokenX.approve(admin, invariant.programId(), 10000000000n) - await tokenY.approve(admin, invariant.programId(), 10000000000n) - await invariant.depositSingleToken(admin, tokenX.programId(), 10000000000n) - await invariant.depositSingleToken(admin, tokenY.programId(), 10000000000n) + await GRC20.mint(admin.addressRaw, 10000000000n, token0Address) + await GRC20.mint(admin.addressRaw, 10000000000n, token1Address) + await GRC20.approve(admin, invariant.programId(), 10000000000n, token0Address) + await GRC20.approve(admin, invariant.programId(), 10000000000n, token1Address) + await invariant.depositSingleToken(admin, token0Address, 10000000000n) + await invariant.depositSingleToken(admin, token1Address, 10000000000n) }) it('check get liquidity by y', async function () { @@ -193,7 +195,7 @@ describe('math', async function () { const lowerTickIndex = -22000n const upperTickIndex = -21000n - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(token0Address, token1Address, feeTier) const { l, amount } = getLiquidityByY( providedAmount, @@ -205,9 +207,9 @@ describe('math', async function () { assert.deepEqual(amount, 0n) - await tokenY.mint(positionOwner.addressRaw, providedAmount) - await tokenY.approve(positionOwner, invariant.programId(), providedAmount) - await invariant.depositSingleToken(positionOwner, tokenY.programId(), providedAmount) + await GRC20.mint(positionOwner.addressRaw, providedAmount, token1Address) + await GRC20.approve(positionOwner, invariant.programId(), providedAmount, token1Address) + await invariant.depositSingleToken(positionOwner, token1Address, providedAmount) await invariant.createPosition( positionOwner, @@ -238,7 +240,7 @@ describe('math', async function () { const lowerTickIndex = -25000n const upperTickIndex = -19000n - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(token0Address, token1Address, feeTier) const { l, amount } = getLiquidityByY( providedAmount, @@ -248,13 +250,13 @@ describe('math', async function () { true ) - await tokenY.mint(positionOwner.addressRaw, providedAmount) - await tokenY.approve(positionOwner, invariant.programId(), providedAmount) - await tokenX.mint(positionOwner.addressRaw, amount) - await tokenX.approve(positionOwner, invariant.programId(), amount) + await GRC20.mint(positionOwner.addressRaw, providedAmount, token0Address) + await GRC20.approve(positionOwner, invariant.programId(), providedAmount, token0Address) + await GRC20.mint(positionOwner.addressRaw, amount, token1Address) + await GRC20.approve(positionOwner, invariant.programId(), amount, token1Address) - await invariant.depositSingleToken(positionOwner, tokenY.programId(), providedAmount) - await invariant.depositSingleToken(positionOwner, tokenX.programId(), amount) + await invariant.depositSingleToken(positionOwner, token0Address, providedAmount) + await invariant.depositSingleToken(positionOwner, token1Address, amount) await invariant.createPosition( positionOwner, @@ -285,7 +287,7 @@ describe('math', async function () { const lowerTickIndex = -10000n const upperTickIndex = 0n - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(token0Address, token1Address, feeTier) assert.throw(() => { getLiquidityByY(providedAmount, lowerTickIndex, upperTickIndex, pool.sqrtPrice, true) diff --git a/sdk/tests/position.test.ts b/sdk/tests/position.test.ts index bd079e8..d03f3f8 100644 --- a/sdk/tests/position.test.ts +++ b/sdk/tests/position.test.ts @@ -21,7 +21,7 @@ import { subscribeToNewHeads } from '../src/utils' import { u8aToHex } from '@polkadot/util' -import { GearKeyring } from '@gear-js/api' +import { GearKeyring, HexString } from '@gear-js/api' import { Network } from '../src/consts' const api = await initGearApi({ providerAddress: Network.Local }) @@ -29,8 +29,10 @@ const admin = await GearKeyring.fromSuri('//Alice') const user = await GearKeyring.fromSuri('//Bob') let unsub: Promise | null = null -let tokenX: FungibleToken = null as any -let tokenY: FungibleToken = null as any +let tokenXAddress: HexString = null as any +let tokenYAddress: HexString = null as any +const GRC20: FungibleToken = await FungibleToken.load(api) +GRC20.setAdmin(admin) let invariant: Invariant = null as any const lowerTickIndex = -20n const upperTickIndex = 10n @@ -49,17 +51,16 @@ describe('position', async function () { beforeEach(async function () { this.timeout(80000) invariant = await Invariant.deploy(api, admin, 10000000000n) - tokenX = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) - tokenY = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) - ;[tokenX, tokenY] = sortTokens(tokenX, tokenY) - - poolKey = newPoolKey(tokenX.programId(), tokenY.programId(), feeTier) + tokenXAddress = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) + tokenYAddress = await FungibleToken.deploy(api, admin, 'Coin', 'COIN', 0n) + ;[tokenXAddress, tokenYAddress] = sortTokens(tokenXAddress, tokenYAddress) + poolKey = newPoolKey(tokenXAddress, tokenYAddress, feeTier) await invariant.addFeeTier(admin, feeTier) await invariant.createPool(user, poolKey, 1000000000000000000000000n) - pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + pool = await invariant.getPool(tokenXAddress, tokenYAddress, feeTier) invariant.on({ ident: InvariantEvent.PositionCreatedEvent, @@ -74,13 +75,13 @@ describe('position', async function () { } }) - await tokenX.mint(user.addressRaw, 10000000000n) - await tokenY.mint(user.addressRaw, 10000000000n) - await tokenX.approve(user, invariant.programId(), 10000000000n) - await tokenY.approve(user, invariant.programId(), 10000000000n) + await GRC20.mint(user.addressRaw, 10000000000n, tokenXAddress) + await GRC20.mint(user.addressRaw, 10000000000n, tokenYAddress) + await GRC20.approve(user, invariant.programId(), 10000000000n, tokenXAddress) + await GRC20.approve(user, invariant.programId(), 10000000000n, tokenYAddress) - await invariant.depositSingleToken(user, tokenX.programId(), 10000000000n) - await invariant.depositSingleToken(user, tokenY.programId(), 10000000000n) + await invariant.depositSingleToken(user, tokenXAddress, 10000000000n) + await invariant.depositSingleToken(user, tokenYAddress, 10000000000n) await invariant.createPosition( user, @@ -125,7 +126,7 @@ describe('position', async function () { this.timeout(80000) const position = await invariant.getPosition(user.addressRaw, 0n) - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(tokenXAddress, tokenYAddress, feeTier) const providedAmount = 500n const { amount: expectedYAmount } = getLiquidityByX( @@ -213,40 +214,38 @@ describe('position', async function () { const swapper = admin //clear balances from beforeEach block - await invariant.withdrawSingleToken(positionOwner, tokenX.programId()) - await invariant.withdrawSingleToken(positionOwner, tokenY.programId()) + await invariant.withdrawSingleToken(positionOwner, tokenXAddress) + await invariant.withdrawSingleToken(positionOwner, tokenYAddress) { const amount: TokenAmount = 1000n - await tokenX.mint(swapper.addressRaw, amount) - await tokenX.approve(swapper, invariant.programId(), amount) - await invariant.depositSingleToken(swapper, tokenX.programId(), amount) + await GRC20.mint(swapper.addressRaw, amount, tokenXAddress) + await GRC20.approve(swapper, invariant.programId(), amount, tokenXAddress) + await invariant.depositSingleToken(swapper, tokenXAddress, amount) - const poolBefore = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const poolBefore = await invariant.getPool(tokenXAddress, tokenYAddress, feeTier) const targetSqrtPrice: SqrtPrice = 15258932000000000000n await invariant.swap(swapper, poolKey, true, amount, true, targetSqrtPrice) - await invariant.withdrawSingleToken(swapper, tokenY.programId()) - const poolAfter = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + await invariant.withdrawSingleToken(swapper, tokenYAddress) + const poolAfter = await invariant.getPool(tokenXAddress, tokenYAddress, feeTier) await assertThrowsAsync( - invariant.withdrawSingleToken(swapper, tokenX.programId(), amount), + invariant.withdrawSingleToken(swapper, tokenXAddress, amount), "Panic occurred: panicked with 'InvariantError: NoBalanceForTheToken'" ) - const swapperX = await tokenX.balanceOf(swapper.addressRaw) - const swapperY = await tokenY.balanceOf(swapper.addressRaw) + const swapperX = await GRC20.balanceOf(swapper.addressRaw, tokenXAddress) + const swapperY = await GRC20.balanceOf(swapper.addressRaw, tokenYAddress) assert.equal(swapperX, 0n) assert.equal(swapperY, 993n) - const invariantX = await tokenX.balanceOf(invariant.programId()) - const invariantY = await tokenY.balanceOf(invariant.programId()) - + const invariantX = await GRC20.balanceOf(invariant.programId(), tokenXAddress) + const invariantY = await GRC20.balanceOf(invariant.programId(), tokenYAddress) assert.equal(invariantX, 1500n) assert.equal(invariantY, 7n) - assert.deepEqual(poolAfter.liquidity, poolBefore.liquidity) assert.notDeepEqual(poolAfter.sqrtPrice, poolBefore.sqrtPrice) assert.deepEqual(poolAfter.currentTickIndex, lowerTickIndex) @@ -256,22 +255,21 @@ describe('position', async function () { assert.deepEqual(poolAfter.feeProtocolTokenY, 0n) } { - const positionOwnerBeforeX = await tokenX.balanceOf(positionOwner.addressRaw) - const invariantBeforeX = await tokenX.balanceOf(invariant.programId()) - + const positionOwnerBeforeX = await GRC20.balanceOf(positionOwner.addressRaw, tokenXAddress) + const invariantBeforeX = await GRC20.balanceOf(invariant.programId(), tokenXAddress) await invariant.claimFee(positionOwner, 0n) - await invariant.withdrawSingleToken(positionOwner, tokenX.programId()) + await invariant.withdrawSingleToken(positionOwner, tokenXAddress) await assertThrowsAsync( - invariant.withdrawSingleToken(positionOwner, tokenY.programId()), + invariant.withdrawSingleToken(positionOwner, tokenYAddress), "Panic occurred: panicked with 'InvariantError: NoBalanceForTheToken'" ) - const positionOwnerAfterX = await tokenX.balanceOf(positionOwner.addressRaw) + const positionOwnerAfterX = await GRC20.balanceOf(positionOwner.addressRaw, tokenXAddress) - const invariantAfterX = await tokenX.balanceOf(invariant.programId()) + const invariantAfterX = await GRC20.balanceOf(invariant.programId(), tokenXAddress) const position = await invariant.getPosition(positionOwner.addressRaw, 0n) - const pool = await invariant.getPool(tokenX.programId(), tokenY.programId(), feeTier) + const pool = await invariant.getPool(tokenXAddress, tokenYAddress, feeTier) const expectedTokensClaimed = 5n assert.deepEqual(positionOwnerAfterX - expectedTokensClaimed, positionOwnerBeforeX) diff --git a/sdk/tests/protocol-fee.test.ts b/sdk/tests/protocol-fee.test.ts index 1de81c3..710a9ff 100644 --- a/sdk/tests/protocol-fee.test.ts +++ b/sdk/tests/protocol-fee.test.ts @@ -1,9 +1,9 @@ import { initGearApi, newFeeTier, newPoolKey, subscribeToNewHeads } from '../src/utils.js' -import { GearKeyring } from '@gear-js/api' +import { GearKeyring, HexString } from '@gear-js/api' import { Network } from '../src/consts' import { Invariant } from '../src/invariant' import { assert } from 'chai' -import { FungibleToken } from '../src/erc20' +import { FungibleToken } from '../src/erc20.js' import { assertThrowsAsync } from '../src/test-utils.js' const api = await initGearApi({ providerAddress: Network.Local }) @@ -11,8 +11,10 @@ const admin = await GearKeyring.fromSuri('//Alice') const user = await GearKeyring.fromSuri('//Bob') let unsub: Promise | null = null -let token0: FungibleToken = null as any -let token1: FungibleToken = null as any +const GRC20: FungibleToken = await FungibleToken.load(api) +GRC20.setAdmin(admin) +let token0: HexString = null as any +let token1: HexString = null as any let invariant: Invariant = null as any const feeTier = newFeeTier(10000000000n, 1n) @@ -29,18 +31,18 @@ describe('protocol-fee', async function () { await invariant.addFeeTier(admin, feeTier) - const poolKey = newPoolKey(token0.programId(), token1.programId(), feeTier) + const poolKey = newPoolKey(token0, token1, feeTier) await invariant.createPool(admin, poolKey, 1000000000000000000000000n) - await token0.mint(admin.addressRaw, 10000000000000n) - await token1.mint(admin.addressRaw, 10000000000000n) + await GRC20.mint(admin.addressRaw, 10000000000000n, token0) + await GRC20.mint(admin.addressRaw, 10000000000000n, token1) - await token0.approve(admin, invariant.programId(), 10000000000000n) - await token1.approve(admin, invariant.programId(), 10000000000000n) + await GRC20.approve(admin, invariant.programId(), 10000000000000n, token0) + await GRC20.approve(admin, invariant.programId(), 10000000000000n, token1) - await invariant.depositSingleToken(admin, token0.programId(), 10000000000000n) - await invariant.depositSingleToken(admin, token1.programId(), 10000000000000n) + await invariant.depositSingleToken(admin, token0, 10000000000000n) + await invariant.depositSingleToken(admin, token1, 10000000000000n) await invariant.createPosition( admin, @@ -52,8 +54,8 @@ describe('protocol-fee', async function () { 10000000000n ) - await token0.approve(admin, invariant.programId(), 1000000000n) - await token1.approve(admin, invariant.programId(), 1000000000n) + await GRC20.approve(admin, invariant.programId(), 1000000000n, token0) + await GRC20.approve(admin, invariant.programId(), 1000000000n, token1) await invariant.swap(admin, poolKey, true, 4999n, true, 999505344804856076727628n) }) @@ -61,33 +63,33 @@ describe('protocol-fee', async function () { it('should withdraw protocol fee', async function () { this.timeout(80000) let withdrawnToken - const poolKey = newPoolKey(token0.programId(), token1.programId(), feeTier) + const poolKey = newPoolKey(token0, token1, feeTier) - if (poolKey.tokenX === token0.programId()) { + if (poolKey.tokenX === token0) { withdrawnToken = token0 } else { withdrawnToken = token1 } - await invariant.withdrawSingleToken(admin, withdrawnToken.programId()) - const token0Before = await token0.balanceOf(admin.addressRaw) - const token1Before = await token1.balanceOf(admin.addressRaw) + await invariant.withdrawSingleToken(admin, withdrawnToken) + const token0Before = await GRC20.balanceOf(admin.addressRaw, token0) + const token1Before = await GRC20.balanceOf(admin.addressRaw, token1) - const poolBefore = await invariant.getPool(token0.programId(), token1.programId(), feeTier) + const poolBefore = await invariant.getPool(token0, token1, feeTier) assert.deepEqual(poolBefore.feeProtocolTokenX, 1n, "tokenX fee mismatch") assert.deepEqual(poolBefore.feeProtocolTokenY, 0n, "tokenY fee mismatch") await invariant.withdrawProtocolFee(admin, poolKey) - const poolAfter = await invariant.getPool(token0.programId(), token1.programId(), feeTier) + const poolAfter = await invariant.getPool(token0, token1, feeTier) assert.deepEqual(poolAfter.feeProtocolTokenX, 0n, "tokenX fee mismatch") assert.deepEqual(poolAfter.feeProtocolTokenY, 0n, "tokenY fee mismatch") - await invariant.withdrawSingleToken(admin, withdrawnToken.programId()) - const token0After = await token0.balanceOf(admin.addressRaw) - const token1After = await token1.balanceOf(admin.addressRaw) + await invariant.withdrawSingleToken(admin, withdrawnToken) + const token0After = await GRC20.balanceOf(admin.addressRaw, token0) + const token1After = await GRC20.balanceOf(admin.addressRaw, token1) - if (poolKey.tokenX === token0.programId()) { + if (poolKey.tokenX === token0) { assert.deepEqual(token0Before + 1n, token0After) assert.deepEqual(token1Before, token1After) } else { @@ -98,10 +100,10 @@ describe('protocol-fee', async function () { it('should change fee receiver', async function () { this.timeout(80000) - const poolKey = newPoolKey(token0.programId(), token1.programId(), feeTier) + const poolKey = newPoolKey(token0, token1, feeTier) let withdrawnToken - if (poolKey.tokenX === token0.programId()) { + if (poolKey.tokenX === token0) { withdrawnToken = token0 } else { withdrawnToken = token1 @@ -109,10 +111,10 @@ describe('protocol-fee', async function () { await invariant.changeFeeReceiver(admin, poolKey, user.addressRaw) - const token0Before = await token0.balanceOf(user.addressRaw) - const token1Before = await token1.balanceOf(user.addressRaw) + const token0Before = await GRC20.balanceOf(user.addressRaw, token0) + const token1Before = await GRC20.balanceOf(user.addressRaw, token1) - const poolBefore = await invariant.getPool(token0.programId(), token1.programId(), feeTier) + const poolBefore = await invariant.getPool(token0, token1, feeTier) assert.strictEqual(poolBefore.feeProtocolTokenX, 1n, "tokenX fee mismatch") assert.strictEqual(poolBefore.feeProtocolTokenY, 0n, "tokenY fee mismatch") @@ -122,16 +124,16 @@ describe('protocol-fee', async function () { "Panic occurred: panicked with 'InvariantError: NotFeeReceiver'" ) - const poolAfter = await invariant.getPool(token0.programId(), token1.programId(), feeTier) + const poolAfter = await invariant.getPool(token0, token1, feeTier) assert.strictEqual(poolAfter.feeProtocolTokenX, 0n, "tokenX fee mismatch") assert.strictEqual(poolAfter.feeProtocolTokenY, 0n, "tokenY fee mismatch") - await invariant.withdrawSingleToken(user, withdrawnToken.programId()) - const token0After = await token0.balanceOf(user.addressRaw) - const token1After = await token1.balanceOf(user.addressRaw) + await invariant.withdrawSingleToken(user, withdrawnToken) + const token0After = await GRC20.balanceOf(user.addressRaw, token0) + const token1After = await GRC20.balanceOf(user.addressRaw, token1) - if (poolKey.tokenX === token0.programId()) { + if (poolKey.tokenX === token0) { assert.deepEqual(token0Before + 1n, token0After) assert.deepEqual(token1Before, token1After) } else {