Skip to content

Commit

Permalink
Create a helper function for creating splash pools (#198)
Browse files Browse the repository at this point in the history
* Create a helper function for creating splash pools

* Version bump

* Tweak

* Tweaks

* Tweak

* Comment

* Update whirlpool-client-impl.ts
  • Loading branch information
wjthieme authored Aug 14, 2024
1 parent af1503e commit 0c8f482
Show file tree
Hide file tree
Showing 5 changed files with 493 additions and 9 deletions.
2 changes: 1 addition & 1 deletion legacy-sdk/whirlpool/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@orca-so/whirlpools-sdk",
"version": "0.13.3",
"version": "0.13.4",
"description": "Typescript SDK to interact with Orca's Whirlpool program.",
"license": "Apache-2.0",
"main": "dist/index.js",
Expand Down
125 changes: 124 additions & 1 deletion legacy-sdk/whirlpool/src/impl/whirlpool-client-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ import {
WhirlpoolAccountFetcherInterface,
} from "../network/public/fetcher";
import { WhirlpoolRouter, WhirlpoolRouterBuilder } from "../router/public";
import { WhirlpoolData } from "../types/public";
import { MAX_TICK_INDEX, MIN_TICK_INDEX, SPLASH_POOL_TICK_SPACING, WhirlpoolData } from "../types/public";
import { getTickArrayDataForPosition } from "../utils/builder/position-builder-util";
import { PDAUtil, PoolUtil, PriceMath, TickUtil } from "../utils/public";
import { Position, Whirlpool, WhirlpoolClient } from "../whirlpool-client";
import { PositionImpl } from "./position-impl";
import { getRewardInfos, getTokenMintInfos, getTokenVaultAccountInfos } from "./util";
import { WhirlpoolImpl } from "./whirlpool-impl";
import { NO_TOKEN_EXTENSION_CONTEXT, TokenExtensionContextForPool, TokenExtensionUtil } from "../utils/public/token-extension-util";
import Decimal from "decimal.js";

export class WhirlpoolClientImpl implements WhirlpoolClient {
constructor(readonly ctx: WhirlpoolContext) {}
Expand Down Expand Up @@ -187,6 +188,128 @@ export class WhirlpoolClientImpl implements WhirlpoolClient {
return Object.fromEntries(results);
}

public async createSplashPool(
whirlpoolsConfig: Address,
tokenMintA: Address,
tokenMintB: Address,
initialPrice = new Decimal(1),
funder: Address,
opts = PREFER_CACHE
): Promise<{ poolKey: PublicKey; tx: TransactionBuilder }> {
const correctTokenOrder = PoolUtil.orderMints(tokenMintA, tokenMintB).map((addr) =>
addr.toString()
);

invariant(
correctTokenOrder[0] === tokenMintA.toString(),
"Token order needs to be flipped to match the canonical ordering (i.e. sorted on the byte repr. of the mint pubkeys)"
);

const mintInfos = await this.getFetcher().getMintInfos([tokenMintA, tokenMintB], opts);
invariant(mintInfos.size === 2, "At least one of the token mints cannot be found.");

const tokenExtensionCtx: TokenExtensionContextForPool = {
...NO_TOKEN_EXTENSION_CONTEXT,
tokenMintWithProgramA: mintInfos.get(tokenMintA.toString())!,
tokenMintWithProgramB: mintInfos.get(tokenMintB.toString())!,
};

whirlpoolsConfig = AddressUtil.toPubKey(whirlpoolsConfig);

const feeTierKey = PDAUtil.getFeeTier(
this.ctx.program.programId,
whirlpoolsConfig,
SPLASH_POOL_TICK_SPACING
).publicKey;

const whirlpoolPda = PDAUtil.getWhirlpool(
this.ctx.program.programId,
whirlpoolsConfig,
new PublicKey(tokenMintA),
new PublicKey(tokenMintB),
SPLASH_POOL_TICK_SPACING
);

const tokenDecimalsA = mintInfos.get(tokenMintA.toString())?.decimals ?? 0;
const tokenDecimalsB = mintInfos.get(tokenMintB.toString())?.decimals ?? 0;
const initSqrtPrice = PriceMath.priceToSqrtPriceX64(initialPrice, tokenDecimalsA, tokenDecimalsB);
const tokenVaultAKeypair = Keypair.generate();
const tokenVaultBKeypair = Keypair.generate();

const txBuilder = new TransactionBuilder(
this.ctx.provider.connection,
this.ctx.provider.wallet,
this.ctx.txBuilderOpts
);

const tokenBadgeA = PDAUtil.getTokenBadge(this.ctx.program.programId, whirlpoolsConfig, AddressUtil.toPubKey(tokenMintA)).publicKey;
const tokenBadgeB = PDAUtil.getTokenBadge(this.ctx.program.programId, whirlpoolsConfig, AddressUtil.toPubKey(tokenMintB)).publicKey;

const baseParams = {
initSqrtPrice,
whirlpoolsConfig,
whirlpoolPda,
tokenMintA: new PublicKey(tokenMintA),
tokenMintB: new PublicKey(tokenMintB),
tokenVaultAKeypair,
tokenVaultBKeypair,
feeTierKey,
tickSpacing: SPLASH_POOL_TICK_SPACING,
funder: new PublicKey(funder),
};

const initPoolIx = !TokenExtensionUtil.isV2IxRequiredPool(tokenExtensionCtx)
? WhirlpoolIx.initializePoolIx(this.ctx.program, baseParams)
: WhirlpoolIx.initializePoolV2Ix(this.ctx.program, {
...baseParams,
tokenProgramA: tokenExtensionCtx.tokenMintWithProgramA.tokenProgram,
tokenProgramB: tokenExtensionCtx.tokenMintWithProgramB.tokenProgram,
tokenBadgeA,
tokenBadgeB,
});

txBuilder.addInstruction(initPoolIx);

const [startTickIndex, endTickIndex] = TickUtil.getFullRangeTickIndex(SPLASH_POOL_TICK_SPACING);
const startInitializableTickIndex = TickUtil.getStartTickIndex(startTickIndex, SPLASH_POOL_TICK_SPACING);
const endInitializableTickIndex = TickUtil.getStartTickIndex(endTickIndex, SPLASH_POOL_TICK_SPACING);

const startTickArrayPda = PDAUtil.getTickArray(
this.ctx.program.programId,
whirlpoolPda.publicKey,
startInitializableTickIndex
);

const endTickArrayPda = PDAUtil.getTickArray(
this.ctx.program.programId,
whirlpoolPda.publicKey,
endInitializableTickIndex
);

txBuilder.addInstruction(
initTickArrayIx(this.ctx.program, {
startTick: startInitializableTickIndex,
tickArrayPda: startTickArrayPda,
whirlpool: whirlpoolPda.publicKey,
funder: AddressUtil.toPubKey(funder),
})
);

txBuilder.addInstruction(
initTickArrayIx(this.ctx.program, {
startTick: endInitializableTickIndex,
tickArrayPda: endTickArrayPda,
whirlpool: whirlpoolPda.publicKey,
funder: AddressUtil.toPubKey(funder),
})
);

return {
poolKey: whirlpoolPda.publicKey,
tx: txBuilder,
};
}

public async createPool(
whirlpoolsConfig: Address,
tokenMintA: Address,
Expand Down
7 changes: 7 additions & 0 deletions legacy-sdk/whirlpool/src/types/public/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,10 @@ export const WHIRLPOOL_NFT_UPDATE_AUTH = new PublicKey(
* @category Constants
*/
export const FULL_RANGE_ONLY_TICK_SPACING_THRESHOLD = 32768;


/**
* The tick spacing for splash pools.
* @category Constants
*/
export const SPLASH_POOL_TICK_SPACING = 32896;
19 changes: 19 additions & 0 deletions legacy-sdk/whirlpool/src/whirlpool-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
WhirlpoolData,
} from "./types/public";
import { TokenAccountInfo, TokenInfo, WhirlpoolRewardInfo } from "./types/public/client-types";
import Decimal from "decimal.js";

/**
* Helper class to help interact with Whirlpool Accounts with a simpler interface.
Expand Down Expand Up @@ -92,6 +93,24 @@ export interface WhirlpoolClient {
opts?: WhirlpoolAccountFetchOptions
) => Promise<TransactionBuilder[]>;

/**
* Create a Whirlpool account for a group of token A, token B and tick spacing
* @param whirlpoolConfig the address of the whirlpool config
* @param tokenMintA the address of the token A
* @param tokenMintB the address of the token B
* @param initialPrice the initial price of the pool (as x token B per 1 token A)
* @param funder the account to debit SOL from to fund the creation of the account(s)
* @return `poolKey`: The public key of the newly created whirlpool account. `tx`: The transaction containing instructions for the on-chain operations.
* @throws error when the tokens are not in the canonical byte-based ordering. To resolve this, invert the token order and the initialTick (see `TickUtil.invertTick()`, `PriceMath.invertSqrtPriceX64()`, or `PriceMath.invertPrice()`).
*/
createSplashPool: (
whirlpoolsConfig: Address,
tokenMintA: Address,
tokenMintB: Address,
initialPrice: Decimal,
funder: Address
) => Promise<{ poolKey: PublicKey; tx: TransactionBuilder }>;

/**
* Create a Whirlpool account for a group of token A, token B and tick spacing
* @param whirlpoolConfig the address of the whirlpool config
Expand Down
Loading

0 comments on commit 0c8f482

Please sign in to comment.