diff --git a/src/Trading/dex/jupiter/swap.js b/src/Trading/dex/jupiter/swap.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Trading/dex/jupiter/swap/buy-helper.js b/src/Trading/dex/jupiter/swap/buy-helper.js new file mode 100644 index 00000000..a69b1c1f --- /dev/null +++ b/src/Trading/dex/jupiter/swap/buy-helper.js @@ -0,0 +1,43 @@ +const swap_helper = require("./swap-helper"); +const { wallet } = require("../../../../helpers/config"); +const { getDecimals } = require("../../../../helpers/util"); +const wsol = "So11111111111111111111111111111111111111112"; +/** + * Buys a token by performing a swap transaction. + * + * @param {string} tokenIn - The token to be swapped. + * @param {number} amountTokenOut - The amount of token to be swapped. + * @param {number} slippage - The slippage tolerance for the swap. + * @returns {Promise} - A promise that resolves when the swap transaction is completed. + * @throws {Error} - If an error occurs during the swap transaction. + */ +async function buy(tokenIn, amountTokenOut, slippage) { + try { + const decimals = await getDecimals(wsol); + const convertedAmountOfTokenOut = swap_helper.convertToInteger( + amountTokenOut, + decimals + ); + const quoteResponse = await swap_helper.getQuote( + wsol, + tokenIn, + convertedAmountOfTokenOut, + slippage + ); + const wallet_PubKey = wallet.publicKey.toBase58(); + const swapTransaction = await swap_helper.getSwapTransaction( + quoteResponse, + wallet_PubKey + ); + const { confirmed, signature } = await swap_helper.finalizeTransaction( + swapTransaction + ); + if (confirmed) { + console.log("http://solscan.io/tx/" + signature); + } + } catch (error) { + console.error(error); + } +} + +module.exports = { buy }; diff --git a/src/Trading/dex/jupiter/swap/sell-helper.js b/src/Trading/dex/jupiter/swap/sell-helper.js new file mode 100644 index 00000000..bd64f1d2 --- /dev/null +++ b/src/Trading/dex/jupiter/swap/sell-helper.js @@ -0,0 +1,35 @@ +const swap_helper = require("./swap-helper"); +const { wallet } = require("../../../../helpers/config"); +const { getDecimals } = require("../../../../helpers/util"); +const wsol = "So11111111111111111111111111111111111111112"; + +async function sell(addressOfTokenOut, amountOfTokenToSell, slippage) { + try { + const decimals = await getDecimals(addressOfTokenOut); + const convertedAmountOfTokenOut = swap_helper.convertToInteger( + amountOfTokenToSell, + decimals + ); + const quoteResponse = await swap_helper.getQuote( + addressOfTokenOut, + wsol, + convertedAmountOfTokenOut, + slippage + ); + const wallet_PubKey = wallet.publicKey.toBase58(); + const swapTransaction = await swap_helper.getSwapTransaction( + quoteResponse, + wallet_PubKey + ); + const { confirmed, signature } = await swap_helper.finalizeTransaction( + swapTransaction + ); + if (confirmed) { + console.log("http://solscan.io/tx/" + signature); + } + } catch (error) { + console.error(error); + } +} + +module.exports = { sell }; diff --git a/src/Trading/dex/jupiter/swap/swap-helper.js b/src/Trading/dex/jupiter/swap/swap-helper.js new file mode 100644 index 00000000..1717269d --- /dev/null +++ b/src/Trading/dex/jupiter/swap/swap-helper.js @@ -0,0 +1,104 @@ +const { VersionedTransaction } = require("@solana/web3.js"); +const fetch = require("cross-fetch"); +const { connection, wallet, jito_fee } = require("../../../../helpers/config"); +const { + jito_executeAndConfirm, +} = require("../../../../Transactions/jito_tips_tx_executor"); +/** + * Get quote for the swap + * @param {string} addressOfTokenOut The token that we are selling + * @param {string} addressOfTokenIn The token that we are buying + * @param {number} convertedAmountOfTokenOut The amount of tokens that we are selling + * @param {number} slippage The slippage percentage + * @returns Promise + */ +async function getQuote( + tokenOut, + tokenIn, + convertedAmountOfTokenOut, + slippage +) { + const url = `https://quote-api.jup.ag/v6/quote?inputMint=${tokenIn}\&outputMint=${tokenOut}\&amount=${convertedAmountOfTokenOut}\&slippageBps=${slippage}`; + const response = await fetch(url); + const quote = await response.json(); + return quote; +} + +/** + * Get serialized transactions for the swap + * @returns {Promise} swapTransaction + */ +async function getSwapTransaction(quoteResponse, wallet_pubKey) { + try { + let body = null; + body = { + quoteResponse, + userPublicKey: wallet_pubKey, + wrapAndUnwrapSol: true, + restrictIntermediateTokens: false, + prioritizationFeeLamports: "auto", + autoMultiplier: 2, + }; + const resp = await fetch("https://quote-api.jup.ag/v6/swap", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + }); + const swapResponse = await resp.json(); + return swapResponse.swapTransaction; + } catch (error) { + throw new Error(error); + } +} +async function convertToInteger(amount, decimals) { + return Math.floor(amount * 10 ** decimals); +} + +/** + * @param {*} swapTransaction + * @returns Promise txid + */ +async function finalizeTransaction(swapTransaction) { + try { + // deserialize the transaction + const swapTransactionBuf = Buffer.from(swapTransaction, "base64"); + let transaction = VersionedTransaction.deserialize(swapTransactionBuf); + + // sign the transaction + transaction.sign([wallet]); + + const rawTransaction = transaction.serialize(); + const latestBlockhash = await connection.getLatestBlockhash(); + let { confirmed, signature } = await jito_executeAndConfirm( + rawTransaction, + wallet, + latestBlockhash, + jito_fee + ); + while (!confirmed) { + console.log("Transaction failed"); + console.log("resubmitting transaction..."); + confirmed, + (signature = await jito_executeAndConfirm( + rawTransaction, + wallet, + latestBlockhash, + jito_fee + )); + } + console.log(`Jito Transaction sent and confirmed with txid: ${signature}`); + return { confirmed, signature }; + } catch (error) { + throw new Error(error); + } + return { confirmed: false, signature: null }; +} + +module.exports = { + getQuote, + getSwapTransaction, + finalizeTransaction, + convertToInteger, +}; diff --git a/src/Trading/memecoin_trading_strategies/copy_trading/wallet_listener.js b/src/Trading/memecoin_trading_strategies/copy_trading/wallet_listener.js index 1f1ea8bd..1bcf83bf 100644 --- a/src/Trading/memecoin_trading_strategies/copy_trading/wallet_listener.js +++ b/src/Trading/memecoin_trading_strategies/copy_trading/wallet_listener.js @@ -14,7 +14,8 @@ const { currencyEquals } = require("@raydium-io/raydium-sdk"); const { sol } = require("@metaplex-foundation/js"); let walletsToListen = []; -var previous_wallet_state = {}; +var previous_trader_wallet_state = {}; +var previous_our_wallet_state = {}; // [usdc, sol, usdt, wsol] const quoteToken = [ "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", @@ -74,7 +75,7 @@ async function listenToWallets() { // Compare the current wallet state with the previous state // to determine if the trader is buying or selling - const prevState = previous_wallet_state || {}; + const prevState = previous_trader_wallet_state || {}; const currentState = current_wallet_state; // Check if there is one token that decreased and one token that increased @@ -148,7 +149,7 @@ async function listenToWallets() { } // Update the previous wallet state - previous_wallet_state = currentState; + previous_trader_wallet_state = currentState; }, "confirmed", [ @@ -197,8 +198,10 @@ async function retriveWalletState(wallet_address) { results[mintAddress] = tokenBalance; results["SOL"] = solBalance / 10 ** 9; + //Log results }); + console.log(results); return results; } @@ -211,13 +214,18 @@ async function copy_trade() { // wallet object let payer_wallet = wallet; // 0.1 SOL, fixed order size - let solperorder = 0.1; + let buyPercentage = 0; // depends the account's token balance changes // 20 A -> 10 A, (10 - 20) / 20 = -50% == sell 50% // (current token balance - previous token balance / previous token balance) * 100 - let sellPercentage = 100; - let smart_money_address = "smart_money_wallet_address"; - previous_wallet_state = await retriveWalletState(smart_money_address); + let sellPercentage = 0; + // smart money wallet address + let smart_money_address = "your_smart_money_wallet_address_here"; + // our wallet address + let our_wallet_address = wallet.publicKey.toBase58(); + previous_trader_wallet_state = await retriveWalletState(smart_money_address); + previous_our_wallet_state = await retriveWalletState(our_wallet_address); + // subscribe to the smart money wallet walletsToListen.push(new PublicKey(smart_money_address)); await listenToWallets(); } diff --git a/src/Transactions/simple_tx_executor.js b/src/Transactions/simple_tx_executor.js index 7fd2ec9c..7de46111 100644 --- a/src/Transactions/simple_tx_executor.js +++ b/src/Transactions/simple_tx_executor.js @@ -15,7 +15,8 @@ async function simple_executeAndConfirm(transaction, payer, lastestBlockhash) { async function simple_execute(transaction) { return connection.sendRawTransaction(transaction.serialize(), { - preflightCommitment: connection.commitment, + skipPreflight: true, + maxRetries: 0, }); }