Skip to content

Commit

Permalink
[+] add memo for send sol and spl-token
Browse files Browse the repository at this point in the history
  • Loading branch information
heng30 committed Jul 14, 2024
1 parent ea28a38 commit 00433a8
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 19 deletions.
17 changes: 9 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions libs/wallet/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions libs/wallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ solana-zk-token-sdk = "2.0"
solana-account-decoder = "2.0"
solana-transaction-status = "2.0"

spl-memo = "5.0"
spl-token = "6.0"
spl-associated-token-account = "4.0"

Expand Down
142 changes: 134 additions & 8 deletions libs/wallet/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pub struct SendLamportsProps {
pub lamports: u64,
pub timeout: Option<u64>,
pub is_wait_confirmed: bool,
pub memo: Option<String>,
}

#[derive(Debug)]
Expand All @@ -67,6 +68,7 @@ pub struct SendSplTokenProps {
pub decimals: u8,
pub timeout: Option<u64>,
pub is_wait_confirmed: bool,
pub memo: Option<String>,
}

#[derive(Debug)]
Expand All @@ -79,6 +81,7 @@ pub struct SendSplTokenWithCreateProps {
pub decimals: u8,
pub timeout: Option<u64>,
pub is_wait_confirmed: bool,
pub memo: Option<String>,
}

#[derive(Debug)]
Expand Down Expand Up @@ -163,13 +166,22 @@ pub async fn send_lamports(props: SendLamportsProps) -> Result<Signature> {
.await
.with_context(|| "Get latest blockhash failed")?;

let instruction = system_instruction::transfer(
let send_instruction = system_instruction::transfer(
&props.sender_keypair.pubkey(),
&props.recipient_pubkey,
props.lamports,
);

let message = Message::new(&[instruction], Some(&props.sender_keypair.pubkey()));
let message = if let Some(memo) = props.memo {
let memo_instruction = spl_memo::build_memo(memo.as_bytes(), &[]);
Message::new(
&[send_instruction, memo_instruction],
Some(&props.sender_keypair.pubkey()),
)
} else {
Message::new(&[send_instruction], Some(&props.sender_keypair.pubkey()))
};

let transaction = Transaction::new(&[props.sender_keypair], message, recent_blockhash);

match props.is_wait_confirmed {
Expand Down Expand Up @@ -270,7 +282,7 @@ pub async fn send_spl_token(props: SendSplTokenProps) -> Result<Signature> {
);
}

let instruction = spl_token::instruction::transfer_checked(
let send_instruction = spl_token::instruction::transfer_checked(
&spl_token::ID,
&props.sender_token_account_pubkey,
&props.mint_pubkey,
Expand All @@ -286,7 +298,16 @@ pub async fn send_spl_token(props: SendSplTokenProps) -> Result<Signature> {
.await
.with_context(|| "Get latest blockhash failed")?;

let message = Message::new(&[instruction], Some(&props.sender_keypair.pubkey()));
let message = if let Some(memo) = props.memo {
let memo_instruction = spl_memo::build_memo(memo.as_bytes(), &[]);
Message::new(
&[send_instruction, memo_instruction],
Some(&props.sender_keypair.pubkey()),
)
} else {
Message::new(&[send_instruction], Some(&props.sender_keypair.pubkey()))
};

let transaction = Transaction::new(&[props.sender_keypair], message, recent_blockhash);

match props.is_wait_confirmed {
Expand Down Expand Up @@ -348,10 +369,19 @@ pub async fn send_spl_token_with_create(props: SendSplTokenWithCreateProps) -> R
.await
.with_context(|| "Get latest blockhash failed")?;

let message = Message::new(
&[create_instruction, send_instruction],
Some(&props.sender_keypair.pubkey()),
);
let message = if let Some(memo) = props.memo {
let memo_instruction = spl_memo::build_memo(memo.as_bytes(), &[]);
Message::new(
&[create_instruction, send_instruction, memo_instruction],
Some(&props.sender_keypair.pubkey()),
)
} else {
Message::new(
&[create_instruction, send_instruction],
Some(&props.sender_keypair.pubkey()),
)
};

let transaction = Transaction::new(&[props.sender_keypair], message, recent_blockhash);

match props.is_wait_confirmed {
Expand Down Expand Up @@ -938,6 +968,7 @@ mod tests {
use rand::distributions::{Alphanumeric, DistString};
use std::str::FromStr;

//mnemonic: text rail defense total joke enough question net dance hello health absurd
const SENDER_KEYPAIR: &[u8] = &[
82, 58, 225, 224, 31, 242, 176, 82, 123, 252, 190, 95, 252, 168, 178, 81, 25, 117, 29, 235,
149, 159, 9, 226, 31, 41, 77, 251, 85, 225, 84, 142, 226, 85, 29, 242, 3, 193, 99, 113,
Expand Down Expand Up @@ -990,6 +1021,7 @@ mod tests {
decimals: 6,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: true,
memo: None,
};

let instructions = send_spl_token_instruction(&props)?;
Expand Down Expand Up @@ -1056,6 +1088,7 @@ mod tests {
decimals: 6,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: true,
memo: None,
};
let send_instructions = send_spl_token_instruction(&props)?;

Expand All @@ -1082,6 +1115,27 @@ mod tests {
lamports: 100,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: true,
memo: None,
};

let signature = send_lamports(props).await?;
println!("{signature:?}");

Ok(())
}

#[tokio::test]
async fn test_send_lamports_with_memo() -> Result<()> {
let sender_keypair = Keypair::from_bytes(SENDER_KEYPAIR)?;
let recipient_pubkey = Pubkey::from_str(RECIPIENT_WALLET_ADDRESS)?;
let props = SendLamportsProps {
rpc_url_ty: RpcUrlType::Test,
sender_keypair,
recipient_pubkey,
lamports: 100,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: true,
memo: Some("Hello World From Sollaw".to_string()),
};

let signature = send_lamports(props).await?;
Expand Down Expand Up @@ -1116,6 +1170,7 @@ mod tests {
lamports: 1_000_000,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: true,
memo: None,
};
let signature = send_lamports(props).await?;
println!("{signature:?}");
Expand Down Expand Up @@ -1153,6 +1208,33 @@ mod tests {
decimals: 6,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: true,
memo: None,
};

let signature = send_spl_token(props).await?;
println!("{signature:?}");

Ok(())
}

#[tokio::test]
async fn test_send_spl_token_with_memo() -> Result<()> {
let sender_keypair = Keypair::from_bytes(SENDER_KEYPAIR)?;
let sender_token_account_pubkey = Pubkey::from_str(TOKEN_ACCOUNT_ADDRESS_SENDER)?;
let recipient_token_account_pubkey = Pubkey::from_str(TOKEN_ACCOUNT_ADDRESS_RECIPENT)?;
let mint_pubkey = Pubkey::from_str(USDC_TOKEN_CONTRACT_TEST_NET_ADDRESS)?;

let props = SendSplTokenProps {
rpc_url_ty: RpcUrlType::Test,
sender_keypair,
sender_token_account_pubkey,
recipient_token_account_pubkey,
mint_pubkey,
amount: 1000_000,
decimals: 6,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: true,
memo: Some("Hello World from Sollaw".to_string()),
};

let signature = send_spl_token(props).await?;
Expand All @@ -1177,6 +1259,46 @@ mod tests {
decimals: 6,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: true,
memo: None,
};

println!(
"recipient_pubkey: {}",
recipient_keypair.pubkey().to_string()
);

let signature = send_spl_token_with_create(props).await?;
println!("{signature:?}");

let info = fetch_account_token(
RpcUrlType::Test,
&recipient_pubkey.to_string(),
USDC_TOKEN_CONTRACT_TEST_NET_ADDRESS,
Some(DEFAULT_TIMEOUT_SECS),
)
.await?;
println!("{info:?}");

Ok(())
}

#[tokio::test]
async fn test_send_spl_token_with_create_with_memo() -> Result<()> {
let sender_keypair = Keypair::from_bytes(SENDER_KEYPAIR)?;
let mint_pubkey = Pubkey::from_str(USDC_TOKEN_CONTRACT_TEST_NET_ADDRESS)?;
let recipient_keypair = Keypair::new();
let recipient_pubkey = recipient_keypair.pubkey();

let props = SendSplTokenWithCreateProps {
rpc_url_ty: RpcUrlType::Test,
sender_keypair,
recipient_pubkey: recipient_pubkey.clone(),
mint_pubkey,
amount: 1_000_000,
decimals: 6,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: true,
memo: Some("Hello World From Sollaw".to_string()),
};

println!(
Expand Down Expand Up @@ -1334,6 +1456,7 @@ mod tests {
lamports: 100,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: false,
memo: None,
};

let signature = send_lamports(props).await?;
Expand All @@ -1356,6 +1479,7 @@ mod tests {
lamports: 100,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: false,
memo: None,
};

let signature = send_lamports(props).await?;
Expand All @@ -1380,6 +1504,7 @@ mod tests {
lamports: 100,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: false,
memo: None,
};

let signature = send_lamports(props).await?;
Expand All @@ -1403,6 +1528,7 @@ mod tests {
lamports: 100,
timeout: Some(DEFAULT_TIMEOUT_SECS),
is_wait_confirmed: true,
memo: None,
};

let signature = send_lamports(props).await?;
Expand Down
Loading

0 comments on commit 00433a8

Please sign in to comment.