Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 953e06b

Browse files
committed
token-client: support wrap
also convert cli to use client for wrap
1 parent 6b05f02 commit 953e06b

File tree

4 files changed

+127
-72
lines changed

4 files changed

+127
-72
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

token/cli/src/main.rs

Lines changed: 32 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -497,16 +497,6 @@ async fn command_set_interest_rate(
497497
})
498498
}
499499

500-
// XXX OK wtf do i need to do for this shit
501-
// create account needs to go through the client
502-
// create associated vs create aux with ext... pretty simple?
503-
// then i want to impl --immutable, also simple
504-
// error if the mint is tokenkeg, rebuke if the token is associated
505-
// XXX umm then for default... i think its not possible to use this for ata?
506-
// test it out quicky
507-
508-
// XXX NEXT UP impl this shit for wrap. maybe put wrap/unwrap in the client?
509-
// and also reply to jon. i need to take a nap tho omg im dying
510500
async fn command_create_account(
511501
config: &Config<'_>,
512502
token_pubkey: Pubkey,
@@ -1199,6 +1189,7 @@ async fn command_thaw(
11991189
})
12001190
}
12011191

1192+
// XXX TODO remove this when functionality moved into client
12021193
fn native_mint(program_id: &Pubkey) -> Result<Pubkey, Error> {
12031194
if program_id == &spl_token_2022::id() {
12041195
Ok(spl_token_2022::native_mint::id())
@@ -1217,72 +1208,36 @@ async fn command_wrap(
12171208
bulk_signers: BulkSigners,
12181209
) -> CommandResult {
12191210
let lamports = sol_to_lamports(sol);
1220-
1211+
// XXX TODO i think i want a Token fn `new_native` that encapsulates the `native_mint` logic in one place
1212+
// also a function on it `is_native` maybe
12211213
let native_mint = native_mint(&config.program_id)?;
1222-
let instructions = if let Some(wrapped_sol_account) = wrapped_sol_account {
1223-
println_display(
1224-
config,
1225-
format!("Wrapping {} SOL into {}", sol, wrapped_sol_account),
1226-
);
1227-
vec![
1228-
system_instruction::create_account(
1229-
&wallet_address,
1230-
&wrapped_sol_account,
1231-
lamports,
1232-
Account::LEN as u64,
1233-
&config.program_id,
1234-
),
1235-
initialize_account(
1236-
&config.program_id,
1237-
&wrapped_sol_account,
1238-
&native_mint,
1239-
&wallet_address,
1240-
)?,
1241-
]
1242-
} else {
1243-
let account = get_associated_token_address_with_program_id(
1214+
let token = token_client_from_config(config, &native_mint);
1215+
1216+
let account = wrapped_sol_account.unwrap_or_else(|| {
1217+
get_associated_token_address_with_program_id(
12441218
&wallet_address,
12451219
&native_mint,
12461220
&config.program_id,
1247-
);
1221+
)
1222+
});
12481223

1249-
if !config.sign_only {
1250-
if let Some(account_data) = config
1251-
.rpc_client
1252-
.get_account_with_commitment(&account, config.rpc_client.commitment())
1253-
.await?
1254-
.value
1255-
{
1256-
if account_data.owner != system_program::id() {
1257-
return Err(format!("Error: Account already exists: {}", account).into());
1258-
}
1224+
println_display(config, format!("Wrapping {} SOL into {}", sol, account));
1225+
1226+
if !config.sign_only {
1227+
if let Ok(account_data) = config.get_account_checked(&account).await {
1228+
if account_data.owner != system_program::id() {
1229+
return Err(format!("Error: Account already exists: {}", account).into());
12591230
}
12601231
}
12611232

1262-
println_display(config, format!("Wrapping {} SOL into {}", sol, account));
1263-
vec![
1264-
system_instruction::transfer(&wallet_address, &account, lamports),
1265-
create_associated_token_account(
1266-
&config.fee_payer.pubkey(),
1267-
&wallet_address,
1268-
&native_mint,
1269-
&config.program_id,
1270-
),
1271-
]
1272-
};
1273-
if !config.sign_only {
12741233
check_wallet_balance(config, &wallet_address, lamports).await?;
12751234
}
1276-
let tx_return = handle_tx(
1277-
&CliSignerInfo {
1278-
signers: bulk_signers,
1279-
},
1280-
config,
1281-
false,
1282-
0,
1283-
instructions,
1284-
)
1285-
.await?;
1235+
1236+
let res = token
1237+
.wrap_transferable(&account, &wallet_address, lamports, &bulk_signers)
1238+
.await?;
1239+
1240+
let tx_return = finish_tx(config, &res, false).await?;
12861241
Ok(match tx_return {
12871242
TransactionReturnData::CliSignature(signature) => {
12881243
config.output_format.formatted_string(&signature)
@@ -3775,9 +3730,16 @@ mod tests {
37753730
let address = auxiliary.pubkey();
37763731
let bulk_signers: Vec<Arc<dyn Signer>> =
37773732
vec![Arc::new(clone_keypair(payer)), Arc::new(auxiliary)];
3778-
command_create_account(config, mint, payer.pubkey(), Some(address), bulk_signers)
3779-
.await
3780-
.unwrap();
3733+
command_create_account(
3734+
config,
3735+
mint,
3736+
payer.pubkey(),
3737+
Some(address),
3738+
false,
3739+
bulk_signers,
3740+
)
3741+
.await
3742+
.unwrap();
37813743
address
37823744
}
37833745

@@ -3787,7 +3749,7 @@ mod tests {
37873749
mint: Pubkey,
37883750
) -> Pubkey {
37893751
let bulk_signers: Vec<Arc<dyn Signer>> = vec![Arc::new(clone_keypair(payer))];
3790-
command_create_account(config, mint, payer.pubkey(), None, bulk_signers)
3752+
command_create_account(config, mint, payer.pubkey(), None, false, bulk_signers)
37913753
.await
37923754
.unwrap();
37933755
get_associated_token_address_with_program_id(&payer.pubkey(), &mint, &config.program_id)

token/client/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ solana-sdk = "=1.11.6"
1717
# testing token
1818
spl-associated-token-account = { version = "1.1", path = "../../associated-token-account/program", features = ["no-entrypoint"] }
1919
spl-memo = { version = "3.0.1", path = "../../memo/program", features = ["no-entrypoint"] }
20+
spl-token = { version = "3.5", path="../program", features = [ "no-entrypoint" ] }
2021
spl-token-2022 = { version = "0.4", path="../program-2022" }
2122
thiserror = "1.0"
2223

token/client/src/token.rs

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use {
2121
confidential_transfer, default_account_state, interest_bearing_mint, memo_transfer,
2222
transfer_fee, ExtensionType, StateWithExtensionsOwned,
2323
},
24-
instruction, native_mint,
24+
instruction,
2525
solana_zk_token_sdk::{
2626
encryption::{auth_encryption::*, elgamal::*},
2727
errors::ProofError,
@@ -443,7 +443,7 @@ where
443443
program_id: &Pubkey,
444444
payer: Arc<dyn Signer>,
445445
) -> TokenResult<Self> {
446-
let token = Self::new(client, program_id, &native_mint::id(), payer);
446+
let token = Self::new(client, program_id, &native_mint(program_id), payer);
447447
token
448448
.process_ixs::<[&dyn Signer; 0]>(
449449
&[instruction::create_native_mint(
@@ -894,6 +894,87 @@ where
894894
.await
895895
}
896896

897+
pub async fn wrap<S: Signers>(
898+
&self,
899+
account: &Pubkey,
900+
owner: &Pubkey,
901+
lamports: u64,
902+
signing_keypairs: &S,
903+
) -> TokenResult<T::Output> {
904+
// mutable owner for Tokenkeg, immutable otherwise
905+
let immutable_owner = self.program_id != spl_token::id();
906+
let instructions = self.wrap_ixs(account, owner, lamports, immutable_owner)?;
907+
908+
self.process_ixs(&instructions, signing_keypairs).await
909+
}
910+
911+
pub async fn wrap_transferable<S: Signers>(
912+
&self,
913+
account: &Pubkey,
914+
owner: &Pubkey,
915+
lamports: u64,
916+
signing_keypairs: &S,
917+
) -> TokenResult<T::Output> {
918+
let instructions = self.wrap_ixs(account, owner, lamports, false)?;
919+
920+
self.process_ixs(&instructions, signing_keypairs).await
921+
}
922+
923+
/// Wrap lamports into native account
924+
fn wrap_ixs(
925+
&self,
926+
account: &Pubkey,
927+
owner: &Pubkey,
928+
lamports: u64,
929+
immutable_owner: bool,
930+
) -> TokenResult<Vec<Instruction>> {
931+
if self.pubkey != native_mint(&self.program_id) {
932+
return Err(TokenError::AccountInvalidMint);
933+
}
934+
935+
let mut instructions = vec![];
936+
if *account == self.get_associated_token_address(owner) {
937+
instructions.push(system_instruction::transfer(owner, account, lamports));
938+
instructions.push(create_associated_token_account(
939+
&self.payer.pubkey(),
940+
owner,
941+
&self.pubkey,
942+
&self.program_id,
943+
));
944+
} else {
945+
let extensions = if immutable_owner {
946+
vec![ExtensionType::ImmutableOwner]
947+
} else {
948+
vec![]
949+
};
950+
let space = ExtensionType::get_account_len::<Account>(&extensions);
951+
952+
instructions.push(system_instruction::create_account(
953+
&self.payer.pubkey(),
954+
account,
955+
lamports,
956+
space as u64,
957+
&self.program_id,
958+
));
959+
960+
if immutable_owner {
961+
instructions.push(instruction::initialize_immutable_owner(
962+
&self.program_id,
963+
account,
964+
)?)
965+
}
966+
967+
instructions.push(instruction::initialize_account(
968+
&self.program_id,
969+
account,
970+
&self.pubkey,
971+
owner,
972+
)?);
973+
};
974+
975+
Ok(instructions)
976+
}
977+
897978
/// Sync native account lamports
898979
pub async fn sync_native(&self, account: &Pubkey) -> TokenResult<T::Output> {
899980
self.process_ixs::<[&dyn Signer; 0]>(
@@ -1925,3 +2006,13 @@ where
19252006
.await
19262007
}
19272008
}
2009+
2010+
fn native_mint(program_id: &Pubkey) -> Pubkey {
2011+
if program_id == &spl_token_2022::id() {
2012+
spl_token_2022::native_mint::id()
2013+
} else if program_id == &spl_token::id() {
2014+
spl_token::native_mint::id()
2015+
} else {
2016+
panic!("Unrecognized token program id: {}", program_id);
2017+
}
2018+
}

0 commit comments

Comments
 (0)