From 57b01e475bbba20f1dde30211bf98bc56df3652c Mon Sep 17 00:00:00 2001 From: Arrowana Date: Wed, 26 Jul 2023 15:11:34 +1000 Subject: [PATCH 1/2] feat: ATA always allow off curve --- ts-client/src/amm/constants.ts | 2 -- ts-client/src/amm/index.ts | 45 +++++++++++++++++----------------- ts-client/src/amm/utils.ts | 36 +++++---------------------- 3 files changed, 29 insertions(+), 54 deletions(-) diff --git a/ts-client/src/amm/constants.ts b/ts-client/src/amm/constants.ts index 627545ec..6b7942c5 100644 --- a/ts-client/src/amm/constants.ts +++ b/ts-client/src/amm/constants.ts @@ -106,8 +106,6 @@ export const VAULT_BASE_KEY = new PublicKey('HWzXGcGHy4tcpYfaRDCyLNzXqBTv3E6Bttp export const POOL_BASE_KEY = new PublicKey('H9NnqW5Thn9dUzW3DRXe2xDhKjwZd4qbjngnZwEvnDuC'); -export const WRAPPED_SOL_MINT = new PublicKey('So11111111111111111111111111111111111111112'); - export const DEFAULT_SLIPPAGE = 1; export const UNLOCK_AMOUNT_BUFFER = 0.998; diff --git a/ts-client/src/amm/index.ts b/ts-client/src/amm/index.ts index ab748e5e..d0b2009b 100644 --- a/ts-client/src/amm/index.ts +++ b/ts-client/src/amm/index.ts @@ -13,7 +13,14 @@ import { ComputeBudgetProgram, } from '@solana/web3.js'; import { TokenInfo } from '@solana/spl-token-registry'; -import { AccountLayout, ASSOCIATED_TOKEN_PROGRAM_ID, MintLayout, TOKEN_PROGRAM_ID, u64 } from '@solana/spl-token'; +import { + AccountLayout, + ASSOCIATED_TOKEN_PROGRAM_ID, + MintLayout, + NATIVE_MINT, + TOKEN_PROGRAM_ID, + u64, +} from '@solana/spl-token'; import VaultImpl, { calculateWithdrawableAmount, getVaultPdas } from '@mercurial-finance/vault-sdk'; import invariant from 'invariant'; import { @@ -27,7 +34,7 @@ import { VaultProgram, WithdrawQuote, } from './types'; -import { ERROR, SEEDS, WRAPPED_SOL_MINT, UNLOCK_AMOUNT_BUFFER, FEE_OWNER } from './constants'; +import { ERROR, SEEDS, UNLOCK_AMOUNT_BUFFER, FEE_OWNER } from './constants'; import { StableSwap, SwapCurve, TradeDirection } from './curve'; import { ConstantProductSwap } from './curve/constant-product'; import { @@ -51,7 +58,6 @@ import { } from './utils'; type Opt = { - allowOwnerOffCurve?: boolean; cluster: Cluster; }; @@ -132,7 +138,6 @@ const deserializeAccountsBuffer = (accountInfoMap: Map) export default class AmmImpl implements AmmImplementation { private opt: Opt = { cluster: 'mainnet-beta', - allowOwnerOffCurve: false, }; private constructor( @@ -241,11 +246,11 @@ export default class AmmImpl implements AmmImplementation { const payerPoolLp = await getAssociatedTokenAccount(lpMint, payer); - if (tokenInfoA.address === WRAPPED_SOL_MINT.toBase58()) { + if (tokenInfoA.address === NATIVE_MINT.toBase58()) { preInstructions = preInstructions.concat(wrapSOLInstruction(payer, payerTokenA, BigInt(tokenAAmount.toString()))); } - if (tokenInfoB.address === WRAPPED_SOL_MINT.toBase58()) { + if (tokenInfoB.address === NATIVE_MINT.toBase58()) { preInstructions = preInstructions.concat(wrapSOLInstruction(payer, payerTokenB, BigInt(tokenBAmount.toString()))); } @@ -290,7 +295,6 @@ export default class AmmImpl implements AmmImplementation { connection: Connection, poolList: Array<{ pool: PublicKey; tokenInfoA: TokenInfo; tokenInfoB: TokenInfo }>, opt?: { - allowOwnerOffCurve?: boolean; cluster?: Cluster; programId?: string; }, @@ -457,7 +461,6 @@ export default class AmmImpl implements AmmImplementation { swapCurve, depegAccounts, { - allowOwnerOffCurve: opt?.allowOwnerOffCurve, cluster, }, ); @@ -494,7 +497,6 @@ export default class AmmImpl implements AmmImplementation { opt?: { programId?: string; vaultSeedBaseKey?: PublicKey; - allowOwnerOffCurve?: boolean; cluster?: Cluster; }, ): Promise { @@ -593,7 +595,6 @@ export default class AmmImpl implements AmmImplementation { swapCurve, depegAccounts, { - allowOwnerOffCurve: opt?.allowOwnerOffCurve, cluster, }, ); @@ -747,7 +748,7 @@ export default class AmmImpl implements AmmImplementation { * @returns The amount of tokens the user has. */ public async getUserBalance(owner: PublicKey) { - const account = await getAssociatedTokenAccount(this.poolState.lpMint, owner, this.opt.allowOwnerOffCurve); + const account = await getAssociatedTokenAccount(this.poolState.lpMint, owner); if (!account) return new BN(0); const parsedAccountInfo = await this.program.provider.connection.getParsedAccountInfo(account); @@ -861,15 +862,15 @@ export default class AmmImpl implements AmmImplementation { createUserSourceIx && preInstructions.push(createUserSourceIx); createUserDestinationIx && preInstructions.push(createUserDestinationIx); - if (sourceToken.equals(WRAPPED_SOL_MINT)) { + if (sourceToken.equals(NATIVE_MINT)) { preInstructions = preInstructions.concat( wrapSOLInstruction(owner, userSourceToken, BigInt(inAmountLamport.toString())), ); } const postInstructions: Array = []; - if (WRAPPED_SOL_MINT.equals(destinationToken)) { - const unwrapSOLIx = await unwrapSOLInstruction(owner, this.opt.allowOwnerOffCurve); + if (NATIVE_MINT.equals(destinationToken)) { + const unwrapSOLIx = await unwrapSOLInstruction(owner); unwrapSOLIx && postInstructions.push(unwrapSOLIx); } @@ -1082,20 +1083,20 @@ export default class AmmImpl implements AmmImplementation { createTokenBIx && preInstructions.push(createTokenBIx); createLpMintIx && preInstructions.push(createLpMintIx); - if (WRAPPED_SOL_MINT.equals(new PublicKey(this.tokenA.address))) { + if (NATIVE_MINT.equals(new PublicKey(this.tokenA.address))) { preInstructions = preInstructions.concat( wrapSOLInstruction(owner, userAToken, BigInt(tokenAInAmount.toString())), ); } - if (WRAPPED_SOL_MINT.equals(new PublicKey(this.tokenB.address))) { + if (NATIVE_MINT.equals(new PublicKey(this.tokenB.address))) { preInstructions = preInstructions.concat( wrapSOLInstruction(owner, userBToken, BigInt(tokenBInAmount.toString())), ); } const postInstructions: Array = []; - if ([this.tokenA.address, this.tokenB.address].includes(WRAPPED_SOL_MINT.toBase58())) { - const closeWrappedSOLIx = await unwrapSOLInstruction(owner, this.opt.allowOwnerOffCurve); + if ([this.tokenA.address, this.tokenB.address].includes(NATIVE_MINT.toBase58())) { + const closeWrappedSOLIx = await unwrapSOLInstruction(owner); closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx); } @@ -1238,7 +1239,7 @@ export default class AmmImpl implements AmmImplementation { const preInstructions: Array = []; const [[userAToken, createUserAIx], [userBToken, createUserBIx], [userPoolLp, createLpTokenIx]] = await Promise.all( [this.poolState.tokenAMint, this.poolState.tokenBMint, this.poolState.lpMint].map((key) => - getOrCreateATAInstruction(key, owner, this.program.provider.connection, this.opt.allowOwnerOffCurve), + getOrCreateATAInstruction(key, owner, this.program.provider.connection), ), ); @@ -1247,8 +1248,8 @@ export default class AmmImpl implements AmmImplementation { createLpTokenIx && preInstructions.push(createLpTokenIx); const postInstructions: Array = []; - if ([this.tokenA.address, this.tokenB.address].includes(WRAPPED_SOL_MINT.toBase58())) { - const closeWrappedSOLIx = await unwrapSOLInstruction(owner, this.opt.allowOwnerOffCurve); + if ([this.tokenA.address, this.tokenB.address].includes(NATIVE_MINT.toBase58())) { + const closeWrappedSOLIx = await unwrapSOLInstruction(owner); closeWrappedSOLIx && postInstructions.push(closeWrappedSOLIx); } @@ -1305,7 +1306,7 @@ export default class AmmImpl implements AmmImplementation { private async createATAPreInstructions(owner: PublicKey, mintList: Array) { return Promise.all( mintList.map((mint) => { - return getOrCreateATAInstruction(mint, owner, this.program.provider.connection, this.opt.allowOwnerOffCurve); + return getOrCreateATAInstruction(mint, owner, this.program.provider.connection); }), ); } diff --git a/ts-client/src/amm/utils.ts b/ts-client/src/amm/utils.ts index 844259b7..30eae345 100644 --- a/ts-client/src/amm/utils.ts +++ b/ts-client/src/amm/utils.ts @@ -15,6 +15,7 @@ import { AccountInfo as AccountInfoInt, AccountLayout, u64, + NATIVE_MINT, } from '@solana/spl-token'; import { AccountInfo, @@ -30,7 +31,6 @@ import invariant from 'invariant'; import { CURVE_TYPE_ACCOUNTS, ERROR, - WRAPPED_SOL_MINT, PROGRAM_ID, VIRTUAL_PRICE_PRECISION, PERMISSIONLESS_AMP, @@ -89,35 +89,18 @@ export const getMinAmountWithSlippage = (amount: BN, slippageRate: number) => { return amount.mul(new BN(slippage)).div(new BN(10000)); }; -export const getAssociatedTokenAccount = async ( - tokenMint: PublicKey, - owner: PublicKey, - allowOwnerOffCurve: boolean = false, -) => { - return await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - tokenMint, - owner, - allowOwnerOffCurve, - ); +export const getAssociatedTokenAccount = async (tokenMint: PublicKey, owner: PublicKey) => { + return await Token.getAssociatedTokenAddress(ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, tokenMint, owner, true); }; export const getOrCreateATAInstruction = async ( tokenMint: PublicKey, owner: PublicKey, connection: Connection, - allowOwnerOffCurve?: boolean, ): Promise<[PublicKey, TransactionInstruction?]> => { let toAccount; try { - toAccount = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - tokenMint, - owner, - allowOwnerOffCurve ?? false, - ); + toAccount = await getAssociatedTokenAccount(tokenMint, owner); const account = await connection.getAccountInfo(toAccount); if (!account) { const ix = Token.createAssociatedTokenAccountInstruction( @@ -159,15 +142,8 @@ export const wrapSOLInstruction = (from: PublicKey, to: PublicKey, amount: bigin ]; }; -export const unwrapSOLInstruction = async (owner: PublicKey, allowOwnerOffCurve?: boolean) => { - const wSolATAAccount = await Token.getAssociatedTokenAddress( - ASSOCIATED_TOKEN_PROGRAM_ID, - TOKEN_PROGRAM_ID, - WRAPPED_SOL_MINT, - owner, - allowOwnerOffCurve ?? false, - ); - +export const unwrapSOLInstruction = async (owner: PublicKey) => { + const wSolATAAccount = await getAssociatedTokenAccount(NATIVE_MINT, owner); if (wSolATAAccount) { const closedWrappedSolInstruction = Token.createCloseAccountInstruction( TOKEN_PROGRAM_ID, From cd410913dd6b83a0e5a5bb30f63cee7b0d1eb70e Mon Sep 17 00:00:00 2001 From: Arrowana Date: Thu, 27 Jul 2023 14:18:09 +1000 Subject: [PATCH 2/2] bump version to 0.4.7 --- ts-client/package.json | 4 ++-- ts-client/pnpm-lock.yaml | 8 ++++---- ts-client/src/amm/tests/utils/index.ts | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ts-client/package.json b/ts-client/package.json index f707796a..dba09bd5 100644 --- a/ts-client/package.json +++ b/ts-client/package.json @@ -1,6 +1,6 @@ { "name": "@mercurial-finance/dynamic-amm-sdk", - "version": "0.4.6", + "version": "0.4.7", "description": "Mercurial Vaults SDK is a typescript library that allows you to interact with Mercurial v2's AMM.", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", @@ -13,7 +13,7 @@ "dist" ], "dependencies": { - "@mercurial-finance/vault-sdk": "0.5.0", + "@mercurial-finance/vault-sdk": "0.5.1", "@project-serum/anchor": "0.24.2", "@project-serum/borsh": "^0.2.5", "@saberhq/anchor-contrib": "1.13.32", diff --git a/ts-client/pnpm-lock.yaml b/ts-client/pnpm-lock.yaml index fd8dbd1b..921f82cc 100644 --- a/ts-client/pnpm-lock.yaml +++ b/ts-client/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@mercurial-finance/vault-sdk': - specifier: 0.5.0 - version: 0.5.0(@saberhq/solana-contrib@1.14.11)(@saberhq/token-utils@1.13.32) + specifier: 0.5.1 + version: 0.5.1(@saberhq/solana-contrib@1.14.11)(@saberhq/token-utils@1.13.32) '@project-serum/anchor': specifier: 0.24.2 version: 0.24.2 @@ -980,8 +980,8 @@ packages: - utf-8-validate dev: false - /@mercurial-finance/vault-sdk@0.5.0(@saberhq/solana-contrib@1.14.11)(@saberhq/token-utils@1.13.32): - resolution: {integrity: sha512-zdn9/9XNJepBX9f4drd1ID7S5rZX6oWm3ojV4Ga63qqX5oy8/x01vSj7MOZr3H55ylqozBjKLzucpMWbM+Gsaw==} + /@mercurial-finance/vault-sdk@0.5.1(@saberhq/solana-contrib@1.14.11)(@saberhq/token-utils@1.13.32): + resolution: {integrity: sha512-cnjQAxEULFdcuZfQVGJcoFRmMIh3nULwUU8/liQa9epF2q2YnLols0GpFVyl+lBZrNvSjs6F5/2lstMsEs4lfA==} dependencies: '@blockworks-foundation/mango-client': 3.6.20 '@mercurial-finance/apricot-sdk': 0.17.6 diff --git a/ts-client/src/amm/tests/utils/index.ts b/ts-client/src/amm/tests/utils/index.ts index fc1f0248..7d125967 100644 --- a/ts-client/src/amm/tests/utils/index.ts +++ b/ts-client/src/amm/tests/utils/index.ts @@ -1,8 +1,7 @@ import { Wallet } from '@project-serum/anchor'; import { bs58 } from '@project-serum/anchor/dist/cjs/utils/bytes'; -import { Connection, Keypair, PublicKey } from '@solana/web3.js'; +import { Connection, Keypair, LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js'; -const LAMPORTS_PER_SOL = 1e9; export const airDropSol = async (connection: Connection, publicKey: PublicKey, amount = 1) => { try { const airdropSignature = await connection.requestAirdrop(publicKey, amount * LAMPORTS_PER_SOL);