Created
February 23, 2022 11:13
-
-
Save Gsuz/f6d4cf56653f798f90a17a476bc61e74 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Connection, PublicKey } from "@solana/web3.js"; | |
| import fetch from "isomorphic-fetch"; | |
| import { Jupiter, RouteInfo, TOKEN_LIST_URL } from "@jup-ag/core"; | |
| import { | |
| ENV, | |
| INPUT_MINT_ADDRESS, | |
| OUTPUT_MINT_ADDRESS, | |
| SOLANA_RPC_ENDPOINT, | |
| Token, | |
| USER_KEYPAIR, | |
| } from "./constants"; | |
| const getPossiblePairsTokenInfo = ({ | |
| tokens, | |
| routeMap, | |
| inputToken, | |
| }: { | |
| tokens: Token[]; | |
| routeMap: Map<string, string[]>; | |
| inputToken?: Token; | |
| }) => { | |
| try { | |
| if (!inputToken) { | |
| return {}; | |
| } | |
| const possiblePairs = inputToken | |
| ? routeMap.get(inputToken.address) || [] | |
| : []; // return an array of token mints that can be swapped with SOL | |
| const possiblePairsTokenInfo: { [key: string]: Token | undefined } = {}; | |
| possiblePairs.forEach((address) => { | |
| possiblePairsTokenInfo[address] = tokens.find((t) => { | |
| return t.address == address; | |
| }); | |
| }); | |
| // Perform your conditionals here to use other outputToken | |
| // const alternativeOutputToken = possiblePairsTokenInfo[USDT_MINT_ADDRESS] | |
| return possiblePairsTokenInfo; | |
| } catch (error) { | |
| throw error; | |
| } | |
| }; | |
| const getRoutes = async ({ | |
| jupiter, | |
| inputToken, | |
| outputToken, | |
| inputAmount, | |
| slippage, | |
| }: { | |
| jupiter: Jupiter; | |
| inputToken?: Token; | |
| outputToken?: Token; | |
| inputAmount: number; | |
| slippage: number; | |
| }) => { | |
| try { | |
| if (!inputToken || !outputToken) { | |
| return null; | |
| } | |
| console.log( | |
| `Getting routes for ${inputAmount} ${inputToken.symbol} -> ${outputToken.symbol}...` | |
| ); | |
| const inputAmountInSmallestUnits = inputToken | |
| ? Math.round(inputAmount * 10 ** inputToken.decimals) | |
| : 0; | |
| const routes = | |
| inputToken && outputToken | |
| ? await jupiter.computeRoutes( | |
| new PublicKey(inputToken.address), | |
| new PublicKey(outputToken.address), | |
| inputAmountInSmallestUnits, // raw input amount of tokens | |
| slippage, | |
| true | |
| ) | |
| : null; | |
| if (routes && routes.routesInfos) { | |
| console.log("Possible number of routes:", routes.routesInfos.length); | |
| console.log( | |
| "Best quote: ", | |
| routes.routesInfos[0].outAmount / 10 ** outputToken.decimals, | |
| `(${outputToken.symbol})` | |
| ); | |
| return routes; | |
| } else { | |
| return null; | |
| } | |
| } catch (error) { | |
| throw error; | |
| } | |
| }; | |
| const executeSwap = async ({ | |
| jupiter, | |
| route, | |
| }: { | |
| jupiter: Jupiter; | |
| route: RouteInfo; | |
| }) => { | |
| try { | |
| console.log('excecuting swap') | |
| // Prepare execute exchange | |
| const { execute } = await jupiter.exchange({ | |
| route, | |
| }); | |
| // Execute swap | |
| const swapResult: any = await execute(); // Force any to ignore TS misidentifying SwapResult type | |
| if (swapResult.error) { | |
| (console.log('we found an error: ')) | |
| console.log(swapResult.error); | |
| } else { | |
| console.log(`https://explorer.solana.com/tx/${swapResult.txid}`); | |
| console.log( | |
| `inputAddress=${swapResult.inputAddress.toString()} outputAddress=${swapResult.outputAddress.toString()}` | |
| ); | |
| console.log( | |
| `inputAmount=${swapResult.inputAmount} outputAmount=${swapResult.outputAmount}` | |
| ); | |
| } | |
| } catch (error) { | |
| throw error; | |
| } | |
| }; | |
| const main = async () => { | |
| try { | |
| const connection = new Connection(SOLANA_RPC_ENDPOINT); // Setup Solana RPC connection | |
| const tokens: Token[] = await (await fetch(TOKEN_LIST_URL[ENV])).json(); // Fetch token list from Jupiter API | |
| // Load Jupiter | |
| const jupiter = await Jupiter.load({ | |
| connection, | |
| cluster: ENV, | |
| user: USER_KEYPAIR, // or public key | |
| }); | |
| // Get routeMap, which maps each tokenMint and their respective tokenMints that are swappable | |
| const routeMap = jupiter.getRouteMap(); | |
| // If you know which input/output pair you want | |
| const inputToken = tokens.find((t) => t.address == INPUT_MINT_ADDRESS); // USDC Mint Info | |
| const outputToken = tokens.find((t) => t.address == OUTPUT_MINT_ADDRESS); // USDT Mint Info | |
| // Alternatively, find all possible outputToken based on your inputToken | |
| const possiblePairsTokenInfo = await getPossiblePairsTokenInfo({ | |
| tokens, | |
| routeMap, | |
| inputToken, | |
| }); | |
| //console.dir(possiblePairsTokenInfo) | |
| //console.log(possiblePairsTokenInfo.address) | |
| const routes = await getRoutes({ | |
| jupiter, | |
| inputToken, | |
| outputToken, | |
| inputAmount: 1, // 1 unit in UI | |
| slippage: 1, // 1% slippage | |
| }); | |
| // Routes are sorted based on outputAmount, so ideally the first route is the best. | |
| await executeSwap({ jupiter, route: routes!.routesInfos[0] }); | |
| } catch (error) { | |
| console.log({ error }); | |
| } | |
| }; | |
| main(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment