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}