Jupiter
Jupiter adalah agregator likuiditas utama untuk Solana, menawarkan rentang token terluas dan penemuan rute terbaik di antara pasangan token mana pun.
Instalasi
@jup-ag/core adalah paket Core yang digunakan untuk berinteraksi dengan program on-chain jupiter untuk melakukan swap antara dua kemungkinan pasangan token.
yarn add @jup-ag/core
npm install @jup-ag/core
Mengambil List Token dari Jupiter
Semua kemungkinan token yang dapat ditukar dengan jupiter untuk jaringan tertentu sedang diambil.
import { Jupiter, RouteInfo, TOKEN_LIST_URL } from "@jup-ag/core";
import { Connection, PublicKey } from "@solana/web3.js";
interface Token {
chainId: number;
address: string;
symbol: string;
name: string;
decimals: number;
logoURI: string;
tags: string[];
}
(async () => {
const ENV = "mainnet-beta";
const tokens: Token[] = await (await fetch(TOKEN_LIST_URL[ENV])).json();
})();
const ENV = "mainnet-beta";
const tokens: Token[] = await(await fetch(TOKEN_LIST_URL[ENV])).json();
Loading instance dari Jupiter
Instance Jupiter sedang dibuat dengan konfigurasi yang disediakan. Ada banyak parameter opsional yang diperlukan instance untuk mengetahui lebih banyak tentangnya, buka di sini
import { Jupiter, RouteInfo, TOKEN_LIST_URL } from "@jup-ag/core";
import { Connection, PublicKey, Keypair } from "@solana/web3.js";
interface Token {
chainId: number;
address: string;
symbol: string;
name: string;
decimals: number;
logoURI: string;
tags: string[];
}
(async () => {
const ENV = "devnet";
const tokens: Token[] = await (await fetch(TOKEN_LIST_URL[ENV])).json();
const USER_KEYPAIR = Keypair.generate();
const connection = new Connection("https://api.devnet.solana.com");
const jupiter = await Jupiter.load({
connection,
cluster: ENV,
user: USER_KEYPAIR,
});
})();
const jupiter = await Jupiter.load({
connection,
cluster: ENV,
user: USER_KEYPAIR,
});
Mendapatkan RouteMap
RouteMap mengidentifikasi token apa yang dapat ditukar dengan token input yang diberikan. RouteMap hanya berisi alamat token mint dan tidak ada metadata.
import { Jupiter, RouteInfo, TOKEN_LIST_URL } from "@jup-ag/core";
import { Connection, PublicKey, Keypair } from "@solana/web3.js";
interface Token {
chainId: number;
address: string;
symbol: string;
name: string;
decimals: number;
logoURI: string;
tags: string[];
}
(async () => {
const ENV = "devnet";
const tokens: Token[] = await (await fetch(TOKEN_LIST_URL[ENV])).json();
const USER_KEYPAIR = Keypair.generate();
const connection = new Connection("https://api.devnet.solana.com");
const jupiter = await Jupiter.load({
connection,
cluster: ENV,
user: USER_KEYPAIR,
});
const routeMap = jupiter.getRouteMap();
})();
const routeMap = jupiter.getRouteMap();
Mendapatkan route dari Input dengan Output token
Metode computeRoutes
mengambil alamat Mint input dan alamat Mint output dan memberikan semua kemungkinan rute dalam urutan harga terbaik terlebih dahulu.
import { Jupiter, RouteInfo, TOKEN_LIST_URL } from "@jup-ag/core";
import { Connection, PublicKey, Keypair } from "@solana/web3.js";
interface Token {
chainId: number;
address: string;
symbol: string;
name: string;
decimals: number;
logoURI: string;
tags: string[];
}
(async () => {
const ENV = "devnet";
const tokens: Token[] = await (await fetch(TOKEN_LIST_URL[ENV])).json();
const USER_KEYPAIR = Keypair.generate();
const connection = new Connection("https://api.devnet.solana.com");
const jupiter = await Jupiter.load({
connection,
cluster: ENV,
user: USER_KEYPAIR,
});
const routeMap = jupiter.getRouteMap();
const inputToken = "So11111111111111111111111111111111111111112";
const outputToken = "SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt";
const inputAmount = 1;
const slippage = 1;
const routes = await jupiter.computeRoutes({
inputMint: new PublicKey(inputToken),
outputMint: new PublicKey(outputToken),
inputAmount,
slippage,
forceFetch: false,
});
})();
const routes = await jupiter.computeRoutes({
inputMint: new PublicKey(inputToken),
outputMint: new PublicKey(outputToken),
inputAmount,
slippage,
forceFetch: false,
});
Ekskusi Token Swap
Metode exchange
dipanggil di sini yang membuat transaksi untuk rute tertentu.
import { Jupiter, RouteInfo, TOKEN_LIST_URL } from "@jup-ag/core";
import { Connection, PublicKey, Keypair } from "@solana/web3.js";
interface Token {
chainId: number;
address: string;
symbol: string;
name: string;
decimals: number;
logoURI: string;
tags: string[];
}
(async () => {
const ENV = "devnet";
const tokens: Token[] = await (await fetch(TOKEN_LIST_URL[ENV])).json();
const USER_KEYPAIR = Keypair.generate();
const connection = new Connection("https://api.devnet.solana.com");
const jupiter = await Jupiter.load({
connection,
cluster: ENV,
user: USER_KEYPAIR,
});
const routeMap = jupiter.getRouteMap();
const inputToken = "So11111111111111111111111111111111111111112";
const outputToken = "SRMuApVNdxXokk5GT7XD5cUUgXMBCoAz2LHeuAoKWRt";
const inputAmount = 1;
const slippage = 1;
const routes = await jupiter.computeRoutes({
inputMint: new PublicKey(inputToken),
outputMint: new PublicKey(outputToken),
inputAmount,
slippage,
forceFetch: false,
});
const { execute } = await jupiter.exchange({
routeInfo: routes.routesInfos[0],
});
const swapResult: any = await execute();
})();
bestRoute = routes.routesInfos[0];
const { execute } = await jupiter.exchange({
bestRoute,
});
const swapResult = await execute();
How to use Jupiter in a React Application
Installation
yarn add @jup-ag/react-hook
npm install @jup-ag/react-hook
Menambahkan Provider
Kita menyiapkan JupiterProvider di sini untuk menggunakan useJupiter Hook Melalui Aplikasi React. Parameter cluster disetel sebagai mainnet-beta untuk mendapatkan berbagai macam token, tetapi jika mau, Anda juga dapat mengubahnya menjadi devnet
import {
ConnectionProvider,
WalletProvider,
useConnection,
useWallet,
} from "@solana/wallet-adapter-react";
import {
getLedgerWallet,
getPhantomWallet,
getSlopeWallet,
getSolflareWallet,
getSolletExtensionWallet,
getSolletWallet,
getTorusWallet,
} from "@solana/wallet-adapter-wallets";
const JupiterApp = ({ children }) => {
const { connection } = useConnection();
const wallet = useWallet();
return (
<JupiterProvider
cluster="mainnet-beta"
connection={connection}
userPublicKey={wallet.publicKey || undefined}
>
{children}
</JupiterProvider>
);
};
const App = ({ children }) => {
const network = WalletAdapterNetwork.Devnet;
const wallets = useMemo(
() => [
getPhantomWallet(),
getSlopeWallet(),
getSolflareWallet(),
getTorusWallet(),
getLedgerWallet(),
getSolletWallet({ network }),
getSolletExtensionWallet({ network }),
],
[network]
);
const endpoint = "https://solana-api.projectserum.com";
return (
<ConnectionProvider endpoint={endpoint}>
<WalletProvider wallets={wallets} autoConnect>
<JupiterApp>{children}</JupiterApp>
</WalletProvider>
</ConnectionProvider>
);
};
export default App;
const JupiterApp = ({ children }) => {
const { connection } = useConnection();
const wallet = useWallet();
return (
<JupiterProvider
cluster="mainnet-beta"
connection={connection}
userPublicKey={wallet.publicKey || undefined}
>
{children}
</JupiterProvider>
);
};
Mendapatkan List dari Token
Semua Token yang mungkin dapat ditukar dalam jaringan diambil dan disimpan di dalam state.
import { TOKEN_LIST_URL } from "@jup-ag/core";
const JupiterApp = () => {
const [tokens, setTokens] = useState<Token[]>([]);
useEffect(() => {
fetch(TOKEN_LIST_URL[ENV])
.then((response) => response.json())
.then((result) => setTokens(result));
}, []);
};
export default JupiterApp;
const [tokens, setTokens] = useState<Token[]>([]);
useEffect(() => {
fetch(TOKEN_LIST_URL[ENV])
.then((response) => response.json())
.then((result) => setTokens(result));
}, []);
Seting State
InputMint dan OutputMint adalah status yang ditambahkan agar dapat ditukar satu sama lain atau dapat diambil dari pengguna juga.
import { TOKEN_LIST_URL } from "@jup-ag/core";
const JupiterApp = () => {
const [tokens, setTokens] = useState<Token[]>([]);
const [inputMint] = useState<PublicKey>(
new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")
);
const [outputMint] = useState<PublicKey>(
new PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB")
);
useEffect(() => {
fetch(TOKEN_LIST_URL[ENV])
.then((response) => response.json())
.then((result) => setTokens(result));
}, []);
};
export default JupiterApp;
const [inputMint] = useState<PublicKey>(
new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")
);
const [outputMint] = useState<PublicKey>(
new PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB")
);
Menggunakan useJupiter react hook
useJupiter Hook mengambil semua parameter yang diperlukan untuk menemukan rute yang melaluinya Token dari InputMint dan OutputMint dapat ditukar. Untuk mempelajari lebih lanjut tentang itu bisa klik di sini
import { TOKEN_LIST_URL } from "@jup-ag/core";
const JupiterApp = () => {
const [tokens, setTokens] = useState<Token[]>([]);
const [inputMint] = useState<PublicKey>(
new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")
);
const [outputMint] = useState<PublicKey>(
new PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB")
);
useEffect(() => {
fetch(TOKEN_LIST_URL[ENV])
.then((response) => response.json())
.then((result) => setTokens(result));
}, []);
const jupiter = useJupiter({
amount: 1 * 10 ** 6,
inputMint,
outputMint,
slippage: 1,
debounceTime: 250,
});
const {
allTokenMints,
routeMap,
exchange,
refresh,
lastRefreshTimestamp,
loading,
routes,
error,
} = jupiter;
return (
<>
<div style={{ fontWeight: "600", fontSize: 16, marginTop: 24 }}>
Hook example
</div>
<div>Number of tokens: {tokens.length}</div>
<div>Number of input tokens {allTokenMints.length}</div>
<div>Possible number of routes: {routes?.length}</div>
<div>Best quote: {routes ? routes[0].outAmount : ""}</div>
</>
);
};
export default JupiterApp;
const jupiter = useJupiter({
amount: 1 * 10 ** 6,
inputMint,
outputMint,
slippage: 1,
debounceTime: 250,
});
const {
allTokenMints,
routeMap,
exchange,
refresh,
lastRefreshTimestamp,
loading,
routes,
error,
} = jupiter;
Perform Swap
Setelah memberikan semua data ke useJupiter Hook. Kita dapat menggunakan instance jupiter untuk melakukan swap menggunakan metode exchange
import { TOKEN_LIST_URL } from "@jup-ag/core";
const JupiterApp = () => {
const [tokens, setTokens] = useState<Token[]>([]);
const [inputMint] = useState<PublicKey>(
new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")
);
const [outputMint] = useState<PublicKey>(
new PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB")
);
useEffect(() => {
fetch(TOKEN_LIST_URL[ENV])
.then((response) => response.json())
.then((result) => setTokens(result));
}, []);
const jupiter = useJupiter({
amount: 1 * 10 ** 6,
inputMint,
outputMint,
slippage: 1,
debounceTime: 250,
});
const {
allTokenMints,
routeMap,
exchange,
refresh,
lastRefreshTimestamp,
loading,
routes,
error,
} = jupiter;
const onClickSwapBestRoute = async () => {
const bestRoute = routes[0];
await exchange({
wallet: {
sendTransaction: wallet.sendTransaction,
publicKey: wallet.publicKey,
signAllTransactions: wallet.signAllTransactions,
signTransaction: wallet.signTransaction,
},
route: bestRoute,
confirmationWaiterFactory: async (txid) => {
console.log("sending transaction");
await connection.confirmTransaction(txid);
console.log("confirmed transaction");
return await connection.getTransaction(txid, {
commitment: "confirmed",
});
},
});
console.log({ swapResult });
if ("error" in swapResult) {
console.log("Error:", swapResult.error);
} else if ("txid" in swapResult) {
console.log("Sucess:", swapResult.txid);
console.log("Input:", swapResult.inputAmount);
console.log("Output:", swapResult.outputAmount);
}
};
return (
<>
<div style={{ fontWeight: "600", fontSize: 16, marginTop: 24 }}>
Hook example
</div>
<div>Number of tokens: {tokens.length}</div>
<div>Number of input tokens {allTokenMints.length}</div>
<div>Possible number of routes: {routes?.length}</div>
<div>Best quote: {routes ? routes[0].outAmount : ""}</div>
<button type="button" onClick={onClickSwapBestRoute}>
Swap best route
</button>
</>
);
};
export default JupiterApp;
(async() => {
await exchange({
wallet: {
sendTransaction: wallet.sendTransaction,
publicKey: wallet.publicKey,
signAllTransactions: wallet.signAllTransactions,
signTransaction: wallet.signTransaction,
},
route: bestRoute,
confirmationWaiterFactory: async (txid) => {
console.log("sending transaction");
await connection.confirmTransaction(txid);
console.log("confirmed transaction");
return await connection.getTransaction(txid, {
commitment: "confirmed",
});
},
});
})()
Cara Menggunakan Jupiter API
Ini adalah cara termudah untuk berinteraksi dengan program jupiter untuk menukar 2 token yang disediakan.
Instalasi
yarn i @solana/web3.js
yarn i cross-fetch
yarn i @project-serum/anchor
yarn i bs58
npm i @solana/web3.js
npm i cross-fetch
npm i @project-serum/anchor
npm i bs58
Mendapatkan Route Map
API ini mengambil semua token yang tersedia yang dapat ditukar menggunakan API jupiter. Daftar semua kemungkinan rute token sedang diambil di sini dan allInputMints
berisi daftar semua Token Input yang mungkin berdasarkan alamat mint dan swappableOutputForSol
berisi semua kemungkinan token yang dapat ditukar dengan SOL dalam kasus ini.
const routeMap = await(
await fetch("https://quote-api.jup.ag/v1/route-map")
).json();
const allInputMints = Object.keys(routeMap);
const swappableOutputForSol =
routeMap["So11111111111111111111111111111111111111112"];
const routeMap = await(
await fetch("https://quote-api.jup.ag/v1/route-map")
).json();
Mendapatkan Serialisasi Transaksi untuk perform Swap
Permintaan POST API dilakukan dengan rute yang ingin kita tuju dan alamat wallet pengguna ada beberapa parameter opsional yang dapat ditambahkan ke api ini seperti wrapUnwrapSOL dan feeAccount untuk mempelajarinya lebih lanjut buka dokumen resmi di sini link
(async() => {
const transactions = await(
fetch("https://quote-api.jup.ag/v1/swap", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
route: routes[0],
userPublicKey: wallet.publicKey.toString(),
wrapUnwrapSOL: true,
feeAccount: "xxxx",
}),
})
).json();
const { setupTransaction, swapTransaction, cleanupTransaction } = transactions;
})()
await fetch("https://quote-api.jup.ag/v1/swap", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
route: routes[0],
userPublicKey: wallet.publicKey.toString(),
wrapUnwrapSOL: true,
feeAccount: "xxxx",
}),
});
Eksekusi Transaksi Swap
Objek Transaksi dibuat dan kemudian ditandatangani oleh pengguna.
(async() => {
for (let serializedTransaction of [
setupTransaction,
swapTransaction,
cleanupTransaction,
].filter(Boolean)) {
const transaction = Transaction.from(
Buffer.from(serializedTransaction, "base64")
);
const txid = await connection.sendTransaction(transaction, [wallet.payer], {
skipPreflight: false,
});
await connection.confirmTransaction(txid);
}
})()
const transaction = Transaction.from(
Buffer.from(serializedTransaction, "base64")
);
const txid = await connection.sendTransaction(transaction, [wallet.payer], {
skipPreflight: false,
});