Skip to main content

typhoon_token/
lib.rs

1#![no_std]
2
3use {
4    core::{mem::transmute, ops::Deref},
5    pinocchio_associated_token_account::ID as ATA_PROGRAM_ID,
6    pinocchio_token::{
7        state::{Mint as SplMint, TokenAccount as SplTokenAccount},
8        ID as TOKEN_PROGRAM_ID,
9    },
10    solana_address::Address,
11    typhoon_accounts::RefFromBytes,
12    typhoon_traits::{Discriminator, Owner, Owners, ProgramId, ProgramIds},
13};
14
15mod traits;
16
17pub use {
18    pinocchio_associated_token_account::instructions as ata_instructions,
19    pinocchio_token::instructions as spl_instructions, traits::*,
20};
21
22const TOKEN_2022_PROGRAM_ID: Address =
23    Address::from_str_const("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
24
25pub struct AtaTokenProgram;
26
27impl ProgramId for AtaTokenProgram {
28    const ID: Address = ATA_PROGRAM_ID;
29}
30
31pub struct TokenProgram;
32
33impl ProgramId for TokenProgram {
34    const ID: Address = TOKEN_PROGRAM_ID;
35}
36
37impl ProgramIds for TokenProgram {
38    const IDS: &'static [Address] = &[TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID];
39}
40
41#[repr(transparent)]
42pub struct Mint(SplMint);
43
44impl Mint {
45    pub const LEN: usize = SplMint::LEN;
46}
47
48impl RefFromBytes for Mint {
49    fn read(data: &[u8]) -> Option<&Self> {
50        Some(unsafe { transmute::<&SplMint, &Mint>(SplMint::from_bytes_unchecked(data)) })
51    }
52
53    fn read_mut(_data: &mut [u8]) -> Option<&mut Self> {
54        unimplemented!()
55    }
56}
57
58impl Discriminator for Mint {
59    const DISCRIMINATOR: &'static [u8] = &[];
60}
61
62impl Owner for Mint {
63    const OWNER: Address = TOKEN_PROGRAM_ID;
64}
65
66impl Owners for Mint {
67    const OWNERS: &'static [Address] = &[TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID];
68}
69
70impl Deref for Mint {
71    type Target = SplMint;
72
73    fn deref(&self) -> &Self::Target {
74        &self.0
75    }
76}
77
78#[repr(transparent)]
79pub struct TokenAccount(SplTokenAccount);
80
81impl TokenAccount {
82    pub const LEN: usize = SplTokenAccount::LEN;
83}
84
85impl RefFromBytes for TokenAccount {
86    fn read(data: &[u8]) -> Option<&Self> {
87        Some(unsafe {
88            transmute::<&SplTokenAccount, &TokenAccount>(SplTokenAccount::from_bytes_unchecked(
89                data,
90            ))
91        })
92    }
93
94    fn read_mut(_data: &mut [u8]) -> Option<&mut Self> {
95        unimplemented!()
96    }
97}
98
99impl Discriminator for TokenAccount {
100    const DISCRIMINATOR: &'static [u8] = &[];
101}
102
103impl Owner for TokenAccount {
104    const OWNER: Address = TOKEN_PROGRAM_ID;
105}
106
107impl Owners for TokenAccount {
108    const OWNERS: &'static [Address] = &[TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID];
109}
110
111impl Deref for TokenAccount {
112    type Target = SplTokenAccount;
113
114    fn deref(&self) -> &Self::Target {
115        &self.0
116    }
117}
118
119pub fn find_associated_token_address(mint: &Address, owner: &Address) -> Address {
120    Address::find_program_address(
121        &[owner.as_ref(), TOKEN_PROGRAM_ID.as_ref(), mint.as_ref()],
122        &ATA_PROGRAM_ID,
123    )
124    .0
125}