Skip to content

Instantly share code, notes, and snippets.

@Gsuz
Created February 23, 2022 11:13
Show Gist options
  • Select an option

  • Save Gsuz/f6d4cf56653f798f90a17a476bc61e74 to your computer and use it in GitHub Desktop.

Select an option

Save Gsuz/f6d4cf56653f798f90a17a476bc61e74 to your computer and use it in GitHub Desktop.
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