Token type renaming (#70)

This commit is contained in:
Jack May 2020-07-01 01:40:36 -07:00 committed by GitHub
parent b292d4cb3f
commit fc7a808461
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 236 additions and 240 deletions

View File

@ -11,7 +11,7 @@ import { newAccountWithLamports } from '../client/util/new-account-with-lamports
import { url } from '../url';
import { sleep } from '../client/util/sleep';
// The following globals are created by `createNewTokenSwap` and used by subsequent tests
// The following globals are created by `createTokenSwap` and used by subsequent tests
// Token swap
let tokenSwap: TokenSwap;
// authority of the token and accounts
@ -116,7 +116,7 @@ export async function createTokenSwap(): Promise<void> {
);
// create pool
[tokenPool, tokenAccountPool] = await Token.createNewToken(
[tokenPool, tokenAccountPool] = await Token.createToken(
connection,
payer,
authority,
@ -128,7 +128,7 @@ export async function createTokenSwap(): Promise<void> {
);
// create token A
[tokenA, tokenAccountA] = await Token.createNewToken(
[tokenA, tokenAccountA] = await Token.createToken(
connection,
payer,
owner.publicKey,
@ -140,7 +140,7 @@ export async function createTokenSwap(): Promise<void> {
);
// create token B
[tokenB, tokenAccountB] = await Token.createNewToken(
[tokenB, tokenAccountB] = await Token.createToken(
connection,
payer,
owner.publicKey,
@ -177,25 +177,25 @@ export async function createTokenSwap(): Promise<void> {
}
export async function deposit(): Promise<void> {
let userAccountA = await tokenA.newAccount(owner.publicKey);
let userAccountA = await tokenA.createAccount(owner.publicKey);
await tokenA.mintTo(owner, userAccountA, USER_AMOUNT);
let delegateAccountA = await tokenA.newAccount(authority, userAccountA);
let delegateAccountA = await tokenA.createAccount(authority, userAccountA);
await tokenA.approve(
owner,
userAccountA,
delegateAccountA,
USER_AMOUNT,
);
let userAccountB = await tokenB.newAccount(owner.publicKey);
let userAccountB = await tokenB.createAccount(owner.publicKey);
await tokenB.mintTo(owner, userAccountB, USER_AMOUNT);
let delegateAccountB = await tokenB.newAccount(authority, userAccountB);
let delegateAccountB = await tokenB.createAccount(authority, userAccountB);
await tokenB.approve(
owner,
userAccountB,
delegateAccountB,
USER_AMOUNT,
);
let newAccountPool = await tokenPool.newAccount(owner.publicKey);
let newAccountPool = await tokenPool.createAccount(owner.publicKey);
const [tokenProgramId,] = await GetPrograms(connection);
await tokenSwap.deposit(
@ -237,9 +237,9 @@ export async function deposit(): Promise<void> {
}
export async function withdraw(): Promise<void> {
let userAccountA = await tokenA.newAccount(owner.publicKey);
let userAccountB = await tokenB.newAccount(owner.publicKey);
let delegateAccountPool = await tokenPool.newAccount(authority, tokenAccountPool);
let userAccountA = await tokenA.createAccount(owner.publicKey);
let userAccountB = await tokenB.createAccount(owner.publicKey);
let delegateAccountPool = await tokenPool.createAccount(authority, tokenAccountPool);
await tokenPool.approve(
owner,
tokenAccountPool,
@ -283,16 +283,16 @@ export async function withdraw(): Promise<void> {
}
export async function swap(): Promise<void> {
let userAccountA = await tokenA.newAccount(owner.publicKey);
let userAccountA = await tokenA.createAccount(owner.publicKey);
await tokenA.mintTo(owner, userAccountA, USER_AMOUNT);
let delegateAccountA = await tokenA.newAccount(authority, userAccountA);
let delegateAccountA = await tokenA.createAccount(authority, userAccountA);
await tokenA.approve(
owner,
userAccountA,
delegateAccountA,
USER_AMOUNT,
);
let userAccountB = await tokenB.newAccount(owner.publicKey);
let userAccountB = await tokenB.createAccount(owner.publicKey);
const [tokenProgramId,] = await GetPrograms(connection);
await tokenSwap.swap(

View File

@ -382,7 +382,7 @@ impl State {
/// Deserializes a spl_token `State`.
pub fn token_deserialize(info: &AccountInfo) -> Result<spl_token::state::Token, Error> {
if let Ok(spl_token::state::State::Token(token)) =
if let Ok(spl_token::state::State::Mint(token)) =
spl_token::state::State::deserialize(&info.data.borrow())
{
Ok(token)
@ -838,7 +838,7 @@ mod tests {
account::Account, account_info::create_is_signer_account_infos, instruction::Instruction,
};
use spl_token::{
instruction::{new_account, new_token, TokenInfo},
instruction::{initialize_account, initialize_mint, TokenInfo},
state::State as SplState,
};
@ -883,7 +883,8 @@ mod tests {
// create pool and pool account
do_process_instruction(
new_account(&program_id, &account_key, &authority_key, &token_key, None).unwrap(),
initialize_account(&program_id, &account_key, &authority_key, &token_key, None)
.unwrap(),
vec![
&mut account_account,
&mut Account::default(),
@ -893,7 +894,7 @@ mod tests {
.unwrap();
let mut authority_account = Account::default();
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token_key,
Some(&account_key),

View File

@ -26,19 +26,20 @@ typedef struct Token_TokenInfo {
*/
typedef enum Token_TokenInstruction_Tag {
/**
* Creates a new token and deposit all the newly minted tokens in an account.
* Initializes a new mint and deposits all the newly minted tokens in an account.
*
* # Accounts expected by this instruction:
*
* 0. `[writable, signer]` New token to create.
* 0. `[writable, signer]` New mint to create.
* 1.
* * If supply is non-zero: `[writable]` Account to hold all the newly minted tokens.
* * If supply is zero: `[]` Owner of the token.
* 2. Optional: `[]` Owner of the token if supply is non-zero, if present then the token allows further minting of tokens.
* * If supply is zero: `[]` Owner of the mint.
* 2. Optional: `[]` Owner of the mint if supply is non-zero, if present then the
* token allows further minting of tokens.
*/
NewToken,
InitializeMint,
/**
* Creates a new account. The new account can either hold tokens or be a delegate
* Initializes a new account. The new account can either hold tokens or be a delegate
* for another account.
*
* # Accounts expected by this instruction:
@ -48,7 +49,7 @@ typedef enum Token_TokenInstruction_Tag {
* 2. `[]` Token this account will be associated with.
* 3. Optional: `[]` Source account that this account will be a delegate for.
*/
NewAccount,
InitializeAccount,
/**
* Transfers tokens from one account to another either directly or via a delegate.
*
@ -104,9 +105,9 @@ typedef enum Token_TokenInstruction_Tag {
Burn,
} Token_TokenInstruction_Tag;
typedef struct Token_NewToken_Body {
typedef struct Token_InitializeMint_Body {
Token_TokenInfo _0;
} Token_NewToken_Body;
} Token_InitializeMint_Body;
typedef struct Token_Transfer_Body {
uint64_t _0;
@ -127,7 +128,7 @@ typedef struct Token_Burn_Body {
typedef struct Token_TokenInstruction {
Token_TokenInstruction_Tag tag;
union {
Token_NewToken_Body new_token;
Token_InitializeMint_Body initialize_mint;
Token_Transfer_Body transfer;
Token_Approve_Body approve;
Token_MintTo_Body mint_to;
@ -163,7 +164,7 @@ typedef struct Token_COption_Pubkey {
} Token_COption_Pubkey;
/**
* Represents a token type identified and identified by its public key. Accounts
* Represents a token type identified by its public key. Accounts
* are associated with a specific token type and only accounts with
* matching types my inter-opt.
*/
@ -173,8 +174,8 @@ typedef struct Token_Token {
*/
Token_TokenInfo info;
/**
* Optional token owner, used to mint new tokens. The owner may only
* be provided during token creation. If no owner is present then the token
* Optional owner, used to mint new tokens. The owner may only
* be provided during mint creation. If no owner is present then the mint
* has a fixed supply and no further tokens may be minted.
*/
Token_COption_Pubkey owner;
@ -220,7 +221,7 @@ typedef struct Token_COption_AccountDelegate {
} Token_COption_AccountDelegate;
/**
* Account that holds or may delegate tokens.
* Account that holds tokens or may delegate tokens.
*/
typedef struct Token_Account {
/**
@ -244,7 +245,7 @@ typedef struct Token_Account {
} Token_Account;
/**
* Token program states.
* Program states.
*/
typedef enum Token_State_Tag {
/**
@ -252,9 +253,9 @@ typedef enum Token_State_Tag {
*/
Unallocated,
/**
* A token type.
* A token mint.
*/
Token,
Mint,
/**
* An account that holds an amount of tokens or was delegated the authority to transfer
* tokens on behalf of another account.
@ -266,9 +267,9 @@ typedef enum Token_State_Tag {
Invalid,
} Token_State_Tag;
typedef struct Token_Token_Body {
typedef struct Token_Mint_Body {
Token_Token _0;
} Token_Token_Body;
} Token_Mint_Body;
typedef struct Token_Account_Body {
Token_Account _0;
@ -277,7 +278,7 @@ typedef struct Token_Account_Body {
typedef struct Token_State {
Token_State_Tag tag;
union {
Token_Token_Body token;
Token_Mint_Body mint;
Token_Account_Body account;
};
} Token_State;

View File

@ -6,8 +6,8 @@
import {
loadTokenProgram,
createNewToken,
createNewAccount,
createToken,
createAccount,
transfer,
approveRevoke,
invalidApprove,
@ -20,10 +20,10 @@ import {
async function main() {
console.log('Run test: loadTokenProgram');
await loadTokenProgram('../target/bpfel-unknown-unknown/release/spl_token.so');
console.log('Run test: createNewToken');
await createNewToken();
console.log('Run test: createNewAccount');
await createNewAccount();
console.log('Run test: createToken');
await createToken();
console.log('Run test: createAccount');
await createAccount();
console.log('Run test: transfer');
await transfer();
console.log('Run test: approveRevoke');

View File

@ -76,12 +76,12 @@ export async function loadTokenProgram(path: string): Promise<PublicKey> {
return programId;
}
export async function createNewToken(): Promise<void> {
export async function createToken(): Promise<void> {
const connection = await getConnection();
const payer = await newAccountWithLamports(connection, 100000000000 /* wag */);
tokenOwner = new Account();
testAccountOwner = new Account();
[testToken, testAccount] = await Token.createNewToken(
[testToken, testAccount] = await Token.createToken(
connection,
payer,
tokenOwner.publicKey,
@ -92,7 +92,7 @@ export async function createNewToken(): Promise<void> {
false,
);
const tokenInfo = await testToken.getTokenInfo();
const tokenInfo = await testToken.getMintInfo();
assert(tokenInfo.supply.toNumber() == 10000);
assert(tokenInfo.decimals == 2);
assert(tokenInfo.owner == null);
@ -105,13 +105,13 @@ export async function createNewToken(): Promise<void> {
assert(accountInfo.originalAmount.toNumber() == 0);
}
export async function createNewAccount(): Promise<void> {
export async function createAccount(): Promise<void> {
const connection = await getConnection();
const balanceNeeded = await Token.getMinBalanceRentForExemptAccount(
connection,
);
const destOwner = await newAccountWithLamports(connection, balanceNeeded);
const dest = await testToken.newAccount(destOwner.publicKey);
const dest = await testToken.createAccount(destOwner.publicKey);
const accountInfo = await testToken.getAccountInfo(dest);
assert(accountInfo.token.equals(testToken.publicKey));
assert(accountInfo.owner.equals(destOwner.publicKey));
@ -125,13 +125,13 @@ export async function transfer(): Promise<void> {
connection,
);
const destOwner = await newAccountWithLamports(connection, balanceNeeded);
const dest = await testToken.newAccount(destOwner.publicKey);
const dest = await testToken.createAccount(destOwner.publicKey);
await testToken.transfer(testAccountOwner, testAccount, dest, 123);
await sleep(500);
let destTokenAccountInfo = await testToken.getAccountInfo(dest);
assert(destTokenAccountInfo.amount.toNumber() == 123);
let destAccountInfo = await testToken.getAccountInfo(dest);
assert(destAccountInfo.amount.toNumber() == 123);
}
export async function approveRevoke(): Promise<void> {
@ -145,7 +145,7 @@ export async function approveRevoke(): Promise<void> {
connection,
);
const delegateOwner = await newAccountWithLamports(connection, balanceNeeded);
const delegate = await testToken.newAccount(
const delegate = await testToken.createAccount(
delegateOwner.publicKey,
testAccount,
);
@ -182,9 +182,9 @@ export async function invalidApprove(): Promise<void> {
const balanceNeeded =
(await Token.getMinBalanceRentForExemptAccount(connection)) * 3;
const owner = await newAccountWithLamports(connection, balanceNeeded);
const account1 = await testToken.newAccount(owner.publicKey);
const account1Delegate = await testToken.newAccount(owner.publicKey, account1);
const account2 = await testToken.newAccount(owner.publicKey);
const account1 = await testToken.createAccount(owner.publicKey);
const account1Delegate = await testToken.createAccount(owner.publicKey, account1);
const account2 = await testToken.createAccount(owner.publicKey);
// account2 is not a delegate account of account1
assert(didThrow(testToken.approve, [owner, account1, account2, 123]));
@ -197,9 +197,9 @@ export async function failOnApproveOverspend(): Promise<void> {
const balanceNeeded =
(await Token.getMinBalanceRentForExemptAccount(connection)) * 3;
const owner = await newAccountWithLamports(connection, balanceNeeded);
const account1 = await testToken.newAccount(owner.publicKey);
const account1Delegate = await testToken.newAccount(owner.publicKey, account1);
const account2 = await testToken.newAccount(owner.publicKey);
const account1 = await testToken.createAccount(owner.publicKey);
const account1Delegate = await testToken.createAccount(owner.publicKey, account1);
const account2 = await testToken.createAccount(owner.publicKey);
await testToken.transfer(
testAccountOwner,
@ -236,7 +236,7 @@ export async function setOwner(): Promise<void> {
);
const owner = await newAccountWithLamports(connection, balanceNeeded);
const newOwner = await newAccountWithLamports(connection, balanceNeeded);
const owned = await testToken.newAccount(owner.publicKey);
const owned = await testToken.createAccount(owner.publicKey);
await testToken.setOwner(owner, owned, newOwner.publicKey);
assert(didThrow(testToken.setOwner, [owner, owned, newOwner.publicKey]));
@ -248,7 +248,7 @@ export async function mintTo(): Promise<void> {
const payer = await newAccountWithLamports(connection, 100000000000 /* wag */);
const tokenOwner = new Account();
const testAccountOwner = new Account();
const [mintableToken, initialAccount] = await Token.createNewToken(
const [mintableToken, initialAccount] = await Token.createToken(
connection,
payer,
tokenOwner.publicKey,
@ -260,7 +260,7 @@ export async function mintTo(): Promise<void> {
);
{
const tokenInfo = await mintableToken.getTokenInfo();
const tokenInfo = await mintableToken.getMintInfo();
assert(tokenInfo.supply.toNumber() == 10000);
assert(tokenInfo.decimals == 2);
if (tokenInfo.owner === null) {
@ -277,11 +277,11 @@ export async function mintTo(): Promise<void> {
assert(accountInfo.originalAmount.toNumber() == 0);
}
const dest = await mintableToken.newAccount(testAccountOwner.publicKey);
const dest = await mintableToken.createAccount(testAccountOwner.publicKey);
await mintableToken.mintTo(tokenOwner, dest, 42);
{
const tokenInfo = await mintableToken.getTokenInfo();
const tokenInfo = await mintableToken.getMintInfo();
assert(tokenInfo.supply.toNumber() == 10042);
assert(tokenInfo.decimals == 2);
if (tokenInfo.owner === null) {
@ -300,7 +300,7 @@ export async function mintTo(): Promise<void> {
}
export async function burn(): Promise<void> {
let tokenInfo = await testToken.getTokenInfo();
let tokenInfo = await testToken.getMintInfo();
const supply = tokenInfo.supply.toNumber();
let accountInfo = await testToken.getAccountInfo(testAccount);
const amount = accountInfo.amount.toNumber();
@ -308,7 +308,7 @@ export async function burn(): Promise<void> {
await testToken.burn(testAccountOwner, testAccount, 1);
await sleep(500);
tokenInfo = await testToken.getTokenInfo();
tokenInfo = await testToken.getMintInfo();
assert(tokenInfo.supply.toNumber() == supply - 1);
accountInfo = await testToken.getAccountInfo(testAccount);
assert(accountInfo.amount.toNumber() == amount - 1);

View File

@ -56,7 +56,7 @@ export class TokenAmount extends BN {
/**
* Information about a token
*/
type TokenInfo = {|
type MintInfo = {|
/**
* Total supply of tokens
*/
@ -72,7 +72,7 @@ type TokenInfo = {|
owner: null | PublicKey,
|};
const TokenInfoLayout = BufferLayout.struct([
const MintLayout = BufferLayout.struct([
BufferLayout.u8('state'),
Layout.uint64('supply'),
BufferLayout.nu64('decimals'),
@ -119,7 +119,7 @@ type AccountInfo = {|
/**
* @private
*/
const AccountInfoLayout = BufferLayout.struct([
const AccountLayout = BufferLayout.struct([
BufferLayout.u8('state'),
Layout.publicKey('token'),
Layout.publicKey('owner'),
@ -177,7 +177,7 @@ export class Token {
connection: Connection,
): Promise<number> {
return await connection.getMinimumBalanceForRentExemption(
TokenInfoLayout.span,
MintLayout.span,
);
}
@ -190,12 +190,12 @@ export class Token {
connection: Connection,
): Promise<number> {
return await connection.getMinimumBalanceForRentExemption(
AccountInfoLayout.span,
AccountLayout.span,
);
}
/**
* Create a new Token
* Creates and initializes a token.
*
* @param connection The connection to use
* @param owner User account that will own the returned account
@ -204,7 +204,7 @@ export class Token {
* @param programId Optional token programId, uses the system programId by default
* @return Token object for the newly minted token, Public key of the account holding the total supply of new tokens
*/
static async createNewToken(
static async createToken(
connection: Connection,
payer: Account,
tokenOwner: PublicKey,
@ -217,7 +217,7 @@ export class Token {
let transaction;
const tokenAccount = new Account();
const token = new Token(connection, tokenAccount.publicKey, programId, payer);
const initialAccountPublicKey = await token.newAccount(accountOwner, null);
const initialAccountPublicKey = await token.createAccount(accountOwner, null);
// Allocate memory for the account
const balanceNeeded = await Token.getMinBalanceRentForExemptToken(
@ -227,7 +227,7 @@ export class Token {
fromPubkey: payer.publicKey,
newAccountPubkey: tokenAccount.publicKey,
lamports: balanceNeeded,
space: TokenInfoLayout.span,
space: MintLayout.span,
programId,
});
await sendAndConfirmTransaction(
@ -257,7 +257,7 @@ export class Token {
{
const encodeLength = commandDataLayout.encode(
{
instruction: 0, // NewToken instruction
instruction: 0, // InitializeToken instruction
supply: supply.toBuffer(),
decimals,
},
@ -272,7 +272,7 @@ export class Token {
data,
});
await sendAndConfirmTransaction(
'New Account',
'InitializeToken',
connection,
transaction,
payer,
@ -288,7 +288,7 @@ export class Token {
}
/**
* Create a new and empty account.
* Create and initializes a new account.
*
* This account may then be used as a `transfer()` or `approve()` destination
*
@ -297,7 +297,7 @@ export class Token {
* may transfer tokens from this `source` account
* @return Public key of the new empty account
*/
async newAccount(
async createAccount(
owner: PublicKey,
source: null | PublicKey = null,
): Promise<PublicKey> {
@ -308,12 +308,11 @@ export class Token {
const balanceNeeded = await Token.getMinBalanceRentForExemptAccount(
this.connection,
);
transaction = SystemProgram.createAccount({
fromPubkey: this.payer.publicKey,
newAccountPubkey: tokenAccount.publicKey,
lamports: balanceNeeded,
space: AccountInfoLayout.span,
space: AccountLayout.span,
programId: this.programId,
});
await sendAndConfirmTransaction(
@ -337,7 +336,7 @@ export class Token {
const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
instruction: 1, // NewAccount instruction
instruction: 1, // InitializeAccount instruction
},
data,
);
@ -347,7 +346,7 @@ export class Token {
data,
});
await sendAndConfirmTransaction(
'new account',
'InitializeAccount',
this.connection,
transaction,
this.payer,
@ -360,30 +359,30 @@ export class Token {
/**
* Retrieve token information
*/
async getTokenInfo(): Promise<TokenInfo> {
const accountInfo = await this.connection.getAccountInfo(this.publicKey);
if (accountInfo === null) {
async getMintInfo(): Promise<MintInfo> {
const info = await this.connection.getAccountInfo(this.publicKey);
if (info === null) {
throw new Error('Failed to find token info account');
}
if (!accountInfo.owner.equals(this.programId)) {
if (!info.owner.equals(this.programId)) {
throw new Error(
`Invalid token owner: ${JSON.stringify(accountInfo.owner)}`,
`Invalid token owner: ${JSON.stringify(info.owner)}`,
);
}
const data = Buffer.from(accountInfo.data);
const data = Buffer.from(info.data);
const tokenInfo = TokenInfoLayout.decode(data);
if (tokenInfo.state !== 1) {
const mintInfo = MintLayout.decode(data);
if (mintInfo.state !== 1) {
throw new Error(`Invalid account data`);
}
tokenInfo.supply = TokenAmount.fromBuffer(tokenInfo.supply);
if (tokenInfo.option === 0) {
tokenInfo.owner = null;
mintInfo.supply = TokenAmount.fromBuffer(mintInfo.supply);
if (mintInfo.option === 0) {
mintInfo.owner = null;
} else {
tokenInfo.owner = new PublicKey(tokenInfo.owner);
mintInfo.owner = new PublicKey(mintInfo.owner);
}
return tokenInfo;
return mintInfo;
}
/**
@ -392,41 +391,41 @@ export class Token {
* @param account Public key of the account
*/
async getAccountInfo(account: PublicKey): Promise<AccountInfo> {
const accountInfo = await this.connection.getAccountInfo(account);
if (accountInfo === null) {
const info = await this.connection.getAccountInfo(account);
if (info === null) {
throw new Error('Failed to find account');
}
if (!accountInfo.owner.equals(this.programId)) {
if (!info.owner.equals(this.programId)) {
throw new Error(`Invalid account owner`);
}
const data = Buffer.from(accountInfo.data);
const tokenAccountInfo = AccountInfoLayout.decode(data);
const data = Buffer.from(info.data);
const accountInfo = AccountLayout.decode(data);
if (tokenAccountInfo.state !== 2) {
if (accountInfo.state !== 2) {
throw new Error(`Invalid account data`);
}
tokenAccountInfo.token = new PublicKey(tokenAccountInfo.token);
tokenAccountInfo.owner = new PublicKey(tokenAccountInfo.owner);
tokenAccountInfo.amount = TokenAmount.fromBuffer(tokenAccountInfo.amount);
if (tokenAccountInfo.option === 0) {
tokenAccountInfo.source = null;
tokenAccountInfo.originalAmount = new TokenAmount();
accountInfo.token = new PublicKey(accountInfo.token);
accountInfo.owner = new PublicKey(accountInfo.owner);
accountInfo.amount = TokenAmount.fromBuffer(accountInfo.amount);
if (accountInfo.option === 0) {
accountInfo.source = null;
accountInfo.originalAmount = new TokenAmount();
} else {
tokenAccountInfo.source = new PublicKey(tokenAccountInfo.source);
tokenAccountInfo.originalAmount = TokenAmount.fromBuffer(
tokenAccountInfo.originalAmount,
accountInfo.source = new PublicKey(accountInfo.source);
accountInfo.originalAmount = TokenAmount.fromBuffer(
accountInfo.originalAmount,
);
}
if (!tokenAccountInfo.token.equals(this.publicKey)) {
if (!accountInfo.token.equals(this.publicKey)) {
throw new Error(
`Invalid account token: ${JSON.stringify(
tokenAccountInfo.token,
accountInfo.token,
)} !== ${JSON.stringify(this.publicKey)}`,
);
}
return tokenAccountInfo;
return accountInfo;
}
/**

View File

@ -9,7 +9,7 @@ use solana_sdk::{
};
use thiserror::Error;
/// Errors that may be returned by the Token program
/// Errors that may be returned by the Token program.
#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
pub enum TokenError {
/// Insufficient funds for the operation requested.
@ -37,19 +37,16 @@ pub enum TokenError {
#[error("An owner is required if supply is zero")]
OwnerRequiredIfNoInitialSupply,
}
impl From<TokenError> for ProgramError {
fn from(e: TokenError) -> Self {
ProgramError::Custom(e as u32)
}
}
impl<T> DecodeError<T> for TokenError {
fn type_of() -> &'static str {
"TokenError"
}
}
impl PrintProgramError for TokenError {
fn print<E>(&self)
where

View File

@ -22,17 +22,18 @@ pub struct TokenInfo {
#[repr(C)]
#[derive(Clone, Debug, PartialEq)]
pub enum TokenInstruction {
/// Creates a new token and deposit all the newly minted tokens in an account.
/// Initializes a new mint and deposits all the newly minted tokens in an account.
///
/// # Accounts expected by this instruction:
///
/// 0. `[writable, signer]` New token to create.
/// 0. `[writable, signer]` New mint to create.
/// 1.
/// * If supply is non-zero: `[writable]` Account to hold all the newly minted tokens.
/// * If supply is zero: `[]` Owner of the token.
/// 2. Optional: `[]` Owner of the token if supply is non-zero, if present then the token allows further minting of tokens.
NewToken(TokenInfo),
/// Creates a new account. The new account can either hold tokens or be a delegate
/// * If supply is zero: `[]` Owner of the mint.
/// 2. Optional: `[]` Owner of the mint if supply is non-zero, if present then the
/// token allows further minting of tokens.
InitializeMint(TokenInfo),
/// Initializes a new account. The new account can either hold tokens or be a delegate
/// for another account.
///
/// # Accounts expected by this instruction:
@ -41,7 +42,7 @@ pub enum TokenInstruction {
/// 1. `[]` Owner of the new account.
/// 2. `[]` Token this account will be associated with.
/// 3. Optional: `[]` Source account that this account will be a delegate for.
NewAccount,
InitializeAccount,
/// Transfers tokens from one account to another either directly or via a delegate.
///
/// # Accounts expected by this instruction:
@ -87,7 +88,7 @@ pub enum TokenInstruction {
Burn(u64),
}
impl TokenInstruction {
/// Deserializes a byte buffer into an [TokenInstruction](enum.TokenInstruction.html)
/// Deserializes a byte buffer into an [TokenInstruction](enum.TokenInstruction.html).
pub fn deserialize(input: &[u8]) -> Result<Self, ProgramError> {
if input.len() < size_of::<u8>() {
return Err(ProgramError::InvalidAccountData);
@ -99,9 +100,9 @@ impl TokenInstruction {
}
#[allow(clippy::cast_ptr_alignment)]
let info: &TokenInfo = unsafe { &*(&input[1] as *const u8 as *const TokenInfo) };
Self::NewToken(*info)
Self::InitializeMint(*info)
}
1 => Self::NewAccount,
1 => Self::InitializeAccount,
2 => {
if input.len() < size_of::<u8>() + size_of::<u64>() {
return Err(ProgramError::InvalidAccountData);
@ -139,17 +140,17 @@ impl TokenInstruction {
})
}
/// Serializes an [TokenInstruction](enum.TokenInstruction.html) into a byte buffer
/// Serializes an [TokenInstruction](enum.TokenInstruction.html) into a byte buffer.
pub fn serialize(self: &Self) -> Result<Vec<u8>, ProgramError> {
let mut output = vec![0u8; size_of::<TokenInstruction>()];
match self {
Self::NewToken(info) => {
Self::InitializeMint(info) => {
output[0] = 0;
#[allow(clippy::cast_ptr_alignment)]
let value = unsafe { &mut *(&mut output[1] as *mut u8 as *mut TokenInfo) };
*value = *info;
}
Self::NewAccount => output[0] = 1,
Self::InitializeAccount => output[0] = 1,
Self::Transfer(amount) => {
output[0] = 2;
#[allow(clippy::cast_ptr_alignment)]
@ -180,15 +181,15 @@ impl TokenInstruction {
}
}
/// Creates a 'NewToken' instruction
pub fn new_token(
/// Creates a 'InitializeMint' instruction.
pub fn initialize_mint(
token_program_id: &Pubkey,
token_pubkey: &Pubkey,
account_pubkey: Option<&Pubkey>,
owner_pubkey: Option<&Pubkey>,
token_info: TokenInfo,
) -> Result<Instruction, ProgramError> {
let data = TokenInstruction::NewToken(token_info).serialize()?;
let data = TokenInstruction::InitializeMint(token_info).serialize()?;
let mut accounts = vec![AccountMeta::new(*token_pubkey, true)];
if token_info.supply != 0 {
@ -215,15 +216,15 @@ pub fn new_token(
})
}
/// Creates a `NewAccount` instruction
pub fn new_account(
/// Creates a `InitializeAccount` instruction.
pub fn initialize_account(
token_program_id: &Pubkey,
account_pubkey: &Pubkey,
owner_pubkey: &Pubkey,
token_pubkey: &Pubkey,
source_pubkey: Option<&Pubkey>,
) -> Result<Instruction, ProgramError> {
let data = TokenInstruction::NewAccount.serialize()?;
let data = TokenInstruction::InitializeAccount.serialize()?;
let mut accounts = vec![
AccountMeta::new(*account_pubkey, true),
@ -241,7 +242,7 @@ pub fn new_account(
})
}
/// Creates a `Transfer` instruction
/// Creates a `Transfer` instruction.
pub fn transfer(
token_program_id: &Pubkey,
owner_pubkey: &Pubkey,
@ -268,7 +269,7 @@ pub fn transfer(
})
}
/// Creates an `Approve` instruction
/// Creates an `Approve` instruction.
pub fn approve(
token_program_id: &Pubkey,
owner_pubkey: &Pubkey,
@ -291,11 +292,7 @@ pub fn approve(
})
}
/// 0. `[signer]` Current owner of the account.
/// 1. `[writable]` account to change the owner of.
/// 2. `[]` New owner of the account.
/// Creates an `SetOwner` instruction
/// Creates an `SetOwner` instruction.
pub fn set_owner(
token_program_id: &Pubkey,
owner_pubkey: &Pubkey,
@ -317,7 +314,7 @@ pub fn set_owner(
})
}
/// Creates an `MintTo` instruction
/// Creates an `MintTo` instruction.
pub fn mint_to(
token_program_id: &Pubkey,
owner_pubkey: &Pubkey,
@ -340,7 +337,7 @@ pub fn mint_to(
})
}
/// Creates an `Burn` instruction
/// Creates an `Burn` instruction.
pub fn burn(
token_program_id: &Pubkey,
owner_pubkey: &Pubkey,

View File

@ -11,7 +11,7 @@ use solana_sdk::{
};
use std::mem::size_of;
/// Represents a token type identified and identified by its public key. Accounts
/// Represents a token type identified by its public key. Accounts
/// are associated with a specific token type and only accounts with
/// matching types my inter-opt.
#[repr(C)]
@ -19,8 +19,8 @@ use std::mem::size_of;
pub struct Token {
/// The total supply of tokens.
pub info: TokenInfo,
/// Optional token owner, used to mint new tokens. The owner may only
/// be provided during token creation. If no owner is present then the token
/// Optional owner, used to mint new tokens. The owner may only
/// be provided during mint creation. If no owner is present then the mint
/// has a fixed supply and no further tokens may be minted.
pub owner: COption<Pubkey>,
}
@ -35,7 +35,7 @@ pub struct AccountDelegate {
pub original_amount: u64,
}
/// Account that holds or may delegate tokens.
/// Account that holds tokens or may delegate tokens.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Account {
@ -51,14 +51,14 @@ pub struct Account {
pub delegate: COption<AccountDelegate>,
}
/// Token program states.
/// Program states.
#[repr(C)]
#[derive(Clone, Debug, PartialEq)]
pub enum State {
/// Unallocated state, may be initialized into another state.
Unallocated,
/// A token type.
Token(Token),
/// A token mint.
Mint(Token),
/// An account that holds an amount of tokens or was delegated the authority to transfer
/// tokens on behalf of another account.
Account(Account),
@ -70,10 +70,9 @@ impl Default for State {
Self::Unallocated
}
}
impl State {
/// Processes a [NewToken](enum.TokenInstruction.html) instruction.
pub fn process_new_token(accounts: &[AccountInfo], info: TokenInfo) -> ProgramResult {
/// Processes a [InitializeMint](enum.TokenInstruction.html) instruction.
pub fn process_initialize_mint(accounts: &[AccountInfo], info: TokenInfo) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let token_account_info = next_account_info(account_info_iter)?;
@ -113,23 +112,23 @@ impl State {
return Err(TokenError::OwnerRequiredIfNoInitialSupply.into());
};
State::Token(Token { info, owner }).serialize(&mut token_account_info.data.borrow_mut())
State::Mint(Token { info, owner }).serialize(&mut token_account_info.data.borrow_mut())
}
/// Processes a [NewAccount](enum.TokenInstruction.html) instruction.
pub fn process_new_account(accounts: &[AccountInfo]) -> ProgramResult {
/// Processes a [InitializeAccount](enum.TokenInstruction.html) instruction.
pub fn process_initialize_account(accounts: &[AccountInfo]) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let new_account_info = next_account_info(account_info_iter)?;
let initialize_account_info = next_account_info(account_info_iter)?;
let owner_account_info = next_account_info(account_info_iter)?;
let token_account_info = next_account_info(account_info_iter)?;
if !new_account_info.is_signer {
if !initialize_account_info.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
let mut new_account_data = new_account_info.data.borrow_mut();
let mut initialize_account_data = initialize_account_info.data.borrow_mut();
if State::Unallocated != State::deserialize(&new_account_data)? {
if State::Unallocated != State::deserialize(&initialize_account_data)? {
return Err(TokenError::AlreadyInUse.into());
}
@ -146,7 +145,7 @@ impl State {
});
}
State::Account(token_account).serialize(&mut new_account_data)
State::Account(token_account).serialize(&mut initialize_account_data)
}
/// Processes a [Transfer](enum.TokenInstruction.html) instruction.
@ -279,7 +278,7 @@ impl State {
account.owner = *new_owner_account_info.key;
State::Account(account).serialize(&mut account_data)?;
}
State::Token(mut token) => {
State::Mint(mut token) => {
if COption::Some(*owner_account_info.key) != token.owner {
return Err(TokenError::NoOwner.into());
}
@ -288,7 +287,7 @@ impl State {
}
token.owner = COption::Some(*new_owner_account_info.key);
State::Token(token).serialize(&mut account_data)?;
State::Mint(token).serialize(&mut account_data)?;
}
_ => {
return Err(ProgramError::InvalidArgument);
@ -298,7 +297,7 @@ impl State {
}
/// Processes a [MintTo](enum.TokenInstruction.html) instruction.
pub fn process_mintto(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
pub fn process_mint_to(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
let account_info_iter = &mut accounts.iter();
let owner_account_info = next_account_info(account_info_iter)?;
let token_account_info = next_account_info(account_info_iter)?;
@ -309,7 +308,7 @@ impl State {
}
let mut token_account_data = token_account_info.data.borrow_mut();
if let State::Token(mut token) = State::deserialize(&token_account_data)? {
if let State::Mint(mut token) = State::deserialize(&token_account_data)? {
match token.owner {
COption::Some(owner) => {
if *owner_account_info.key != owner {
@ -332,7 +331,7 @@ impl State {
}
token.info.supply += amount;
State::Token(token).serialize(&mut token_account_data)?;
State::Mint(token).serialize(&mut token_account_data)?;
dest_token_account.amount = amount;
State::Account(dest_token_account).serialize(&mut dest_account_data)?;
@ -362,10 +361,10 @@ impl State {
}
};
let (mut token_account, mut token_data) = {
let (mut token, mut token_data) = {
let token_data = token_account_info.data.borrow_mut();
match State::deserialize(&token_data)? {
State::Token(token_account) => (token_account, token_data),
State::Mint(token) => (token, token_data),
_ => {
return Err(ProgramError::InvalidArgument);
}
@ -409,8 +408,8 @@ impl State {
source_account.amount -= amount;
State::Account(source_account).serialize(&mut source_data)?;
token_account.info.supply -= amount;
State::Token(token_account).serialize(&mut token_data)?;
token.info.supply -= amount;
State::Mint(token).serialize(&mut token_data)?;
Ok(())
}
@ -419,13 +418,13 @@ impl State {
let instruction = TokenInstruction::deserialize(input)?;
match instruction {
TokenInstruction::NewToken(info) => {
info!("Instruction: NewToken");
Self::process_new_token(accounts, info)
TokenInstruction::InitializeMint(info) => {
info!("Instruction: InitializeMint");
Self::process_initialize_mint(accounts, info)
}
TokenInstruction::NewAccount => {
info!("Instruction: NewAccount");
Self::process_new_account(accounts)
TokenInstruction::InitializeAccount => {
info!("Instruction: InitializeAccount");
Self::process_initialize_account(accounts)
}
TokenInstruction::Transfer(amount) => {
info!("Instruction: Transfer");
@ -441,7 +440,7 @@ impl State {
}
TokenInstruction::MintTo(amount) => {
info!("Instruction: MintTo");
Self::process_mintto(accounts, amount)
Self::process_mint_to(accounts, amount)
}
TokenInstruction::Burn(amount) => {
info!("Instruction: Burn");
@ -450,7 +449,7 @@ impl State {
}
}
/// Deserializes a byte buffer into a Token Program [State](struct.State.html)
/// Deserializes a byte buffer into a Token Program [State](struct.State.html).
pub fn deserialize(input: &[u8]) -> Result<Self, ProgramError> {
if input.len() < size_of::<u8>() {
return Err(ProgramError::InvalidAccountData);
@ -463,7 +462,7 @@ impl State {
}
#[allow(clippy::cast_ptr_alignment)]
let token: &Token = unsafe { &*(&input[1] as *const u8 as *const Token) };
Self::Token(*token)
Self::Mint(*token)
}
2 => {
if input.len() < size_of::<u8>() + size_of::<Account>() {
@ -478,14 +477,14 @@ impl State {
})
}
/// Serializes Token Program [State](struct.State.html) into a byte buffer
/// Serializes Token Program [State](struct.State.html) into a byte buffer.
pub fn serialize(self: &Self, output: &mut [u8]) -> ProgramResult {
if output.len() < size_of::<u8>() {
return Err(ProgramError::InvalidAccountData);
}
match self {
Self::Unallocated => output[0] = 0,
Self::Token(token) => {
Self::Mint(token) => {
if output.len() < size_of::<u8>() + size_of::<Token>() {
return Err(ProgramError::InvalidAccountData);
}
@ -509,14 +508,16 @@ impl State {
}
}
// Pulls in the stubs required for `info!()`
// Pulls in the stubs required for `info!()`.
#[cfg(not(target_arch = "bpf"))]
solana_sdk_bpf_test::stubs!();
#[cfg(test)]
mod tests {
use super::*;
use crate::instruction::{approve, burn, mint_to, new_account, new_token, set_owner, transfer};
use crate::instruction::{
approve, burn, initialize_account, initialize_mint, mint_to, set_owner, transfer,
};
use solana_sdk::{
account::Account, account_info::create_is_signer_account_infos, instruction::Instruction,
};
@ -541,7 +542,7 @@ mod tests {
}
#[test]
fn test_new_token() {
fn test_initialize_mint() {
let program_id = pubkey_rand();
let token_account_key = pubkey_rand();
let mut token_account_account = Account::new(0, size_of::<State>(), &program_id);
@ -560,7 +561,7 @@ mod tests {
assert_eq!(
Err(ProgramError::InvalidArgument),
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token_key,
Some(&token_account_key),
@ -577,7 +578,7 @@ mod tests {
// create account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account_key,
&owner_key,
@ -595,7 +596,7 @@ mod tests {
// create new token
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token_key,
Some(&token_account_key),
@ -612,7 +613,7 @@ mod tests {
// create another account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account2_key,
&owner_key,
@ -632,7 +633,7 @@ mod tests {
assert_eq!(
Err(TokenError::TokenMismatch.into()),
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token2_key,
Some(&token_account2_key),
@ -649,7 +650,7 @@ mod tests {
// create delegate account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&delegate_account_key,
&owner_key,
@ -670,7 +671,7 @@ mod tests {
assert_eq!(
Err(TokenError::AlreadyInUse.into()),
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token_key,
Some(&delegate_account_key),
@ -689,7 +690,7 @@ mod tests {
assert_eq!(
Err(TokenError::AlreadyInUse.into()),
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token_key,
Some(&token_account_key),
@ -706,7 +707,7 @@ mod tests {
}
#[test]
fn test_new_token_account() {
fn test_initialize_mint_account() {
let program_id = pubkey_rand();
let token_account_key = pubkey_rand();
let mut token_account_account = Account::new(0, size_of::<State>(), &program_id);
@ -716,7 +717,7 @@ mod tests {
let mut token_account = Account::new(0, size_of::<State>(), &program_id);
// missing signer
let mut instruction = new_account(
let mut instruction = initialize_account(
&program_id,
&token_account_key,
&owner_key,
@ -739,7 +740,7 @@ mod tests {
// create account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account_key,
&owner_key,
@ -759,7 +760,7 @@ mod tests {
assert_eq!(
Err(TokenError::AlreadyInUse.into()),
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account_key,
&owner_key,
@ -803,7 +804,7 @@ mod tests {
// create account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account_key,
&owner_key,
@ -821,7 +822,7 @@ mod tests {
// create another account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account2_key,
&owner_key,
@ -839,7 +840,7 @@ mod tests {
// create another account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account3_key,
&owner_key,
@ -857,7 +858,7 @@ mod tests {
// create mismatch account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&mismatch_account_key,
&owner_key,
@ -875,7 +876,7 @@ mod tests {
// create delegate account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&delegate_account_key,
&owner_key,
@ -894,7 +895,7 @@ mod tests {
// create mismatch delegate account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&mismatch_delegate_account_key,
&owner_key,
@ -913,7 +914,7 @@ mod tests {
// create new token
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token_key,
Some(&token_account_key),
@ -1267,7 +1268,7 @@ mod tests {
// create account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account_key,
&owner_key,
@ -1283,8 +1284,8 @@ mod tests {
)
.unwrap();
// create mintable token without owner
let mut instruction = new_token(
// create mint-able token without owner
let mut instruction = initialize_mint(
&program_id,
&token_key,
None,
@ -1301,17 +1302,17 @@ mod tests {
do_process_instruction(instruction, vec![&mut token_account])
);
// create mintable token with zero supply
// create mint-able token with zero supply
let info = TokenInfo {
supply: 0,
decimals: 2,
};
do_process_instruction(
new_token(&program_id, &token_key, None, Some(&owner_key), info).unwrap(),
initialize_mint(&program_id, &token_key, None, Some(&owner_key), info).unwrap(),
vec![&mut token_account, &mut token_account_account],
)
.unwrap();
if let State::Token(token) = State::deserialize(&token_account.data).unwrap() {
if let State::Mint(token) = State::deserialize(&token_account.data).unwrap() {
assert_eq!(
token,
Token {
@ -1334,7 +1335,7 @@ mod tests {
)
.unwrap();
if let State::Token(token) = State::deserialize(&token_account.data).unwrap() {
if let State::Mint(token) = State::deserialize(&token_account.data).unwrap() {
assert_eq!(token.info.supply, 42);
} else {
panic!("not an account");
@ -1371,7 +1372,7 @@ mod tests {
// create account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account_key,
&owner_key,
@ -1389,7 +1390,7 @@ mod tests {
// create another account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account2_key,
&owner_key,
@ -1407,7 +1408,7 @@ mod tests {
// create delegate account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&delegate_account_key,
&owner_key,
@ -1426,7 +1427,7 @@ mod tests {
// create mismatch delegate account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&mismatch_delegate_account_key,
&owner_key,
@ -1445,7 +1446,7 @@ mod tests {
// create new token
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token_key,
Some(&token_account_key),
@ -1634,7 +1635,7 @@ mod tests {
// create account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account_key,
&owner_key,
@ -1652,7 +1653,7 @@ mod tests {
// create token account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account2_key,
&owner_key,
@ -1710,7 +1711,7 @@ mod tests {
// create new token with owner
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token_key,
Some(&token_account_key),
@ -1758,7 +1759,7 @@ mod tests {
// create new token without owner
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token2_key,
Some(&token_account2_key),
@ -1773,7 +1774,7 @@ mod tests {
)
.unwrap();
// set owner for unownable token
// set owner for non-mint-able token
assert_eq!(
Err(TokenError::NoOwner.into()),
do_process_instruction(
@ -1809,7 +1810,7 @@ mod tests {
// create token account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account_key,
&owner_key,
@ -1827,7 +1828,7 @@ mod tests {
// create another token account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account2_key,
&owner_key,
@ -1845,7 +1846,7 @@ mod tests {
// create another token account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account3_key,
&owner_key,
@ -1863,7 +1864,7 @@ mod tests {
// create mismatch token account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&mismatch_account_key,
&owner_key,
@ -1881,7 +1882,7 @@ mod tests {
// create delegate account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&delegate_account_key,
&owner_key,
@ -1900,7 +1901,7 @@ mod tests {
// create new token with owner
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token_key,
Some(&token_account_key),
@ -1930,7 +1931,7 @@ mod tests {
)
.unwrap();
if let State::Token(token) = State::deserialize(&token_account.data).unwrap() {
if let State::Mint(token) = State::deserialize(&token_account.data).unwrap() {
assert_eq!(token.info.supply, 1000 + 42);
} else {
panic!("not an account");
@ -2060,7 +2061,7 @@ mod tests {
// create token account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account_key,
&owner_key,
@ -2078,7 +2079,7 @@ mod tests {
// create another token account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account2_key,
&owner_key,
@ -2096,7 +2097,7 @@ mod tests {
// create another token account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&token_account3_key,
&owner_key,
@ -2114,7 +2115,7 @@ mod tests {
// create mismatch token account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&mismatch_account_key,
&owner_key,
@ -2132,7 +2133,7 @@ mod tests {
// create delegate account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&delegate_account_key,
&owner_key,
@ -2150,7 +2151,7 @@ mod tests {
.unwrap();
// create mismatch delegate account
do_process_instruction(
new_account(
initialize_account(
&program_id,
&mismatch_delegate_account_key,
&owner_key,
@ -2169,7 +2170,7 @@ mod tests {
// create new token
do_process_instruction(
new_token(
initialize_mint(
&program_id,
&token_key,
Some(&token_account_key),
@ -2268,7 +2269,7 @@ mod tests {
)
.unwrap();
if let State::Token(token) = State::deserialize(&token_account.data).unwrap() {
if let State::Mint(token) = State::deserialize(&token_account.data).unwrap() {
assert_eq!(token.info.supply, 1000 - 42);
} else {
panic!("not a token account");
@ -2359,7 +2360,7 @@ mod tests {
)
.unwrap();
if let State::Token(token) = State::deserialize(&token_account.data).unwrap() {
if let State::Mint(token) = State::deserialize(&token_account.data).unwrap() {
assert_eq!(token.info.supply, 1000 - 42 - 84);
} else {
panic!("not a token account");