spl: Implement token::set_authority (#307)
This commit is contained in:
parent
1777ecaee4
commit
dd64779273
|
@ -15,6 +15,7 @@ incremented for features.
|
|||
|
||||
* ts: Address metadata is now optional for `anchor.workspace` clients ([#310](https://github.com/project-serum/anchor/pull/310)).
|
||||
* cli: Add global options for override Anchor.toml values ([#313](https://github.com/project-serum/anchor/pull/313)).
|
||||
* spl: Add `SetAuthority` instruction ([#307](https://github.com/project-serum/anchor/pull/307/files)).
|
||||
|
||||
## [0.6.0] - 2021-05-23
|
||||
|
||||
|
|
|
@ -15,3 +15,4 @@ cpi = ["no-entrypoint"]
|
|||
[dependencies]
|
||||
anchor-lang = { path = "../../../../../lang" }
|
||||
anchor-spl = { path = "../../../../../spl" }
|
||||
spl-token = { version = "3.1.1", features = ["no-entrypoint"] }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! This example demonstrates the use of the `anchor_spl::token` CPI client.
|
||||
|
||||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::{self, Burn, MintTo, Transfer};
|
||||
use anchor_spl::token::{self, Burn, MintTo, SetAuthority, Transfer};
|
||||
|
||||
#[program]
|
||||
mod token_proxy {
|
||||
|
@ -18,6 +18,26 @@ mod token_proxy {
|
|||
pub fn proxy_burn(ctx: Context<ProxyBurn>, amount: u64) -> ProgramResult {
|
||||
token::burn(ctx.accounts.into(), amount)
|
||||
}
|
||||
|
||||
pub fn proxy_set_authority(
|
||||
ctx: Context<ProxySetAuthority>,
|
||||
authority_type: AuthorityType,
|
||||
new_authority: Option<Pubkey>,
|
||||
) -> ProgramResult {
|
||||
token::set_authority(ctx.accounts.into(), authority_type.into(), new_authority)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(AnchorSerialize, AnchorDeserialize)]
|
||||
pub enum AuthorityType {
|
||||
/// Authority to mint new tokens
|
||||
MintTokens,
|
||||
/// Authority to freeze any account associated with the Mint
|
||||
FreezeAccount,
|
||||
/// Owner of a given token account
|
||||
AccountOwner,
|
||||
/// Authority to close a token account
|
||||
CloseAccount,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
|
@ -53,6 +73,15 @@ pub struct ProxyBurn<'info> {
|
|||
pub token_program: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct ProxySetAuthority<'info> {
|
||||
#[account(signer)]
|
||||
pub current_authority: AccountInfo<'info>,
|
||||
#[account(mut)]
|
||||
pub account_or_mint: AccountInfo<'info>,
|
||||
pub token_program: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c, 'info> From<&mut ProxyTransfer<'info>>
|
||||
for CpiContext<'a, 'b, 'c, 'info, Transfer<'info>>
|
||||
{
|
||||
|
@ -92,3 +121,29 @@ impl<'a, 'b, 'c, 'info> From<&mut ProxyBurn<'info>> for CpiContext<'a, 'b, 'c, '
|
|||
CpiContext::new(cpi_program, cpi_accounts)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c, 'info> From<&mut ProxySetAuthority<'info>>
|
||||
for CpiContext<'a, 'b, 'c, 'info, SetAuthority<'info>>
|
||||
{
|
||||
fn from(
|
||||
accounts: &mut ProxySetAuthority<'info>,
|
||||
) -> CpiContext<'a, 'b, 'c, 'info, SetAuthority<'info>> {
|
||||
let cpi_accounts = SetAuthority {
|
||||
account_or_mint: accounts.account_or_mint.clone(),
|
||||
current_authority: accounts.current_authority.clone(),
|
||||
}; // TODO: Support multisig signers
|
||||
let cpi_program = accounts.token_program.clone();
|
||||
CpiContext::new(cpi_program, cpi_accounts)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AuthorityType> for spl_token::instruction::AuthorityType {
|
||||
fn from(authority_ty: AuthorityType) -> spl_token::instruction::AuthorityType {
|
||||
match authority_ty {
|
||||
AuthorityType::MintTokens => spl_token::instruction::AuthorityType::MintTokens,
|
||||
AuthorityType::FreezeAccount => spl_token::instruction::AuthorityType::FreezeAccount,
|
||||
AuthorityType::AccountOwner => spl_token::instruction::AuthorityType::AccountOwner,
|
||||
AuthorityType::CloseAccount => spl_token::instruction::AuthorityType::CloseAccount,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,24 @@ describe("token", () => {
|
|||
const toAccount = await getTokenAccount(provider, to);
|
||||
assert.ok(toAccount.amount.eq(new anchor.BN(1)));
|
||||
});
|
||||
|
||||
it("Set new mint authority", async () => {
|
||||
const newMintAuthority = anchor.web3.Keypair.generate();
|
||||
await program.rpc.proxySetAuthority(
|
||||
{ mintTokens: {} },
|
||||
newMintAuthority.publicKey,
|
||||
{
|
||||
accounts: {
|
||||
accountOrMint: mint,
|
||||
currentAuthority: provider.wallet.publicKey,
|
||||
tokenProgram: TokenInstructions.TOKEN_PROGRAM_ID,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const mintInfo = await getMintInfo(provider, mint);
|
||||
assert.ok(mintInfo.mintAuthority.equals(newMintAuthority.publicKey));
|
||||
});
|
||||
});
|
||||
|
||||
// SPL token client boilerplate for test initialization. Everything below here is
|
||||
|
@ -82,6 +100,10 @@ async function getTokenAccount(provider, addr) {
|
|||
return await serumCmn.getTokenAccount(provider, addr);
|
||||
}
|
||||
|
||||
async function getMintInfo(provider, mintAddr) {
|
||||
return await serumCmn.getMintInfo(provider, mintAddr);
|
||||
}
|
||||
|
||||
async function createMint(provider, authority) {
|
||||
if (authority === undefined) {
|
||||
authority = provider.wallet.publicKey;
|
||||
|
|
|
@ -126,6 +126,35 @@ pub fn initialize_account<'a, 'b, 'c, 'info>(
|
|||
)
|
||||
}
|
||||
|
||||
pub fn set_authority<'a, 'b, 'c, 'info>(
|
||||
ctx: CpiContext<'a, 'b, 'c, 'info, SetAuthority<'info>>,
|
||||
authority_type: spl_token::instruction::AuthorityType,
|
||||
new_authority: Option<Pubkey>,
|
||||
) -> ProgramResult {
|
||||
let mut spl_new_authority: Option<&Pubkey> = None;
|
||||
if new_authority.is_some() {
|
||||
spl_new_authority = new_authority.as_ref()
|
||||
}
|
||||
|
||||
let ix = spl_token::instruction::set_authority(
|
||||
&spl_token::ID,
|
||||
ctx.accounts.account_or_mint.key,
|
||||
spl_new_authority,
|
||||
authority_type,
|
||||
ctx.accounts.current_authority.key,
|
||||
&[], // TODO: Support multisig signers.
|
||||
)?;
|
||||
solana_program::program::invoke_signed(
|
||||
&ix,
|
||||
&[
|
||||
ctx.accounts.account_or_mint.clone(),
|
||||
ctx.accounts.current_authority.clone(),
|
||||
ctx.program.clone(),
|
||||
],
|
||||
ctx.signer_seeds,
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Transfer<'info> {
|
||||
pub from: AccountInfo<'info>,
|
||||
|
@ -161,6 +190,12 @@ pub struct InitializeAccount<'info> {
|
|||
pub authority: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct SetAuthority<'info> {
|
||||
pub current_authority: AccountInfo<'info>,
|
||||
pub account_or_mint: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TokenAccount(spl_token::state::Account);
|
||||
|
||||
|
|
Loading…
Reference in New Issue