@@ -7,6 +7,85 @@ type FTCache = {
77 set : ( key : string , value : any , ttl : number ) => void ;
88} ;
99
10+ interface FastNearToken {
11+ balance : string ;
12+ contract_id : string ;
13+ last_update_block_height : number ;
14+ }
15+
16+ interface FtMeta {
17+ name : string ;
18+ symbol : string ;
19+ decimals : number ;
20+ icon ?: string ;
21+ reference ?: string | null ;
22+ price ?: number ;
23+ }
24+
25+ interface FtsToken {
26+ contract : string ;
27+ amount : string ;
28+ ft_meta : FtMeta ;
29+ }
30+
31+ async function updateFtsWithFastNear (
32+ fastnearTokens : FastNearToken [ ] ,
33+ fts : FtsToken [ ]
34+ ) : Promise < FtsToken [ ] > {
35+ const ftsMap = new Map < string , FtsToken > (
36+ fts . map ( ( token ) => [ token . contract , token ] )
37+ ) ;
38+
39+ const missingTokens = fastnearTokens . filter (
40+ ( token ) => ! ftsMap . has ( token . contract_id )
41+ ) ;
42+
43+ const fetchedTokens = await Promise . all (
44+ missingTokens . map ( async ( token ) : Promise < FtsToken | null > => {
45+ try {
46+ const { data } = await axios . get (
47+ `https://api.nearblocks.io/v1/fts/${ token . contract_id } ` ,
48+ {
49+ headers : {
50+ Authorization : `Bearer ${ process . env . NEARBLOCKS_API_KEY } ` ,
51+ } ,
52+ }
53+ ) ;
54+
55+ const contractData = data ?. contracts ?. [ 0 ] ;
56+
57+ if ( ! contractData ) return null ; // Skip if no data
58+
59+ return {
60+ contract : token . contract_id ,
61+ amount : token . balance ,
62+ ft_meta : {
63+ name : contractData . name ,
64+ symbol : contractData . symbol ,
65+ decimals : contractData . decimals ,
66+ icon : contractData . icon || undefined ,
67+ reference : contractData . reference || null ,
68+ price : parseFloat ( contractData . price ) || 0 ,
69+ } ,
70+ } ;
71+ } catch ( error ) {
72+ console . error (
73+ `Failed to fetch metadata for ${ token . contract_id } :` ,
74+ error
75+ ) ;
76+ return null ; // Skip failed requests
77+ }
78+ } )
79+ ) ;
80+
81+ // Add fetched tokens to ftsMap, filtering out any failed requests
82+ fetchedTokens
83+ . filter ( ( token ) : token is FtsToken => token !== null )
84+ . forEach ( ( token ) => ftsMap . set ( token . contract , token ) ) ;
85+
86+ return Array . from ( ftsMap . values ( ) ) ;
87+ }
88+
1089export async function getFTTokens ( account_id : string , cache : FTCache ) {
1190 if ( ! account_id ) {
1291 throw new Error ( "Account ID is required" ) ;
@@ -33,24 +112,32 @@ export async function getFTTokens(account_id: string, cache: FTCache) {
33112 }
34113 ) ;
35114
36- const fts = data ?. inventory ?. fts ;
115+ // sometimes nearblocks doesn't return correct tokens, so to cross check with fastnear
116+ const fastnearResp = await axios . get (
117+ `https://api.fastnear.com/v1/account/${ account_id } /full`
118+ ) ;
119+
120+ const updatedFts = await updateFtsWithFastNear (
121+ fastnearResp ?. data ?. tokens || [ ] ,
122+ data ?. inventory ?. fts || [ ]
123+ ) ;
37124
38- if ( ! fts || ! Array . isArray ( fts ) ) {
125+ if ( ! updatedFts || ! Array . isArray ( updatedFts ) ) {
39126 throw new Error ( "No FT tokens found" ) ;
40127 }
41128
42129 // Sort tokens by value (amount * price) in descending order
43- const sortedFts = fts . sort (
44- ( a , b ) =>
45- parseFloat ( a . amount ) * ( a . ft_meta . price || 0 ) -
46- parseFloat ( b . amount ) * ( b . ft_meta . price || 0 )
130+ const sortedFts = updatedFts . sort (
131+ ( a : any , b : any ) =>
132+ parseFloat ( a . amount ) * ( a . ft_meta ? .price || 0 ) -
133+ parseFloat ( b . amount ) * ( b . ft_meta ? .price || 0 )
47134 ) ;
48135
49136 // Map tokens to compute cumulative amounts
50- const amounts = sortedFts . map ( ( ft ) => {
137+ const amounts = sortedFts . map ( ( ft : any ) => {
51138 const amount = Big ( ft . amount ?? "0" ) ;
52- const decimals = ft . ft_meta . decimals || 0 ;
53- const tokenPrice = ft . ft_meta . price || 0 ;
139+ const decimals = ft . ft_meta ? .decimals || 0 ;
140+ const tokenPrice = ft . ft_meta ? .price || 0 ;
54141
55142 // Format amount and compute value
56143 const tokensNumber = amount . div ( Big ( 10 ) . pow ( decimals ) ) ;
@@ -67,7 +154,7 @@ export async function getFTTokens(account_id: string, cache: FTCache) {
67154 data : {
68155 account_id,
69156 totalCumulativeAmt,
70- fts,
157+ fts : updatedFts as any ,
71158 } ,
72159 } ) ;
73160
0 commit comments