Skip to content

Commit bb043de

Browse files
committed
Merge branch 'main' into test/LW-12806_prometheus_script
2 parents f7602d4 + 0089352 commit bb043de

File tree

50 files changed

+439
-213
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+439
-213
lines changed

.github/workflows/e2e-tests-linux-split.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ jobs:
241241
echo "https://${{ secrets.E2E_REPORTS_USER }}:${{ secrets.E2E_REPORTS_PASSWORD }}@${{ secrets.E2E_REPORTS_URL }}/all/linux/${{ env.BROWSER }}/${{ env.RUN }}/index.html | browser: ${{ env.BROWSER }} | network: ${{ env.NETWORK }} | platform: linux | tags: ${{ needs.setup.outputs.tags }} | smoke only: ${{ needs.setup.outputs.smoke_only }}" >> $GITHUB_STEP_SUMMARY
242242
243243
- name: Slack Notification
244-
uses: rtCamp/action-slack-notify@v2.3.2
244+
uses: rtCamp/action-slack-notify@v2.3.3
245245
env:
246246
SLACK_COLOR: "${{ contains(needs.*.result, 'failure') && 'failure' || 'good' }}"
247247
SLACK_ICON_EMOJI: ':lace:'

apps/browser-extension-wallet/.env.defaults

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ USE_BITCOIN_NETWORK_SWITCHING=false
1616
USE_PASSWORD_VERIFICATION=false
1717
USE_DAPP_CONNECTOR=true
1818
USE_TREZOR_HW=true
19-
USE_TOKEN_PRICING=true
2019
USE_NFT_FOLDERS=true
2120
USE_MULTI_CURRENCY=true
2221
USE_HIDE_MY_BALANCE=true
@@ -106,6 +105,10 @@ MAESTRO_URL_TESTNET=https://xbt-testnet.gomaestro-api.org
106105
MAESTRO_PROJECT_ID_MAINNET=
107106
MAESTRO_PROJECT_ID_TESTNET=
108107

108+
# Lace proxy to CoinGecko
109+
110+
TOKEN_PRICES_URL=https://coingecko.live-mainnet.eks.lw.iog.io/api/v3/onchain/networks
111+
109112
# Bitcoin Explorer URLs
110113
MEMPOOL_URL_MAINNET=https://mempool.space/tx
111114
MEMPOOL_URL_TESTNET4=https://mempool.space/testnet4/tx

apps/browser-extension-wallet/.env.developerpreview

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ SAVED_PRICE_DURATION_IN_MINUTES=720
1414
USE_PASSWORD_VERIFICATION=false
1515
USE_DAPP_CONNECTOR=true
1616
USE_TREZOR_HW=false
17-
USE_TOKEN_PRICING=true
1817
USE_NFT_FOLDERS=true
1918
USE_MULTI_CURRENCY=true
2019
USE_HIDE_MY_BALANCE=true

apps/browser-extension-wallet/.env.example

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ WALLET_POLLING_INTERVAL_IN_SEC=45
1414
USE_PASSWORD_VERIFICATION=false
1515
USE_DAPP_CONNECTOR=true
1616
USE_TREZOR_HW=true
17-
USE_TOKEN_PRICING=true
1817
USE_NFT_FOLDERS=true
1918
USE_MULTI_CURRENCY=true
2019
USE_HIDE_MY_BALANCE=true

apps/browser-extension-wallet/src/api/__tests__/token-transformer.test.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,11 @@ describe('Testing tokenTransformer function', () => {
4040
test('should format token with fiatBalance', () => {
4141
const prices = {
4242
...mockPrices,
43-
tokens: new Map([
44-
[
45-
balance[0],
46-
{
47-
id: balance[0].toString(),
48-
priceInAda: 1.2,
49-
priceVariationPercentage24h: 2.9
50-
}
51-
]
52-
])
43+
cardano: {
44+
...mockPrices.cardano,
45+
getTokenPrice: (assetId: Wallet.Cardano.AssetId) =>
46+
assetId === balance[0] ? { priceInAda: 1.2, priceVariationPercentage24h: 2.9 } : undefined
47+
}
5348
};
5449
const result = tokenTransformer(mockAsset, balance, prices, defaultCurrency);
5550
const tokenPrice = 1.2;

apps/browser-extension-wallet/src/api/transformers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export const tokenTransformer = (
6161
const { name } = { ...tokenMetadata, ...nftMetadata };
6262
const [assetId, bigintBalance] = assetBalance;
6363
const amount = Wallet.util.calculateAssetBalance(bigintBalance, assetInfo);
64-
const tokenPriceInAda = prices?.tokens?.get(assetId)?.priceInAda;
64+
const tokenPriceInAda = prices?.cardano.getTokenPrice(assetId)?.priceInAda;
6565
const fiatBalance =
6666
tokenMetadata !== undefined &&
6767
tokenPriceInAda &&

apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/UserInfo.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ import { WalletStatusContainer } from '@components/WalletStatus';
1111
import { UserAvatar } from './UserAvatar';
1212
import { useGetHandles, useWalletAvatar, useWalletManager } from '@hooks';
1313
import { useAnalyticsContext } from '@providers';
14-
import { PostHogAction } from '@providers/AnalyticsProvider/analyticsTracker';
14+
import { PostHogAction, WALLET_TYPE_KEY } from '@providers/AnalyticsProvider/analyticsTracker';
1515
import { ProfileDropdown } from '@input-output-hk/lace-ui-toolkit';
1616
import { AnyBip32Wallet, AnyWallet, Bip32WalletAccount, ScriptWallet, WalletType } from '@cardano-sdk/web-extension';
1717
import { Wallet } from '@lace/cardano';
1818
import { Separator } from './Separator';
1919
import { getUiWalletType } from '@src/utils/get-ui-wallet-type';
20+
import { isScriptWallet } from '@lace/core';
21+
import { useCurrentBlockchain } from '@src/multichain';
2022

2123
const ADRESS_FIRST_PART_LENGTH = 10;
2224
const ADRESS_LAST_PART_LENGTH = 5;
@@ -65,6 +67,7 @@ export const UserInfo = ({
6567
const [lastActiveAccount, setLastActiveAccount] = useState<number>(0);
6668
const [handle] = useGetHandles();
6769
const { activeWalletAvatar, getAvatar } = useWalletAvatar();
70+
const { blockchain } = useCurrentBlockchain();
6871

6972
const handleName = handle?.nftMetadata?.name;
7073

@@ -142,7 +145,9 @@ export const UserInfo = ({
142145
return;
143146
}
144147

145-
void analytics.sendEventToPostHog(PostHogAction.MultiWalletSwitchWallet);
148+
void analytics.sendEventToPostHog(PostHogAction.MultiWalletSwitchWallet, {
149+
[WALLET_TYPE_KEY]: walletType
150+
});
146151

147152
await activateWallet({
148153
walletId: wallet.walletId,
@@ -153,6 +158,9 @@ export const UserInfo = ({
153158
duration: TOAST_DEFAULT_DURATION,
154159
text: t('multiWallet.activated.wallet', { walletName: wallet.metadata.name })
155160
});
161+
// reload if we switch from, to or between btc wallet(s)
162+
if ((!isScriptWallet(wallet) && wallet.blockchainName === 'Bitcoin') || blockchain === 'bitcoin')
163+
window.location.reload();
156164
}}
157165
type={walletType}
158166
profile={
@@ -180,7 +188,8 @@ export const UserInfo = ({
180188
onOpenWalletAccounts,
181189
setIsDropdownMenuOpen,
182190
activeWalletId,
183-
t
191+
t,
192+
blockchain
184193
]
185194
);
186195

apps/browser-extension-wallet/src/hooks/__tests__/useFetchCoinPrice.test.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { act } from 'react-dom/test-utils';
88
import { BehaviorSubject } from 'rxjs';
99

1010
import { BackgroundServiceAPIProviderProps } from '@src/providers';
11+
import { Wallet } from '@lace/cardano';
1112

1213
const tokenPrices$ = new BehaviorSubject({});
1314
const adaPrices$ = new BehaviorSubject({});
@@ -17,6 +18,14 @@ jest.mock('@providers/currency', (): typeof CurrencyProvider => ({
1718
useCurrencyStore: mockUseCurrencyStore
1819
}));
1920

21+
jest.mock('../../stores', () => ({
22+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
23+
...jest.requireActual<any>('../../stores'),
24+
useWalletStore: () => ({
25+
currentChain: { networkId: Wallet.Cardano.NetworkId.Mainnet }
26+
})
27+
}));
28+
2029
const backgroundServices = {
2130
getBackgroundStorage: jest.fn(),
2231
setBackgroundStorage: jest.fn(),
@@ -32,9 +41,11 @@ jest.mock('@providers/BackgroundServiceAPI', () => ({
3241
describe('Testing useFetchCoinPrice hook', () => {
3342
test('should return proper state', async () => {
3443
const hook = renderHook(() => useFetchCoinPrice());
44+
expect(typeof hook.result.current.priceResult.cardano.getTokenPrice).toBe('function');
3545
expect(hook.result.current).toEqual({
3646
priceResult: {
3747
cardano: {
48+
getTokenPrice: hook.result.current.priceResult.cardano.getTokenPrice,
3849
price: 1,
3950
priceVariationPercentage24h: 0
4051
},
@@ -108,12 +119,14 @@ describe('Testing useFetchCoinPrice hook', () => {
108119
priceVariationPercentage24h: 0
109120
},
110121
cardano: {
122+
getTokenPrice: hook.result.current.priceResult.cardano.getTokenPrice,
111123
price: 1,
112124
priceVariationPercentage24h: 0
113125
},
114126
tokens
115127
},
116-
status: 'fetched'
128+
status: 'fetched',
129+
timestamp: undefined
117130
});
118131

119132
const fiatCurrency = { code: 'USD', symbol: '$' };
@@ -130,6 +143,7 @@ describe('Testing useFetchCoinPrice hook', () => {
130143
priceVariationPercentage24h: 0
131144
},
132145
cardano: {
146+
getTokenPrice: hook.result.current.priceResult.cardano.getTokenPrice,
133147
price: prices.usd,
134148
priceVariationPercentage24h: prices.usd_24h_change
135149
},

apps/browser-extension-wallet/src/hooks/__tests__/useWalletManager.test.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ describe('Testing useWalletManager hook', () => {
403403

404404
describe('createWallet', () => {
405405
test('should store wallet in repository', async () => {
406+
const setBackgroundStorage = jest.fn();
406407
const walletId = 'walletId';
407408
(walletApiUi.walletRepository as any).addWallet = jest.fn().mockResolvedValue(walletId);
408409
(walletApiUi.walletManager as any).activate = jest.fn().mockResolvedValue(undefined);
@@ -432,7 +433,13 @@ describe('Testing useWalletManager hook', () => {
432433
current: { createWallet }
433434
}
434435
} = renderHook(() => useWalletManager(), {
435-
wrapper: getWrapper({})
436+
wrapper: getWrapper({
437+
backgroundService: {
438+
clearBackgroundStorage: jest.fn(),
439+
getBackgroundStorage: jest.fn().mockResolvedValue({ activeBlockchain: 'cardano' }),
440+
setBackgroundStorage
441+
} as unknown as BackgroundServiceAPIProviderProps['value']
442+
})
436443
});
437444

438445
expect(createWallet).toBeDefined();
@@ -453,6 +460,8 @@ describe('Testing useWalletManager hook', () => {
453460
expect(walletApiUi.walletRepository.addWallet).toBeCalledTimes(1);
454461
expect(walletApiUi.walletManager.activate).toBeCalledTimes(1);
455462
expect(mockUseSecrets.clearSecrets).toBeCalledTimes(1);
463+
expect(setBackgroundStorage).toBeCalledTimes(1);
464+
expect(setBackgroundStorage).toBeCalledWith({ activeBlockchain: 'cardano' });
456465
});
457466
});
458467

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import { useMemo } from 'react';
2-
import { useObservable } from '@lace/common';
3-
import { TokenPrices, StatusTypes, ADAPricesKeys } from '@lib/scripts/types';
2+
import { logger, useObservable } from '@lace/common';
3+
import { TokenPrices, StatusTypes, ADAPricesKeys, TokenPrice } from '@lib/scripts/types';
44
import { useBackgroundServiceAPIContext, useCurrencyStore } from '../providers';
55
import { CARDANO_COIN_SYMBOL } from '@src/utils/constants';
66
import { Wallet } from '@lace/cardano';
7+
import { config } from '@src/config';
8+
import { useWalletStore } from '@stores';
79

810
export interface PriceResult {
911
cardano: {
12+
getTokenPrice: (assetId: Wallet.Cardano.AssetId) => TokenPrice | undefined;
1013
price: number;
1114
priceVariationPercentage24h: number;
1215
};
1316
bitcoin: {
1417
price: number;
1518
priceVariationPercentage24h: number;
1619
};
20+
/** @deprecated Use `cardano.getTokenPrice` instead. */
1721
tokens: TokenPrices;
1822
}
1923

@@ -23,13 +27,15 @@ export interface UseFetchCoinPrice {
2327
timestamp?: number;
2428
}
2529

30+
const { TOKEN_PRICE_CHECK_INTERVAL } = config();
31+
2632
export const useFetchCoinPrice = (): UseFetchCoinPrice => {
27-
const backgroundServices = useBackgroundServiceAPIContext();
33+
const { coinPrices, trackCardanoTokenPrice } = useBackgroundServiceAPIContext();
2834
const { fiatCurrency } = useCurrencyStore();
29-
const { coinPrices } = backgroundServices;
3035
const tokenPrices = useObservable(coinPrices.tokenPrices$);
3136
const adaPrices = useObservable(coinPrices.adaPrices$);
3237
const bitcoinPrices = useObservable(coinPrices.bitcoinPrices$);
38+
const networkId = useWalletStore((state) => state.currentChain?.networkId);
3339

3440
const isAdaCurrency = fiatCurrency.code === CARDANO_COIN_SYMBOL[Wallet.Cardano.NetworkId.Mainnet];
3541

@@ -42,25 +48,49 @@ export const useFetchCoinPrice = (): UseFetchCoinPrice => {
4248
[bitcoinPrices?.prices, fiatCurrency.code]
4349
);
4450

45-
const price = useMemo(
51+
const cardano = useMemo(
4652
() => ({
53+
getTokenPrice: (assetId: Wallet.Cardano.AssetId): TokenPrice | undefined => {
54+
const tokenPrice = tokenPrices?.tokens.get(assetId);
55+
// Actually track the price only for token in Cardano mainnet, otherwise just do nothing
56+
const trackPrice = () =>
57+
networkId === Wallet.Cardano.NetworkId.Mainnet
58+
? trackCardanoTokenPrice(assetId).catch((error) => logger.error(error))
59+
: undefined;
60+
61+
// If the price for this token was never fetched, wee need to track it
62+
if (!tokenPrice) {
63+
trackPrice();
64+
65+
return undefined;
66+
}
67+
68+
const { lastFetchTime, price } = tokenPrice;
69+
70+
// If the price was fetched, but it is still not present, it means the price for this token is not tracked by CoinGecko:
71+
// let's retry a new fetch only after the TOKEN_PRICE_CHECK_INTERVAL to check if now the price is being tracked.
72+
if (!price && lastFetchTime < Date.now() - TOKEN_PRICE_CHECK_INTERVAL) trackPrice();
73+
74+
// eslint-disable-next-line consistent-return
75+
return price;
76+
},
4777
price: isAdaCurrency ? 1 : adaPrices?.prices?.[fiatCurrency.code.toLowerCase() as ADAPricesKeys],
4878
priceVariationPercentage24h:
4979
adaPrices?.prices?.[`${fiatCurrency.code.toLowerCase()}_24h_change` as ADAPricesKeys] || 0
5080
}),
51-
[adaPrices?.prices, fiatCurrency.code, isAdaCurrency]
81+
[adaPrices?.prices, fiatCurrency.code, isAdaCurrency, tokenPrices?.tokens, trackCardanoTokenPrice, networkId]
5282
);
5383

5484
return useMemo(
5585
() => ({
5686
priceResult: {
57-
cardano: price,
87+
cardano,
5888
bitcoin: bitcoinPrice,
5989
tokens: tokenPrices?.tokens
6090
},
6191
status: adaPrices?.status,
6292
timestamp: adaPrices?.timestamp
6393
}),
64-
[tokenPrices, adaPrices, price, bitcoinPrice]
94+
[tokenPrices, adaPrices, cardano, bitcoinPrice]
6595
);
6696
};

apps/browser-extension-wallet/src/hooks/useWalletManager.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,10 @@ export const useWalletManager = (): UseWalletManager => {
822822
accountIndex
823823
});
824824

825+
await backgroundService.setBackgroundStorage({
826+
activeBlockchain: 'cardano'
827+
});
828+
825829
// Needed for reset password flow
826830
saveValueInLocalStorage({ key: 'wallet', value: { name } });
827831

@@ -842,7 +846,7 @@ export const useWalletManager = (): UseWalletManager => {
842846
}
843847
};
844848
},
845-
[getCurrentChainId, clearSecrets]
849+
[getCurrentChainId, backgroundService, clearSecrets]
846850
);
847851

848852
/**

apps/browser-extension-wallet/src/lib/scripts/background/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const backgroundServiceProperties: RemoteApiProperties<BackgroundService>
1919
adaPrices$: RemoteApiPropertyType.HotObservable,
2020
tokenPrices$: RemoteApiPropertyType.HotObservable
2121
},
22+
trackCardanoTokenPrice: RemoteApiPropertyType.MethodReturningPromise,
2223
handleOpenBrowser: RemoteApiPropertyType.MethodReturningPromise,
2324
handleOpenNamiBrowser: RemoteApiPropertyType.MethodReturningPromise,
2425
closeAllTabsAndOpenPopup: RemoteApiPropertyType.MethodReturningPromise,

0 commit comments

Comments
 (0)