token-client: memo now explicitly declares signers

This commit is contained in:
hanako mumei 2022-09-07 13:51:55 -07:00 committed by hana
parent 8e6caf45ac
commit 4dfd23e0b6
3 changed files with 40 additions and 8 deletions

View File

@ -393,7 +393,7 @@ async fn command_create_token(
} }
if let Some(text) = memo { if let Some(text) = memo {
token.with_memo(text); token.with_memo(text, vec![config.default_signer.pubkey()]);
} }
let res = token let res = token
@ -1073,7 +1073,7 @@ async fn command_burn(
let token = token_client_from_config(config, &mint_info.program_id, &mint_info.address); let token = token_client_from_config(config, &mint_info.program_id, &mint_info.address);
if let Some(text) = memo { if let Some(text) = memo {
token.with_memo(text); token.with_memo(text, vec![config.default_signer.pubkey()]);
} }
let res = token let res = token
@ -1120,7 +1120,7 @@ async fn command_mint(
let token = token_client_from_config(config, &mint_info.program_id, &mint_info.address); let token = token_client_from_config(config, &mint_info.program_id, &mint_info.address);
if let Some(text) = memo { if let Some(text) = memo {
token.with_memo(text); token.with_memo(text, vec![config.default_signer.pubkey()]);
} }
let res = token let res = token

View File

@ -60,6 +60,8 @@ pub enum TokenError {
AccountDecryption, AccountDecryption,
#[error("not enough funds in account")] #[error("not enough funds in account")]
NotEnoughFunds, NotEnoughFunds,
#[error("missing memo signer")]
MissingMemoSigner,
} }
impl PartialEq for TokenError { impl PartialEq for TokenError {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
@ -77,6 +79,7 @@ impl PartialEq for TokenError {
) => true, ) => true,
(Self::AccountDecryption, Self::AccountDecryption) => true, (Self::AccountDecryption, Self::AccountDecryption) => true,
(Self::NotEnoughFunds, Self::NotEnoughFunds) => true, (Self::NotEnoughFunds, Self::NotEnoughFunds) => true,
(Self::MissingMemoSigner, Self::MissingMemoSigner) => true,
_ => false, _ => false,
} }
} }
@ -172,6 +175,20 @@ impl ExtensionInitializationParams {
pub type TokenResult<T> = Result<T, TokenError>; pub type TokenResult<T> = Result<T, TokenError>;
#[derive(Debug)]
struct TokenMemo {
text: String,
signers: Vec<Pubkey>,
}
impl TokenMemo {
pub fn to_instruction(&self) -> Instruction {
spl_memo::build_memo(
self.text.as_bytes(),
&self.signers.iter().collect::<Vec<_>>(),
)
}
}
pub struct Token<T> { pub struct Token<T> {
client: Arc<dyn ProgramClient<T>>, client: Arc<dyn ProgramClient<T>>,
pubkey: Pubkey, /*token mint*/ pubkey: Pubkey, /*token mint*/
@ -179,7 +196,7 @@ pub struct Token<T> {
program_id: Pubkey, program_id: Pubkey,
nonce_account: Option<Pubkey>, nonce_account: Option<Pubkey>,
nonce_authority: Option<Pubkey>, nonce_authority: Option<Pubkey>,
memo: Arc<RwLock<Option<String>>>, memo: Arc<RwLock<Option<TokenMemo>>>,
} }
impl<T> fmt::Debug for Token<T> { impl<T> fmt::Debug for Token<T> {
@ -187,6 +204,9 @@ impl<T> fmt::Debug for Token<T> {
f.debug_struct("Token") f.debug_struct("Token")
.field("pubkey", &self.pubkey) .field("pubkey", &self.pubkey)
.field("payer", &self.payer.pubkey()) .field("payer", &self.payer.pubkey())
.field("program_id", &self.program_id)
.field("nonce_account", &self.nonce_account)
.field("nonce_authority", &self.nonce_authority)
.field("memo", &self.memo.read().unwrap()) .field("memo", &self.memo.read().unwrap())
.finish() .finish()
} }
@ -242,9 +262,12 @@ where
} }
} }
pub fn with_memo<M: AsRef<str>>(&self, memo: M) -> &Self { pub fn with_memo<M: AsRef<str>>(&self, memo: M, signers: Vec<Pubkey>) -> &Self {
let mut w_memo = self.memo.write().unwrap(); let mut w_memo = self.memo.write().unwrap();
*w_memo = Some(memo.as_ref().to_string()); *w_memo = Some(TokenMemo {
text: memo.as_ref().to_string(),
signers,
});
self self
} }
@ -305,7 +328,16 @@ where
{ {
let mut w_memo = self.memo.write().unwrap(); let mut w_memo = self.memo.write().unwrap();
if let Some(memo) = w_memo.take() { if let Some(memo) = w_memo.take() {
instructions.push(spl_memo::build_memo(memo.as_bytes(), &[&payer_key])); let signing_pubkeys = signing_keypairs.pubkeys();
if !memo
.signers
.iter()
.all(|signer| signing_pubkeys.contains(signer))
{
return Err(TokenError::MissingMemoSigner);
}
instructions.push(memo.to_instruction());
} }
} }

View File

@ -131,7 +131,7 @@ async fn test_memo_transfers(
// transfer with memo // transfer with memo
token token
.with_memo("🦖") .with_memo("🦖", vec![alice.pubkey()])
.transfer( .transfer(
&alice_account, &alice_account,
&bob_account, &bob_account,