Skip to content

Commit a25080a

Browse files
authored
Merge pull request #12 from NEAR-DevHub/fix-ft-tokens
Fix ft tokens api
2 parents b6968f7 + dcf1a10 commit a25080a

File tree

1 file changed

+97
-10
lines changed

1 file changed

+97
-10
lines changed

src/ft-tokens.ts

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
1089
export 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

Comments
 (0)