@@ -1716,11 +1716,8 @@ impl Indexer for PhotonIndexer {
17161716}
17171717
17181718// ============ Interface Methods ============
1719- // These methods use the Interface endpoints that race hot (on-chain) and cold (compressed) lookups
1720-
1719+ // These methods use the Interface endpoints that race hot (on-chain) and cold (compressed) lookups.
17211720impl PhotonIndexer {
1722- /// Get account data from either on-chain or compressed sources.
1723- /// Races both lookups and returns the result with the higher slot.
17241721 pub async fn get_account_interface (
17251722 & self ,
17261723 address : & Pubkey ,
@@ -1764,99 +1761,46 @@ impl PhotonIndexer {
17641761 . await
17651762 }
17661763
1767- /// Get token account data from either on-chain or compressed sources.
1768- /// Races both lookups and returns the result with the higher slot.
17691764 pub async fn get_token_account_interface (
17701765 & self ,
17711766 address : & Pubkey ,
17721767 config : Option < IndexerRpcConfig > ,
17731768 ) -> Result < Response < Option < TokenAccountInterface > > , IndexerError > {
1774- let config = config. unwrap_or_default ( ) ;
1775- self . retry ( config. retry_config , || async {
1776- let params = photon_api:: types:: PostGetTokenAccountInterfaceBodyParams {
1777- address : photon_api:: types:: SerializablePubkey ( address. to_string ( ) ) ,
1778- } ;
1779- let request =
1780- photon_api:: apis:: default_api:: make_get_token_account_interface_body ( params) ;
1781-
1782- let result = photon_api:: apis:: default_api:: get_token_account_interface_post (
1783- & self . configuration ,
1784- request,
1785- )
1786- . await ?;
1787-
1788- let api_response = Self :: extract_result_with_error_check (
1789- "get_token_account_interface" ,
1790- result. error ,
1791- result. result ,
1792- ) ?;
1793-
1794- if api_response. context . slot < config. slot {
1795- return Err ( IndexerError :: IndexerNotSyncedToSlot ) ;
1769+ let response = self . get_account_interface ( address, config) . await ?;
1770+ let value = match response. value {
1771+ Some ( ai) => {
1772+ let token = parse_token_data_from_indexer_account ( & ai) ?;
1773+ Some ( TokenAccountInterface { account : ai, token } )
17961774 }
1797-
1798- let account = match api_response. value {
1799- Some ( ref tai) => Some ( TokenAccountInterface :: try_from ( tai) ?) ,
1800- None => None ,
1801- } ;
1802-
1803- Ok ( Response {
1804- context : Context {
1805- slot : api_response. context . slot ,
1806- } ,
1807- value : account,
1808- } )
1775+ None => None ,
1776+ } ;
1777+ Ok ( Response {
1778+ context : response. context ,
1779+ value,
18091780 } )
1810- . await
18111781 }
18121782
1813- /// Get Associated Token Account data from either on-chain or compressed sources.
1814- /// Derives the Light Protocol ATA address from owner+mint, then races hot/cold lookups.
18151783 pub async fn get_associated_token_account_interface (
18161784 & self ,
18171785 owner : & Pubkey ,
18181786 mint : & Pubkey ,
18191787 config : Option < IndexerRpcConfig > ,
18201788 ) -> Result < Response < Option < TokenAccountInterface > > , IndexerError > {
1821- let config = config. unwrap_or_default ( ) ;
1822- self . retry ( config. retry_config , || async {
1823- let params = photon_api:: types:: PostGetAtaInterfaceBodyParams {
1824- owner : photon_api:: types:: SerializablePubkey ( owner. to_string ( ) ) ,
1825- mint : photon_api:: types:: SerializablePubkey ( mint. to_string ( ) ) ,
1826- } ;
1827- let request = photon_api:: apis:: default_api:: make_get_ata_interface_body ( params) ;
1828-
1829- let result =
1830- photon_api:: apis:: default_api:: get_ata_interface_post ( & self . configuration , request)
1831- . await ?;
1832-
1833- let api_response = Self :: extract_result_with_error_check (
1834- "get_associated_token_account_interface" ,
1835- result. error ,
1836- result. result ,
1837- ) ?;
1838-
1839- if api_response. context . slot < config. slot {
1840- return Err ( IndexerError :: IndexerNotSyncedToSlot ) ;
1789+ let ata_address = light_token:: instruction:: get_associated_token_address ( owner, mint) ;
1790+ let response = self . get_account_interface ( & ata_address, config) . await ?;
1791+ let value = match response. value {
1792+ Some ( ai) => {
1793+ let token = parse_token_data_from_indexer_account ( & ai) ?;
1794+ Some ( TokenAccountInterface { account : ai, token } )
18411795 }
1842-
1843- let account = match api_response. value {
1844- Some ( ref tai) => Some ( TokenAccountInterface :: try_from ( tai) ?) ,
1845- None => None ,
1846- } ;
1847-
1848- Ok ( Response {
1849- context : Context {
1850- slot : api_response. context . slot ,
1851- } ,
1852- value : account,
1853- } )
1796+ None => None ,
1797+ } ;
1798+ Ok ( Response {
1799+ context : response. context ,
1800+ value,
18541801 } )
1855- . await
18561802 }
18571803
1858- /// Get multiple account interfaces in a batch.
1859- /// Returns a vector where each element corresponds to an input address.
18601804 pub async fn get_multiple_account_interfaces (
18611805 & self ,
18621806 addresses : Vec < & Pubkey > ,
@@ -1909,3 +1853,19 @@ impl PhotonIndexer {
19091853 . await
19101854 }
19111855}
1856+
1857+ /// Parse token data from an indexer AccountInterface.
1858+ /// For compressed (cold) accounts: borsh-deserializes TokenData from the cold data bytes.
1859+ /// For on-chain (hot) accounts: returns default TokenData (downstream conversion re-parses from SPL layout).
1860+ fn parse_token_data_from_indexer_account (
1861+ ai : & AccountInterface ,
1862+ ) -> Result < light_token:: compat:: TokenData , IndexerError > {
1863+ match & ai. cold {
1864+ Some ( cold) => borsh:: BorshDeserialize :: deserialize ( & mut cold. data . data . as_slice ( ) )
1865+ . map_err ( |e| IndexerError :: decode_error ( "token_data" , e) ) ,
1866+ None => {
1867+ // Hot account — downstream will re-parse from SPL account data directly
1868+ Ok ( light_token:: compat:: TokenData :: default ( ) )
1869+ }
1870+ }
1871+ }
0 commit comments