-
Notifications
You must be signed in to change notification settings - Fork 149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add unit tests for createPool.ts #501
base: main
Are you sure you want to change the base?
Conversation
ts-sdk/whirlpool/src/createPool.ts
Outdated
.send(); | ||
const nonRefundableRents: Lamports[] = await Promise.all( | ||
stateSpaces.map(async (space) => { | ||
const rentExemption = await rpc.getMinimumBalanceForRentExemption(BigInt(space)).send(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't do this since it would change the rpc calls it needs to make from 1 to 5 (or 6)
ts-sdk/whirlpool/src/createPool.ts
Outdated
stateSpace += getWhirlpoolSize(); | ||
stateSpaces.push( | ||
tokenProgramA === TOKEN_2022_PROGRAM_ADDRESS | ||
? getTokenSize(getAccountExtensions(mintA.data)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this a separate function (should be able to check mint.owner so mint would be the only parameter)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suspect we will need the same thing in increase_liquidity too. We can put it in token.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And then we can write a test for it 😄
setDefaultFunder(signer); | ||
}); | ||
|
||
it("Should throw an error if token mints are not ordered", async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: they are ordered, just not ordered correctly
await assert.rejects( | ||
createConcentratedLiquidityPoolInstructions(rpc, mintB, mintA, 64, 1), | ||
{ | ||
name: 'AssertionError', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it exists but is there a new AssertionError("Token order needs to be flipped to match the canonical ordering (i.e. sorted on the byte repr. of the mint pubkeys)")
createConcentratedLiquidityPoolInstructions(rpc, mintB, mintA, 64, 1), | ||
{ | ||
name: 'AssertionError', | ||
message: 'Token order needs to be flipped to match the canonical ordering (i.e. sorted on the byte repr. of the mint pubkeys)' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: we use double quotes for strings in ts (but you can run yarn format and that should format your files correctly
await createSplashPoolInstructions(rpc, mintA, mintB, price); | ||
await sendTransaction(instructions); | ||
|
||
const pool = await fetchWhirlpool(rpc, poolAddress); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would structure the test like this:
- create splash pool
- fetch maybe pool before
- fetch signer balance before
- assert pool does not exist
- send tx
- fetch maybe pool
- fetch signer blance after
- assert pool exists
- assert sqrt, mintA, mintB, and tick spacing
- assert that estInitialization cost equals difference in signer balance
That way you don't need the Should estimate initialization costs correctly
test case entirely
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And then create more tests with similar structure for:
- Splash pool with TE token
- CL pool
- CL pool with TE token
- etc.
import { | ||
SPLASH_POOL_TICK_SPACING, | ||
WHIRLPOOLS_CONFIG_ADDRESS, | ||
} from "../../src/config"; | ||
import { tickIndexToSqrtPrice } from "@orca-so/whirlpools-core"; | ||
import { fetchMint } from "@solana-program/token"; | ||
import { a } from "vitest/dist/chunks/suite.B2jumIFP.js"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
ts-sdk/whirlpool/src/createPool.ts
Outdated
.send(); | ||
const nonRefundableRents: Lamports[] = await Promise.all( | ||
stateSpaces.map(async (space) => { | ||
const rentExemption = await calculateMinimumBalance(rpc, space); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still doing the same thing where it fetches the rent 5 (or 6 times).
The way I would do it. Change the function to:
export function calculateMinimumBalance(
rent: Rent,
dataSize: number,
): Lamports {
Fetcht he rent sysvar at the beginning of this function and then instead of keeping track of stateSpace: Array<bigint>
you can just straight up keep track of estInitializationCost: Lamports
.
And then instead of doing stateSpace.push(...)
you can just do estInitializationCost += calculateMinimumBalance(rent, ...)
ts-sdk/whirlpool/src/sysvar.ts
Outdated
* @param {number} dataSize - The size of the account data in bytes. | ||
* @returns {Promise<BigInt>} The minimum balance required for rent exemption in lamports. | ||
*/ | ||
export async function calculateMinimumBalance( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you write a test for this?
const price = 10; | ||
const sqrtPrice = priceToSqrtPrice(price, 6, 6); | ||
|
||
let signerAccount = await rpc.getAccountInfo(signer.address).send(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think nicer if we implement getBalance on the mockRpc so we don't have to duplicate this every time.
assertAccountExists(pool); | ||
|
||
signerAccount = await rpc.getAccountInfo(signer.address).send(); | ||
const balanceAfter = signerAccount.value?.lamports ?? lamports(0n); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I would group all the fetch together before starting on any assertions. poolBefore together with balanceBefore, poolAfter together with balanceAfter.
const balanceChange = balanceBefore - balanceAfter; | ||
const txFee = 15000n; // 3 signing accounts * 5000 lamports | ||
const minRentExempt = balanceChange - txFee; | ||
assert.strictEqual(estInitializationCost, minRentExempt); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me see if I can make the tx fee go to 0 in bankrun so that this assertion can just become:
assert.strictEqual(estInitializationCost, balanceBefore - balanceAfter);
}); | ||
|
||
it("Should create splash pool with 1 TE token", async () => { | ||
const mint1 = await setupMint(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would set up these mints in the beforeAll as well since that will get faster execution (init the TE mint once opposed to doing it for each TE test)
}); | ||
|
||
it("Should create splash pool with 2 TE tokens", async () => { | ||
const mint1 = await setupMintTEFee(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the tests I would do (instead of trying to combine Transfer fee and 1/2 TE token tests):
- 1 TE token (without extensions)
- 2 TE tokens (without extensions)
- 1 TE token (with transfer fee)
ts-sdk/whirlpool/src/sysvar.ts
Outdated
@@ -0,0 +1,28 @@ | |||
import { fetchSysvarRent } from "@solana/sysvars"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: This should be re-exported by @solana/web3.js so you can use that as import
Title
Add unit tests for createPool.ts
Details
estInitializationCosts
in thecreateConcentratedLiquidityPool
function.