├── test.http ├── generated ├── .openapi-generator │ ├── VERSION │ └── FILES ├── apis │ ├── index.ts │ └── SwapApi.ts ├── index.ts ├── models │ ├── index.ts │ ├── SwapMode.ts │ ├── PlatformFee.ts │ ├── JitoTipLamports.ts │ ├── AccountMeta.ts │ ├── IndexedRouteMapResponse.ts │ ├── RoutePlanStep.ts │ ├── SwapResponse.ts │ ├── Instruction.ts │ ├── JitoTipLamportsWithPayerJitoTipLamportsWithPayer.ts │ ├── JitoTipLamportsWithPayer.ts │ ├── PriorityLevelWithMaxLamports.ts │ ├── SwapInfo.ts │ ├── SwapRequestPrioritizationFeeLamports.ts │ ├── PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports.ts │ ├── SwapInstructionsResponse.ts │ ├── QuoteResponse.ts │ └── SwapRequest.ts ├── .openapi-generator-ignore └── runtime.ts ├── .gitignore ├── PUBLISH.md ├── bun.lockb ├── example ├── utils │ ├── wait.ts │ ├── getSignature.ts │ └── transactionSender.ts ├── handlingError.ts └── index.ts ├── openapitools.json ├── .env.example ├── tsconfig.json ├── src └── index.ts ├── tests └── index.test.ts ├── package.json ├── README.md └── swagger.yaml /test.http: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /generated/.openapi-generator/VERSION: -------------------------------------------------------------------------------- 1 | 7.3.0 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .DS_Store 4 | .env 5 | .idea -------------------------------------------------------------------------------- /PUBLISH.md: -------------------------------------------------------------------------------- 1 | - bump version 2 | - pnpm build 3 | - npm publish --access public -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jup-ag/jupiter-quote-api-node/HEAD/bun.lockb -------------------------------------------------------------------------------- /generated/apis/index.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export * from './SwapApi'; 4 | -------------------------------------------------------------------------------- /example/utils/wait.ts: -------------------------------------------------------------------------------- 1 | export const wait = (time: number) => 2 | new Promise((resolve) => setTimeout(resolve, time)); 3 | -------------------------------------------------------------------------------- /generated/index.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export * from './runtime'; 4 | export * from './apis/index'; 5 | export * from './models/index'; 6 | -------------------------------------------------------------------------------- /openapitools.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json", 3 | "spaces": 2, 4 | "generator-cli": { 5 | "version": "7.3.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY=your_base58_private_key 2 | FLOW=quoteAndSwap # or quote 3 | 4 | # Jupiter API Key (optional) 5 | # If provided, the client will use the paid tier API endpoint 6 | JUPITER_API_KEY=your_api_key_here 7 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "commonjs", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "baseUrl": "." 16 | }, 17 | "include": ["**/*.ts", "**/*.tsx"], 18 | "exclude": ["node_modules"] 19 | } 20 | -------------------------------------------------------------------------------- /example/utils/getSignature.ts: -------------------------------------------------------------------------------- 1 | import bs58 from "bs58"; 2 | import { Transaction, VersionedTransaction } from "@solana/web3.js"; 3 | 4 | export function getSignature( 5 | transaction: Transaction | VersionedTransaction 6 | ): string { 7 | const signature = 8 | "signature" in transaction 9 | ? transaction.signature 10 | : transaction.signatures[0]; 11 | if (!signature) { 12 | throw new Error( 13 | "Missing transaction signature, the transaction was not signed by the fee payer" 14 | ); 15 | } 16 | return bs58.encode(signature); 17 | } 18 | -------------------------------------------------------------------------------- /example/handlingError.ts: -------------------------------------------------------------------------------- 1 | import { ResponseError, createJupiterApiClient } from "src"; 2 | 3 | async function main() { 4 | try { 5 | const jupiterQuoteApi = createJupiterApiClient(); 6 | 7 | await jupiterQuoteApi.quoteGet({ 8 | inputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", 9 | amount: 35281.123, // decimal 10 | outputMint: "So11111111111111111111111111111111111111112", 11 | }); 12 | } catch (e) { 13 | if (e instanceof ResponseError) { 14 | console.log(await e.response.json()); 15 | } 16 | } 17 | } 18 | 19 | main(); 20 | -------------------------------------------------------------------------------- /generated/.openapi-generator/FILES: -------------------------------------------------------------------------------- 1 | apis/SwapApi.ts 2 | apis/index.ts 3 | index.ts 4 | models/AccountMeta.ts 5 | models/IndexedRouteMapResponse.ts 6 | models/Instruction.ts 7 | models/JitoTipLamports.ts 8 | models/JitoTipLamportsWithPayer.ts 9 | models/JitoTipLamportsWithPayerJitoTipLamportsWithPayer.ts 10 | models/PlatformFee.ts 11 | models/PriorityLevelWithMaxLamports.ts 12 | models/PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports.ts 13 | models/QuoteResponse.ts 14 | models/RoutePlanStep.ts 15 | models/SwapInfo.ts 16 | models/SwapInstructionsResponse.ts 17 | models/SwapMode.ts 18 | models/SwapRequest.ts 19 | models/SwapRequestPrioritizationFeeLamports.ts 20 | models/SwapResponse.ts 21 | models/index.ts 22 | runtime.ts 23 | -------------------------------------------------------------------------------- /generated/models/index.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export * from './AccountMeta'; 4 | export * from './IndexedRouteMapResponse'; 5 | export * from './Instruction'; 6 | export * from './JitoTipLamports'; 7 | export * from './JitoTipLamportsWithPayer'; 8 | export * from './JitoTipLamportsWithPayerJitoTipLamportsWithPayer'; 9 | export * from './PlatformFee'; 10 | export * from './PriorityLevelWithMaxLamports'; 11 | export * from './PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports'; 12 | export * from './QuoteResponse'; 13 | export * from './RoutePlanStep'; 14 | export * from './SwapInfo'; 15 | export * from './SwapInstructionsResponse'; 16 | export * from './SwapMode'; 17 | export * from './SwapRequest'; 18 | export * from './SwapRequestPrioritizationFeeLamports'; 19 | export * from './SwapResponse'; 20 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { SwapApi } from "../generated/apis/SwapApi"; 2 | import { ConfigurationParameters, Configuration } from "../generated/runtime"; 3 | 4 | // Define server URLs 5 | const PUBLIC_SERVER_URL = "https://lite-api.jup.ag/swap/v1"; 6 | const API_KEY_SERVER_URL = "https://api.jup.ag/swap/v1"; 7 | 8 | /** 9 | * Creates a Jupiter API client with optional API key support 10 | * @param config Configuration parameters 11 | * @returns SwapApi instance 12 | */ 13 | export const createJupiterApiClient = (config?: ConfigurationParameters) => { 14 | // Determine which server URL to use based on whether an API key is provided 15 | const hasApiKey = config?.apiKey !== undefined; 16 | 17 | // Create a new configuration with the appropriate base path 18 | const configWithServer: ConfigurationParameters = { 19 | ...config, 20 | basePath: hasApiKey ? API_KEY_SERVER_URL : PUBLIC_SERVER_URL, 21 | headers: hasApiKey ? { 'x-api-key': config?.apiKey as string } : undefined 22 | }; 23 | 24 | return new SwapApi(new Configuration(configWithServer)); 25 | }; 26 | 27 | export * from "../generated"; 28 | -------------------------------------------------------------------------------- /tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import { ResponseError, createJupiterApiClient } from "src"; 2 | import { describe, expect, it } from "vitest"; 3 | describe("api", () => { 4 | const apiClient = createJupiterApiClient(); 5 | it("success state", async () => { 6 | await apiClient.quoteGet({ 7 | inputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", 8 | amount: 35281, 9 | outputMint: "So11111111111111111111111111111111111111112", 10 | }); 11 | }); 12 | 13 | it("error state", async () => { 14 | try { 15 | await apiClient.quoteGet({ 16 | inputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", 17 | amount: 35281.123, // decimal 18 | outputMint: "So11111111111111111111111111111111111111112", 19 | }); 20 | } catch (e) { 21 | if (e instanceof ResponseError) { 22 | expect(await e.response.json()).toMatchInlineSnapshot(` 23 | { 24 | "error": "Query parameter amount cannot be parsed: ParseIntError { kind: InvalidDigit }", 25 | } 26 | `); 27 | } else { 28 | throw e; 29 | } 30 | } 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /generated/.openapi-generator-ignore: -------------------------------------------------------------------------------- 1 | # OpenAPI Generator Ignore 2 | # Generated by openapi-generator https://github.com/openapitools/openapi-generator 3 | 4 | # Use this file to prevent files from being overwritten by the generator. 5 | # The patterns follow closely to .gitignore or .dockerignore. 6 | 7 | # As an example, the C# client generator defines ApiClient.cs. 8 | # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: 9 | #ApiClient.cs 10 | 11 | # You can match any string of characters against a directory, file or extension with a single asterisk (*): 12 | #foo/*/qux 13 | # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux 14 | 15 | # You can recursively match patterns against a directory, file or extension with a double asterisk (**): 16 | #foo/**/qux 17 | # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux 18 | 19 | # You can also negate patterns with an exclamation (!). 20 | # For example, you can ignore all files in a docs folder with the file extension .md: 21 | #docs/*.md 22 | # Then explicitly reverse the ignore rule for a single file: 23 | #!docs/README.md 24 | -------------------------------------------------------------------------------- /generated/models/SwapMode.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | 16 | /** 17 | * 18 | * @export 19 | */ 20 | export const SwapMode = { 21 | ExactIn: 'ExactIn', 22 | ExactOut: 'ExactOut' 23 | } as const; 24 | export type SwapMode = typeof SwapMode[keyof typeof SwapMode]; 25 | 26 | 27 | export function SwapModeFromJSON(json: any): SwapMode { 28 | return SwapModeFromJSONTyped(json, false); 29 | } 30 | 31 | export function SwapModeFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapMode { 32 | return json as SwapMode; 33 | } 34 | 35 | export function SwapModeToJSON(value?: SwapMode | null): any { 36 | return value as any; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jup-ag/api", 3 | "version": "6.0.47", 4 | "homepage": "https://github.com/jup-ag/jupiter-quote-api-node", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/jup-ag/jupiter-quote-api-node.git" 8 | }, 9 | "description": "## Generate typescript types from swagger schema", 10 | "main": "dist/index.js", 11 | "module": "dist/index.mjs", 12 | "typings": "dist/index.d.ts", 13 | "sideEffects": false, 14 | "scripts": { 15 | "dev-swap": "FLOW=quoteAndSwap ts-node ./example/index.ts", 16 | "dev-quote": "FLOW=quote ts-node ./example/index.ts", 17 | "test": "vitest", 18 | "build": "npm run openapi-gen && tsup src/index.ts --dts --format esm,cjs", 19 | "openapi-gen": "openapi-generator-cli generate -i swagger.yaml -o generated -g typescript-fetch --skip-validate-spec --additional-properties=supportsES6=true,typescriptThreePlus=true", 20 | "openapi-gen-rust": "openapi-generator-cli generate -i swagger.yaml -o generated -g rust" 21 | }, 22 | "author": "", 23 | "license": "MIT", 24 | "dependencies": {}, 25 | "devDependencies": { 26 | "@openapitools/openapi-generator-cli": "^2.9.0", 27 | "@project-serum/anchor": "^0.26.0", 28 | "@solana/web3.js": "^1.87.6", 29 | "@types/promise-retry": "^1.1.3", 30 | "bs58": "^5.0.0", 31 | "cross-fetch": "^3.1.5", 32 | "dotenv": "^16.4.7", 33 | "promise-retry": "2.0.1", 34 | "ts-node": "^10.5.0", 35 | "tsup": "^7.1.0", 36 | "typescript": "^5.1.6", 37 | "vitest": "^0.34.1" 38 | }, 39 | "files": [ 40 | "dist" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaScript API Client for Jupiter V6 2 | 3 | ## Table of Contents 4 | 5 | - [Installation](#installation) 6 | - [Developing](#developing) 7 | - [Usage](#usage) 8 | - [Examples](#examples) 9 | - Paid Hosted APIs (Deprecated and will not be supported, reach out in Discord for more information) 10 | 11 | ## Installation 12 | 13 | To use the Jupiter API client, you need to have Node.js and npm (Node Package Manager) installed. Then, you can install the package using npm: 14 | 15 | ```bash 16 | npm install @jup-ag/api 17 | ``` 18 | 19 | ## Developing 20 | 21 | - pnpm dev-quote 22 | - Get request a quote based on mints and amount 23 | - pnpm dev-swap 24 | - Post request with the quote response to receive the swap transaction to sign and send to the network 25 | - Ensure you have setup `process.env.PRIVATE_KEY` to sign 26 | 27 | - Please set up `process.env.API_KEY` if you have a Pro plan via https://portal.jup.ag/ 28 | 29 | Refer to our developer documentation for more information and tips: 30 | - Swap API: https://dev.jup.ag/docs/swap-api 31 | - API Key setup: https://dev.jup.ag/docs/api-setup 32 | 33 | ## Usage 34 | 35 | To start using the API client, you need to require it in your Node.js project: 36 | 37 | ```typescript 38 | import { createJupiterApiClient } from '@jup-ag/api'; 39 | 40 | const jupiterQuoteApi = createJupiterApiClient(config); // config is optional such as api key 41 | ``` 42 | 43 | Now, you can call methods provided by the API client to interact with Jupiter's API. For example: 44 | 45 | ```typescript 46 | jupiterQuoteApi.quoteGet({ 47 | inputMint: "So11111111111111111111111111111111111111112", 48 | outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", 49 | amount: "100000000", 50 | slippageBps: 100, 51 | }) 52 | ``` 53 | 54 | ## Examples 55 | 56 | Checkout the [example in the repo](/example/index.ts). 57 | -------------------------------------------------------------------------------- /generated/models/PlatformFee.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | /** 17 | * 18 | * @export 19 | * @interface PlatformFee 20 | */ 21 | export interface PlatformFee { 22 | /** 23 | * 24 | * @type {string} 25 | * @memberof PlatformFee 26 | */ 27 | amount?: string; 28 | /** 29 | * 30 | * @type {number} 31 | * @memberof PlatformFee 32 | */ 33 | feeBps?: number; 34 | } 35 | 36 | /** 37 | * Check if a given object implements the PlatformFee interface. 38 | */ 39 | export function instanceOfPlatformFee(value: object): boolean { 40 | let isInstance = true; 41 | 42 | return isInstance; 43 | } 44 | 45 | export function PlatformFeeFromJSON(json: any): PlatformFee { 46 | return PlatformFeeFromJSONTyped(json, false); 47 | } 48 | 49 | export function PlatformFeeFromJSONTyped(json: any, ignoreDiscriminator: boolean): PlatformFee { 50 | if ((json === undefined) || (json === null)) { 51 | return json; 52 | } 53 | return { 54 | 55 | 'amount': !exists(json, 'amount') ? undefined : json['amount'], 56 | 'feeBps': !exists(json, 'feeBps') ? undefined : json['feeBps'], 57 | }; 58 | } 59 | 60 | export function PlatformFeeToJSON(value?: PlatformFee | null): any { 61 | if (value === undefined) { 62 | return undefined; 63 | } 64 | if (value === null) { 65 | return null; 66 | } 67 | return { 68 | 69 | 'amount': value.amount, 70 | 'feeBps': value.feeBps, 71 | }; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /generated/models/JitoTipLamports.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | /** 17 | * 18 | * @export 19 | * @interface JitoTipLamports 20 | */ 21 | export interface JitoTipLamports { 22 | /** 23 | * - Exact amount of tip to use in a tip instruction 24 | * - Refer to Jito docs on how to estimate the tip amount based on percentiles 25 | * - It has to be used together with a connection to a Jito RPC 26 | * - See their docs at https://docs.jito.wtf/ 27 | * 28 | * @type {number} 29 | * @memberof JitoTipLamports 30 | */ 31 | jitoTipLamports: number; 32 | } 33 | 34 | /** 35 | * Check if a given object implements the JitoTipLamports interface. 36 | */ 37 | export function instanceOfJitoTipLamports(value: object): boolean { 38 | let isInstance = true; 39 | isInstance = isInstance && "jitoTipLamports" in value; 40 | 41 | return isInstance; 42 | } 43 | 44 | export function JitoTipLamportsFromJSON(json: any): JitoTipLamports { 45 | return JitoTipLamportsFromJSONTyped(json, false); 46 | } 47 | 48 | export function JitoTipLamportsFromJSONTyped(json: any, ignoreDiscriminator: boolean): JitoTipLamports { 49 | if ((json === undefined) || (json === null)) { 50 | return json; 51 | } 52 | return { 53 | 54 | 'jitoTipLamports': json['jitoTipLamports'], 55 | }; 56 | } 57 | 58 | export function JitoTipLamportsToJSON(value?: JitoTipLamports | null): any { 59 | if (value === undefined) { 60 | return undefined; 61 | } 62 | if (value === null) { 63 | return null; 64 | } 65 | return { 66 | 67 | 'jitoTipLamports': value.jitoTipLamports, 68 | }; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /generated/models/AccountMeta.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | /** 17 | * 18 | * @export 19 | * @interface AccountMeta 20 | */ 21 | export interface AccountMeta { 22 | /** 23 | * 24 | * @type {string} 25 | * @memberof AccountMeta 26 | */ 27 | pubkey: string; 28 | /** 29 | * 30 | * @type {boolean} 31 | * @memberof AccountMeta 32 | */ 33 | isSigner: boolean; 34 | /** 35 | * 36 | * @type {boolean} 37 | * @memberof AccountMeta 38 | */ 39 | isWritable: boolean; 40 | } 41 | 42 | /** 43 | * Check if a given object implements the AccountMeta interface. 44 | */ 45 | export function instanceOfAccountMeta(value: object): boolean { 46 | let isInstance = true; 47 | isInstance = isInstance && "pubkey" in value; 48 | isInstance = isInstance && "isSigner" in value; 49 | isInstance = isInstance && "isWritable" in value; 50 | 51 | return isInstance; 52 | } 53 | 54 | export function AccountMetaFromJSON(json: any): AccountMeta { 55 | return AccountMetaFromJSONTyped(json, false); 56 | } 57 | 58 | export function AccountMetaFromJSONTyped(json: any, ignoreDiscriminator: boolean): AccountMeta { 59 | if ((json === undefined) || (json === null)) { 60 | return json; 61 | } 62 | return { 63 | 64 | 'pubkey': json['pubkey'], 65 | 'isSigner': json['isSigner'], 66 | 'isWritable': json['isWritable'], 67 | }; 68 | } 69 | 70 | export function AccountMetaToJSON(value?: AccountMeta | null): any { 71 | if (value === undefined) { 72 | return undefined; 73 | } 74 | if (value === null) { 75 | return null; 76 | } 77 | return { 78 | 79 | 'pubkey': value.pubkey, 80 | 'isSigner': value.isSigner, 81 | 'isWritable': value.isWritable, 82 | }; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /generated/models/IndexedRouteMapResponse.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | /** 17 | * 18 | * @export 19 | * @interface IndexedRouteMapResponse 20 | */ 21 | export interface IndexedRouteMapResponse { 22 | /** 23 | * All the mints that are indexed to match in indexedRouteMap 24 | * @type {Array} 25 | * @memberof IndexedRouteMapResponse 26 | */ 27 | mintKeys: Array; 28 | /** 29 | * All the possible route and their corresponding output mints 30 | * @type {{ [key: string]: Array; }} 31 | * @memberof IndexedRouteMapResponse 32 | */ 33 | indexedRouteMap: { [key: string]: Array; }; 34 | } 35 | 36 | /** 37 | * Check if a given object implements the IndexedRouteMapResponse interface. 38 | */ 39 | export function instanceOfIndexedRouteMapResponse(value: object): boolean { 40 | let isInstance = true; 41 | isInstance = isInstance && "mintKeys" in value; 42 | isInstance = isInstance && "indexedRouteMap" in value; 43 | 44 | return isInstance; 45 | } 46 | 47 | export function IndexedRouteMapResponseFromJSON(json: any): IndexedRouteMapResponse { 48 | return IndexedRouteMapResponseFromJSONTyped(json, false); 49 | } 50 | 51 | export function IndexedRouteMapResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): IndexedRouteMapResponse { 52 | if ((json === undefined) || (json === null)) { 53 | return json; 54 | } 55 | return { 56 | 57 | 'mintKeys': json['mintKeys'], 58 | 'indexedRouteMap': json['indexedRouteMap'], 59 | }; 60 | } 61 | 62 | export function IndexedRouteMapResponseToJSON(value?: IndexedRouteMapResponse | null): any { 63 | if (value === undefined) { 64 | return undefined; 65 | } 66 | if (value === null) { 67 | return null; 68 | } 69 | return { 70 | 71 | 'mintKeys': value.mintKeys, 72 | 'indexedRouteMap': value.indexedRouteMap, 73 | }; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /generated/models/RoutePlanStep.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | import type { SwapInfo } from './SwapInfo'; 17 | import { 18 | SwapInfoFromJSON, 19 | SwapInfoFromJSONTyped, 20 | SwapInfoToJSON, 21 | } from './SwapInfo'; 22 | 23 | /** 24 | * 25 | * @export 26 | * @interface RoutePlanStep 27 | */ 28 | export interface RoutePlanStep { 29 | /** 30 | * 31 | * @type {SwapInfo} 32 | * @memberof RoutePlanStep 33 | */ 34 | swapInfo: SwapInfo; 35 | /** 36 | * 37 | * @type {number} 38 | * @memberof RoutePlanStep 39 | */ 40 | percent?: number | null; 41 | /** 42 | * 43 | * @type {number} 44 | * @memberof RoutePlanStep 45 | */ 46 | bps?: number; 47 | } 48 | 49 | /** 50 | * Check if a given object implements the RoutePlanStep interface. 51 | */ 52 | export function instanceOfRoutePlanStep(value: object): boolean { 53 | let isInstance = true; 54 | isInstance = isInstance && "swapInfo" in value; 55 | 56 | return isInstance; 57 | } 58 | 59 | export function RoutePlanStepFromJSON(json: any): RoutePlanStep { 60 | return RoutePlanStepFromJSONTyped(json, false); 61 | } 62 | 63 | export function RoutePlanStepFromJSONTyped(json: any, ignoreDiscriminator: boolean): RoutePlanStep { 64 | if ((json === undefined) || (json === null)) { 65 | return json; 66 | } 67 | return { 68 | 69 | 'swapInfo': SwapInfoFromJSON(json['swapInfo']), 70 | 'percent': !exists(json, 'percent') ? undefined : json['percent'], 71 | 'bps': !exists(json, 'bps') ? undefined : json['bps'], 72 | }; 73 | } 74 | 75 | export function RoutePlanStepToJSON(value?: RoutePlanStep | null): any { 76 | if (value === undefined) { 77 | return undefined; 78 | } 79 | if (value === null) { 80 | return null; 81 | } 82 | return { 83 | 84 | 'swapInfo': SwapInfoToJSON(value.swapInfo), 85 | 'percent': value.percent, 86 | 'bps': value.bps, 87 | }; 88 | } 89 | 90 | -------------------------------------------------------------------------------- /generated/models/SwapResponse.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | /** 17 | * 18 | * @export 19 | * @interface SwapResponse 20 | */ 21 | export interface SwapResponse { 22 | /** 23 | * 24 | * @type {string} 25 | * @memberof SwapResponse 26 | */ 27 | swapTransaction: string; 28 | /** 29 | * 30 | * @type {number} 31 | * @memberof SwapResponse 32 | */ 33 | lastValidBlockHeight: number; 34 | /** 35 | * 36 | * @type {number} 37 | * @memberof SwapResponse 38 | */ 39 | prioritizationFeeLamports?: number; 40 | } 41 | 42 | /** 43 | * Check if a given object implements the SwapResponse interface. 44 | */ 45 | export function instanceOfSwapResponse(value: object): boolean { 46 | let isInstance = true; 47 | isInstance = isInstance && "swapTransaction" in value; 48 | isInstance = isInstance && "lastValidBlockHeight" in value; 49 | 50 | return isInstance; 51 | } 52 | 53 | export function SwapResponseFromJSON(json: any): SwapResponse { 54 | return SwapResponseFromJSONTyped(json, false); 55 | } 56 | 57 | export function SwapResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapResponse { 58 | if ((json === undefined) || (json === null)) { 59 | return json; 60 | } 61 | return { 62 | 63 | 'swapTransaction': json['swapTransaction'], 64 | 'lastValidBlockHeight': json['lastValidBlockHeight'], 65 | 'prioritizationFeeLamports': !exists(json, 'prioritizationFeeLamports') ? undefined : json['prioritizationFeeLamports'], 66 | }; 67 | } 68 | 69 | export function SwapResponseToJSON(value?: SwapResponse | null): any { 70 | if (value === undefined) { 71 | return undefined; 72 | } 73 | if (value === null) { 74 | return null; 75 | } 76 | return { 77 | 78 | 'swapTransaction': value.swapTransaction, 79 | 'lastValidBlockHeight': value.lastValidBlockHeight, 80 | 'prioritizationFeeLamports': value.prioritizationFeeLamports, 81 | }; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /generated/models/Instruction.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | import type { AccountMeta } from './AccountMeta'; 17 | import { 18 | AccountMetaFromJSON, 19 | AccountMetaFromJSONTyped, 20 | AccountMetaToJSON, 21 | } from './AccountMeta'; 22 | 23 | /** 24 | * 25 | * @export 26 | * @interface Instruction 27 | */ 28 | export interface Instruction { 29 | /** 30 | * 31 | * @type {string} 32 | * @memberof Instruction 33 | */ 34 | programId: string; 35 | /** 36 | * 37 | * @type {Array} 38 | * @memberof Instruction 39 | */ 40 | accounts: Array; 41 | /** 42 | * 43 | * @type {string} 44 | * @memberof Instruction 45 | */ 46 | data: string; 47 | } 48 | 49 | /** 50 | * Check if a given object implements the Instruction interface. 51 | */ 52 | export function instanceOfInstruction(value: object): boolean { 53 | let isInstance = true; 54 | isInstance = isInstance && "programId" in value; 55 | isInstance = isInstance && "accounts" in value; 56 | isInstance = isInstance && "data" in value; 57 | 58 | return isInstance; 59 | } 60 | 61 | export function InstructionFromJSON(json: any): Instruction { 62 | return InstructionFromJSONTyped(json, false); 63 | } 64 | 65 | export function InstructionFromJSONTyped(json: any, ignoreDiscriminator: boolean): Instruction { 66 | if ((json === undefined) || (json === null)) { 67 | return json; 68 | } 69 | return { 70 | 71 | 'programId': json['programId'], 72 | 'accounts': ((json['accounts'] as Array).map(AccountMetaFromJSON)), 73 | 'data': json['data'], 74 | }; 75 | } 76 | 77 | export function InstructionToJSON(value?: Instruction | null): any { 78 | if (value === undefined) { 79 | return undefined; 80 | } 81 | if (value === null) { 82 | return null; 83 | } 84 | return { 85 | 86 | 'programId': value.programId, 87 | 'accounts': ((value.accounts as Array).map(AccountMetaToJSON)), 88 | 'data': value.data, 89 | }; 90 | } 91 | 92 | -------------------------------------------------------------------------------- /generated/models/JitoTipLamportsWithPayerJitoTipLamportsWithPayer.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | /** 17 | * 18 | * @export 19 | * @interface JitoTipLamportsWithPayerJitoTipLamportsWithPayer 20 | */ 21 | export interface JitoTipLamportsWithPayerJitoTipLamportsWithPayer { 22 | /** 23 | * Exact amount of lamports to use for the tip 24 | * @type {number} 25 | * @memberof JitoTipLamportsWithPayerJitoTipLamportsWithPayer 26 | */ 27 | lamports: number; 28 | /** 29 | * Public key of an account that will be used to pay for the tip 30 | * @type {string} 31 | * @memberof JitoTipLamportsWithPayerJitoTipLamportsWithPayer 32 | */ 33 | payer: string; 34 | } 35 | 36 | /** 37 | * Check if a given object implements the JitoTipLamportsWithPayerJitoTipLamportsWithPayer interface. 38 | */ 39 | export function instanceOfJitoTipLamportsWithPayerJitoTipLamportsWithPayer(value: object): boolean { 40 | let isInstance = true; 41 | isInstance = isInstance && "lamports" in value; 42 | isInstance = isInstance && "payer" in value; 43 | 44 | return isInstance; 45 | } 46 | 47 | export function JitoTipLamportsWithPayerJitoTipLamportsWithPayerFromJSON(json: any): JitoTipLamportsWithPayerJitoTipLamportsWithPayer { 48 | return JitoTipLamportsWithPayerJitoTipLamportsWithPayerFromJSONTyped(json, false); 49 | } 50 | 51 | export function JitoTipLamportsWithPayerJitoTipLamportsWithPayerFromJSONTyped(json: any, ignoreDiscriminator: boolean): JitoTipLamportsWithPayerJitoTipLamportsWithPayer { 52 | if ((json === undefined) || (json === null)) { 53 | return json; 54 | } 55 | return { 56 | 57 | 'lamports': json['lamports'], 58 | 'payer': json['payer'], 59 | }; 60 | } 61 | 62 | export function JitoTipLamportsWithPayerJitoTipLamportsWithPayerToJSON(value?: JitoTipLamportsWithPayerJitoTipLamportsWithPayer | null): any { 63 | if (value === undefined) { 64 | return undefined; 65 | } 66 | if (value === null) { 67 | return null; 68 | } 69 | return { 70 | 71 | 'lamports': value.lamports, 72 | 'payer': value.payer, 73 | }; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /generated/models/JitoTipLamportsWithPayer.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | import type { JitoTipLamportsWithPayerJitoTipLamportsWithPayer } from './JitoTipLamportsWithPayerJitoTipLamportsWithPayer'; 17 | import { 18 | JitoTipLamportsWithPayerJitoTipLamportsWithPayerFromJSON, 19 | JitoTipLamportsWithPayerJitoTipLamportsWithPayerFromJSONTyped, 20 | JitoTipLamportsWithPayerJitoTipLamportsWithPayerToJSON, 21 | } from './JitoTipLamportsWithPayerJitoTipLamportsWithPayer'; 22 | 23 | /** 24 | * 25 | * @export 26 | * @interface JitoTipLamportsWithPayer 27 | */ 28 | export interface JitoTipLamportsWithPayer { 29 | /** 30 | * 31 | * @type {JitoTipLamportsWithPayerJitoTipLamportsWithPayer} 32 | * @memberof JitoTipLamportsWithPayer 33 | */ 34 | jitoTipLamportsWithPayer: JitoTipLamportsWithPayerJitoTipLamportsWithPayer; 35 | } 36 | 37 | /** 38 | * Check if a given object implements the JitoTipLamportsWithPayer interface. 39 | */ 40 | export function instanceOfJitoTipLamportsWithPayer(value: object): boolean { 41 | let isInstance = true; 42 | isInstance = isInstance && "jitoTipLamportsWithPayer" in value; 43 | 44 | return isInstance; 45 | } 46 | 47 | export function JitoTipLamportsWithPayerFromJSON(json: any): JitoTipLamportsWithPayer { 48 | return JitoTipLamportsWithPayerFromJSONTyped(json, false); 49 | } 50 | 51 | export function JitoTipLamportsWithPayerFromJSONTyped(json: any, ignoreDiscriminator: boolean): JitoTipLamportsWithPayer { 52 | if ((json === undefined) || (json === null)) { 53 | return json; 54 | } 55 | return { 56 | 57 | 'jitoTipLamportsWithPayer': JitoTipLamportsWithPayerJitoTipLamportsWithPayerFromJSON(json['jitoTipLamportsWithPayer']), 58 | }; 59 | } 60 | 61 | export function JitoTipLamportsWithPayerToJSON(value?: JitoTipLamportsWithPayer | null): any { 62 | if (value === undefined) { 63 | return undefined; 64 | } 65 | if (value === null) { 66 | return null; 67 | } 68 | return { 69 | 70 | 'jitoTipLamportsWithPayer': JitoTipLamportsWithPayerJitoTipLamportsWithPayerToJSON(value.jitoTipLamportsWithPayer), 71 | }; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /generated/models/PriorityLevelWithMaxLamports.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | import type { PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports } from './PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports'; 17 | import { 18 | PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsFromJSON, 19 | PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsFromJSONTyped, 20 | PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsToJSON, 21 | } from './PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports'; 22 | 23 | /** 24 | * 25 | * @export 26 | * @interface PriorityLevelWithMaxLamports 27 | */ 28 | export interface PriorityLevelWithMaxLamports { 29 | /** 30 | * 31 | * @type {PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports} 32 | * @memberof PriorityLevelWithMaxLamports 33 | */ 34 | priorityLevelWithMaxLamports: PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports; 35 | } 36 | 37 | /** 38 | * Check if a given object implements the PriorityLevelWithMaxLamports interface. 39 | */ 40 | export function instanceOfPriorityLevelWithMaxLamports(value: object): boolean { 41 | let isInstance = true; 42 | isInstance = isInstance && "priorityLevelWithMaxLamports" in value; 43 | 44 | return isInstance; 45 | } 46 | 47 | export function PriorityLevelWithMaxLamportsFromJSON(json: any): PriorityLevelWithMaxLamports { 48 | return PriorityLevelWithMaxLamportsFromJSONTyped(json, false); 49 | } 50 | 51 | export function PriorityLevelWithMaxLamportsFromJSONTyped(json: any, ignoreDiscriminator: boolean): PriorityLevelWithMaxLamports { 52 | if ((json === undefined) || (json === null)) { 53 | return json; 54 | } 55 | return { 56 | 57 | 'priorityLevelWithMaxLamports': PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsFromJSON(json['priorityLevelWithMaxLamports']), 58 | }; 59 | } 60 | 61 | export function PriorityLevelWithMaxLamportsToJSON(value?: PriorityLevelWithMaxLamports | null): any { 62 | if (value === undefined) { 63 | return undefined; 64 | } 65 | if (value === null) { 66 | return null; 67 | } 68 | return { 69 | 70 | 'priorityLevelWithMaxLamports': PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsToJSON(value.priorityLevelWithMaxLamports), 71 | }; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /example/utils/transactionSender.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BlockhashWithExpiryBlockHeight, 3 | Connection, 4 | TransactionExpiredBlockheightExceededError, 5 | VersionedTransactionResponse, 6 | } from "@solana/web3.js"; 7 | import promiseRetry from "promise-retry"; 8 | import { wait } from "./wait"; 9 | 10 | type TransactionSenderAndConfirmationWaiterArgs = { 11 | connection: Connection; 12 | serializedTransaction: Buffer; 13 | blockhashWithExpiryBlockHeight: BlockhashWithExpiryBlockHeight; 14 | }; 15 | 16 | const SEND_OPTIONS = { 17 | skipPreflight: true, 18 | }; 19 | 20 | export async function transactionSenderAndConfirmationWaiter({ 21 | connection, 22 | serializedTransaction, 23 | blockhashWithExpiryBlockHeight, 24 | }: TransactionSenderAndConfirmationWaiterArgs): Promise { 25 | const txid = await connection.sendRawTransaction( 26 | serializedTransaction, 27 | SEND_OPTIONS 28 | ); 29 | 30 | const controller = new AbortController(); 31 | const abortSignal = controller.signal; 32 | 33 | const abortableResender = async () => { 34 | while (true) { 35 | await wait(2_000); 36 | if (abortSignal.aborted) return; 37 | try { 38 | await connection.sendRawTransaction( 39 | serializedTransaction, 40 | SEND_OPTIONS 41 | ); 42 | } catch (e) { 43 | console.warn(`Failed to resend transaction: ${e}`); 44 | } 45 | } 46 | }; 47 | 48 | try { 49 | abortableResender(); 50 | const lastValidBlockHeight = 51 | blockhashWithExpiryBlockHeight.lastValidBlockHeight; 52 | 53 | // this would throw TransactionExpiredBlockheightExceededError 54 | await Promise.race([ 55 | connection.confirmTransaction( 56 | { 57 | ...blockhashWithExpiryBlockHeight, 58 | lastValidBlockHeight, 59 | signature: txid, 60 | abortSignal, 61 | }, 62 | "confirmed" 63 | ), 64 | new Promise(async (resolve) => { 65 | // in case ws socket died 66 | while (!abortSignal.aborted) { 67 | await wait(2_000); 68 | const tx = await connection.getSignatureStatus(txid, { 69 | searchTransactionHistory: false, 70 | }); 71 | if (tx?.value?.confirmationStatus === "confirmed") { 72 | resolve(tx); 73 | } 74 | } 75 | }), 76 | ]); 77 | } catch (e) { 78 | if (e instanceof TransactionExpiredBlockheightExceededError) { 79 | // we consume this error and getTransaction would return null 80 | return null; 81 | } else { 82 | // invalid state from web3.js 83 | throw e; 84 | } 85 | } finally { 86 | controller.abort(); 87 | } 88 | 89 | // in case rpc is not synced yet, we add some retries 90 | const response = promiseRetry( 91 | async (retry) => { 92 | const response = await connection.getTransaction(txid, { 93 | commitment: "confirmed", 94 | maxSupportedTransactionVersion: 0, 95 | }); 96 | if (!response) { 97 | retry(response); 98 | } 99 | return response; 100 | }, 101 | { 102 | retries: 5, 103 | minTimeout: 1e3, 104 | } 105 | ); 106 | 107 | return response; 108 | } 109 | -------------------------------------------------------------------------------- /generated/models/SwapInfo.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | /** 17 | * 18 | * @export 19 | * @interface SwapInfo 20 | */ 21 | export interface SwapInfo { 22 | /** 23 | * 24 | * @type {string} 25 | * @memberof SwapInfo 26 | */ 27 | ammKey: string; 28 | /** 29 | * 30 | * @type {string} 31 | * @memberof SwapInfo 32 | */ 33 | label?: string; 34 | /** 35 | * 36 | * @type {string} 37 | * @memberof SwapInfo 38 | */ 39 | inputMint: string; 40 | /** 41 | * 42 | * @type {string} 43 | * @memberof SwapInfo 44 | */ 45 | outputMint: string; 46 | /** 47 | * 48 | * @type {string} 49 | * @memberof SwapInfo 50 | */ 51 | inAmount: string; 52 | /** 53 | * 54 | * @type {string} 55 | * @memberof SwapInfo 56 | */ 57 | outAmount: string; 58 | } 59 | 60 | /** 61 | * Check if a given object implements the SwapInfo interface. 62 | */ 63 | export function instanceOfSwapInfo(value: object): boolean { 64 | let isInstance = true; 65 | isInstance = isInstance && "ammKey" in value; 66 | isInstance = isInstance && "inputMint" in value; 67 | isInstance = isInstance && "outputMint" in value; 68 | isInstance = isInstance && "inAmount" in value; 69 | isInstance = isInstance && "outAmount" in value; 70 | 71 | return isInstance; 72 | } 73 | 74 | export function SwapInfoFromJSON(json: any): SwapInfo { 75 | return SwapInfoFromJSONTyped(json, false); 76 | } 77 | 78 | export function SwapInfoFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapInfo { 79 | if ((json === undefined) || (json === null)) { 80 | return json; 81 | } 82 | return { 83 | 84 | 'ammKey': json['ammKey'], 85 | 'label': !exists(json, 'label') ? undefined : json['label'], 86 | 'inputMint': json['inputMint'], 87 | 'outputMint': json['outputMint'], 88 | 'inAmount': json['inAmount'], 89 | 'outAmount': json['outAmount'], 90 | }; 91 | } 92 | 93 | export function SwapInfoToJSON(value?: SwapInfo | null): any { 94 | if (value === undefined) { 95 | return undefined; 96 | } 97 | if (value === null) { 98 | return null; 99 | } 100 | return { 101 | 102 | 'ammKey': value.ammKey, 103 | 'label': value.label, 104 | 'inputMint': value.inputMint, 105 | 'outputMint': value.outputMint, 106 | 'inAmount': value.inAmount, 107 | 'outAmount': value.outAmount, 108 | }; 109 | } 110 | 111 | -------------------------------------------------------------------------------- /generated/models/SwapRequestPrioritizationFeeLamports.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import type { JitoTipLamports } from './JitoTipLamports'; 16 | import { 17 | instanceOfJitoTipLamports, 18 | JitoTipLamportsFromJSON, 19 | JitoTipLamportsFromJSONTyped, 20 | JitoTipLamportsToJSON, 21 | } from './JitoTipLamports'; 22 | import type { JitoTipLamportsWithPayer } from './JitoTipLamportsWithPayer'; 23 | import { 24 | instanceOfJitoTipLamportsWithPayer, 25 | JitoTipLamportsWithPayerFromJSON, 26 | JitoTipLamportsWithPayerFromJSONTyped, 27 | JitoTipLamportsWithPayerToJSON, 28 | } from './JitoTipLamportsWithPayer'; 29 | import type { PriorityLevelWithMaxLamports } from './PriorityLevelWithMaxLamports'; 30 | import { 31 | instanceOfPriorityLevelWithMaxLamports, 32 | PriorityLevelWithMaxLamportsFromJSON, 33 | PriorityLevelWithMaxLamportsFromJSONTyped, 34 | PriorityLevelWithMaxLamportsToJSON, 35 | } from './PriorityLevelWithMaxLamports'; 36 | 37 | /** 38 | * @type SwapRequestPrioritizationFeeLamports 39 | * - To specify a level or amount of additional fees to prioritize the transaction 40 | * - It can be used for EITHER priority fee OR Jito tip (not both at the same time) 41 | * - If you want to include both, you will need to use `/swap-instructions` to add both at the same time 42 | * - Defaults to `auto`, but preferred to use `priorityLevelWithMaxLamports` as it may be more accurate when accounting local fee market 43 | * - Fixed lamports can be passed in as an integer in the `prioritizationFeeLamports` parameter 44 | * 45 | * @export 46 | */ 47 | export type SwapRequestPrioritizationFeeLamports = JitoTipLamports | JitoTipLamportsWithPayer | PriorityLevelWithMaxLamports; 48 | 49 | export function SwapRequestPrioritizationFeeLamportsFromJSON(json: any): SwapRequestPrioritizationFeeLamports { 50 | return SwapRequestPrioritizationFeeLamportsFromJSONTyped(json, false); 51 | } 52 | 53 | export function SwapRequestPrioritizationFeeLamportsFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapRequestPrioritizationFeeLamports { 54 | if ((json === undefined) || (json === null)) { 55 | return json; 56 | } 57 | return { ...JitoTipLamportsFromJSONTyped(json, true), ...JitoTipLamportsWithPayerFromJSONTyped(json, true), ...PriorityLevelWithMaxLamportsFromJSONTyped(json, true) }; 58 | } 59 | 60 | export function SwapRequestPrioritizationFeeLamportsToJSON(value?: SwapRequestPrioritizationFeeLamports | null): any { 61 | if (value === undefined) { 62 | return undefined; 63 | } 64 | if (value === null) { 65 | return null; 66 | } 67 | 68 | if (instanceOfJitoTipLamports(value)) { 69 | return JitoTipLamportsToJSON(value as JitoTipLamports); 70 | } 71 | if (instanceOfJitoTipLamportsWithPayer(value)) { 72 | return JitoTipLamportsWithPayerToJSON(value as JitoTipLamportsWithPayer); 73 | } 74 | if (instanceOfPriorityLevelWithMaxLamports(value)) { 75 | return PriorityLevelWithMaxLamportsToJSON(value as PriorityLevelWithMaxLamports); 76 | } 77 | 78 | return {}; 79 | } 80 | 81 | -------------------------------------------------------------------------------- /generated/models/PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | /** 17 | * 18 | * @export 19 | * @interface PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports 20 | */ 21 | export interface PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports { 22 | /** 23 | * 24 | * @type {string} 25 | * @memberof PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports 26 | */ 27 | priorityLevel: PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsPriorityLevelEnum; 28 | /** 29 | * - Maximum lamports to cap the priority fee estimation, to prevent overpaying 30 | * 31 | * @type {number} 32 | * @memberof PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports 33 | */ 34 | maxLamports: number; 35 | /** 36 | * - A boolean to choose between using a global or local fee market to estimate. If `global` is set to `false`, the estimation focuses on fees relevant to the **writable accounts** involved in the instruction. 37 | * 38 | * @type {boolean} 39 | * @memberof PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports 40 | */ 41 | global?: boolean; 42 | } 43 | 44 | 45 | /** 46 | * @export 47 | */ 48 | export const PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsPriorityLevelEnum = { 49 | Medium: 'medium', 50 | High: 'high', 51 | VeryHigh: 'veryHigh' 52 | } as const; 53 | export type PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsPriorityLevelEnum = typeof PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsPriorityLevelEnum[keyof typeof PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsPriorityLevelEnum]; 54 | 55 | 56 | /** 57 | * Check if a given object implements the PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports interface. 58 | */ 59 | export function instanceOfPriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports(value: object): boolean { 60 | let isInstance = true; 61 | isInstance = isInstance && "priorityLevel" in value; 62 | isInstance = isInstance && "maxLamports" in value; 63 | 64 | return isInstance; 65 | } 66 | 67 | export function PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsFromJSON(json: any): PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports { 68 | return PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsFromJSONTyped(json, false); 69 | } 70 | 71 | export function PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsFromJSONTyped(json: any, ignoreDiscriminator: boolean): PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports { 72 | if ((json === undefined) || (json === null)) { 73 | return json; 74 | } 75 | return { 76 | 77 | 'priorityLevel': json['priorityLevel'], 78 | 'maxLamports': json['maxLamports'], 79 | 'global': !exists(json, 'global') ? undefined : json['global'], 80 | }; 81 | } 82 | 83 | export function PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamportsToJSON(value?: PriorityLevelWithMaxLamportsPriorityLevelWithMaxLamports | null): any { 84 | if (value === undefined) { 85 | return undefined; 86 | } 87 | if (value === null) { 88 | return null; 89 | } 90 | return { 91 | 92 | 'priorityLevel': value.priorityLevel, 93 | 'maxLamports': value.maxLamports, 94 | 'global': value.global, 95 | }; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /generated/models/SwapInstructionsResponse.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | import type { Instruction } from './Instruction'; 17 | import { 18 | InstructionFromJSON, 19 | InstructionFromJSONTyped, 20 | InstructionToJSON, 21 | } from './Instruction'; 22 | 23 | /** 24 | * 25 | * @export 26 | * @interface SwapInstructionsResponse 27 | */ 28 | export interface SwapInstructionsResponse { 29 | /** 30 | * - If you set jito tips using the `prioritizationFeeLamports` parameter, you will see a custom tip instruction to Jito here. 31 | * 32 | * @type {Array} 33 | * @memberof SwapInstructionsResponse 34 | */ 35 | otherInstructions: Array; 36 | /** 37 | * - To setup the compute budget for the transaction. 38 | * 39 | * @type {Array} 40 | * @memberof SwapInstructionsResponse 41 | */ 42 | computeBudgetInstructions: Array; 43 | /** 44 | * - To setup required token accounts for the users. 45 | * 46 | * @type {Array} 47 | * @memberof SwapInstructionsResponse 48 | */ 49 | setupInstructions: Array; 50 | /** 51 | * 52 | * @type {Instruction} 53 | * @memberof SwapInstructionsResponse 54 | */ 55 | swapInstruction: Instruction; 56 | /** 57 | * 58 | * @type {Instruction} 59 | * @memberof SwapInstructionsResponse 60 | */ 61 | cleanupInstruction?: Instruction; 62 | /** 63 | * - The lookup table addresses if you are using versioned transaction. 64 | * 65 | * @type {Array} 66 | * @memberof SwapInstructionsResponse 67 | */ 68 | addressLookupTableAddresses: Array; 69 | } 70 | 71 | /** 72 | * Check if a given object implements the SwapInstructionsResponse interface. 73 | */ 74 | export function instanceOfSwapInstructionsResponse(value: object): boolean { 75 | let isInstance = true; 76 | isInstance = isInstance && "otherInstructions" in value; 77 | isInstance = isInstance && "computeBudgetInstructions" in value; 78 | isInstance = isInstance && "setupInstructions" in value; 79 | isInstance = isInstance && "swapInstruction" in value; 80 | isInstance = isInstance && "addressLookupTableAddresses" in value; 81 | 82 | return isInstance; 83 | } 84 | 85 | export function SwapInstructionsResponseFromJSON(json: any): SwapInstructionsResponse { 86 | return SwapInstructionsResponseFromJSONTyped(json, false); 87 | } 88 | 89 | export function SwapInstructionsResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapInstructionsResponse { 90 | if ((json === undefined) || (json === null)) { 91 | return json; 92 | } 93 | return { 94 | 95 | 'otherInstructions': ((json['otherInstructions'] as Array).map(InstructionFromJSON)), 96 | 'computeBudgetInstructions': ((json['computeBudgetInstructions'] as Array).map(InstructionFromJSON)), 97 | 'setupInstructions': ((json['setupInstructions'] as Array).map(InstructionFromJSON)), 98 | 'swapInstruction': InstructionFromJSON(json['swapInstruction']), 99 | 'cleanupInstruction': !exists(json, 'cleanupInstruction') ? undefined : InstructionFromJSON(json['cleanupInstruction']), 100 | 'addressLookupTableAddresses': json['addressLookupTableAddresses'], 101 | }; 102 | } 103 | 104 | export function SwapInstructionsResponseToJSON(value?: SwapInstructionsResponse | null): any { 105 | if (value === undefined) { 106 | return undefined; 107 | } 108 | if (value === null) { 109 | return null; 110 | } 111 | return { 112 | 113 | 'otherInstructions': ((value.otherInstructions as Array).map(InstructionToJSON)), 114 | 'computeBudgetInstructions': ((value.computeBudgetInstructions as Array).map(InstructionToJSON)), 115 | 'setupInstructions': ((value.setupInstructions as Array).map(InstructionToJSON)), 116 | 'swapInstruction': InstructionToJSON(value.swapInstruction), 117 | 'cleanupInstruction': InstructionToJSON(value.cleanupInstruction), 118 | 'addressLookupTableAddresses': value.addressLookupTableAddresses, 119 | }; 120 | } 121 | 122 | -------------------------------------------------------------------------------- /example/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | QuoteGetRequest, 3 | QuoteResponse, 4 | SwapResponse, 5 | createJupiterApiClient, 6 | } from "../src/index"; 7 | import { Connection, Keypair, VersionedTransaction } from "@solana/web3.js"; 8 | import { Wallet } from "@project-serum/anchor"; 9 | import bs58 from "bs58"; 10 | import { transactionSenderAndConfirmationWaiter } from "./utils/transactionSender"; 11 | import { getSignature } from "./utils/getSignature"; 12 | import dotenv from "dotenv"; 13 | 14 | dotenv.config(); 15 | 16 | // If you have problem landing transactions, read this: https://dev.jup.ag/docs/swap-api/send-swap-transaction#how-jupiter-estimates-priority-fee 17 | 18 | // Make sure that you are using your own RPC endpoint. 19 | // Helius and Triton have staked SOL and they can usually land transactions better. 20 | const connection = new Connection( 21 | "https://api.mainnet-beta.solana.com" // We only support mainnet. 22 | ); 23 | 24 | // Get API key from environment variables 25 | const apiKey = process.env.API_KEY; 26 | 27 | // Create Jupiter API client with API key if available 28 | const jupiterQuoteApi = createJupiterApiClient( 29 | apiKey ? { apiKey } : undefined 30 | ); 31 | 32 | // Log which API endpoint is being used 33 | console.log("Using API endpoint:", apiKey 34 | ? "https://api.jup.ag/swap/v1 (with API key)" 35 | : "https://lite-api.jup.ag/swap/v1 (free tier)"); 36 | 37 | async function getQuote() { 38 | const params: QuoteGetRequest = { 39 | inputMint: "So11111111111111111111111111111111111111112", // SOL 40 | outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC 41 | amount: 100000000, // 0.1 SOL 42 | slippageBps: 100, // 1% 43 | }; 44 | 45 | // get quote 46 | const quote = await jupiterQuoteApi.quoteGet(params); 47 | 48 | if (!quote) { 49 | throw new Error("unable to quote"); 50 | } 51 | return quote; 52 | } 53 | 54 | async function getSwapResponse(wallet: Wallet, quote: QuoteResponse) { 55 | // Get serialized transaction 56 | const swapResponse = await jupiterQuoteApi.swapPost({ 57 | swapRequest: { 58 | quoteResponse: quote, 59 | userPublicKey: wallet.publicKey.toBase58(), 60 | dynamicComputeUnitLimit: true, 61 | dynamicSlippage: true, 62 | prioritizationFeeLamports: { 63 | priorityLevelWithMaxLamports: { 64 | maxLamports: 10000000, 65 | priorityLevel: "veryHigh", // If you want to land transaction fast, set this to use `veryHigh`. You will pay on average higher priority fee. 66 | }, 67 | }, 68 | }, 69 | }); 70 | return swapResponse; 71 | } 72 | 73 | async function flowQuote() { 74 | const quote = await getQuote(); 75 | console.dir(quote, { depth: null }); 76 | } 77 | 78 | async function flowQuoteAndSwap() { 79 | const wallet = new Wallet( 80 | Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY || "")) 81 | ); 82 | console.log("Wallet:", wallet.publicKey.toBase58()); 83 | 84 | const quote = await getQuote(); 85 | console.dir(quote, { depth: null }); 86 | const swapResponse = await getSwapResponse(wallet, quote); 87 | console.dir(swapResponse, { depth: null }); 88 | 89 | // Serialize the transaction 90 | const swapTransactionBuf = Uint8Array.from( 91 | Buffer.from(swapResponse.swapTransaction, "base64") 92 | ); 93 | const transaction = VersionedTransaction.deserialize(swapTransactionBuf); 94 | 95 | // Sign the transaction 96 | transaction.sign([wallet.payer]); 97 | const signature = getSignature(transaction); 98 | 99 | // We first simulate whether the transaction would be successful 100 | const { value: simulatedTransactionResponse } = 101 | await connection.simulateTransaction(transaction, { 102 | replaceRecentBlockhash: true, 103 | commitment: "processed", 104 | }); 105 | const { err, logs } = simulatedTransactionResponse; 106 | 107 | if (err) { 108 | // Simulation error, we can check the logs for more details 109 | // If you are getting an invalid account error, make sure that you have the input mint account to actually swap from. 110 | console.error("Simulation Error:"); 111 | console.error({ err, logs }); 112 | return; 113 | } 114 | 115 | const serializedTransaction = Buffer.from(transaction.serialize()); 116 | const blockhash = transaction.message.recentBlockhash; 117 | 118 | const transactionResponse = await transactionSenderAndConfirmationWaiter({ 119 | connection, 120 | serializedTransaction, 121 | blockhashWithExpiryBlockHeight: { 122 | blockhash, 123 | lastValidBlockHeight: swapResponse.lastValidBlockHeight, 124 | }, 125 | }); 126 | 127 | // If we are not getting a response back, the transaction has not confirmed. 128 | if (!transactionResponse) { 129 | console.error("Transaction not confirmed"); 130 | return; 131 | } 132 | 133 | if (transactionResponse.meta?.err) { 134 | console.error(transactionResponse.meta?.err); 135 | } 136 | 137 | console.log(`https://solscan.io/tx/${signature}`); 138 | } 139 | 140 | export async function main() { 141 | switch (process.env.FLOW) { 142 | case "quote": { 143 | await flowQuote(); 144 | break; 145 | } 146 | 147 | case "quoteAndSwap": { 148 | await flowQuoteAndSwap(); 149 | break; 150 | } 151 | 152 | default: { 153 | console.error("Please set the FLOW environment"); 154 | } 155 | } 156 | } 157 | 158 | main(); 159 | -------------------------------------------------------------------------------- /generated/models/QuoteResponse.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | import type { PlatformFee } from './PlatformFee'; 17 | import { 18 | PlatformFeeFromJSON, 19 | PlatformFeeFromJSONTyped, 20 | PlatformFeeToJSON, 21 | } from './PlatformFee'; 22 | import type { RoutePlanStep } from './RoutePlanStep'; 23 | import { 24 | RoutePlanStepFromJSON, 25 | RoutePlanStepFromJSONTyped, 26 | RoutePlanStepToJSON, 27 | } from './RoutePlanStep'; 28 | import type { SwapMode } from './SwapMode'; 29 | import { 30 | SwapModeFromJSON, 31 | SwapModeFromJSONTyped, 32 | SwapModeToJSON, 33 | } from './SwapMode'; 34 | 35 | /** 36 | * 37 | * @export 38 | * @interface QuoteResponse 39 | */ 40 | export interface QuoteResponse { 41 | /** 42 | * 43 | * @type {string} 44 | * @memberof QuoteResponse 45 | */ 46 | inputMint: string; 47 | /** 48 | * 49 | * @type {string} 50 | * @memberof QuoteResponse 51 | */ 52 | inAmount: string; 53 | /** 54 | * 55 | * @type {string} 56 | * @memberof QuoteResponse 57 | */ 58 | outputMint: string; 59 | /** 60 | * - Calculated output amount from routing engine 61 | * - The value includes platform fees and DEX fees, excluding slippage 62 | * 63 | * @type {string} 64 | * @memberof QuoteResponse 65 | */ 66 | outAmount: string; 67 | /** 68 | * - Calculated minimum output amount after accounting for `slippageBps` on the `outAmount` value 69 | * - Not used by `/swap` endpoint to build transaction 70 | * 71 | * @type {string} 72 | * @memberof QuoteResponse 73 | */ 74 | otherAmountThreshold: string; 75 | /** 76 | * 77 | * @type {SwapMode} 78 | * @memberof QuoteResponse 79 | */ 80 | swapMode: SwapMode; 81 | /** 82 | * 83 | * @type {number} 84 | * @memberof QuoteResponse 85 | */ 86 | slippageBps: number; 87 | /** 88 | * 89 | * @type {PlatformFee} 90 | * @memberof QuoteResponse 91 | */ 92 | platformFee?: PlatformFee; 93 | /** 94 | * 95 | * @type {string} 96 | * @memberof QuoteResponse 97 | */ 98 | priceImpactPct: string; 99 | /** 100 | * 101 | * @type {Array} 102 | * @memberof QuoteResponse 103 | */ 104 | routePlan: Array; 105 | /** 106 | * 107 | * @type {number} 108 | * @memberof QuoteResponse 109 | */ 110 | contextSlot?: number; 111 | /** 112 | * 113 | * @type {number} 114 | * @memberof QuoteResponse 115 | */ 116 | timeTaken?: number; 117 | } 118 | 119 | /** 120 | * Check if a given object implements the QuoteResponse interface. 121 | */ 122 | export function instanceOfQuoteResponse(value: object): boolean { 123 | let isInstance = true; 124 | isInstance = isInstance && "inputMint" in value; 125 | isInstance = isInstance && "inAmount" in value; 126 | isInstance = isInstance && "outputMint" in value; 127 | isInstance = isInstance && "outAmount" in value; 128 | isInstance = isInstance && "otherAmountThreshold" in value; 129 | isInstance = isInstance && "swapMode" in value; 130 | isInstance = isInstance && "slippageBps" in value; 131 | isInstance = isInstance && "priceImpactPct" in value; 132 | isInstance = isInstance && "routePlan" in value; 133 | 134 | return isInstance; 135 | } 136 | 137 | export function QuoteResponseFromJSON(json: any): QuoteResponse { 138 | return QuoteResponseFromJSONTyped(json, false); 139 | } 140 | 141 | export function QuoteResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): QuoteResponse { 142 | if ((json === undefined) || (json === null)) { 143 | return json; 144 | } 145 | return { 146 | 147 | 'inputMint': json['inputMint'], 148 | 'inAmount': json['inAmount'], 149 | 'outputMint': json['outputMint'], 150 | 'outAmount': json['outAmount'], 151 | 'otherAmountThreshold': json['otherAmountThreshold'], 152 | 'swapMode': SwapModeFromJSON(json['swapMode']), 153 | 'slippageBps': json['slippageBps'], 154 | 'platformFee': !exists(json, 'platformFee') ? undefined : PlatformFeeFromJSON(json['platformFee']), 155 | 'priceImpactPct': json['priceImpactPct'], 156 | 'routePlan': ((json['routePlan'] as Array).map(RoutePlanStepFromJSON)), 157 | 'contextSlot': !exists(json, 'contextSlot') ? undefined : json['contextSlot'], 158 | 'timeTaken': !exists(json, 'timeTaken') ? undefined : json['timeTaken'], 159 | }; 160 | } 161 | 162 | export function QuoteResponseToJSON(value?: QuoteResponse | null): any { 163 | if (value === undefined) { 164 | return undefined; 165 | } 166 | if (value === null) { 167 | return null; 168 | } 169 | return { 170 | 171 | 'inputMint': value.inputMint, 172 | 'inAmount': value.inAmount, 173 | 'outputMint': value.outputMint, 174 | 'outAmount': value.outAmount, 175 | 'otherAmountThreshold': value.otherAmountThreshold, 176 | 'swapMode': SwapModeToJSON(value.swapMode), 177 | 'slippageBps': value.slippageBps, 178 | 'platformFee': PlatformFeeToJSON(value.platformFee), 179 | 'priceImpactPct': value.priceImpactPct, 180 | 'routePlan': ((value.routePlan as Array).map(RoutePlanStepToJSON)), 181 | 'contextSlot': value.contextSlot, 182 | 'timeTaken': value.timeTaken, 183 | }; 184 | } 185 | 186 | -------------------------------------------------------------------------------- /generated/apis/SwapApi.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | 16 | import * as runtime from '../runtime'; 17 | import type { 18 | QuoteResponse, 19 | SwapInstructionsResponse, 20 | SwapRequest, 21 | SwapResponse, 22 | } from '../models/index'; 23 | import { 24 | QuoteResponseFromJSON, 25 | QuoteResponseToJSON, 26 | SwapInstructionsResponseFromJSON, 27 | SwapInstructionsResponseToJSON, 28 | SwapRequestFromJSON, 29 | SwapRequestToJSON, 30 | SwapResponseFromJSON, 31 | SwapResponseToJSON, 32 | } from '../models/index'; 33 | 34 | export interface QuoteGetRequest { 35 | inputMint: string; 36 | outputMint: string; 37 | amount: number; 38 | slippageBps?: number; 39 | swapMode?: QuoteGetSwapModeEnum; 40 | dexes?: Array; 41 | excludeDexes?: Array; 42 | restrictIntermediateTokens?: boolean; 43 | onlyDirectRoutes?: boolean; 44 | asLegacyTransaction?: boolean; 45 | platformFeeBps?: number; 46 | maxAccounts?: number; 47 | instructionVersion?: QuoteGetInstructionVersionEnum; 48 | dynamicSlippage?: boolean; 49 | } 50 | 51 | export interface SwapInstructionsPostRequest { 52 | swapRequest: SwapRequest; 53 | } 54 | 55 | export interface SwapPostRequest { 56 | swapRequest: SwapRequest; 57 | } 58 | 59 | /** 60 | * 61 | */ 62 | export class SwapApi extends runtime.BaseAPI { 63 | 64 | /** 65 | * Returns a hash, which key is the program id and value is the label. This is used to help map error from transaction by identifying the fault program id. This can be used in conjunction with the `excludeDexes` or `dexes` parameter. 66 | * program-id-to-label 67 | */ 68 | async programIdToLabelGetRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { 69 | const queryParameters: any = {}; 70 | 71 | const headerParameters: runtime.HTTPHeaders = {}; 72 | 73 | const response = await this.request({ 74 | path: `/program-id-to-label`, 75 | method: 'GET', 76 | headers: headerParameters, 77 | query: queryParameters, 78 | }, initOverrides); 79 | 80 | return new runtime.JSONApiResponse(response); 81 | } 82 | 83 | /** 84 | * Returns a hash, which key is the program id and value is the label. This is used to help map error from transaction by identifying the fault program id. This can be used in conjunction with the `excludeDexes` or `dexes` parameter. 85 | * program-id-to-label 86 | */ 87 | async programIdToLabelGet(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{ [key: string]: string; }> { 88 | const response = await this.programIdToLabelGetRaw(initOverrides); 89 | return await response.value(); 90 | } 91 | 92 | /** 93 | * Request for a quote to be used in `POST /swap` 94 | * quote 95 | */ 96 | async quoteGetRaw(requestParameters: QuoteGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { 97 | if (requestParameters.inputMint === null || requestParameters.inputMint === undefined) { 98 | throw new runtime.RequiredError('inputMint','Required parameter requestParameters.inputMint was null or undefined when calling quoteGet.'); 99 | } 100 | 101 | if (requestParameters.outputMint === null || requestParameters.outputMint === undefined) { 102 | throw new runtime.RequiredError('outputMint','Required parameter requestParameters.outputMint was null or undefined when calling quoteGet.'); 103 | } 104 | 105 | if (requestParameters.amount === null || requestParameters.amount === undefined) { 106 | throw new runtime.RequiredError('amount','Required parameter requestParameters.amount was null or undefined when calling quoteGet.'); 107 | } 108 | 109 | const queryParameters: any = {}; 110 | 111 | if (requestParameters.inputMint !== undefined) { 112 | queryParameters['inputMint'] = requestParameters.inputMint; 113 | } 114 | 115 | if (requestParameters.outputMint !== undefined) { 116 | queryParameters['outputMint'] = requestParameters.outputMint; 117 | } 118 | 119 | if (requestParameters.amount !== undefined) { 120 | queryParameters['amount'] = requestParameters.amount; 121 | } 122 | 123 | if (requestParameters.slippageBps !== undefined) { 124 | queryParameters['slippageBps'] = requestParameters.slippageBps; 125 | } 126 | 127 | if (requestParameters.swapMode !== undefined) { 128 | queryParameters['swapMode'] = requestParameters.swapMode; 129 | } 130 | 131 | if (requestParameters.dexes) { 132 | queryParameters['dexes'] = requestParameters.dexes; 133 | } 134 | 135 | if (requestParameters.excludeDexes) { 136 | queryParameters['excludeDexes'] = requestParameters.excludeDexes; 137 | } 138 | 139 | if (requestParameters.restrictIntermediateTokens !== undefined) { 140 | queryParameters['restrictIntermediateTokens'] = requestParameters.restrictIntermediateTokens; 141 | } 142 | 143 | if (requestParameters.onlyDirectRoutes !== undefined) { 144 | queryParameters['onlyDirectRoutes'] = requestParameters.onlyDirectRoutes; 145 | } 146 | 147 | if (requestParameters.asLegacyTransaction !== undefined) { 148 | queryParameters['asLegacyTransaction'] = requestParameters.asLegacyTransaction; 149 | } 150 | 151 | if (requestParameters.platformFeeBps !== undefined) { 152 | queryParameters['platformFeeBps'] = requestParameters.platformFeeBps; 153 | } 154 | 155 | if (requestParameters.maxAccounts !== undefined) { 156 | queryParameters['maxAccounts'] = requestParameters.maxAccounts; 157 | } 158 | 159 | if (requestParameters.instructionVersion !== undefined) { 160 | queryParameters['instructionVersion'] = requestParameters.instructionVersion; 161 | } 162 | 163 | if (requestParameters.dynamicSlippage !== undefined) { 164 | queryParameters['dynamicSlippage'] = requestParameters.dynamicSlippage; 165 | } 166 | 167 | const headerParameters: runtime.HTTPHeaders = {}; 168 | 169 | const response = await this.request({ 170 | path: `/quote`, 171 | method: 'GET', 172 | headers: headerParameters, 173 | query: queryParameters, 174 | }, initOverrides); 175 | 176 | return new runtime.JSONApiResponse(response, (jsonValue) => QuoteResponseFromJSON(jsonValue)); 177 | } 178 | 179 | /** 180 | * Request for a quote to be used in `POST /swap` 181 | * quote 182 | */ 183 | async quoteGet(requestParameters: QuoteGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { 184 | const response = await this.quoteGetRaw(requestParameters, initOverrides); 185 | return await response.value(); 186 | } 187 | 188 | /** 189 | * Request for swap instructions that you can use from the quote you get from `/quote` 190 | * swap-instructions 191 | */ 192 | async swapInstructionsPostRaw(requestParameters: SwapInstructionsPostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { 193 | if (requestParameters.swapRequest === null || requestParameters.swapRequest === undefined) { 194 | throw new runtime.RequiredError('swapRequest','Required parameter requestParameters.swapRequest was null or undefined when calling swapInstructionsPost.'); 195 | } 196 | 197 | const queryParameters: any = {}; 198 | 199 | const headerParameters: runtime.HTTPHeaders = {}; 200 | 201 | headerParameters['Content-Type'] = 'application/json'; 202 | 203 | const response = await this.request({ 204 | path: `/swap-instructions`, 205 | method: 'POST', 206 | headers: headerParameters, 207 | query: queryParameters, 208 | body: SwapRequestToJSON(requestParameters.swapRequest), 209 | }, initOverrides); 210 | 211 | return new runtime.JSONApiResponse(response, (jsonValue) => SwapInstructionsResponseFromJSON(jsonValue)); 212 | } 213 | 214 | /** 215 | * Request for swap instructions that you can use from the quote you get from `/quote` 216 | * swap-instructions 217 | */ 218 | async swapInstructionsPost(requestParameters: SwapInstructionsPostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { 219 | const response = await this.swapInstructionsPostRaw(requestParameters, initOverrides); 220 | return await response.value(); 221 | } 222 | 223 | /** 224 | * Request for a base64-encoded unsigned swap transaction based on the `/quote` response 225 | * swap 226 | */ 227 | async swapPostRaw(requestParameters: SwapPostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { 228 | if (requestParameters.swapRequest === null || requestParameters.swapRequest === undefined) { 229 | throw new runtime.RequiredError('swapRequest','Required parameter requestParameters.swapRequest was null or undefined when calling swapPost.'); 230 | } 231 | 232 | const queryParameters: any = {}; 233 | 234 | const headerParameters: runtime.HTTPHeaders = {}; 235 | 236 | headerParameters['Content-Type'] = 'application/json'; 237 | 238 | const response = await this.request({ 239 | path: `/swap`, 240 | method: 'POST', 241 | headers: headerParameters, 242 | query: queryParameters, 243 | body: SwapRequestToJSON(requestParameters.swapRequest), 244 | }, initOverrides); 245 | 246 | return new runtime.JSONApiResponse(response, (jsonValue) => SwapResponseFromJSON(jsonValue)); 247 | } 248 | 249 | /** 250 | * Request for a base64-encoded unsigned swap transaction based on the `/quote` response 251 | * swap 252 | */ 253 | async swapPost(requestParameters: SwapPostRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { 254 | const response = await this.swapPostRaw(requestParameters, initOverrides); 255 | return await response.value(); 256 | } 257 | 258 | } 259 | 260 | /** 261 | * @export 262 | */ 263 | export const QuoteGetSwapModeEnum = { 264 | ExactIn: 'ExactIn', 265 | ExactOut: 'ExactOut' 266 | } as const; 267 | export type QuoteGetSwapModeEnum = typeof QuoteGetSwapModeEnum[keyof typeof QuoteGetSwapModeEnum]; 268 | /** 269 | * @export 270 | */ 271 | export const QuoteGetInstructionVersionEnum = { 272 | V1: 'V1', 273 | V2: 'V2' 274 | } as const; 275 | export type QuoteGetInstructionVersionEnum = typeof QuoteGetInstructionVersionEnum[keyof typeof QuoteGetInstructionVersionEnum]; 276 | -------------------------------------------------------------------------------- /generated/models/SwapRequest.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | import { exists, mapValues } from '../runtime'; 16 | import type { QuoteResponse } from './QuoteResponse'; 17 | import { 18 | QuoteResponseFromJSON, 19 | QuoteResponseFromJSONTyped, 20 | QuoteResponseToJSON, 21 | } from './QuoteResponse'; 22 | import type { SwapRequestPrioritizationFeeLamports } from './SwapRequestPrioritizationFeeLamports'; 23 | import { 24 | SwapRequestPrioritizationFeeLamportsFromJSON, 25 | SwapRequestPrioritizationFeeLamportsFromJSONTyped, 26 | SwapRequestPrioritizationFeeLamportsToJSON, 27 | } from './SwapRequestPrioritizationFeeLamports'; 28 | 29 | /** 30 | * 31 | * @export 32 | * @interface SwapRequest 33 | */ 34 | export interface SwapRequest { 35 | /** 36 | * 37 | * @type {string} 38 | * @memberof SwapRequest 39 | */ 40 | userPublicKey: string; 41 | /** 42 | * - Allow a custom payer to pay for the transaction fees and rent of token accounts 43 | * - Note that users can close their ATAs elsewhere and have you reopen them again, your fees should account for this 44 | * 45 | * @type {string} 46 | * @memberof SwapRequest 47 | */ 48 | payer?: string; 49 | /** 50 | * - To automatically wrap/unwrap SOL in the transaction, as WSOL is an SPL token while native SOL is not 51 | * - When true and input mint is SOL, it will wrap the SOL amount to WSOL and swap 52 | * - When true and output mint is SOL, it will unwrap the WSOL back to SOL 53 | * - When false and input mint is SOL, it will use existing WSOL amount to swap 54 | * - When false and output mint is SOL, it will not unwrap the WSOL to SOL 55 | * - To set this parameter to false, you need to have the WSOL token account initialized 56 | * 57 | * @type {boolean} 58 | * @memberof SwapRequest 59 | */ 60 | wrapAndUnwrapSol?: boolean; 61 | /** 62 | * - The default is determined dynamically by the routing engine, allowing us to optimize for compute units, etc 63 | * - This enables the usage of shared program accounts, this is essential as complex routing will require multiple intermediate token accounts which the user might not have 64 | * - If true, you do not need to handle the creation of intermediate token accounts for the user 65 | * - Do note, shared accounts route will fail on some new AMMs (low liquidity token) 66 | * 67 | * @type {boolean} 68 | * @memberof SwapRequest 69 | */ 70 | useSharedAccounts?: boolean; 71 | /** 72 | * - An initialized token account that will be used to collect fees 73 | * - The mint of the token account **can only be either the input or output mint of the swap** 74 | * - Swap API no longer requires the use of the Referral Program 75 | * - If `platformFeeBps` is passed in `/quote`, the `feeAccount` must be passed as well 76 | * 77 | * @type {string} 78 | * @memberof SwapRequest 79 | */ 80 | feeAccount?: string; 81 | /** 82 | * - Specify any public key that belongs to you to track the transactions 83 | * - Useful for integrators to get all the swap transactions from this public key 84 | * - Query the data using a block explorer like Solscan/SolanaFM or query like Dune/Flipside 85 | * 86 | * @type {string} 87 | * @memberof SwapRequest 88 | */ 89 | trackingAccount?: string; 90 | /** 91 | * 92 | * @type {SwapRequestPrioritizationFeeLamports} 93 | * @memberof SwapRequest 94 | */ 95 | prioritizationFeeLamports?: SwapRequestPrioritizationFeeLamports; 96 | /** 97 | * - Builds a legacy transaction rather than the default versioned transaction 98 | * - Used together with `asLegacyTransaction` in `/quote`, otherwise the transaction might be too large 99 | * 100 | * @type {boolean} 101 | * @memberof SwapRequest 102 | */ 103 | asLegacyTransaction?: boolean; 104 | /** 105 | * - Public key of a token account that will be used to receive the token out of the swap 106 | * - If not provided, the signer's token account will be used 107 | * - If provided, we assume that the token account is already initialized 108 | * - `destinationTokenAccount` and `nativeDestinationAccount` are mutually exclusive 109 | * 110 | * @type {string} 111 | * @memberof SwapRequest 112 | */ 113 | destinationTokenAccount?: string; 114 | /** 115 | * - Public key of an account that will be used to receive the native SOL token out of the swap 116 | * - If not provided, the swap will default unwrap the WSOL and transfer the native SOL to the swap authority account 117 | * - If provided, we will unwrap the WSOL and transfer the native SOL to the account 118 | * - Only works if the output mint is SOL, is using the V2 instructions and the account passed in is not owned by token program 119 | * - When sending native SOL to a new account, you must swap at least enough to cover the rent required to create it. 120 | * - `destinationTokenAccount` and `nativeDestinationAccount` are mutually exclusive 121 | * 122 | * @type {string} 123 | * @memberof SwapRequest 124 | */ 125 | nativeDestinationAccount?: string; 126 | /** 127 | * - When enabled, it will do a swap simulation to get the compute unit used and set it in ComputeBudget's compute unit limit 128 | * - This incurs one extra RPC call to simulate this 129 | * - We recommend to enable this to estimate compute unit correctly and reduce priority fees needed or have higher chance to be included in a block 130 | * 131 | * @type {boolean} 132 | * @memberof SwapRequest 133 | */ 134 | dynamicComputeUnitLimit?: boolean; 135 | /** 136 | * - When enabled, it will not do any additional RPC calls to check on required accounts 137 | * - The returned swap transaction will still attempt to create required accounts regardless if it exists or not 138 | * 139 | * @type {boolean} 140 | * @memberof SwapRequest 141 | */ 142 | skipUserAccountsRpcCalls?: boolean; 143 | /** 144 | * - When enabled, it estimates slippage and apply it in the swap transaction directly, overwriting the `slippageBps` parameter in the quote response. 145 | * - This is no longer maintained, we are focusing efforts on RTSE on Ultra Swap API 146 | * 147 | * @type {boolean} 148 | * @memberof SwapRequest 149 | */ 150 | dynamicSlippage?: boolean; 151 | /** 152 | * - To use an exact compute unit price to calculate priority fee 153 | * - `computeUnitLimit (1400000) * computeUnitPriceMicroLamports` 154 | * - We recommend using `prioritizationFeeLamports` and `dynamicComputeUnitLimit` instead of passing in your own compute unit price 155 | * 156 | * @type {number} 157 | * @memberof SwapRequest 158 | */ 159 | computeUnitPriceMicroLamports?: number; 160 | /** 161 | * - Pass in the number of slots we want the transaction to be valid for 162 | * - Example: If you pass in 10 slots, the transaction will be valid for ~400ms * 10 = approximately 4 seconds before it expires 163 | * 164 | * @type {number} 165 | * @memberof SwapRequest 166 | */ 167 | blockhashSlotsToExpiry?: number; 168 | /** 169 | * 170 | * @type {QuoteResponse} 171 | * @memberof SwapRequest 172 | */ 173 | quoteResponse: QuoteResponse; 174 | } 175 | 176 | /** 177 | * Check if a given object implements the SwapRequest interface. 178 | */ 179 | export function instanceOfSwapRequest(value: object): boolean { 180 | let isInstance = true; 181 | isInstance = isInstance && "userPublicKey" in value; 182 | isInstance = isInstance && "quoteResponse" in value; 183 | 184 | return isInstance; 185 | } 186 | 187 | export function SwapRequestFromJSON(json: any): SwapRequest { 188 | return SwapRequestFromJSONTyped(json, false); 189 | } 190 | 191 | export function SwapRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwapRequest { 192 | if ((json === undefined) || (json === null)) { 193 | return json; 194 | } 195 | return { 196 | 197 | 'userPublicKey': json['userPublicKey'], 198 | 'payer': !exists(json, 'payer') ? undefined : json['payer'], 199 | 'wrapAndUnwrapSol': !exists(json, 'wrapAndUnwrapSol') ? undefined : json['wrapAndUnwrapSol'], 200 | 'useSharedAccounts': !exists(json, 'useSharedAccounts') ? undefined : json['useSharedAccounts'], 201 | 'feeAccount': !exists(json, 'feeAccount') ? undefined : json['feeAccount'], 202 | 'trackingAccount': !exists(json, 'trackingAccount') ? undefined : json['trackingAccount'], 203 | 'prioritizationFeeLamports': !exists(json, 'prioritizationFeeLamports') ? undefined : SwapRequestPrioritizationFeeLamportsFromJSON(json['prioritizationFeeLamports']), 204 | 'asLegacyTransaction': !exists(json, 'asLegacyTransaction') ? undefined : json['asLegacyTransaction'], 205 | 'destinationTokenAccount': !exists(json, 'destinationTokenAccount') ? undefined : json['destinationTokenAccount'], 206 | 'nativeDestinationAccount': !exists(json, 'nativeDestinationAccount') ? undefined : json['nativeDestinationAccount'], 207 | 'dynamicComputeUnitLimit': !exists(json, 'dynamicComputeUnitLimit') ? undefined : json['dynamicComputeUnitLimit'], 208 | 'skipUserAccountsRpcCalls': !exists(json, 'skipUserAccountsRpcCalls') ? undefined : json['skipUserAccountsRpcCalls'], 209 | 'dynamicSlippage': !exists(json, 'dynamicSlippage') ? undefined : json['dynamicSlippage'], 210 | 'computeUnitPriceMicroLamports': !exists(json, 'computeUnitPriceMicroLamports') ? undefined : json['computeUnitPriceMicroLamports'], 211 | 'blockhashSlotsToExpiry': !exists(json, 'blockhashSlotsToExpiry') ? undefined : json['blockhashSlotsToExpiry'], 212 | 'quoteResponse': QuoteResponseFromJSON(json['quoteResponse']), 213 | }; 214 | } 215 | 216 | export function SwapRequestToJSON(value?: SwapRequest | null): any { 217 | if (value === undefined) { 218 | return undefined; 219 | } 220 | if (value === null) { 221 | return null; 222 | } 223 | return { 224 | 225 | 'userPublicKey': value.userPublicKey, 226 | 'payer': value.payer, 227 | 'wrapAndUnwrapSol': value.wrapAndUnwrapSol, 228 | 'useSharedAccounts': value.useSharedAccounts, 229 | 'feeAccount': value.feeAccount, 230 | 'trackingAccount': value.trackingAccount, 231 | 'prioritizationFeeLamports': SwapRequestPrioritizationFeeLamportsToJSON(value.prioritizationFeeLamports), 232 | 'asLegacyTransaction': value.asLegacyTransaction, 233 | 'destinationTokenAccount': value.destinationTokenAccount, 234 | 'nativeDestinationAccount': value.nativeDestinationAccount, 235 | 'dynamicComputeUnitLimit': value.dynamicComputeUnitLimit, 236 | 'skipUserAccountsRpcCalls': value.skipUserAccountsRpcCalls, 237 | 'dynamicSlippage': value.dynamicSlippage, 238 | 'computeUnitPriceMicroLamports': value.computeUnitPriceMicroLamports, 239 | 'blockhashSlotsToExpiry': value.blockhashSlotsToExpiry, 240 | 'quoteResponse': QuoteResponseToJSON(value.quoteResponse), 241 | }; 242 | } 243 | 244 | -------------------------------------------------------------------------------- /generated/runtime.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * Swap API 5 | * API reference for Jupiter\'s Swap API, including Quote, Swap and Swap Instructions endpoints. ### Rate Limits Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. ### Usage - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node ### Data Types To Note - Public keys are base58 encoded strings - Raw data such as Vec are base64 encoded strings 6 | * 7 | * The version of the OpenAPI document: 1.0.0 8 | * 9 | * 10 | * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). 11 | * https://openapi-generator.tech 12 | * Do not edit the class manually. 13 | */ 14 | 15 | 16 | export const BASE_PATH = "https://api.jup.ag/swap/v1".replace(/\/+$/, ""); 17 | 18 | export interface ConfigurationParameters { 19 | basePath?: string; // override base path 20 | fetchApi?: FetchAPI; // override for fetch implementation 21 | middleware?: Middleware[]; // middleware to apply before/after fetch requests 22 | queryParamsStringify?: (params: HTTPQuery) => string; // stringify function for query strings 23 | username?: string; // parameter for basic security 24 | password?: string; // parameter for basic security 25 | apiKey?: string | Promise | ((name: string) => string | Promise); // parameter for apiKey security 26 | accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string | Promise); // parameter for oauth2 security 27 | headers?: HTTPHeaders; //header params we want to use on every request 28 | credentials?: RequestCredentials; //value for the credentials param we want to use on each request 29 | } 30 | 31 | export class Configuration { 32 | constructor(private configuration: ConfigurationParameters = {}) {} 33 | 34 | set config(configuration: Configuration) { 35 | this.configuration = configuration; 36 | } 37 | 38 | get basePath(): string { 39 | return this.configuration.basePath != null ? this.configuration.basePath : BASE_PATH; 40 | } 41 | 42 | get fetchApi(): FetchAPI | undefined { 43 | return this.configuration.fetchApi; 44 | } 45 | 46 | get middleware(): Middleware[] { 47 | return this.configuration.middleware || []; 48 | } 49 | 50 | get queryParamsStringify(): (params: HTTPQuery) => string { 51 | return this.configuration.queryParamsStringify || querystring; 52 | } 53 | 54 | get username(): string | undefined { 55 | return this.configuration.username; 56 | } 57 | 58 | get password(): string | undefined { 59 | return this.configuration.password; 60 | } 61 | 62 | get apiKey(): ((name: string) => string | Promise) | undefined { 63 | const apiKey = this.configuration.apiKey; 64 | if (apiKey) { 65 | return typeof apiKey === 'function' ? apiKey : () => apiKey; 66 | } 67 | return undefined; 68 | } 69 | 70 | get accessToken(): ((name?: string, scopes?: string[]) => string | Promise) | undefined { 71 | const accessToken = this.configuration.accessToken; 72 | if (accessToken) { 73 | return typeof accessToken === 'function' ? accessToken : async () => accessToken; 74 | } 75 | return undefined; 76 | } 77 | 78 | get headers(): HTTPHeaders | undefined { 79 | return this.configuration.headers; 80 | } 81 | 82 | get credentials(): RequestCredentials | undefined { 83 | return this.configuration.credentials; 84 | } 85 | } 86 | 87 | export const DefaultConfig = new Configuration(); 88 | 89 | /** 90 | * This is the base class for all generated API classes. 91 | */ 92 | export class BaseAPI { 93 | 94 | private static readonly jsonRegex = new RegExp('^(:?application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(:?;.*)?$', 'i'); 95 | private middleware: Middleware[]; 96 | 97 | constructor(protected configuration = DefaultConfig) { 98 | this.middleware = configuration.middleware; 99 | } 100 | 101 | withMiddleware(this: T, ...middlewares: Middleware[]) { 102 | const next = this.clone(); 103 | next.middleware = next.middleware.concat(...middlewares); 104 | return next; 105 | } 106 | 107 | withPreMiddleware(this: T, ...preMiddlewares: Array) { 108 | const middlewares = preMiddlewares.map((pre) => ({ pre })); 109 | return this.withMiddleware(...middlewares); 110 | } 111 | 112 | withPostMiddleware(this: T, ...postMiddlewares: Array) { 113 | const middlewares = postMiddlewares.map((post) => ({ post })); 114 | return this.withMiddleware(...middlewares); 115 | } 116 | 117 | /** 118 | * Check if the given MIME is a JSON MIME. 119 | * JSON MIME examples: 120 | * application/json 121 | * application/json; charset=UTF8 122 | * APPLICATION/JSON 123 | * application/vnd.company+json 124 | * @param mime - MIME (Multipurpose Internet Mail Extensions) 125 | * @return True if the given MIME is JSON, false otherwise. 126 | */ 127 | protected isJsonMime(mime: string | null | undefined): boolean { 128 | if (!mime) { 129 | return false; 130 | } 131 | return BaseAPI.jsonRegex.test(mime); 132 | } 133 | 134 | protected async request(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction): Promise { 135 | const { url, init } = await this.createFetchParams(context, initOverrides); 136 | const response = await this.fetchApi(url, init); 137 | if (response && (response.status >= 200 && response.status < 300)) { 138 | return response; 139 | } 140 | throw new ResponseError(response, 'Response returned an error code'); 141 | } 142 | 143 | private async createFetchParams(context: RequestOpts, initOverrides?: RequestInit | InitOverrideFunction) { 144 | let url = this.configuration.basePath + context.path; 145 | if (context.query !== undefined && Object.keys(context.query).length !== 0) { 146 | // only add the querystring to the URL if there are query parameters. 147 | // this is done to avoid urls ending with a "?" character which buggy webservers 148 | // do not handle correctly sometimes. 149 | url += '?' + this.configuration.queryParamsStringify(context.query); 150 | } 151 | 152 | const headers = Object.assign({}, this.configuration.headers, context.headers); 153 | Object.keys(headers).forEach(key => headers[key] === undefined ? delete headers[key] : {}); 154 | 155 | const initOverrideFn = 156 | typeof initOverrides === "function" 157 | ? initOverrides 158 | : async () => initOverrides; 159 | 160 | const initParams = { 161 | method: context.method, 162 | headers, 163 | body: context.body, 164 | credentials: this.configuration.credentials, 165 | }; 166 | 167 | const overriddenInit: RequestInit = { 168 | ...initParams, 169 | ...(await initOverrideFn({ 170 | init: initParams, 171 | context, 172 | })) 173 | }; 174 | 175 | let body: any; 176 | if (isFormData(overriddenInit.body) 177 | || (overriddenInit.body instanceof URLSearchParams) 178 | || isBlob(overriddenInit.body)) { 179 | body = overriddenInit.body; 180 | } else if (this.isJsonMime(headers['Content-Type'])) { 181 | body = JSON.stringify(overriddenInit.body); 182 | } else { 183 | body = overriddenInit.body; 184 | } 185 | 186 | const init: RequestInit = { 187 | ...overriddenInit, 188 | body 189 | }; 190 | 191 | return { url, init }; 192 | } 193 | 194 | private fetchApi = async (url: string, init: RequestInit) => { 195 | let fetchParams = { url, init }; 196 | for (const middleware of this.middleware) { 197 | if (middleware.pre) { 198 | fetchParams = await middleware.pre({ 199 | fetch: this.fetchApi, 200 | ...fetchParams, 201 | }) || fetchParams; 202 | } 203 | } 204 | let response: Response | undefined = undefined; 205 | try { 206 | response = await (this.configuration.fetchApi || fetch)(fetchParams.url, fetchParams.init); 207 | } catch (e) { 208 | for (const middleware of this.middleware) { 209 | if (middleware.onError) { 210 | response = await middleware.onError({ 211 | fetch: this.fetchApi, 212 | url: fetchParams.url, 213 | init: fetchParams.init, 214 | error: e, 215 | response: response ? response.clone() : undefined, 216 | }) || response; 217 | } 218 | } 219 | if (response === undefined) { 220 | if (e instanceof Error) { 221 | throw new FetchError(e, 'The request failed and the interceptors did not return an alternative response'); 222 | } else { 223 | throw e; 224 | } 225 | } 226 | } 227 | for (const middleware of this.middleware) { 228 | if (middleware.post) { 229 | response = await middleware.post({ 230 | fetch: this.fetchApi, 231 | url: fetchParams.url, 232 | init: fetchParams.init, 233 | response: response.clone(), 234 | }) || response; 235 | } 236 | } 237 | return response; 238 | } 239 | 240 | /** 241 | * Create a shallow clone of `this` by constructing a new instance 242 | * and then shallow cloning data members. 243 | */ 244 | private clone(this: T): T { 245 | const constructor = this.constructor as any; 246 | const next = new constructor(this.configuration); 247 | next.middleware = this.middleware.slice(); 248 | return next; 249 | } 250 | }; 251 | 252 | function isBlob(value: any): value is Blob { 253 | return typeof Blob !== 'undefined' && value instanceof Blob; 254 | } 255 | 256 | function isFormData(value: any): value is FormData { 257 | return typeof FormData !== "undefined" && value instanceof FormData; 258 | } 259 | 260 | export class ResponseError extends Error { 261 | override name: "ResponseError" = "ResponseError"; 262 | constructor(public response: Response, msg?: string) { 263 | super(msg); 264 | } 265 | } 266 | 267 | export class FetchError extends Error { 268 | override name: "FetchError" = "FetchError"; 269 | constructor(public cause: Error, msg?: string) { 270 | super(msg); 271 | } 272 | } 273 | 274 | export class RequiredError extends Error { 275 | override name: "RequiredError" = "RequiredError"; 276 | constructor(public field: string, msg?: string) { 277 | super(msg); 278 | } 279 | } 280 | 281 | export const COLLECTION_FORMATS = { 282 | csv: ",", 283 | ssv: " ", 284 | tsv: "\t", 285 | pipes: "|", 286 | }; 287 | 288 | export type FetchAPI = WindowOrWorkerGlobalScope['fetch']; 289 | 290 | export type Json = any; 291 | export type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD'; 292 | export type HTTPHeaders = { [key: string]: string }; 293 | export type HTTPQuery = { [key: string]: string | number | null | boolean | Array | Set | HTTPQuery }; 294 | export type HTTPBody = Json | FormData | URLSearchParams; 295 | export type HTTPRequestInit = { headers?: HTTPHeaders; method: HTTPMethod; credentials?: RequestCredentials; body?: HTTPBody }; 296 | export type ModelPropertyNaming = 'camelCase' | 'snake_case' | 'PascalCase' | 'original'; 297 | 298 | export type InitOverrideFunction = (requestContext: { init: HTTPRequestInit, context: RequestOpts }) => Promise 299 | 300 | export interface FetchParams { 301 | url: string; 302 | init: RequestInit; 303 | } 304 | 305 | export interface RequestOpts { 306 | path: string; 307 | method: HTTPMethod; 308 | headers: HTTPHeaders; 309 | query?: HTTPQuery; 310 | body?: HTTPBody; 311 | } 312 | 313 | export function exists(json: any, key: string) { 314 | const value = json[key]; 315 | return value !== null && value !== undefined; 316 | } 317 | 318 | export function querystring(params: HTTPQuery, prefix: string = ''): string { 319 | return Object.keys(params) 320 | .map(key => querystringSingleKey(key, params[key], prefix)) 321 | .filter(part => part.length > 0) 322 | .join('&'); 323 | } 324 | 325 | function querystringSingleKey(key: string, value: string | number | null | undefined | boolean | Array | Set | HTTPQuery, keyPrefix: string = ''): string { 326 | const fullKey = keyPrefix + (keyPrefix.length ? `[${key}]` : key); 327 | if (value instanceof Array) { 328 | const multiValue = value.map(singleValue => encodeURIComponent(String(singleValue))) 329 | .join(`&${encodeURIComponent(fullKey)}=`); 330 | return `${encodeURIComponent(fullKey)}=${multiValue}`; 331 | } 332 | if (value instanceof Set) { 333 | const valueAsArray = Array.from(value); 334 | return querystringSingleKey(key, valueAsArray, keyPrefix); 335 | } 336 | if (value instanceof Date) { 337 | return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`; 338 | } 339 | if (value instanceof Object) { 340 | return querystring(value as HTTPQuery, fullKey); 341 | } 342 | return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`; 343 | } 344 | 345 | export function mapValues(data: any, fn: (item: any) => any) { 346 | return Object.keys(data).reduce( 347 | (acc, key) => ({ ...acc, [key]: fn(data[key]) }), 348 | {} 349 | ); 350 | } 351 | 352 | export function canConsumeForm(consumes: Consume[]): boolean { 353 | for (const consume of consumes) { 354 | if ('multipart/form-data' === consume.contentType) { 355 | return true; 356 | } 357 | } 358 | return false; 359 | } 360 | 361 | export interface Consume { 362 | contentType: string; 363 | } 364 | 365 | export interface RequestContext { 366 | fetch: FetchAPI; 367 | url: string; 368 | init: RequestInit; 369 | } 370 | 371 | export interface ResponseContext { 372 | fetch: FetchAPI; 373 | url: string; 374 | init: RequestInit; 375 | response: Response; 376 | } 377 | 378 | export interface ErrorContext { 379 | fetch: FetchAPI; 380 | url: string; 381 | init: RequestInit; 382 | error: unknown; 383 | response?: Response; 384 | } 385 | 386 | export interface Middleware { 387 | pre?(context: RequestContext): Promise; 388 | post?(context: ResponseContext): Promise; 389 | onError?(context: ErrorContext): Promise; 390 | } 391 | 392 | export interface ApiResponse { 393 | raw: Response; 394 | value(): Promise; 395 | } 396 | 397 | export interface ResponseTransformer { 398 | (json: any): T; 399 | } 400 | 401 | export class JSONApiResponse { 402 | constructor(public raw: Response, private transformer: ResponseTransformer = (jsonValue: any) => jsonValue) {} 403 | 404 | async value(): Promise { 405 | return this.transformer(await this.raw.json()); 406 | } 407 | } 408 | 409 | export class VoidApiResponse { 410 | constructor(public raw: Response) {} 411 | 412 | async value(): Promise { 413 | return undefined; 414 | } 415 | } 416 | 417 | export class BlobApiResponse { 418 | constructor(public raw: Response) {} 419 | 420 | async value(): Promise { 421 | return await this.raw.blob(); 422 | }; 423 | } 424 | 425 | export class TextApiResponse { 426 | constructor(public raw: Response) {} 427 | 428 | async value(): Promise { 429 | return await this.raw.text(); 430 | }; 431 | } 432 | -------------------------------------------------------------------------------- /swagger.yaml: -------------------------------------------------------------------------------- 1 | openapi: '3.0.2' 2 | info: 3 | title: Swap API 4 | version: 1.0.0 5 | description: | 6 | API reference for Jupiter's Swap API, including Quote, Swap and Swap Instructions endpoints. 7 | 8 | ### Rate Limits 9 | Since 1 December 2024, we have updated our API structure. Please refer to https://dev.jup.ag/ for further details on usage and rate limits. 10 | 11 | ### Usage 12 | - API Wrapper Typescript https://github.com/jup-ag/jupiter-quote-api-node 13 | 14 | ### Data Types To Note 15 | - Public keys are base58 encoded strings 16 | - Raw data such as Vec are base64 encoded strings 17 | 18 | servers: 19 | - url: https://api.jup.ag/swap/v1 20 | 21 | paths: 22 | /quote: 23 | get: 24 | operationId: QuoteGet 25 | tags: 26 | - Swap 27 | summary: quote 28 | description: | 29 | Request for a quote to be used in `POST /swap` 30 | parameters: 31 | - $ref: '#/components/parameters/InputMintParameter' 32 | - $ref: '#/components/parameters/OutputMintParameter' 33 | - $ref: '#/components/parameters/AmountParameter' 34 | - $ref: '#/components/parameters/SlippageParameter' 35 | - $ref: '#/components/parameters/SwapModeParameter' 36 | - $ref: '#/components/parameters/DexesParameter' 37 | - $ref: '#/components/parameters/ExcludeDexesParameter' 38 | - $ref: '#/components/parameters/RestrictIntermediateTokensParameter' 39 | - $ref: '#/components/parameters/OnlyDirectRoutesParameter' 40 | - $ref: '#/components/parameters/AsLegacyTransactionParameter' 41 | - $ref: '#/components/parameters/PlatformFeeBpsParameter' 42 | - $ref: '#/components/parameters/MaxAccountsParameter' 43 | - $ref: '#/components/parameters/InstructionVersion' 44 | - $ref: '#/components/parameters/DynamicSlippage' 45 | responses: 46 | '200': 47 | description: "Successful response to be used in `/swap`" 48 | content: 49 | application/json: 50 | schema: 51 | $ref: '#/components/schemas/QuoteResponse' 52 | /swap: 53 | post: 54 | operationId: SwapPost 55 | tags: 56 | - Swap 57 | summary: swap 58 | description: | 59 | Request for a base64-encoded unsigned swap transaction based on the `/quote` response 60 | requestBody: 61 | required: true 62 | content: 63 | application/json: 64 | schema: 65 | $ref: '#/components/schemas/SwapRequest' 66 | responses: 67 | '200': 68 | description: Successful response 69 | content: 70 | application/json: 71 | schema: 72 | $ref: '#/components/schemas/SwapResponse' 73 | /swap-instructions: 74 | post: 75 | operationId: SwapInstructionsPost 76 | tags: 77 | - Swap 78 | summary: swap-instructions 79 | description: | 80 | Request for swap instructions that you can use from the quote you get from `/quote` 81 | requestBody: 82 | required: true 83 | content: 84 | application/json: 85 | schema: 86 | $ref: '#/components/schemas/SwapRequest' 87 | responses: 88 | '200': 89 | description: Successful response 90 | content: 91 | application/json: 92 | schema: 93 | $ref: '#/components/schemas/SwapInstructionsResponse' 94 | /program-id-to-label: 95 | get: 96 | operationId: ProgramIdToLabelGet 97 | tags: 98 | - Swap 99 | summary: program-id-to-label 100 | description: | 101 | Returns a hash, which key is the program id and value is the label. 102 | This is used to help map error from transaction by identifying the fault program id. 103 | This can be used in conjunction with the `excludeDexes` or `dexes` parameter. 104 | responses: 105 | '200': 106 | description: Default response 107 | content: 108 | application/json: 109 | schema: 110 | type: object 111 | additionalProperties: 112 | type: string 113 | 114 | components: 115 | schemas: 116 | Instruction: 117 | type: object 118 | properties: 119 | programId: 120 | type: string 121 | accounts: 122 | type: array 123 | items: 124 | $ref: '#/components/schemas/AccountMeta' 125 | data: 126 | type: string 127 | required: 128 | - programId 129 | - accounts 130 | - data 131 | 132 | AccountMeta: 133 | type: object 134 | properties: 135 | pubkey: 136 | type: string 137 | isSigner: 138 | type: boolean 139 | isWritable: 140 | type: boolean 141 | required: 142 | - pubkey 143 | - isSigner 144 | - isWritable 145 | 146 | QuoteResponse: 147 | type: object 148 | required: 149 | - inputMint 150 | - outputMint 151 | - inAmount 152 | - outAmount 153 | - otherAmountThreshold 154 | - swapMode 155 | - slippageBps 156 | - priceImpactPct 157 | - routePlan 158 | properties: 159 | inputMint: 160 | type: string 161 | inAmount: 162 | type: string 163 | outputMint: 164 | type: string 165 | outAmount: 166 | type: string 167 | description: | 168 | - Calculated output amount from routing engine 169 | - The value includes platform fees and DEX fees, excluding slippage 170 | otherAmountThreshold: 171 | type: string 172 | description: | 173 | - Calculated minimum output amount after accounting for `slippageBps` on the `outAmount` value 174 | - Not used by `/swap` endpoint to build transaction 175 | swapMode: 176 | $ref: '#/components/schemas/SwapMode' 177 | required: true 178 | slippageBps: 179 | type: integer 180 | format: uint16 181 | minimum: 0 182 | platformFee: 183 | $ref: '#/components/schemas/PlatformFee' 184 | priceImpactPct: 185 | type: string 186 | routePlan: 187 | type: array 188 | items: 189 | $ref: '#/components/schemas/RoutePlanStep' 190 | contextSlot: 191 | type: integer 192 | format: uint64 193 | timeTaken: 194 | type: number 195 | 196 | SwapMode: 197 | type: string 198 | enum: 199 | - ExactIn 200 | - ExactOut 201 | 202 | PlatformFee: 203 | type: object 204 | properties: 205 | amount: 206 | type: string 207 | feeBps: 208 | type: integer 209 | format: uint16 210 | 211 | RoutePlanStep: 212 | type: object 213 | properties: 214 | swapInfo: 215 | $ref: '#/components/schemas/SwapInfo' 216 | percent: 217 | type: integer 218 | format: uint8 219 | nullable: true 220 | bps: 221 | type: integer 222 | format: uint16 223 | required: 224 | - swapInfo 225 | 226 | SwapInfo: 227 | type: object 228 | required: 229 | - ammKey 230 | - inputMint 231 | - outputMint 232 | - inAmount 233 | - outAmount 234 | properties: 235 | ammKey: 236 | type: string 237 | label: 238 | type: string 239 | inputMint: 240 | type: string 241 | outputMint: 242 | type: string 243 | inAmount: 244 | type: string 245 | outAmount: 246 | type: string 247 | 248 | SwapRequest: 249 | type: object 250 | required: 251 | - userPublicKey 252 | - quoteResponse 253 | properties: 254 | userPublicKey: 255 | type: string 256 | payer: 257 | description: | 258 | - Allow a custom payer to pay for the transaction fees and rent of token accounts 259 | - Note that users can close their ATAs elsewhere and have you reopen them again, your fees should account for this 260 | type: string 261 | wrapAndUnwrapSol: 262 | description: | 263 | - To automatically wrap/unwrap SOL in the transaction, as WSOL is an SPL token while native SOL is not 264 | - When true and input mint is SOL, it will wrap the SOL amount to WSOL and swap 265 | - When true and output mint is SOL, it will unwrap the WSOL back to SOL 266 | - When false and input mint is SOL, it will use existing WSOL amount to swap 267 | - When false and output mint is SOL, it will not unwrap the WSOL to SOL 268 | - To set this parameter to false, you need to have the WSOL token account initialized 269 | type: boolean 270 | default: true 271 | useSharedAccounts: 272 | description: | 273 | - The default is determined dynamically by the routing engine, allowing us to optimize for compute units, etc 274 | - This enables the usage of shared program accounts, this is essential as complex routing will require multiple intermediate token accounts which the user might not have 275 | - If true, you do not need to handle the creation of intermediate token accounts for the user 276 | - Do note, shared accounts route will fail on some new AMMs (low liquidity token) 277 | type: boolean 278 | feeAccount: 279 | description: | 280 | - An initialized token account that will be used to collect fees 281 | - The mint of the token account **can only be either the input or output mint of the swap** 282 | - Swap API no longer requires the use of the Referral Program 283 | - If `platformFeeBps` is passed in `/quote`, the `feeAccount` must be passed as well 284 | type: string 285 | trackingAccount: 286 | description: | 287 | - Specify any public key that belongs to you to track the transactions 288 | - Useful for integrators to get all the swap transactions from this public key 289 | - Query the data using a block explorer like Solscan/SolanaFM or query like Dune/Flipside 290 | type: string 291 | prioritizationFeeLamports: 292 | description: | 293 | - To specify a level or amount of additional fees to prioritize the transaction 294 | - It can be used for EITHER priority fee OR Jito tip (not both at the same time) 295 | - If you want to include both, you will need to use `/swap-instructions` to add both at the same time 296 | - Defaults to `auto`, but preferred to use `priorityLevelWithMaxLamports` as it may be more accurate when accounting local fee market 297 | - Fixed lamports can be passed in as an integer in the `prioritizationFeeLamports` parameter 298 | oneOf: 299 | - $ref: '#/components/schemas/PriorityLevelWithMaxLamports' 300 | - $ref: '#/components/schemas/JitoTipLamports' 301 | - $ref: '#/components/schemas/JitoTipLamportsWithPayer' 302 | asLegacyTransaction: 303 | description: | 304 | - Builds a legacy transaction rather than the default versioned transaction 305 | - Used together with `asLegacyTransaction` in `/quote`, otherwise the transaction might be too large 306 | type: boolean 307 | default: false 308 | destinationTokenAccount: 309 | description: | 310 | - Public key of a token account that will be used to receive the token out of the swap 311 | - If not provided, the signer's token account will be used 312 | - If provided, we assume that the token account is already initialized 313 | - `destinationTokenAccount` and `nativeDestinationAccount` are mutually exclusive 314 | type: string 315 | nativeDestinationAccount: 316 | description: | 317 | - Public key of an account that will be used to receive the native SOL token out of the swap 318 | - If not provided, the swap will default unwrap the WSOL and transfer the native SOL to the swap authority account 319 | - If provided, we will unwrap the WSOL and transfer the native SOL to the account 320 | - Only works if the output mint is SOL, is using the V2 instructions and the account passed in is not owned by token program 321 | - When sending native SOL to a new account, you must swap at least enough to cover the rent required to create it. 322 | - `destinationTokenAccount` and `nativeDestinationAccount` are mutually exclusive 323 | type: string 324 | dynamicComputeUnitLimit: 325 | description: | 326 | - When enabled, it will do a swap simulation to get the compute unit used and set it in ComputeBudget's compute unit limit 327 | - This incurs one extra RPC call to simulate this 328 | - We recommend to enable this to estimate compute unit correctly and reduce priority fees needed or have higher chance to be included in a block 329 | type: boolean 330 | default: false 331 | skipUserAccountsRpcCalls: 332 | description: | 333 | - When enabled, it will not do any additional RPC calls to check on required accounts 334 | - The returned swap transaction will still attempt to create required accounts regardless if it exists or not 335 | type: boolean 336 | default: false 337 | dynamicSlippage: 338 | description: | 339 | - When enabled, it estimates slippage and apply it in the swap transaction directly, overwriting the `slippageBps` parameter in the quote response. 340 | - This is no longer maintained, we are focusing efforts on RTSE on Ultra Swap API 341 | type: boolean 342 | default: false 343 | computeUnitPriceMicroLamports: 344 | description: | 345 | - To use an exact compute unit price to calculate priority fee 346 | - `computeUnitLimit (1400000) * computeUnitPriceMicroLamports` 347 | - We recommend using `prioritizationFeeLamports` and `dynamicComputeUnitLimit` instead of passing in your own compute unit price 348 | type: integer 349 | format: uint64 350 | blockhashSlotsToExpiry: 351 | description: | 352 | - Pass in the number of slots we want the transaction to be valid for 353 | - Example: If you pass in 10 slots, the transaction will be valid for ~400ms * 10 = approximately 4 seconds before it expires 354 | type: integer 355 | format: uint8 356 | quoteResponse: 357 | $ref: '#/components/schemas/QuoteResponse' 358 | 359 | SwapResponse: 360 | type: object 361 | properties: 362 | swapTransaction: 363 | type: string 364 | lastValidBlockHeight: 365 | type: integer 366 | format: uint64 367 | prioritizationFeeLamports: 368 | type: integer 369 | format: uint64 370 | required: 371 | - swapTransaction 372 | - lastValidBlockHeight 373 | 374 | SwapInstructionsResponse: 375 | type: object 376 | properties: 377 | otherInstructions: 378 | description: | 379 | - If you set jito tips using the `prioritizationFeeLamports` parameter, you will see a custom tip instruction to Jito here. 380 | type: array 381 | items: 382 | $ref: '#/components/schemas/Instruction' 383 | computeBudgetInstructions: 384 | description: | 385 | - To setup the compute budget for the transaction. 386 | type: array 387 | items: 388 | $ref: '#/components/schemas/Instruction' 389 | setupInstructions: 390 | description: | 391 | - To setup required token accounts for the users. 392 | type: array 393 | items: 394 | $ref: '#/components/schemas/Instruction' 395 | swapInstruction: 396 | description: | 397 | - The actual swap instruction. 398 | $ref: '#/components/schemas/Instruction' 399 | cleanupInstruction: 400 | description: | 401 | - To wrap and unwrap the SOL. 402 | $ref: '#/components/schemas/Instruction' 403 | addressLookupTableAddresses: 404 | description: | 405 | - The lookup table addresses if you are using versioned transaction. 406 | type: array 407 | items: 408 | type: string 409 | required: 410 | - computeBudgetInstructions 411 | - otherInstructions 412 | - setupInstructions 413 | - swapInstruction 414 | - addressLookupTableAddresses 415 | 416 | IndexedRouteMapResponse: 417 | type: object 418 | required: 419 | - mintKeys 420 | - indexedRouteMap 421 | properties: 422 | mintKeys: 423 | type: array 424 | items: 425 | type: string 426 | description: All the mints that are indexed to match in indexedRouteMap 427 | indexedRouteMap: 428 | type: object 429 | description: All the possible route and their corresponding output mints 430 | additionalProperties: 431 | type: array 432 | items: 433 | type: number 434 | example: 435 | '1': 436 | - 2 437 | - 3 438 | - 4 439 | '2': 440 | - 1 441 | - 3 442 | - 4 443 | 444 | PriorityLevelWithMaxLamports: 445 | title: "priorityLevelWithMaxLamports" 446 | type: object 447 | properties: 448 | priorityLevelWithMaxLamports: 449 | type: object 450 | properties: 451 | priorityLevel: 452 | type: string 453 | enum: [medium, high, veryHigh] 454 | maxLamports: 455 | type: integer 456 | format: uint64 457 | description: | 458 | - Maximum lamports to cap the priority fee estimation, to prevent overpaying 459 | global: 460 | type: boolean 461 | default: false 462 | description: | 463 | - A boolean to choose between using a global or local fee market to estimate. If `global` is set to `false`, the estimation focuses on fees relevant to the **writable accounts** involved in the instruction. 464 | required: [priorityLevel, maxLamports] 465 | additionalProperties: false 466 | required: [priorityLevelWithMaxLamports] 467 | additionalProperties: false 468 | 469 | JitoTipLamports: 470 | title: "jitoTipLamports" 471 | type: object 472 | properties: 473 | jitoTipLamports: 474 | type: integer 475 | format: uint64 476 | description: | 477 | - Exact amount of tip to use in a tip instruction 478 | - Refer to Jito docs on how to estimate the tip amount based on percentiles 479 | - It has to be used together with a connection to a Jito RPC 480 | - See their docs at https://docs.jito.wtf/ 481 | required: [jitoTipLamports] 482 | additionalProperties: false 483 | 484 | JitoTipLamportsWithPayer: 485 | title: "jitoTipLamportsWithPayer" 486 | type: object 487 | properties: 488 | jitoTipLamportsWithPayer: 489 | type: object 490 | properties: 491 | lamports: 492 | type: integer 493 | format: uint64 494 | description: Exact amount of lamports to use for the tip 495 | payer: 496 | type: string 497 | description: Public key of an account that will be used to pay for the tip 498 | required: [lamports, payer] 499 | additionalProperties: false 500 | required: [jitoTipLamportsWithPayer] 501 | additionalProperties: false 502 | 503 | 504 | parameters: 505 | InputMintParameter: 506 | name: inputMint 507 | in: query 508 | required: true 509 | schema: 510 | type: string 511 | OutputMintParameter: 512 | name: outputMint 513 | in: query 514 | required: true 515 | schema: 516 | type: string 517 | AmountParameter: 518 | name: amount 519 | description: | 520 | - Raw amount to swap (before decimals) 521 | - Input Amount if `SwapMode=ExactIn` 522 | - Output Amount if `SwapMode=ExactOut` 523 | in: query 524 | required: true 525 | schema: 526 | type: integer 527 | format: uint64 528 | SlippageParameter: 529 | name: slippageBps 530 | description: | 531 | - Default: 50 532 | - This is threshold denoted in basis points. 533 | - If exact in and output amount exceeds the threshold, then the swap transaction will fail. 534 | in: query 535 | schema: 536 | type: integer 537 | format: uint16 538 | default: 50 539 | SwapModeParameter: 540 | name: swapMode 541 | description: | 542 | - ExactOut is for supporting use cases where you need an exact output amount 543 | - In the case of `ExactIn`, the slippage is on the output token 544 | - In the case of `ExactOut`, the slippage is on the input token 545 | - Not all AMMs support `ExactOut`: Currently only Orca Whirlpool, Raydium CLMM, Raydium CPMM 546 | - We do not recommend using `ExactOut` for most use cases 547 | in: query 548 | schema: 549 | type: string 550 | enum: 551 | - ExactIn 552 | - ExactOut 553 | default: ExactIn 554 | DexesParameter: 555 | name: dexes 556 | description: | 557 | - Multiple DEXes can be pass in by comma separating them 558 | - For example: `dexes=Raydium,Orca+V2,Meteora+DLMM` 559 | - If a DEX is indicated, the route will **only use** that DEX 560 | - Full list of DEXes here: https://lite-api.jup.ag/swap/v1/program-id-to-label 561 | in: query 562 | schema: 563 | type: array 564 | items: 565 | type: string 566 | ExcludeDexesParameter: 567 | name: excludeDexes 568 | description: | 569 | - Multiple DEXes can be pass in by comma separating them 570 | - For example: `excludeDexes=Raydium,Orca+V2,Meteora+DLMM` 571 | - If a DEX is indicated, the route will **not use** that DEX 572 | - Full list of DEXes here: https://lite-api.jup.ag/swap/v1/program-id-to-label 573 | in: query 574 | schema: 575 | type: array 576 | items: 577 | type: string 578 | RestrictIntermediateTokensParameter: 579 | name: restrictIntermediateTokens 580 | description: | 581 | - Restrict intermediate tokens within a route to a set of more stable tokens 582 | - This will help to reduce exposure to potential high slippage routes 583 | in: query 584 | schema: 585 | type: boolean 586 | default: true 587 | OnlyDirectRoutesParameter: 588 | name: onlyDirectRoutes 589 | description: | 590 | - Direct route limits Jupiter routing to single hop routes only 591 | - This may result in worse routes 592 | in: query 593 | schema: 594 | type: boolean 595 | default: false 596 | AsLegacyTransactionParameter: 597 | name: asLegacyTransaction 598 | description: | 599 | - Instead of using versioned transaction, this will use the legacy transaction 600 | in: query 601 | schema: 602 | type: boolean 603 | default: false 604 | MaxAccountsParameter: 605 | name: maxAccounts 606 | description: | 607 | - Rough estimate of the max accounts to be used for the quote 608 | - Useful if composing your own transaction or to be more precise in resource accounting for better routes 609 | in: query 610 | schema: 611 | type: integer 612 | format: uint64 # usize 613 | default: 64 614 | PlatformFeeBpsParameter: 615 | name: platformFeeBps 616 | description: | 617 | - Take fees in basis points 618 | - If `platformFeeBps` is passed in, the `feeAccount` in `/swap` must be passed as well 619 | in: query 620 | schema: 621 | type: integer 622 | format: uint16 623 | InstructionVersion: 624 | name: instructionVersion 625 | description: | 626 | - The version of instruction to use in the swap program 627 | in: query 628 | schema: 629 | type: string 630 | enum: 631 | - V1 632 | - V2 633 | default: V1 634 | DynamicSlippage: 635 | name: dynamicSlippage 636 | description: | 637 | - No longer applicable, only required to pass in via `/swap` endpoint 638 | in: query 639 | schema: 640 | type: boolean 641 | default: false 642 | --------------------------------------------------------------------------------