import { TokenAccount } from '@blockworks-foundation/mango-client' import useMangoStore, { mangoClient } from '../stores/useMangoStore' export async function deposit({ amount, fromTokenAcc, }: { amount: number fromTokenAcc: TokenAccount }) { const mangoAccount = useMangoStore.getState().selectedMangoAccount.current const mangoGroup = useMangoStore.getState().selectedMangoGroup.current const wallet = useMangoStore.getState().wallet.current const tokenIndex = mangoGroup.getTokenIndex(fromTokenAcc.mint) let newMangoAccount if (!mangoAccount) { const mangoAccountPk = await mangoClient.initMerpsAccount( mangoGroup, wallet ) newMangoAccount = await mangoClient.getMerpsAccount( mangoAccountPk, mangoGroup.dexProgramId ) } // TODO add to basket before deposit for non quote index if (mangoAccount || newMangoAccount) { return mangoClient.deposit( mangoGroup, newMangoAccount || mangoAccount, wallet, mangoGroup.tokens[tokenIndex].rootBank, mangoGroup.rootBankAccounts[tokenIndex].nodeBankAccounts[0].publicKey, mangoGroup.rootBankAccounts[tokenIndex].nodeBankAccounts[0].vault, fromTokenAcc.publicKey, Number(amount) ) } } // import { // createAccountInstruction, // nativeToUi, // uiToNative, // zeroKey, // } from '@blockworks-foundation/mango-client/lib/utils' // import { // Account, // Connection, // LAMPORTS_PER_SOL, // PublicKey, // SystemProgram, // SYSVAR_CLOCK_PUBKEY, // SYSVAR_RENT_PUBKEY, // Transaction, // TransactionInstruction, // TransactionSignature, // } from '@solana/web3.js' // import Wallet from '@project-serum/sol-wallet-adapter' // import { // MangoGroup, // MangoSrmAccountLayout, // MangoAccount, // MangoAccountLayout, // } from '@blockworks-foundation/mango-client' // import { // encodeMangoInstruction, // NUM_MARKETS, // NUM_TOKENS, // } from '@blockworks-foundation/mango-client/lib/layout' // import { // makeBorrowInstruction, // makeSettleBorrowInstruction, // makeSettleFundsInstruction, // makeWithdrawInstruction, // } from '@blockworks-foundation/mango-client/lib/instruction' // import { sendTransaction } from './send' // import { TOKEN_PROGRAM_ID } from './tokens' // import BN from 'bn.js' // import { // getFeeRates, // getFeeTier, // Market, // OpenOrders, // } from '@project-serum/serum' // import { Order } from '@project-serum/serum/lib/market' // import { // closeAccount, // initializeAccount, // SRM_DECIMALS, // WRAPPED_SOL_MINT, // } from '@project-serum/serum/lib/token-instructions' // import { MangoSrmAccount } from '@blockworks-foundation/mango-client/lib/client' // import { capitalize } from './index' // import { // findAssociatedTokenAddress, // createAssociatedTokenAccount, // } from './associated' export const DEFAULT_MANGO_GROUP = 'BTC_ETH_SOL_SRM_USDC' // export async function initMangoAccount( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // wallet: Wallet // ): Promise { // // Create a Solana account for the MangoAccount and allocate space // const accInstr = await createAccountInstruction( // connection, // wallet.publicKey, // MangoAccountLayout.span, // programId // ) // // Specify the accounts this instruction takes in (see program/src/instruction.rs) // const keys = [ // { isSigner: false, isWritable: false, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: accInstr.account.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_RENT_PUBKEY }, // ] // // Encode and create instruction for actual initMangoAccount instruction // const data = encodeMangoInstruction({ InitMangoAccount: {} }) // const initMangoAccountInstruction = new TransactionInstruction({ // keys, // data, // programId, // }) // // Add all instructions to one atomic transaction // const transaction = new Transaction() // transaction.add(accInstr.instruction) // transaction.add(initMangoAccountInstruction) // // Specify signers in addition to the wallet // const signers = [accInstr.account] // const functionName = 'InitMangoAccount' // const sendingMessage = `Sending ${functionName} instruction...` // const successMessage = `${functionName} instruction success` // await sendTransaction({ // transaction, // wallet, // signers, // connection, // sendingMessage, // successMessage, // }) // return accInstr.account.publicKey // } // export async function deposit( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // wallet: Wallet, // token: PublicKey, // tokenAcc: PublicKey, // quantity: number // ): Promise { // const transaction = new Transaction() // const signers = [] // let wrappedSolAccount: Account | null = null // if ( // token.equals(WRAPPED_SOL_MINT) && // tokenAcc.toBase58() === wallet.publicKey.toBase58() // ) { // wrappedSolAccount = new Account() // const lamports = Math.round(quantity * LAMPORTS_PER_SOL) + 1e7 // transaction.add( // SystemProgram.createAccount({ // fromPubkey: wallet.publicKey, // newAccountPubkey: wrappedSolAccount.publicKey, // lamports, // space: 165, // programId: TOKEN_PROGRAM_ID, // }) // ) // transaction.add( // initializeAccount({ // account: wrappedSolAccount.publicKey, // mint: WRAPPED_SOL_MINT, // owner: wallet.publicKey, // }) // ) // signers.push(wrappedSolAccount) // } // const tokenIndex = mangoGroup.getTokenIndex(token) // const nativeQuantity = uiToNative( // quantity, // mangoGroup.mintDecimals[tokenIndex] // ) // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { // isSigner: false, // isWritable: true, // pubkey: wrappedSolAccount?.publicKey ?? tokenAcc, // }, // { // isSigner: false, // isWritable: true, // pubkey: mangoGroup.vaults[tokenIndex], // }, // { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // ] // const data = encodeMangoInstruction({ // Deposit: { quantity: nativeQuantity }, // }) // const instruction = new TransactionInstruction({ keys, data, programId }) // transaction.add(instruction) // if (wrappedSolAccount) { // transaction.add( // closeAccount({ // source: wrappedSolAccount.publicKey, // destination: wallet.publicKey, // owner: wallet.publicKey, // }) // ) // } // // settle borrow // const settleKeys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // ] // const setttleBorrowsData = encodeMangoInstruction({ // SettleBorrow: { tokenIndex: new BN(tokenIndex), quantity: nativeQuantity }, // }) // const settleBorrowsInstruction = new TransactionInstruction({ // keys: settleKeys, // data: setttleBorrowsData, // programId, // }) // transaction.add(settleBorrowsInstruction) // const functionName = 'Deposit' // const sendingMessage = `Sending ${functionName} instruction...` // const successMessage = `${functionName} instruction success` // return await sendTransaction({ // transaction, // wallet, // signers, // connection, // sendingMessage, // successMessage, // }) // } // export async function initMangoAccountAndDeposit( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // wallet: Wallet, // token: PublicKey, // tokenAcc: PublicKey, // quantity: number // ): Promise> { // const transaction = new Transaction() // const signers = [] // let wrappedSolAccount: Account | null = null // if (token.equals(WRAPPED_SOL_MINT)) { // wrappedSolAccount = new Account() // const lamports = Math.round(quantity * LAMPORTS_PER_SOL) + 1e7 // transaction.add( // SystemProgram.createAccount({ // fromPubkey: wallet.publicKey, // newAccountPubkey: wrappedSolAccount.publicKey, // lamports, // space: 165, // programId: TOKEN_PROGRAM_ID, // }) // ) // transaction.add( // initializeAccount({ // account: wrappedSolAccount.publicKey, // mint: WRAPPED_SOL_MINT, // owner: wallet.publicKey, // }) // ) // signers.push(wrappedSolAccount) // } // // Create a Solana account for the MangoAccount and allocate spac // const accInstr = await createAccountInstruction( // connection, // wallet.publicKey, // MangoAccountLayout.span, // programId // ) // // Specify the accounts this instruction takes in (see program/src/instruction.rs) // const keys = [ // { isSigner: false, isWritable: false, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: accInstr.account.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_RENT_PUBKEY }, // ] // // Encode and create instruction for actual initMangoAccount instruction // const data = encodeMangoInstruction({ InitMangoAccount: {} }) // const initMangoAccountInstruction = new TransactionInstruction({ // keys, // data, // programId, // }) // // Add all instructions to one atomic transaction // transaction.add(accInstr.instruction) // transaction.add(initMangoAccountInstruction) // const tokenIndex = mangoGroup.getTokenIndex(token) // const nativeQuantity = uiToNative( // quantity, // mangoGroup.mintDecimals[tokenIndex] // ) // const depositKeys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: accInstr.account.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { // isSigner: false, // isWritable: true, // pubkey: wrappedSolAccount?.publicKey ?? tokenAcc, // }, // { // isSigner: false, // isWritable: true, // pubkey: mangoGroup.vaults[tokenIndex], // }, // { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // ] // const depositData = encodeMangoInstruction({ // Deposit: { quantity: nativeQuantity }, // }) // const instruction = new TransactionInstruction({ // keys: depositKeys, // data: depositData, // programId, // }) // transaction.add(instruction) // if (wrappedSolAccount) { // transaction.add( // closeAccount({ // source: wrappedSolAccount.publicKey, // destination: wallet.publicKey, // owner: wallet.publicKey, // }) // ) // } // // Specify signers in addition to the wallet // signers.push(accInstr.account) // const functionName = 'InitMangoAccount' // const sendingMessage = `Sending ${functionName} instruction...` // const successMessage = `${functionName} instruction success` // const trxHash = await sendTransaction({ // transaction, // wallet, // signers, // connection, // sendingMessage, // successMessage, // }) // return [accInstr.account, trxHash] // } // export async function withdraw( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // wallet: Wallet, // token: PublicKey, // quantity: number // ): Promise { // const transaction = new Transaction() // const signers = [] // let tokenAcc = await findAssociatedTokenAddress(wallet.publicKey, token) // let wrappedSolAccount: Account | null = null // if (token.equals(WRAPPED_SOL_MINT)) { // wrappedSolAccount = new Account() // tokenAcc = wrappedSolAccount.publicKey // const space = 165 // const lamports = await connection.getMinimumBalanceForRentExemption( // space, // 'singleGossip' // ) // transaction.add( // SystemProgram.createAccount({ // fromPubkey: wallet.publicKey, // newAccountPubkey: tokenAcc, // lamports, // space, // programId: TOKEN_PROGRAM_ID, // }) // ) // transaction.add( // initializeAccount({ // account: tokenAcc, // mint: WRAPPED_SOL_MINT, // owner: wallet.publicKey, // }) // ) // signers.push(wrappedSolAccount) // } else { // const tokenAccExists = await connection.getAccountInfo(tokenAcc, 'recent') // if (!tokenAccExists) { // transaction.add( // await createAssociatedTokenAccount( // wallet.publicKey, // wallet.publicKey, // token // ) // ) // } // } // const tokenIndex = mangoGroup.getTokenIndex(token) // const nativeQuantity = uiToNative( // quantity, // mangoGroup.mintDecimals[tokenIndex] // ) // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { // isSigner: false, // isWritable: true, // pubkey: tokenAcc, // }, // { // isSigner: false, // isWritable: true, // pubkey: mangoGroup.vaults[tokenIndex], // }, // { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, // { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // ...mangoAccount.openOrders.map((pubkey) => ({ // isSigner: false, // isWritable: false, // pubkey, // })), // ...mangoGroup.oracles.map((pubkey) => ({ // isSigner: false, // isWritable: false, // pubkey, // })), // ] // const data = encodeMangoInstruction({ // Withdraw: { quantity: nativeQuantity }, // }) // const instruction = new TransactionInstruction({ keys, data, programId }) // transaction.add(instruction) // if (wrappedSolAccount) { // transaction.add( // closeAccount({ // source: wrappedSolAccount.publicKey, // destination: wallet.publicKey, // owner: wallet.publicKey, // }) // ) // } // const functionName = 'Withdraw' // const sendingMessage = `Sending ${functionName} instruction...` // const successMessage = `${functionName} instruction success` // return await sendTransaction({ // transaction, // wallet, // signers, // connection, // sendingMessage, // successMessage, // }) // } // export async function borrowAndWithdraw( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // wallet: Wallet, // token: PublicKey, // withdrawQuantity: number // ): Promise { // const transaction = new Transaction() // const signers = [] // let tokenAcc = await findAssociatedTokenAddress(wallet.publicKey, token) // let wrappedSolAccount: Account | null = null // if (token.equals(WRAPPED_SOL_MINT)) { // wrappedSolAccount = new Account() // tokenAcc = wrappedSolAccount.publicKey // const space = 165 // const lamports = await connection.getMinimumBalanceForRentExemption( // space, // 'singleGossip' // ) // transaction.add( // SystemProgram.createAccount({ // fromPubkey: wallet.publicKey, // newAccountPubkey: tokenAcc, // lamports, // space, // programId: TOKEN_PROGRAM_ID, // }) // ) // transaction.add( // initializeAccount({ // account: wrappedSolAccount.publicKey, // mint: WRAPPED_SOL_MINT, // owner: wallet.publicKey, // }) // ) // signers.push(wrappedSolAccount) // } else { // const tokenAccExists = await connection.getAccountInfo(tokenAcc, 'recent') // if (!tokenAccExists) { // transaction.add( // await createAssociatedTokenAccount( // wallet.publicKey, // wallet.publicKey, // token // ) // ) // } // } // const tokenIndex = mangoGroup.getTokenIndex(token) // const tokenBalance = mangoAccount.getUiDeposit(mangoGroup, tokenIndex) // const borrowQuantity = withdrawQuantity - tokenBalance // const nativeBorrowQuantity = new BN( // Math.ceil( // borrowQuantity * Math.pow(10, mangoGroup.mintDecimals[tokenIndex]) // ) // ).add(new BN(1)) // // add a lamport to make sure that we don't run into rounding issues // // between borrow & withdraw // const borrowInstruction = makeBorrowInstruction( // programId, // mangoGroup.publicKey, // mangoAccount.publicKey, // wallet.publicKey, // tokenIndex, // mangoAccount.openOrders, // mangoGroup.oracles, // nativeBorrowQuantity // ) // transaction.add(borrowInstruction) // // uiToNative() uses Math.round causing // // errors so we use Math.floor here instead // const nativeWithdrawQuantity = new BN( // Math.floor( // withdrawQuantity * Math.pow(10, mangoGroup.mintDecimals[tokenIndex]) // ) // ) // const withdrawInstruction = makeWithdrawInstruction( // programId, // mangoGroup.publicKey, // mangoAccount.publicKey, // wallet.publicKey, // mangoGroup.signerKey, // tokenAcc, // mangoGroup.vaults[tokenIndex], // mangoAccount.openOrders, // mangoGroup.oracles, // nativeWithdrawQuantity // ) // transaction.add(withdrawInstruction) // const settleBorrowInstruction = makeSettleBorrowInstruction( // programId, // mangoGroup.publicKey, // mangoAccount.publicKey, // wallet.publicKey, // tokenIndex, // nativeWithdrawQuantity // ) // transaction.add(settleBorrowInstruction) // if (wrappedSolAccount) { // transaction.add( // closeAccount({ // source: wrappedSolAccount.publicKey, // destination: wallet.publicKey, // owner: wallet.publicKey, // }) // ) // } // const functionName = 'Borrow And Withdraw' // const sendingMessage = `Sending ${functionName} instruction...` // const successMessage = `${functionName} instruction success` // return await sendTransaction({ // transaction, // wallet, // signers, // connection, // sendingMessage, // successMessage, // }) // } // export async function borrow( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // wallet: Wallet, // token: PublicKey, // quantity: number // ): Promise { // const tokenIndex = mangoGroup.getTokenIndex(token) // const nativeQuantity = uiToNative( // quantity, // mangoGroup.mintDecimals[tokenIndex] // ) // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // ...mangoAccount.openOrders.map((pubkey) => ({ // isSigner: false, // isWritable: false, // pubkey, // })), // ...mangoGroup.oracles.map((pubkey) => ({ // isSigner: false, // isWritable: false, // pubkey, // })), // ] // const data = encodeMangoInstruction({ // Borrow: { tokenIndex: new BN(tokenIndex), quantity: nativeQuantity }, // }) // const instruction = new TransactionInstruction({ keys, data, programId }) // const transaction = new Transaction() // transaction.add(instruction) // const signers = [] // const functionName = 'Borrow' // const sendingMessage = `Sending ${functionName} instruction...` // const successMessage = `${functionName} instruction success` // return await sendTransaction({ // transaction, // wallet, // signers, // connection, // sendingMessage, // successMessage, // }) // } // export async function settleBorrow( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // wallet: Wallet, // token: PublicKey, // quantity: number // ): Promise { // const tokenIndex = mangoGroup.getTokenIndex(token) // const nativeQuantity = uiToNative( // quantity, // mangoGroup.mintDecimals[tokenIndex] // ) // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // ] // const data = encodeMangoInstruction({ // SettleBorrow: { tokenIndex: new BN(tokenIndex), quantity: nativeQuantity }, // }) // const instruction = new TransactionInstruction({ keys, data, programId }) // const transaction = new Transaction() // transaction.add(instruction) // return await packageAndSend( // transaction, // connection, // wallet, // [], // 'SettleBorrow' // ) // } // // Settle all borrows in one transaction // export async function settleAllBorrows( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // wallet: Wallet, // token: Array, // quantity: Array // ): Promise { // // Pack all transaction into one transaction // const transaction = new Transaction() // // Signer of the transaction // const signers = [] // // Add each token into transaction // token.forEach((tok: PublicKey, i: number) => { // const tokenIndex = mangoGroup.getTokenIndex(tok) // const nativeQuantity = uiToNative( // quantity[i], // mangoGroup.mintDecimals[tokenIndex] // ) // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // ] // const data = encodeMangoInstruction({ // SettleBorrow: { // tokenIndex: new BN(tokenIndex), // quantity: nativeQuantity, // }, // }) // const instruction = new TransactionInstruction({ keys, data, programId }) // transaction.add(instruction) // }) // const functionName = 'SettleBorrows' // const sendingMessage = `Sending ${functionName} instruction...` // const successMessage = `${functionName} instruction success` // return await sendTransaction({ // transaction, // connection, // wallet, // signers, // sendingMessage, // successMessage, // }) // } // /** // * If there is no mangoSrmAccount provided, it will create one in the same transaction // */ // export async function depositSrm( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // wallet: Wallet, // srmAccount: PublicKey, // quantity: number, // mangoSrmAccount?: PublicKey // ): Promise { // const transaction = new Transaction() // const additionalSigners: Account[] = [] // if (!mangoSrmAccount) { // const accInstr = await createAccountInstruction( // connection, // wallet.publicKey, // MangoSrmAccountLayout.span, // programId // ) // transaction.add(accInstr.instruction) // additionalSigners.push(accInstr.account) // mangoSrmAccount = accInstr.account.publicKey // } // const nativeQuantity = uiToNative(quantity, SRM_DECIMALS) // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoSrmAccount }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: true, pubkey: srmAccount }, // { isSigner: false, isWritable: true, pubkey: mangoGroup.srmVault }, // { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_RENT_PUBKEY }, // ] // const data = encodeMangoInstruction({ // DepositSrm: { quantity: nativeQuantity }, // }) // const instruction = new TransactionInstruction({ keys, data, programId }) // transaction.add(instruction) // await packageAndSend( // transaction, // connection, // wallet, // additionalSigners, // 'Deposit SRM' // ) // return mangoSrmAccount // } // export async function withdrawSrm( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoSrmAccount: MangoSrmAccount, // wallet: Wallet, // srmAccount: PublicKey, // quantity: number // ): Promise { // const nativeQuantity = uiToNative(quantity, SRM_DECIMALS) // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoSrmAccount.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: true, pubkey: srmAccount }, // { isSigner: false, isWritable: true, pubkey: mangoGroup.srmVault }, // { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, // { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // ] // const data = encodeMangoInstruction({ // WithdrawSrm: { quantity: nativeQuantity }, // }) // const instruction = new TransactionInstruction({ keys, data, programId }) // const transaction = new Transaction() // transaction.add(instruction) // return await packageAndSend( // transaction, // connection, // wallet, // [], // 'WithdrawSrm' // ) // } // export async function placeAndSettle( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // spotMarket: Market, // wallet: Wallet, // side: 'buy' | 'sell', // price: number, // size: number, // orderType?: 'limit' | 'ioc' | 'postOnly', // clientId?: BN // ): Promise { // orderType = orderType == undefined ? 'limit' : orderType // // orderType = orderType ?? 'limit' // const limitPrice = spotMarket.priceNumberToLots(price) // const maxBaseQuantity = spotMarket.baseSizeNumberToLots(size) // const feeTier = getFeeTier( // 0, // nativeToUi(mangoGroup.nativeSrm || 0, SRM_DECIMALS) // ) // const rates = getFeeRates(feeTier) // const maxQuoteQuantity = new BN( // maxBaseQuantity // .mul(limitPrice) // .mul(spotMarket['_decoded'].quoteLotSize) // .toNumber() * // (1 + rates.taker) // ) // console.log(maxBaseQuantity.toString(), maxQuoteQuantity.toString()) // if (maxBaseQuantity.lte(new BN(0))) { // throw new Error('size too small') // } // if (limitPrice.lte(new BN(0))) { // throw new Error('invalid price') // } // const selfTradeBehavior = 'decrementTake' // const marketIndex = mangoGroup.getMarketIndex(spotMarket) // // const vaultIndex = side === 'buy' ? mangoGroup.vaults.length - 1 : marketIndex // // Add all instructions to one atomic transaction // const transaction = new Transaction() // // Specify signers in addition to the wallet // const signers: Account[] = [] // const dexSigner = await PublicKey.createProgramAddress( // [ // spotMarket.publicKey.toBuffer(), // spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8), // ], // spotMarket.programId // ) // // Create a Solana account for the open orders account if it's missing // const openOrdersKeys: PublicKey[] = [] // for (let i = 0; i < mangoAccount.openOrders.length; i++) { // if ( // i === marketIndex && // mangoAccount.openOrders[marketIndex].equals(zeroKey) // ) { // // open orders missing for this market; create a new one now // const openOrdersSpace = OpenOrders.getLayout(mangoGroup.dexProgramId).span // const openOrdersLamports = // await connection.getMinimumBalanceForRentExemption( // openOrdersSpace, // 'singleGossip' // ) // const accInstr = await createAccountInstruction( // connection, // wallet.publicKey, // openOrdersSpace, // mangoGroup.dexProgramId, // openOrdersLamports // ) // transaction.add(accInstr.instruction) // signers.push(accInstr.account) // openOrdersKeys.push(accInstr.account.publicKey) // } else { // openOrdersKeys.push(mangoAccount.openOrders[i]) // } // } // // Only send a pre-settle instruction if open orders account already exists // if (!mangoAccount.openOrders[marketIndex].equals(zeroKey)) { // const settleFundsInstr = makeSettleFundsInstruction( // programId, // mangoGroup.publicKey, // wallet.publicKey, // mangoAccount.publicKey, // spotMarket.programId, // spotMarket.publicKey, // openOrdersKeys[marketIndex], // mangoGroup.signerKey, // spotMarket['_decoded'].baseVault, // spotMarket['_decoded'].quoteVault, // mangoGroup.vaults[marketIndex], // mangoGroup.vaults[NUM_TOKENS - 1], // dexSigner // ) // transaction.add(settleFundsInstr) // } // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // { isSigner: false, isWritable: false, pubkey: spotMarket.programId }, // { isSigner: false, isWritable: true, pubkey: spotMarket.publicKey }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].requestQueue, // }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].eventQueue, // }, // { isSigner: false, isWritable: true, pubkey: spotMarket['_decoded'].bids }, // { isSigner: false, isWritable: true, pubkey: spotMarket['_decoded'].asks }, // { // isSigner: false, // isWritable: true, // pubkey: mangoGroup.vaults[marketIndex], // }, // { // isSigner: false, // isWritable: true, // pubkey: mangoGroup.vaults[NUM_TOKENS - 1], // }, // { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].baseVault, // }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].quoteVault, // }, // { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_RENT_PUBKEY }, // { isSigner: false, isWritable: true, pubkey: mangoGroup.srmVault }, // { isSigner: false, isWritable: false, pubkey: dexSigner }, // ...openOrdersKeys.map((pubkey) => ({ // isSigner: false, // isWritable: true, // pubkey, // })), // ...mangoGroup.oracles.map((pubkey) => ({ // isSigner: false, // isWritable: false, // pubkey, // })), // ] // const data = encodeMangoInstruction({ // PlaceAndSettle: clientId // ? { // side, // limitPrice, // maxBaseQuantity, // maxQuoteQuantity, // selfTradeBehavior, // orderType, // clientId, // limit: 65535, // } // : { // side, // limitPrice, // maxBaseQuantity, // maxQuoteQuantity, // selfTradeBehavior, // orderType, // limit: 65535, // }, // }) // const placeAndSettleInstruction = new TransactionInstruction({ // keys, // data, // programId, // }) // transaction.add(placeAndSettleInstruction) // return await packageAndSend( // transaction, // connection, // wallet, // signers, // 'place order and settle' // ) // } // export async function settleFundsAndBorrows( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // wallet: Wallet, // spotMarket: Market // ): Promise { // const transaction = new Transaction() // const marketIndex = mangoGroup.getMarketIndex(spotMarket) // const dexSigner = await PublicKey.createProgramAddress( // [ // spotMarket.publicKey.toBuffer(), // spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8), // ], // spotMarket.programId // ) // const settleFundsIns = await makeSettleFundsInstruction( // programId, // mangoGroup.publicKey, // wallet.publicKey, // mangoAccount.publicKey, // spotMarket.programId, // spotMarket.publicKey, // mangoAccount.openOrders[marketIndex], // mangoGroup.signerKey, // spotMarket['_decoded'].baseVault, // spotMarket['_decoded'].quoteVault, // mangoGroup.vaults[marketIndex], // mangoGroup.vaults[mangoGroup.vaults.length - 1], // dexSigner // ) // transaction.add(settleFundsIns) // const tokenIndex = marketIndex // const quantity = mangoAccount.getUiBorrow(mangoGroup, tokenIndex) // const nativeQuantity = uiToNative( // quantity, // mangoGroup.mintDecimals[tokenIndex] // ) // const settleBorrowIns = await makeSettleBorrowInstruction( // programId, // mangoGroup.publicKey, // mangoAccount.publicKey, // wallet.publicKey, // tokenIndex, // nativeQuantity // ) // transaction.add(settleBorrowIns) // const signers = [] // return await packageAndSend( // transaction, // connection, // wallet, // signers, // 'Settle Funds' // ) // } // export async function settleFunds( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // wallet: Wallet, // spotMarket: Market // ): Promise { // const marketIndex = mangoGroup.getMarketIndex(spotMarket) // const dexSigner = await PublicKey.createProgramAddress( // [ // spotMarket.publicKey.toBuffer(), // spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8), // ], // spotMarket.programId // ) // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // { isSigner: false, isWritable: false, pubkey: spotMarket.programId }, // { isSigner: false, isWritable: true, pubkey: spotMarket.publicKey }, // { // isSigner: false, // isWritable: true, // pubkey: mangoAccount.openOrders[marketIndex], // }, // { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].baseVault, // }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].quoteVault, // }, // { // isSigner: false, // isWritable: true, // pubkey: mangoGroup.vaults[marketIndex], // }, // { // isSigner: false, // isWritable: true, // pubkey: mangoGroup.vaults[mangoGroup.vaults.length - 1], // }, // { isSigner: false, isWritable: false, pubkey: dexSigner }, // { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, // ] // const data = encodeMangoInstruction({ SettleFunds: {} }) // const instruction = new TransactionInstruction({ keys, data, programId }) // // Add all instructions to one atomic transaction // const transaction = new Transaction() // transaction.add(instruction) // const signers = [] // const functionName = 'SettleFunds' // const sendingMessage = `Sending ${functionName} instruction...` // const successMessage = `${functionName} instruction success` // return await sendTransaction({ // transaction, // wallet, // signers, // connection, // sendingMessage, // successMessage, // }) // } // export async function cancelOrderAndSettle( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // wallet: Wallet, // spotMarket: Market, // order: Order // ): Promise { // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // { isSigner: false, isWritable: false, pubkey: mangoGroup.dexProgramId }, // { isSigner: false, isWritable: true, pubkey: spotMarket.publicKey }, // { isSigner: false, isWritable: true, pubkey: spotMarket['_decoded'].bids }, // { isSigner: false, isWritable: true, pubkey: spotMarket['_decoded'].asks }, // { isSigner: false, isWritable: true, pubkey: order.openOrdersAddress }, // { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].eventQueue, // }, // ] // const data = encodeMangoInstruction({ // CancelOrder: { // side: order.side, // orderId: order.orderId, // }, // }) // const instruction = new TransactionInstruction({ keys, data, programId }) // const transaction = new Transaction() // transaction.add(instruction) // const marketIndex = mangoGroup.getMarketIndex(spotMarket) // const dexSigner = await PublicKey.createProgramAddress( // [ // spotMarket.publicKey.toBuffer(), // spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8), // ], // spotMarket.programId // ) // const settleFundsIns = await makeSettleFundsInstruction( // programId, // mangoGroup.publicKey, // wallet.publicKey, // mangoAccount.publicKey, // spotMarket.programId, // spotMarket.publicKey, // mangoAccount.openOrders[marketIndex], // mangoGroup.signerKey, // spotMarket['_decoded'].baseVault, // spotMarket['_decoded'].quoteVault, // mangoGroup.vaults[marketIndex], // mangoGroup.vaults[mangoGroup.vaults.length - 1], // dexSigner // ) // transaction.add(settleFundsIns) // const baseTokenIndex = marketIndex // const quoteTokenIndex = NUM_TOKENS - 1 // const baseTokenQuantity = mangoAccount.getUiBorrow( // mangoGroup, // baseTokenIndex // ) // const baseTokenNativeQuantity = uiToNative( // baseTokenQuantity, // mangoGroup.mintDecimals[baseTokenIndex] // ) // const quoteTokenQuantity = mangoAccount.getUiBorrow( // mangoGroup, // quoteTokenIndex // ) // const quoteTokenNativeQuantity = uiToNative( // quoteTokenQuantity, // mangoGroup.mintDecimals[quoteTokenIndex] // ) // const settleBorrowBaseToken = await makeSettleBorrowInstruction( // programId, // mangoGroup.publicKey, // mangoAccount.publicKey, // wallet.publicKey, // baseTokenIndex, // baseTokenNativeQuantity // ) // transaction.add(settleBorrowBaseToken) // const settleBorrowQuoteToken = await makeSettleBorrowInstruction( // programId, // mangoGroup.publicKey, // mangoAccount.publicKey, // wallet.publicKey, // quoteTokenIndex, // quoteTokenNativeQuantity // ) // transaction.add(settleBorrowQuoteToken) // return await packageAndSend( // transaction, // connection, // wallet, // [], // 'CancelOrder' // ) // } // export async function settleAll( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // markets: Market[], // wallet: Wallet // ): Promise { // const transaction = new Transaction() // const assetGains: number[] = new Array(NUM_TOKENS).fill(0) // for (let i = 0; i < NUM_MARKETS; i++) { // const openOrdersAccount = mangoAccount.openOrdersAccounts[i] // if (openOrdersAccount === undefined) { // continue // } else if ( // openOrdersAccount.quoteTokenFree.toNumber() + // openOrdersAccount['referrerRebatesAccrued'].toNumber() === // 0 && // openOrdersAccount.baseTokenFree.toNumber() === 0 // ) { // continue // } // assetGains[i] += openOrdersAccount.baseTokenFree.toNumber() // assetGains[NUM_TOKENS - 1] += // openOrdersAccount.quoteTokenFree.toNumber() + // openOrdersAccount['referrerRebatesAccrued'].toNumber() // const spotMarket = markets[i] // const dexSigner = await PublicKey.createProgramAddress( // [ // spotMarket.publicKey.toBuffer(), // spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8), // ], // spotMarket.programId // ) // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // { isSigner: false, isWritable: false, pubkey: spotMarket.programId }, // { isSigner: false, isWritable: true, pubkey: spotMarket.publicKey }, // { // isSigner: false, // isWritable: true, // pubkey: mangoAccount.openOrders[i], // }, // { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].baseVault, // }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].quoteVault, // }, // { isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[i] }, // { // isSigner: false, // isWritable: true, // pubkey: mangoGroup.vaults[mangoGroup.vaults.length - 1], // }, // { isSigner: false, isWritable: false, pubkey: dexSigner }, // { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, // ] // const data = encodeMangoInstruction({ SettleFunds: {} }) // const settleFundsInstruction = new TransactionInstruction({ // keys, // data, // programId, // }) // transaction.add(settleFundsInstruction) // } // const deposits = mangoAccount.getDeposits(mangoGroup) // const liabs = mangoAccount.getLiabs(mangoGroup) // for (let i = 0; i < NUM_TOKENS; i++) { // // TODO test this. maybe it hits transaction size limit // const deposit = deposits[i] + assetGains[i] // if (deposit === 0 || liabs[i] === 0) { // continue // } // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // ] // const data = encodeMangoInstruction({ // SettleBorrow: { // tokenIndex: new BN(i), // quantity: uiToNative(liabs[i] * 2, mangoGroup.mintDecimals[i]), // }, // }) // const settleBorrowsInstruction = new TransactionInstruction({ // keys, // data, // programId, // }) // transaction.add(settleBorrowsInstruction) // } // if (transaction.instructions.length === 0) { // throw new Error('No unsettled funds') // } // return await packageAndSend(transaction, connection, wallet, [], 'Settle All') // } // async function packageAndSend( // transaction: Transaction, // connection: Connection, // wallet: Wallet, // signers: Account[], // functionName: string // ): Promise { // const sendingMessage = `Sending ${functionName} instruction...` // const successMessage = `${capitalize(functionName)} instruction success` // return await sendTransaction({ // transaction, // wallet, // signers, // connection, // sendingMessage, // successMessage, // }) // } // export async function settleAllTrades( // connection: Connection, // programId: PublicKey, // mangoGroup: MangoGroup, // mangoAccount: MangoAccount, // markets: Market[], // wallet: Wallet // ): Promise { // const transaction = new Transaction() // const assetGains: number[] = new Array(NUM_TOKENS).fill(0) // for (let i = 0; i < NUM_MARKETS; i++) { // const openOrdersAccount = mangoAccount.openOrdersAccounts[i] // if (openOrdersAccount === undefined) { // continue // } else if ( // openOrdersAccount.quoteTokenFree.toNumber() === 0 && // openOrdersAccount.baseTokenFree.toNumber() === 0 // ) { // continue // } // assetGains[i] += openOrdersAccount.baseTokenFree.toNumber() // assetGains[NUM_TOKENS - 1] += openOrdersAccount.quoteTokenFree.toNumber() // const spotMarket = markets[i] // const dexSigner = await PublicKey.createProgramAddress( // [ // spotMarket.publicKey.toBuffer(), // spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8), // ], // spotMarket.programId // ) // const keys = [ // { isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey }, // { isSigner: true, isWritable: false, pubkey: wallet.publicKey }, // { isSigner: false, isWritable: true, pubkey: mangoAccount.publicKey }, // { isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }, // { isSigner: false, isWritable: false, pubkey: spotMarket.programId }, // { isSigner: false, isWritable: true, pubkey: spotMarket.publicKey }, // { // isSigner: false, // isWritable: true, // pubkey: mangoAccount.openOrders[i], // }, // { isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].baseVault, // }, // { // isSigner: false, // isWritable: true, // pubkey: spotMarket['_decoded'].quoteVault, // }, // { isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[i] }, // { // isSigner: false, // isWritable: true, // pubkey: mangoGroup.vaults[mangoGroup.vaults.length - 1], // }, // { isSigner: false, isWritable: false, pubkey: dexSigner }, // { isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID }, // ] // const data = encodeMangoInstruction({ SettleFunds: {} }) // const settleFundsInstruction = new TransactionInstruction({ // keys, // data, // programId, // }) // transaction.add(settleFundsInstruction) // } // if (transaction.instructions.length === 0) { // throw new Error('No unsettled funds') // } // return await packageAndSend( // transaction, // connection, // wallet, // [], // 'Settle All Trades' // ) // }