Skip to content

Commit 5d6cf6e

Browse files
committed
Merge branch 'release/v2.89' of github.com:AmbireTech/ambire-common into release/v2.89
2 parents 112c220 + deb6aff commit 5d6cf6e

9 files changed

Lines changed: 193 additions & 125 deletions

File tree

src/controllers/portfolio/portfolio.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ import {
6161
import {
6262
AccountAssetsState,
6363
AccountState,
64+
ExchangeInfoMap,
6465
ExtendedError,
6566
ExtendedErrorWithLevel,
6667
ExternalAPITokenMarketDataResponse,
@@ -208,6 +209,18 @@ export class PortfolioController extends EventEmitter implements IPortfolioContr
208209

209210
defiPositionsCountOnDisabledNetworks: PositionCountOnDisabledNetworks = {}
210211

212+
exchangeState: {
213+
exchanges: ExchangeInfoMap | null
214+
updatedAt: number | null
215+
isLoading: boolean
216+
retryCount: number
217+
} = {
218+
exchanges: null,
219+
updatedAt: null,
220+
isLoading: false,
221+
retryCount: 0
222+
}
223+
211224
#hasSimulationChanged: Function
212225

213226
constructor(
@@ -294,6 +307,48 @@ export class PortfolioController extends EventEmitter implements IPortfolioContr
294307
})
295308
}
296309

310+
async updateExchangeList() {
311+
if (this.exchangeState.isLoading || this.exchangeState.retryCount >= 5) return
312+
313+
this.exchangeState.isLoading = true
314+
315+
this.emitUpdate()
316+
317+
try {
318+
const response = await this.#fetch('https://cena.ambire.com/api/v3/exchanges')
319+
320+
if (!response.ok) {
321+
throw new Error(`Failed to fetch exchange list: ${response.statusText}`)
322+
}
323+
324+
const exchanges: ExchangeInfoMap = (await response.json()).data
325+
326+
this.exchangeState = {
327+
exchanges,
328+
updatedAt: Date.now(),
329+
isLoading: false,
330+
retryCount: 0
331+
}
332+
} catch (e: any) {
333+
this.exchangeState.isLoading = false
334+
this.exchangeState.retryCount += 1
335+
this.emitError({
336+
level: 'silent',
337+
error: e,
338+
message: `Error while fetching exchange list: ${e.message}`
339+
})
340+
341+
setTimeout(
342+
async () => {
343+
await this.updateExchangeList()
344+
},
345+
10 * 60 * 1000
346+
)
347+
} finally {
348+
this.emitUpdate()
349+
}
350+
}
351+
297352
async #load() {
298353
try {
299354
await this.#networks.initialLoadPromise
@@ -331,6 +386,9 @@ export class PortfolioController extends EventEmitter implements IPortfolioContr
331386
}
332387

333388
this.emitUpdate()
389+
390+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
391+
this.updateExchangeList()
334392
}
335393

336394
#getHasFundedHotAccount(): boolean {
@@ -757,7 +815,8 @@ export class PortfolioController extends EventEmitter implements IPortfolioContr
757815
amount: BigInt(t.amount || 0),
758816
chainId: BigInt(t.chainId || 1),
759817
availableAmount: BigInt(t.availableAmount || 0),
760-
flags: getFlags(res.data, 'gasTank', t.chainId, t.address, t.name, t.symbol)
818+
flags: getFlags(res.data, 'gasTank', t.chainId, t.address, t.name, t.symbol),
819+
marketDataIn: []
761820
}))
762821

763822
accountState.gasTank = {

src/controllers/swapAndBridge/swapAndBridge.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,9 +1468,7 @@ export class SwapAndBridgeController extends EventEmitter implements ISwapAndBri
14681468
canTopUpGasTank: false,
14691469
rewardsType: null
14701470
},
1471-
marketData: {
1472-
marketDataIn: []
1473-
},
1471+
marketDataIn: [],
14741472
priceIn: price ? [{ baseCurrency: 'usd', price }] : []
14751473
}
14761474

src/controllers/transaction/transactionFormState.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,9 +481,7 @@ export class TransactionFormState extends EventEmitter {
481481
canTopUpGasTank: false,
482482
rewardsType: null
483483
},
484-
marketData: {
485-
marketDataIn: []
486-
},
484+
marketDataIn: [],
487485
priceIn: price ? [{ baseCurrency: 'usd', price }] : []
488486
}
489487

src/interfaces/assets.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ export interface TokenMarketDataByCurrency {
1212
/**
1313
* 24-hour trading volume of the token.
1414
*/
15-
volume24h?: number | null
15+
volume24h?: number
1616
/**
1717
* Market capitalization of the token.
1818
*/
19-
marketCap?: number | null
19+
marketCap?: number
2020
/**
2121
* Percentage change in price over the last 24 hours.
2222
*/
23-
change24h?: number | null
24-
}
25-
26-
export type TokenMarketData = {
27-
marketDataIn: TokenMarketDataByCurrency[]
23+
change24h?: number
24+
/**
25+
* Fully diluted valuation of the token
26+
*/
27+
fullyDilutedValuation?: number
2828
/**
29-
* Ids of exchanges where the token is traded.
29+
* The total supply of the token
3030
*/
31-
exchanges?: string[]
31+
totalSupply?: number
3232
}

src/libs/defiPositions/defiPositions.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,7 @@ const enhancePortfolioTokensWithDefiPositions = (
405405
notYetHandledTokensToAdd.push({
406406
amount: asset.amount,
407407
latestAmount: asset.amount,
408-
marketData: {
409-
marketDataIn: []
410-
},
408+
marketDataIn: [],
411409
// Only list the borrowed asset with no price
412410
priceIn:
413411
asset.type === AssetType.Collateral && asset.priceIn ? [asset.priceIn] : [],

src/libs/portfolio/helpers.ts

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import IERC20 from '../../../contracts/compiled/IERC20.json'
66
import gasTankFeeTokens from '../../consts/gasTankFeeTokens'
77
import humanizerInfoRaw from '../../consts/humanizer/humanizerInfo.json'
88
import { PINNED_TOKENS } from '../../consts/pinnedTokens'
9-
import { Price, TokenMarketData } from '../../interfaces/assets'
9+
import { Price } from '../../interfaces/assets'
1010
import { Network } from '../../interfaces/network'
1111
import { RPCProvider } from '../../interfaces/provider'
1212
import { AssetType } from '../defiPositions/types'
@@ -26,7 +26,6 @@ import {
2626
PortfolioNetworkResult,
2727
SuspectedType,
2828
ToBeLearnedAssets,
29-
TokenDataCache,
3029
TokenDataCacheValue,
3130
TokenResult,
3231
TokenValidationResult,
@@ -394,9 +393,9 @@ export const validateERC20Token = async (
394393
let decimals
395394
try {
396395
;[balance, symbol, decimals] = await Promise.all([
397-
erc20.balanceOf(accountId).catch((e) => handleERC20Error(e, 'balance')),
398-
erc20.symbol().catch((e) => handleERC20Error(e, 'symbol')),
399-
erc20.decimals().catch((e) => handleERC20Error(e, 'decimals'))
396+
erc20.balanceOf!(accountId).catch((e) => handleERC20Error(e, 'balance')),
397+
erc20.symbol!().catch((e) => handleERC20Error(e, 'symbol')),
398+
erc20.decimals!().catch((e) => handleERC20Error(e, 'decimals'))
400399
])
401400
} catch (e) {
402401
handleERC20Error(e, 'token validation')
@@ -833,32 +832,34 @@ export const convertApiTokenDataToTokenDataCache = (
833832
if (!tokenData) {
834833
return {
835834
priceIn: [],
836-
marketData: {
837-
marketDataIn: [],
838-
exchanges: []
839-
}
835+
marketDataIn: []
840836
}
841837
}
842838

843839
const baseCurrency = (tokenData.baseCurrency || 'usd') as 'usd' // stop ts from complaining, we only support usd as base currency for now
844840
const price = (tokenData.price || tokenData.usd) as number | undefined
845841

846-
const baseCurrency24hChange = tokenData[`${baseCurrency}_24h_change`] || null
847-
const baseCurrency24hVolume = tokenData[`${baseCurrency}_24h_vol`] || null
848-
const baseCurrencyMarketCap = tokenData[`${baseCurrency}_market_cap`] || null
842+
const baseCurrency24hChange = tokenData[`${baseCurrency}_24h_change`]
843+
const baseCurrency24hVolume = tokenData[`${baseCurrency}_24h_vol`]
844+
const baseCurrencyMarketCap = tokenData[`${baseCurrency}_market_cap`]
845+
const fullyDilutedValuation = tokenData[`${baseCurrency}_fully_diluted_valuation`]
846+
const website = tokenData.homepage ? tokenData.homepage[0] : undefined
849847

850848
return {
851849
priceIn: typeof price === 'number' ? [{ baseCurrency, price }] : [],
852-
marketData: {
853-
marketDataIn: [
854-
{
855-
baseCurrency,
856-
change24h: baseCurrency24hChange,
857-
volume24h: baseCurrency24hVolume,
858-
marketCap: baseCurrencyMarketCap
859-
}
860-
],
861-
exchanges: tokenData.exchanges || []
850+
marketDataIn: [
851+
{
852+
baseCurrency,
853+
change24h: baseCurrency24hChange,
854+
volume24h: baseCurrency24hVolume,
855+
marketCap: baseCurrencyMarketCap,
856+
fullyDilutedValuation: fullyDilutedValuation,
857+
totalSupply: tokenData.total_supply
858+
}
859+
],
860+
meta: {
861+
exchanges: tokenData.exchanges || [],
862+
website: website
862863
}
863864
}
864865
}

src/libs/portfolio/interfaces.ts

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AccountId, AccountOnchainState } from '../../interfaces/account'
2-
import { Price, TokenMarketData } from '../../interfaces/assets'
2+
import { Price, TokenMarketDataByCurrency } from '../../interfaces/assets'
33
import { BaseAccount } from '../account/BaseAccount'
44
import { AccountOp } from '../accountOp/accountOp'
55
import {
@@ -21,6 +21,17 @@ export type TokenError = string | '0x'
2121
export type AccountAssetsState = { [chainId: string]: boolean }
2222
export type SuspectedType = 'suspected' | null
2323

24+
export type ExchangeInfo = {
25+
id: string
26+
name: string
27+
url: string
28+
image: string
29+
}
30+
31+
export type ExchangeInfoMap = {
32+
[exchangeId: string]: ExchangeInfo
33+
}
34+
2435
export type TokenResult = {
2536
symbol: string
2637
name: string
@@ -33,7 +44,14 @@ export type TokenResult = {
3344
simulationAmount?: bigint
3445
amountPostSimulation?: bigint
3546
priceIn: Price[]
36-
marketData: TokenMarketData
47+
marketDataIn: TokenMarketDataByCurrency[]
48+
meta?: {
49+
/**
50+
* Ids of exchanges where the token is traded.
51+
*/
52+
exchanges?: string[]
53+
website?: string
54+
}
3755
flags: {
3856
onGasTank: boolean
3957
rewardsType: 'wallet-vesting' | 'wallet-rewards' | 'wallet-projected-rewards' | null
@@ -67,10 +85,7 @@ export interface CollectionResult extends TokenResult {
6785
}
6886
}
6987

70-
export type TokenDataCacheValue = {
71-
priceIn: Price[]
72-
marketData: TokenMarketData
73-
}
88+
export type TokenDataCacheValue = Pick<TokenResult, 'marketDataIn' | 'priceIn' | 'meta'>
7489

7590
/**
7691
* Cache for token data
@@ -121,10 +136,13 @@ export type ExternalAPITokenMarketDataResponse = {
121136
/**
122137
* Despite the name, this is a percentage, not USD value change.
123138
*/
139+
usd_fully_diluted_valuation?: number
124140
usd_24h_change: number
125141
usd_market_cap: number
126142
usd_24h_vol: number
143+
total_supply?: number
127144
exchanges: string[]
145+
homepage?: string[]
128146
}
129147

130148
/**

0 commit comments

Comments
 (0)