Assertions
Assert Token Account
AssertTokenAccount Instruction
The AssertTokenAccount instruction is for making assertions on the fields of a spl-token token account struct.
This could also be accomplished by using the AssertAccountData instruction, but this instruction is a convenience instruction for token accounts which checks that the account is owned by the spl-token program and maps enums to offset / type deserialization.
Below are the types of assertions you can make about a token account:
pub enum TokenAccountAssertion {
Mint {
value: Pubkey,
operator: EquatableOperator,
},
Owner {
value: Pubkey,
operator: EquatableOperator,
},
Amount {
value: u64,
operator: IntegerOperator,
},
Delegate {
value: Option<Pubkey>,
operator: EquatableOperator,
},
State {
value: u8,
operator: IntegerOperator,
},
IsNative {
value: Option<u64>,
operator: EquatableOperator,
},
DelegatedAmount {
value: u64,
operator: IntegerOperator,
},
CloseAuthority {
value: Option<Pubkey>,
operator: EquatableOperator,
},
TokenAccountOwnerIsDerived,
}
Note: This instruction will only check that this account is owned by the spl-token program and not the type of account it is. Checking the type of account should be done by the transaction builder.
Example: multi-assertion instruction building showcase.
Assuming there is a token account that looks like the following
let account = Account {
mint: mint_key,
owner: user_key,
amount: 100,
delegate: None,
state: TokenAccountState::Initialized,
is_native: None,
delegated_amount: 0,
close_authority: None,
};
Then, the following example shows how to build an instruction that asserts the token account's data.
Example of the types of assertions there are for the token account
const tx = await pipe(
createTransaction({ version: 0 }),
(tx) =>
appendTransactionInstructions(
[
getAssertTokenAccountMultiInstruction({
targetAccount,
assertions: [
tokenAccountAssertion('Mint', {
value: mintKey,
operator: EquatableOperator.Equal,
}),
tokenAccountAssertion('Owner', {
value: userKey,
operator: EquatableOperator.Equal,
}),
tokenAccountAssertion('Amount', {
value: 100,
operator: IntegerOperator.Equal,
}),
tokenAccountAssertion('Delegate', {
value: null,
operator: EquatableOperator.Equal,
}),
tokenAccountAssertion('State', {
value: 3,
operator: IntegerOperator.NotEqual,
}),
tokenAccountAssertion('IsNative', {
value: null,
operator: EquatableOperator.Equal,
}),
tokenAccountAssertion('DelegatedAmount', {
value: 0,
operator: IntegerOperator.LessThanOrEqual,
}),
tokenAccountAssertion('CloseAuthority', {
value: null,
operator: EquatableOperator.Equal,
}),
tokenAccountAssertion('TokenAccountOwnerIsDerived'),
],
}),
],
tx
),
(tx) => setTransactionFeePayer(userPubkey, tx),
(tx) => setTransactionLifetimeUsingBlockhash(recentBlockhash, tx),
(tx) => signTransaction([userKeyPair], tx)
)
The enum variant TokenAccountOwnerIsDerived is a special assertion that checks if token account's account info key is a PDA using the current owner and the mint as seeds. This is a optimization for saving transaction space since you do not build owner or mint key assertions.