@@ -19,7 +19,7 @@ import { getAccountState } from '../../libs/accountState/accountState'
1919import * as defiPricesLib from '../../libs/defiPositions/defiPrices'
2020import { getProviderId } from '../../libs/defiPositions/helpers'
2121import * as defiProviders from '../../libs/defiPositions/providers'
22- import { DeFiPositionsError } from '../../libs/defiPositions/types'
22+ import { AssetType , DeFiPositionsError } from '../../libs/defiPositions/types'
2323import {
2424 erc721CollectionToLearnedAssetKeys ,
2525 learnedErc721sToHints
@@ -2067,6 +2067,85 @@ describe('Portfolio Controller ', () => {
20672067 restore ( )
20682068 } )
20692069
2070+ it ( "Uniswap V3 shouldn't lose its API enhancement (e.g. rewards) when the discovery call is skipped" , async ( ) => {
2071+ const { controller } = await prepareTest ( )
2072+
2073+ // A formatted discovery response carrying a Debank Uniswap V3 entry. It's mocked rather than
2074+ // relying on the live API, since Debank's coverage of a given account varies over time.
2075+ const discoveryWithDebankUniV3 = {
2076+ data : {
2077+ defi : {
2078+ updatedAt : Date . now ( ) ,
2079+ isForceUpdate : false ,
2080+ positions : [
2081+ {
2082+ providerName : 'Uniswap V3' ,
2083+ chainId : 1n ,
2084+ source : 'debank' as const ,
2085+ iconUrl : '' ,
2086+ siteUrl : 'https://app.uniswap.org' ,
2087+ type : 'common' as const ,
2088+ positions : [
2089+ {
2090+ id : 'debank-uni-v3-eth' ,
2091+ assets : [
2092+ {
2093+ address : '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2' ,
2094+ symbol : 'WETH' ,
2095+ name : 'Wrapped Ether' ,
2096+ decimals : 18 ,
2097+ amount : 1000000000000000000n ,
2098+ priceIn : { price : 3000 , baseCurrency : 'usd' } ,
2099+ value : 3000 ,
2100+ type : AssetType . Liquidity ,
2101+ iconUrl : ''
2102+ }
2103+ ] ,
2104+ additionalData : { positionIndex : 'debank-uni-v3-eth' , name : 'Liquidity Pool' }
2105+ }
2106+ ] ,
2107+ positionInUSD : 3000
2108+ }
2109+ ]
2110+ } ,
2111+ hints : null ,
2112+ otherNetworksDefiCounts : { }
2113+ } ,
2114+ discoveryTime : 1 ,
2115+ errors : [ ]
2116+ }
2117+
2118+ // @ts -expect-error - getPortfolioFromApiDiscovery is private, spied on at runtime
2119+ const discoverySpy : any = jest . spyOn ( controller , 'getPortfolioFromApiDiscovery' )
2120+ // First update: the custom (deployless) position is enhanced with the Debank entry (source: 'mixed')
2121+ discoverySpy . mockResolvedValueOnce ( discoveryWithDebankUniV3 )
2122+ // Second update: a skipped discovery returns null. This is a routine occurrence (the data is
2123+ // still fresh) and is NOT a failure.
2124+ discoverySpy . mockResolvedValueOnce ( null )
2125+
2126+ await controller . updateSelectedAccount ( DEFI_TEST_ACCOUNT . addr , [ ethereum ] )
2127+ const firstResult = controller . getAccountPortfolioState ( DEFI_TEST_ACCOUNT . addr ) [ '1' ] ! . result
2128+ const uniBeforeSkip = firstResult ?. defiPositions . positionsByProvider . find (
2129+ ( p ) => getProviderId ( p . providerName ) === 'uniswap v3'
2130+ )
2131+
2132+ // Check before updating again to ensure it's mixed
2133+ expect ( uniBeforeSkip ?. source ) . toBe ( 'mixed' )
2134+
2135+ await controller . updateSelectedAccount ( DEFI_TEST_ACCOUNT . addr , [ ethereum ] , undefined , {
2136+ defiMaxDataAgeMs : 0 ,
2137+ isManualUpdate : true
2138+ } )
2139+
2140+ const secondResult = controller . getAccountPortfolioState ( DEFI_TEST_ACCOUNT . addr ) [ '1' ] ! . result
2141+ const uniAfterSkip = secondResult ?. defiPositions . positionsByProvider . find (
2142+ ( p ) => getProviderId ( p . providerName ) === 'uniswap v3'
2143+ )
2144+
2145+ // MUST BE MIXED!!!!!
2146+ expect ( uniAfterSkip ?. source ) . toBe ( 'mixed' )
2147+ } )
2148+
20702149 describe ( 'Defi apps' , ( ) => {
20712150 it ( 'should skip update if canSkipUpdate=true' , async ( ) => {
20722151 const { controller } = await prepareTest ( )
0 commit comments