Jupiter: Ensure source account is initialized (#721)
This commit is contained in:
parent
40ad0b7b66
commit
9b224eae1b
|
@ -192,8 +192,15 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||||
let output_mint = pubkey_from_cli(&cmd.output_mint);
|
let output_mint = pubkey_from_cli(&cmd.output_mint);
|
||||||
let client = MangoClient::new_for_existing_account(client, account, owner).await?;
|
let client = MangoClient::new_for_existing_account(client, account, owner).await?;
|
||||||
let txsig = client
|
let txsig = client
|
||||||
.jupiter_v6()
|
.jupiter_v4()
|
||||||
.swap(input_mint, output_mint, cmd.amount, cmd.slippage_bps, false)
|
.swap(
|
||||||
|
input_mint,
|
||||||
|
output_mint,
|
||||||
|
cmd.amount,
|
||||||
|
cmd.slippage_bps,
|
||||||
|
mango_v4_client::JupiterSwapMode::ExactIn,
|
||||||
|
false,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
println!("{}", txsig);
|
println!("{}", txsig);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ impl<'a> JupiterV4<'a> {
|
||||||
input_mint: Pubkey,
|
input_mint: Pubkey,
|
||||||
output_mint: Pubkey,
|
output_mint: Pubkey,
|
||||||
amount: u64,
|
amount: u64,
|
||||||
slippage: u64,
|
slippage_bps: u64,
|
||||||
swap_mode: JupiterSwapMode,
|
swap_mode: JupiterSwapMode,
|
||||||
only_direct_routes: bool,
|
only_direct_routes: bool,
|
||||||
) -> anyhow::Result<QueryRoute> {
|
) -> anyhow::Result<QueryRoute> {
|
||||||
|
@ -115,7 +115,7 @@ impl<'a> JupiterV4<'a> {
|
||||||
("onlyDirectRoutes", only_direct_routes.to_string()),
|
("onlyDirectRoutes", only_direct_routes.to_string()),
|
||||||
("enforceSingleTx", "true".into()),
|
("enforceSingleTx", "true".into()),
|
||||||
("filterTopNResult", "10".into()),
|
("filterTopNResult", "10".into()),
|
||||||
("slippageBps", format!("{}", slippage)),
|
("slippageBps", format!("{}", slippage_bps)),
|
||||||
(
|
(
|
||||||
"swapMode",
|
"swapMode",
|
||||||
match swap_mode {
|
match swap_mode {
|
||||||
|
@ -227,14 +227,13 @@ impl<'a> JupiterV4<'a> {
|
||||||
.map(util::to_writable_account_meta)
|
.map(util::to_writable_account_meta)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let owner = self.mango_client.owner();
|
||||||
|
|
||||||
let token_ams = [source_token.mint_info.mint, target_token.mint_info.mint]
|
let token_ams = [source_token.mint_info.mint, target_token.mint_info.mint]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|mint| {
|
.map(|mint| {
|
||||||
util::to_writable_account_meta(
|
util::to_writable_account_meta(
|
||||||
anchor_spl::associated_token::get_associated_token_address(
|
anchor_spl::associated_token::get_associated_token_address(&owner, &mint),
|
||||||
&self.mango_client.owner(),
|
|
||||||
&mint,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -265,13 +264,24 @@ impl<'a> JupiterV4<'a> {
|
||||||
for ix in &jup_ixs[..jup_action_ix_begin] {
|
for ix in &jup_ixs[..jup_action_ix_begin] {
|
||||||
instructions.push(ix.clone());
|
instructions.push(ix.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure the source token account is created (jupiter takes care of the output account)
|
||||||
|
instructions.push(
|
||||||
|
spl_associated_token_account::instruction::create_associated_token_account_idempotent(
|
||||||
|
&owner,
|
||||||
|
&owner,
|
||||||
|
&source_token.mint_info.mint,
|
||||||
|
&Token::id(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
instructions.push(Instruction {
|
instructions.push(Instruction {
|
||||||
program_id: mango_v4::id(),
|
program_id: mango_v4::id(),
|
||||||
accounts: {
|
accounts: {
|
||||||
let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
|
let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
|
||||||
&mango_v4::accounts::FlashLoanBegin {
|
&mango_v4::accounts::FlashLoanBegin {
|
||||||
account: self.mango_client.mango_account_address,
|
account: self.mango_client.mango_account_address,
|
||||||
owner: self.mango_client.owner(),
|
owner,
|
||||||
token_program: Token::id(),
|
token_program: Token::id(),
|
||||||
instructions: solana_sdk::sysvar::instructions::id(),
|
instructions: solana_sdk::sysvar::instructions::id(),
|
||||||
},
|
},
|
||||||
|
@ -296,7 +306,7 @@ impl<'a> JupiterV4<'a> {
|
||||||
let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
|
let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
|
||||||
&mango_v4::accounts::FlashLoanEnd {
|
&mango_v4::accounts::FlashLoanEnd {
|
||||||
account: self.mango_client.mango_account_address,
|
account: self.mango_client.mango_account_address,
|
||||||
owner: self.mango_client.owner(),
|
owner,
|
||||||
token_program: Token::id(),
|
token_program: Token::id(),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
|
@ -319,7 +329,7 @@ impl<'a> JupiterV4<'a> {
|
||||||
let mut address_lookup_tables = self.mango_client.mango_address_lookup_tables().await?;
|
let mut address_lookup_tables = self.mango_client.mango_address_lookup_tables().await?;
|
||||||
address_lookup_tables.extend(jup_alts.into_iter());
|
address_lookup_tables.extend(jup_alts.into_iter());
|
||||||
|
|
||||||
let payer = self.mango_client.owner.pubkey(); // maybe use fee_payer? but usually it's the same
|
let payer = owner; // maybe use fee_payer? but usually it's the same
|
||||||
|
|
||||||
Ok(TransactionBuilder {
|
Ok(TransactionBuilder {
|
||||||
instructions,
|
instructions,
|
||||||
|
@ -335,7 +345,7 @@ impl<'a> JupiterV4<'a> {
|
||||||
input_mint: Pubkey,
|
input_mint: Pubkey,
|
||||||
output_mint: Pubkey,
|
output_mint: Pubkey,
|
||||||
amount: u64,
|
amount: u64,
|
||||||
slippage: u64,
|
slippage_bps: u64,
|
||||||
swap_mode: JupiterSwapMode,
|
swap_mode: JupiterSwapMode,
|
||||||
only_direct_routes: bool,
|
only_direct_routes: bool,
|
||||||
) -> anyhow::Result<Signature> {
|
) -> anyhow::Result<Signature> {
|
||||||
|
@ -344,7 +354,7 @@ impl<'a> JupiterV4<'a> {
|
||||||
input_mint,
|
input_mint,
|
||||||
output_mint,
|
output_mint,
|
||||||
amount,
|
amount,
|
||||||
slippage,
|
slippage_bps,
|
||||||
swap_mode,
|
swap_mode,
|
||||||
only_direct_routes,
|
only_direct_routes,
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,7 +10,6 @@ use crate::MangoClient;
|
||||||
use crate::{util, TransactionBuilder};
|
use crate::{util, TransactionBuilder};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use solana_sdk::signer::Signer;
|
|
||||||
use solana_sdk::{instruction::Instruction, signature::Signature};
|
use solana_sdk::{instruction::Instruction, signature::Signature};
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
|
@ -148,7 +147,7 @@ impl<'a> JupiterV6<'a> {
|
||||||
input_mint: Pubkey,
|
input_mint: Pubkey,
|
||||||
output_mint: Pubkey,
|
output_mint: Pubkey,
|
||||||
amount: u64,
|
amount: u64,
|
||||||
slippage: u64,
|
slippage_bps: u64,
|
||||||
only_direct_routes: bool,
|
only_direct_routes: bool,
|
||||||
) -> anyhow::Result<QuoteResponse> {
|
) -> anyhow::Result<QuoteResponse> {
|
||||||
let mut account = self.mango_client.mango_account().await?;
|
let mut account = self.mango_client.mango_account().await?;
|
||||||
|
@ -189,7 +188,7 @@ impl<'a> JupiterV6<'a> {
|
||||||
("inputMint", input_mint.to_string()),
|
("inputMint", input_mint.to_string()),
|
||||||
("outputMint", output_mint.to_string()),
|
("outputMint", output_mint.to_string()),
|
||||||
("amount", format!("{}", amount)),
|
("amount", format!("{}", amount)),
|
||||||
("slippageBps", format!("{}", slippage)),
|
("slippageBps", format!("{}", slippage_bps)),
|
||||||
("onlyDirectRoutes", only_direct_routes.to_string()),
|
("onlyDirectRoutes", only_direct_routes.to_string()),
|
||||||
(
|
(
|
||||||
"maxAccounts",
|
"maxAccounts",
|
||||||
|
@ -237,14 +236,13 @@ impl<'a> JupiterV6<'a> {
|
||||||
.map(util::to_writable_account_meta)
|
.map(util::to_writable_account_meta)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let owner = self.mango_client.owner();
|
||||||
|
|
||||||
let token_ams = [source_token.mint_info.mint, target_token.mint_info.mint]
|
let token_ams = [source_token.mint_info.mint, target_token.mint_info.mint]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|mint| {
|
.map(|mint| {
|
||||||
util::to_writable_account_meta(
|
util::to_writable_account_meta(
|
||||||
anchor_spl::associated_token::get_associated_token_address(
|
anchor_spl::associated_token::get_associated_token_address(&owner, &mint),
|
||||||
&self.mango_client.owner(),
|
|
||||||
&mint,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -273,7 +271,7 @@ impl<'a> JupiterV6<'a> {
|
||||||
.http_client
|
.http_client
|
||||||
.post("https://quote-api.jup.ag/v6/swap-instructions")
|
.post("https://quote-api.jup.ag/v6/swap-instructions")
|
||||||
.json(&SwapRequest {
|
.json(&SwapRequest {
|
||||||
user_public_key: self.mango_client.owner.pubkey().to_string(),
|
user_public_key: owner.to_string(),
|
||||||
wrap_and_unwrap_sol: false,
|
wrap_and_unwrap_sol: false,
|
||||||
use_shared_accounts: true,
|
use_shared_accounts: true,
|
||||||
fee_account: None,
|
fee_account: None,
|
||||||
|
@ -299,13 +297,24 @@ impl<'a> JupiterV6<'a> {
|
||||||
for ix in &swap.setup_instructions.unwrap_or_default() {
|
for ix in &swap.setup_instructions.unwrap_or_default() {
|
||||||
instructions.push(ix.try_into()?);
|
instructions.push(ix.try_into()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure the source token account is created (jupiter takes care of the output account)
|
||||||
|
instructions.push(
|
||||||
|
spl_associated_token_account::instruction::create_associated_token_account_idempotent(
|
||||||
|
&owner,
|
||||||
|
&owner,
|
||||||
|
&source_token.mint_info.mint,
|
||||||
|
&Token::id(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
instructions.push(Instruction {
|
instructions.push(Instruction {
|
||||||
program_id: mango_v4::id(),
|
program_id: mango_v4::id(),
|
||||||
accounts: {
|
accounts: {
|
||||||
let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
|
let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
|
||||||
&mango_v4::accounts::FlashLoanBegin {
|
&mango_v4::accounts::FlashLoanBegin {
|
||||||
account: self.mango_client.mango_account_address,
|
account: self.mango_client.mango_account_address,
|
||||||
owner: self.mango_client.owner(),
|
owner,
|
||||||
token_program: Token::id(),
|
token_program: Token::id(),
|
||||||
instructions: solana_sdk::sysvar::instructions::id(),
|
instructions: solana_sdk::sysvar::instructions::id(),
|
||||||
},
|
},
|
||||||
|
@ -328,7 +337,7 @@ impl<'a> JupiterV6<'a> {
|
||||||
let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
|
let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
|
||||||
&mango_v4::accounts::FlashLoanEnd {
|
&mango_v4::accounts::FlashLoanEnd {
|
||||||
account: self.mango_client.mango_account_address,
|
account: self.mango_client.mango_account_address,
|
||||||
owner: self.mango_client.owner(),
|
owner,
|
||||||
token_program: Token::id(),
|
token_program: Token::id(),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
|
@ -363,7 +372,7 @@ impl<'a> JupiterV6<'a> {
|
||||||
.await?;
|
.await?;
|
||||||
address_lookup_tables.extend(jup_alts.into_iter());
|
address_lookup_tables.extend(jup_alts.into_iter());
|
||||||
|
|
||||||
let payer = self.mango_client.owner.pubkey(); // maybe use fee_payer? but usually it's the same
|
let payer = owner; // maybe use fee_payer? but usually it's the same
|
||||||
|
|
||||||
Ok(TransactionBuilder {
|
Ok(TransactionBuilder {
|
||||||
instructions,
|
instructions,
|
||||||
|
@ -379,7 +388,7 @@ impl<'a> JupiterV6<'a> {
|
||||||
input_mint: Pubkey,
|
input_mint: Pubkey,
|
||||||
output_mint: Pubkey,
|
output_mint: Pubkey,
|
||||||
amount: u64,
|
amount: u64,
|
||||||
slippage: u64,
|
slippage_bps: u64,
|
||||||
only_direct_routes: bool,
|
only_direct_routes: bool,
|
||||||
) -> anyhow::Result<Signature> {
|
) -> anyhow::Result<Signature> {
|
||||||
let route = self
|
let route = self
|
||||||
|
@ -387,7 +396,7 @@ impl<'a> JupiterV6<'a> {
|
||||||
input_mint,
|
input_mint,
|
||||||
output_mint,
|
output_mint,
|
||||||
amount,
|
amount,
|
||||||
slippage,
|
slippage_bps,
|
||||||
only_direct_routes,
|
only_direct_routes,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
Loading…
Reference in New Issue