-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3d1b88f
commit ec23c33
Showing
6 changed files
with
774 additions
and
80 deletions.
There are no files selected for viewing
115 changes: 115 additions & 0 deletions
115
packages/core/src/univ3-helpers/__tests__/index.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import Decimal from 'decimal.js'; | ||
import { | ||
bigintToDecimal, | ||
bigintToJsbi, | ||
calculatePriceFromTick, | ||
decimalToBigint, | ||
decimalToEthers, | ||
ethersToDecimal, | ||
getNearestValidTick, | ||
getSqrtRatioAtTick, | ||
getSqrtRatioX96, | ||
getTickAtSqrtRatio, | ||
sqrtX96, | ||
} from '..'; | ||
import { FeeTier, WeiPerEther, feeTierToTickSpacing } from '@nftx/constants'; | ||
import JSBI from 'jsbi'; | ||
import { formatEther, parseEther } from 'viem'; | ||
|
||
describe('bigintToDecimal', () => { | ||
it('converts a bigint to a decimal', () => { | ||
expect(bigintToDecimal(100n)).toEqual(new Decimal(100)); | ||
}); | ||
}); | ||
|
||
describe('ethersToDecimal', () => { | ||
it('converts a ETHER bigint to a decimal', () => { | ||
expect(ethersToDecimal(WeiPerEther * 100n)).toEqual(new Decimal(100)); | ||
}); | ||
}); | ||
|
||
describe('decimalToEthers', () => { | ||
it('converts a decimal to a ETHER bigint', () => { | ||
expect(decimalToEthers(new Decimal(100))).toEqual(WeiPerEther * 100n); | ||
}); | ||
}); | ||
|
||
describe('decimalToBigint', () => { | ||
it('converts a decimal to a bigint', () => { | ||
expect(decimalToBigint(new Decimal(100))).toEqual(100n); | ||
}); | ||
}); | ||
|
||
describe('bigintToJsbi', () => { | ||
it('converts a bigint to a JSBI', () => { | ||
expect(bigintToJsbi(100n)).toEqual(JSBI.BigInt(100)); | ||
}); | ||
}); | ||
|
||
describe('sqrtX96', () => { | ||
it('calculates the X96 square root', () => { | ||
expect(formatEther(sqrtX96(WeiPerEther))).toEqual( | ||
'79228162514264337594000000000' | ||
); | ||
}); | ||
}); | ||
|
||
describe('getSqrtRatioX96', () => { | ||
it('calculates the X96 square root ratio', () => { | ||
expect( | ||
formatEther(getSqrtRatioX96(WeiPerEther, WeiPerEther * 20n)) | ||
).toEqual('17715955711.42957103'); | ||
}); | ||
}); | ||
|
||
describe('getTickAtSqrtRatio', () => { | ||
it('calculates the tick at the sqrt ratio', () => { | ||
const feetier: FeeTier = 3000; | ||
const tickSpacing = feeTierToTickSpacing(feetier); | ||
|
||
expect( | ||
getTickAtSqrtRatio( | ||
parseEther('17732633948.828052598660473723'), | ||
tickSpacing | ||
) | ||
).toEqual(-29940); | ||
}); | ||
}); | ||
|
||
describe('getSqrtRatioAtTick', () => { | ||
it('calculates the sqrt ratio at the tick', () => { | ||
expect(formatEther(getSqrtRatioAtTick(-29940))).toEqual( | ||
'17732633948.828052598660473723' | ||
); | ||
}); | ||
}); | ||
|
||
describe('calculatePriceFromTick', () => { | ||
it('calculates the price from the tick', () => { | ||
expect(formatEther(calculatePriceFromTick(-29940))).toEqual( | ||
'0.050094186778981481' | ||
); | ||
}); | ||
describe('when the tick is below the minimum tick', () => { | ||
it('returns the minimum price', () => { | ||
expect(formatEther(calculatePriceFromTick(-887220))).toEqual('0'); | ||
}); | ||
}); | ||
describe('when the tick is above the maximum tick', () => { | ||
it('returns the maximum price', () => { | ||
expect(formatEther(calculatePriceFromTick(887220))).toEqual( | ||
'338492131855223783700000000000000000000' | ||
); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getNearestValidTick', () => { | ||
it('returns the nearest valid tick', () => { | ||
const feetier: FeeTier = 3000; | ||
const tickSpacing = feeTierToTickSpacing(feetier); | ||
const tick = Math.floor(-29940 - tickSpacing / 3); | ||
|
||
expect(getNearestValidTick(tick, tickSpacing)).toEqual(-29940); | ||
}); | ||
}); |
261 changes: 261 additions & 0 deletions
261
packages/core/src/vaults/__tests__/fetchVaultActivity.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
import { formatJson } from '@nftx/utils'; | ||
import { makeFetchVaultActivity } from '../fetchVaultActivity'; | ||
|
||
let subgraphResponse: any; | ||
let querySubgraph: jest.Mock; | ||
let fetchVaultActivity: ReturnType<typeof makeFetchVaultActivity>; | ||
let args: Parameters<typeof fetchVaultActivity>[0]; | ||
let run: () => ReturnType<typeof fetchVaultActivity>; | ||
|
||
beforeEach(() => { | ||
const defaultActivityEvent = { | ||
source: 'source', | ||
date: '1', | ||
vault: { | ||
id: '0x1', | ||
vaultId: '1', | ||
}, | ||
feeReceipt: { | ||
transfers: [ | ||
{ | ||
amount: '1', | ||
}, | ||
], | ||
}, | ||
}; | ||
|
||
subgraphResponse = { | ||
activityEvents: [ | ||
// Mint | ||
{ | ||
...defaultActivityEvent, | ||
id: 'MINT-0x0', | ||
type: 'Mint', | ||
mintIds: ['1'], | ||
}, | ||
// Sell | ||
{ | ||
...defaultActivityEvent, | ||
id: 'MINT-0x0', | ||
type: 'ZapSell', | ||
mintIds: ['1'], | ||
}, | ||
// Rdeem | ||
{ | ||
...defaultActivityEvent, | ||
id: 'REDEEM-0x0', | ||
type: 'Redeem', | ||
redeemIds: ['1'], | ||
}, | ||
// Buy | ||
{ | ||
...defaultActivityEvent, | ||
id: 'REDEEM-0x0', | ||
type: 'ZapBuy', | ||
redeemIds: ['1'], | ||
}, | ||
// Swap | ||
{ | ||
...defaultActivityEvent, | ||
id: 'SWAP-0x0', | ||
type: 'Swap', | ||
swapMintIds: ['1'], | ||
swapRedeemIds: ['2'], | ||
}, | ||
// LP Stake | ||
{ | ||
...defaultActivityEvent, | ||
id: 'DEPOSIT-0x0', | ||
type: 'AddLiquidity', | ||
}, | ||
// IP Stake | ||
{ | ||
...defaultActivityEvent, | ||
id: 'DEPOSIT-0x0', | ||
type: 'InventoryDeposit', | ||
}, | ||
// LP Unstake | ||
{ | ||
...defaultActivityEvent, | ||
id: 'WITHDRAW-0x0', | ||
type: 'RemoveLiquidity', | ||
}, | ||
// IP Unstake | ||
{ | ||
...defaultActivityEvent, | ||
id: 'WITHDRAW-0x0', | ||
type: 'InventoryWithdraw', | ||
}, | ||
// Created | ||
{ | ||
...defaultActivityEvent, | ||
id: 'VAULT_CREATED-0x0', | ||
type: 'VaultCreated', | ||
}, | ||
// Updated | ||
{ | ||
...defaultActivityEvent, | ||
id: 'VAULT_FEE_UPDATE-0x0', | ||
type: 'VaultFeeUpdate', | ||
}, | ||
// Shutdown | ||
{ | ||
...defaultActivityEvent, | ||
id: 'VAULT_SHUTDOWN-0x0', | ||
type: 'VaultShutdown', | ||
}, | ||
], | ||
}; | ||
querySubgraph = jest.fn().mockResolvedValue(subgraphResponse); | ||
fetchVaultActivity = makeFetchVaultActivity({ querySubgraph }); | ||
args = { | ||
network: 1, | ||
}; | ||
run = () => fetchVaultActivity(args); | ||
}); | ||
|
||
it('returns a list of vault activity', async () => { | ||
const result = await run(); | ||
|
||
const expected = [ | ||
{ | ||
type: 'mint', | ||
vaultId: '1', | ||
vaultAddress: '0x1', | ||
date: 1, | ||
eventType: 'Mint', | ||
source: 'source', | ||
tokenIds: ['1'], | ||
txId: '0x0', | ||
feeAmount: '0', | ||
}, | ||
{ | ||
type: 'sell', | ||
vaultId: '1', | ||
vaultAddress: '0x1', | ||
date: 1, | ||
eventType: 'ZapSell', | ||
source: 'source', | ||
tokenIds: ['1'], | ||
txId: '0x0', | ||
feeAmount: '1', | ||
}, | ||
{ | ||
type: 'redeem', | ||
vaultId: '1', | ||
vaultAddress: '0x1', | ||
date: 1, | ||
eventType: 'Redeem', | ||
source: 'source', | ||
tokenIds: ['1'], | ||
txId: '0x0', | ||
feeAmount: '1', | ||
}, | ||
{ | ||
type: 'buy', | ||
vaultId: '1', | ||
vaultAddress: '0x1', | ||
date: 1, | ||
eventType: 'ZapBuy', | ||
source: 'source', | ||
tokenIds: ['1'], | ||
txId: '0x0', | ||
feeAmount: '1', | ||
}, | ||
{ | ||
type: 'swap', | ||
vaultId: '1', | ||
vaultAddress: '0x1', | ||
date: 1, | ||
eventType: 'Swap', | ||
source: 'source', | ||
tokenIds: ['1'], | ||
txId: '0x0', | ||
feeAmount: '1', | ||
swapTokenIds: ['2'], | ||
}, | ||
{ | ||
type: 'stake', | ||
vaultId: '1', | ||
vaultAddress: '0x1', | ||
date: 1, | ||
eventType: 'AddLiquidity', | ||
source: 'source', | ||
txId: '0x0', | ||
stakeType: 'liquidity', | ||
amount: '0', | ||
}, | ||
{ | ||
type: 'stake', | ||
vaultId: '1', | ||
vaultAddress: '0x1', | ||
date: 1, | ||
eventType: 'InventoryDeposit', | ||
source: 'source', | ||
txId: '0x0', | ||
stakeType: 'inventory', | ||
amount: '0', | ||
}, | ||
]; | ||
|
||
expect(result.length).toBe(7); | ||
expect(formatJson(result)).toEqual(expected); | ||
}); | ||
|
||
describe('when includeAllActivity is true', () => { | ||
beforeEach(() => { | ||
args.includeAllActivity = true; | ||
}); | ||
|
||
it('returns create update and shutdown events', async () => { | ||
const result = (await run()).slice(7); | ||
|
||
const expected = [ | ||
{ | ||
type: 'create', | ||
vaultId: '1', | ||
vaultAddress: '0x1', | ||
date: 1, | ||
eventType: 'VaultCreated', | ||
source: 'source', | ||
txId: '0x0', | ||
}, | ||
{ | ||
type: 'update', | ||
vaultId: '1', | ||
vaultAddress: '0x1', | ||
date: 1, | ||
eventType: 'VaultFeeUpdate', | ||
source: 'source', | ||
txId: '0x0', | ||
}, | ||
{ | ||
type: 'shutdown', | ||
vaultId: '1', | ||
vaultAddress: '0x1', | ||
date: 1, | ||
eventType: 'VaultShutdown', | ||
source: 'source', | ||
txId: '0x0', | ||
}, | ||
]; | ||
|
||
expect(formatJson(result)).toEqual(expected); | ||
}); | ||
}); | ||
|
||
describe('when there are more than 1000 events', () => { | ||
beforeEach(() => { | ||
querySubgraph.mockResolvedValueOnce({ | ||
...subgraphResponse, | ||
activityEvents: Array(1000).fill(subgraphResponse.activityEvents[0]), | ||
}); | ||
}); | ||
|
||
it('recursively fetches more activity', async () => { | ||
const result = await run(); | ||
|
||
expect(result.length).toBe(1007); | ||
expect(querySubgraph).toHaveBeenCalledTimes(2); | ||
}); | ||
}); |
Oops, something went wrong.