From 001c3f9dd949dbcdce6eb416abba8e1bc9bc517c Mon Sep 17 00:00:00 2001 From: DMY <147dmy@gmail.com> Date: Wed, 24 Apr 2024 15:23:35 +0800 Subject: [PATCH 01/14] feat: update GAS_TOP_UP_SUPPORT_TOKENS (#2231) --- src/constant/index.ts | 54 ++++++++++++------------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/src/constant/index.ts b/src/constant/index.ts index cddae76b823..3aa88a296c6 100644 --- a/src/constant/index.ts +++ b/src/constant/index.ts @@ -1140,20 +1140,15 @@ export const GAS_TOP_UP_PAY_ADDRESS = export const GAS_TOP_UP_SUPPORT_TOKENS: Record = { arb: [ + '0xaf88d065e77c8cc2239327c5edb3a432268e5831', '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1', '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', - '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', 'arb', ], astar: ['astar'], aurora: ['aurora'], - avax: [ - '0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7', - '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7', - '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e', - '0xd586e7f844cea2f87f50152665bcbc2c279d8d70', - 'avax', - ], + avax: ['avax'], + base: ['0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', 'base'], boba: ['boba'], bsc: [ '0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3', @@ -1161,23 +1156,13 @@ export const GAS_TOP_UP_SUPPORT_TOKENS: Record = { '0x55d398326f99059ff775485246999027b3197955', '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', - '0xe9e7cea3dedca5984780bafc599bd69add087d56', 'bsc', ], - btt: ['btt'], canto: ['canto'], celo: ['celo'], - cro: [ - '0x5c7f8a570d578ed84e63fdfa7b1ee72deae1ae23', - '0x66e428c3f67a68878562e79a0234c1f83c208770', - '0xc21223249ca28397b4b6541dffaecc539bff0c59', - '0xf2001b145b43032aaf5ee2884e456ccd805f677d', - 'cro', - ], - dfk: ['dfk'], - doge: ['doge'], + cro: ['0x5c7f8a570d578ed84e63fdfa7b1ee72deae1ae23', 'cro'], + era: ['era'], eth: [ - '0x4fabb145d64652a948d72533023f6e7a623c7c53', '0x6b175474e89094c44da98b954eedeac495271d0f', '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', @@ -1185,43 +1170,34 @@ export const GAS_TOP_UP_SUPPORT_TOKENS: Record = { 'eth', ], evmos: ['evmos'], - ftm: [ - '0x04068da6c83afcfa0e13ba15a6696662335d5b75', - '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', - 'ftm', - ], - fuse: ['fuse'], - heco: ['heco'], + ftm: ['0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83', 'ftm'], hmy: ['hmy'], - iotx: ['iotx'], + kava: ['kava'], kcc: ['kcc'], - klay: ['klay'], + linea: ['linea'], matic: [ '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270', - '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', + '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359', '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063', '0xc2132d05d31c914a87c6611c10748aeb04b58e8f', 'matic', ], metis: ['metis'], + mnt: ['mnt'], mobm: ['mobm'], movr: ['movr'], nova: ['nova'], okt: ['okt'], op: [ - '0x7f5c764cbc14f9669b88837ca1490cca17c31607', + '0x0b2c639c533813f4aa9d7837caf62653d097ff85', '0x94b008aa00579c1307b0ef2c499ad98a8ce58e58', '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1', 'op', ], - palm: ['palm'], - rsk: ['rsk'], - sbch: ['sbch'], - sdn: ['sdn'], - sgb: ['sgb'], - // swm: ['swm'], - tlos: ['tlos'], - wan: ['wan'], + opbnb: ['opbnb'], + pls: ['pls'], + pze: ['pze'], + scrl: ['scrl'], xdai: ['xdai'], }; From 9ac90efbec86fad3a788e231defe2151f9041359 Mon Sep 17 00:00:00 2001 From: Hodor Date: Wed, 24 Apr 2024 15:23:56 +0800 Subject: [PATCH 02/14] fix: custom network matomo event (#2226) * fix: custom network matomo event * fix: sign event * feat: event add networkType --- .../controller/provider/controller.ts | 6 +++ src/background/controller/provider/rpcFlow.ts | 2 + src/background/controller/wallet.ts | 22 +++++++- src/background/index.ts | 17 ++++--- src/background/service/customTestnet.ts | 8 +-- src/background/service/notification.ts | 16 ++++-- src/background/service/transactionHistory.ts | 7 +-- .../Approval/components/AddChain/AddChain.tsx | 17 ++++++- .../components/CoinbaseWaiting/index.tsx | 10 ++-- .../Approval/components/CommonWaiting.tsx | 5 +- .../components/ImKeyHardwareWaiting.tsx | 5 +- .../components/LedgerHardwareWaiting.tsx | 5 +- .../Approval/components/PrivatekeyWaiting.tsx | 5 +- .../QRHardWareWaiting/QRHardWareWaiting.tsx | 5 +- .../components/SignTestnetTx/index.tsx | 50 ++++++++++++------- src/ui/views/Approval/components/SignTx.tsx | 8 ++- .../components/SwitchChain/SwitchChain.tsx | 17 ++++++- .../components/WatchAddressWaiting/index.tsx | 12 +++-- .../CustomTestnetAssetListContainer.tsx | 10 ++++ .../components/EditTestnetModal.tsx | 24 +++++++-- src/ui/views/CustomTestnet/index.tsx | 5 ++ src/utils/chain.ts | 2 +- 22 files changed, 196 insertions(+), 62 deletions(-) diff --git a/src/background/controller/provider/controller.ts b/src/background/controller/provider/controller.ts index 9031b711b61..db5a1537351 100644 --- a/src/background/controller/provider/controller.ts +++ b/src/background/controller/provider/controller.ts @@ -457,6 +457,9 @@ class ProviderController extends BaseController { createBy: options?.data?.$ctx?.ga ? 'rabby' : 'dapp', source: options?.data?.$ctx?.ga?.source || '', trigger: options?.data?.$ctx?.ga?.trigger || '', + networkType: chainItem?.isTestnet + ? 'Custom Network' + : 'Integrated Network', reported: false, }; @@ -574,6 +577,9 @@ class ProviderController extends BaseController { createBy: options?.data?.$ctx?.ga ? 'rabby' : 'dapp', source: options?.data?.$ctx?.ga?.source || '', trigger: options?.data?.$ctx?.ga?.trigger || '', + networkType: chainItem?.isTestnet + ? 'Custom Network' + : 'Integrated Network', }); if (!isSpeedUp && !isCancel) { transactionHistoryService.addSubmitFailedTransaction({ diff --git a/src/background/controller/provider/rpcFlow.ts b/src/background/controller/provider/rpcFlow.ts index 41cdacf0808..75c2106e9de 100644 --- a/src/background/controller/provider/rpcFlow.ts +++ b/src/background/controller/provider/rpcFlow.ts @@ -304,6 +304,7 @@ function reportStatsData() { createBy: statsData?.createBy, source: statsData?.source, trigger: statsData?.trigger, + networkType: statsData?.networkType, }; if (statsData.signMethod) { sData.signMethod = statsData.signMethod; @@ -320,6 +321,7 @@ function reportStatsData() { createBy: statsData?.createBy, source: statsData?.source, trigger: statsData?.trigger, + networkType: statsData?.networkType || '', }); } diff --git a/src/background/controller/wallet.ts b/src/background/controller/wallet.ts index 192407e3670..9b98e2a5428 100644 --- a/src/background/controller/wallet.ts +++ b/src/background/controller/wallet.ts @@ -115,6 +115,7 @@ import { customTestnetService } from '../service/customTestnet'; import { getKeyringBridge, hasBridge } from '../service/keyring/bridge'; import { http } from '../utils/http'; import { syncChainService } from '../service/syncChain'; +import { matomoRequestEvent } from '@/utils/matomo-request'; const stashKeyrings: Record = {}; @@ -3684,7 +3685,26 @@ export class WalletController extends BaseController { return signature; }; - addCustomTestnet = customTestnetService.add; + addCustomTestnet = async ( + chain: Parameters[0], + ctx?: { + ga?: { + source?: string; + }; + } + ) => { + const source = ctx?.ga?.source || 'setting'; + + const res = await customTestnetService.add(chain); + if (!('error' in res)) { + matomoRequestEvent({ + category: 'Custom Network', + action: 'Success Add Network', + label: `${source}_${String(chain.id)}`, + }); + } + return res; + }; updateCustomTestnet = customTestnetService.update; removeCustomTestnet = customTestnetService.remove; getCustomTestnetList = customTestnetService.getList; diff --git a/src/background/index.ts b/src/background/index.ts index 295165a8b96..908a4f43ad5 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -120,14 +120,7 @@ restoreAppState(); let interval: NodeJS.Timeout | null; keyringService.on('unlock', () => { walletController.syncMainnetChainList(); - const customTestnetLength = customTestnetService.getList()?.length; - if (customTestnetLength) { - matomoRequestEvent({ - category: 'Custom Network', - action: 'Custom Network Status', - value: customTestnetLength, - }); - } + if (interval) { clearInterval(interval); } @@ -136,6 +129,14 @@ restoreAppState(); if (dayjs(time).utc().isSame(dayjs().utc(), 'day')) { return; } + const customTestnetLength = customTestnetService.getList()?.length; + if (customTestnetLength) { + matomoRequestEvent({ + category: 'Custom Network', + action: 'Custom Network Status', + value: customTestnetLength, + }); + } const chains = preferenceService.getSavedChains(); matomoRequestEvent({ category: 'User', diff --git a/src/background/service/customTestnet.ts b/src/background/service/customTestnet.ts index 013ce2cd4d8..fb8b3955873 100644 --- a/src/background/service/customTestnet.ts +++ b/src/background/service/customTestnet.ts @@ -169,13 +169,7 @@ class CustomTestnetService { }; this.chains[chain.id] = createClientByChain(chain); this.syncChainList(); - if (isAdd) { - matomoRequestEvent({ - category: 'Custom Network', - action: 'Success Add Network', - label: String(chain.id), - }); - } + if (this.getList().length) { matomoRequestEvent({ category: 'Custom Network', diff --git a/src/background/service/notification.ts b/src/background/service/notification.ts index c373b0845ca..ee1724a673c 100644 --- a/src/background/service/notification.ts +++ b/src/background/service/notification.ts @@ -67,6 +67,7 @@ export type StatsData = { trigger: any; reported: boolean; signMethod?: string; + networkType?: string; }; // something need user approval in window @@ -258,15 +259,24 @@ class NotificationService extends Events { : null; const explain = signingTx?.explain; - if (explain && currentAccount) { + const chain = findChain({ + id: signingTx?.rawTx.chainId, + }); + + if ((explain || chain?.isTestnet) && currentAccount) { stats.report('preExecTransaction', { type: currentAccount.brandName, category: KEYRING_CATEGORY_MAP[currentAccount.type], - chainId: explain.native_token.chain, - success: explain.calcSuccess && explain.pre_exec.success, + chainId: chain?.serverId || '', + success: explain + ? explain.calcSuccess && explain.pre_exec.success + : true, createBy: data?.params.$ctx?.ga ? 'rabby' : 'dapp', source: data?.params.$ctx?.ga?.source || '', trigger: data?.params.$ctx?.ga.trigger || '', + networkType: chain?.isTestnet + ? 'Custom Network' + : 'Integrated Network', }); } }; diff --git a/src/background/service/transactionHistory.ts b/src/background/service/transactionHistory.ts index 288a0800b98..998464ecbba 100644 --- a/src/background/service/transactionHistory.ts +++ b/src/background/service/transactionHistory.ts @@ -728,12 +728,13 @@ class TxHistory { stats.report('completeTransaction', { chainId: chain.serverId, success, - preExecSuccess: Boolean( - target.explain?.pre_exec.success && target.explain?.calcSuccess - ), + preExecSuccess: target?.explain + ? target.explain?.pre_exec.success && target.explain?.calcSuccess + : true, createBy: target?.$ctx?.ga ? 'rabby' : 'dapp', source: target?.$ctx?.ga?.source || '', trigger: target?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); } this.clearBefore({ address, chainId, nonce }); diff --git a/src/ui/views/Approval/components/AddChain/AddChain.tsx b/src/ui/views/Approval/components/AddChain/AddChain.tsx index 36eeacd0c43..aa93579188d 100644 --- a/src/ui/views/Approval/components/AddChain/AddChain.tsx +++ b/src/ui/views/Approval/components/AddChain/AddChain.tsx @@ -1,6 +1,6 @@ import { TestnetChainBase } from '@/background/service/customTestnet'; import { CustomTestnetForm } from '@/ui/views/CustomTestnet/components/CustomTestnetForm'; -import { useRequest } from 'ahooks'; +import { useMount, useRequest } from 'ahooks'; import { Button } from 'antd'; import { useForm } from 'antd/lib/form/Form'; import clsx from 'clsx'; @@ -8,6 +8,7 @@ import React, { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { useApproval, useWallet } from 'ui/utils'; import { AddEthereumChainParams } from './type'; +import { matomoRequestEvent } from '@/utils/matomo-request'; interface AddChainProps { data: AddEthereumChainParams[]; @@ -37,11 +38,23 @@ const AddChain = ({ params }: { params: AddChainProps }) => { }); }, [form, addChainParams]); + useMount(() => { + matomoRequestEvent({ + category: 'Custom Network', + action: 'Dapp Add Network', + }); + }); + const { loading, runAsync: runAddChain } = useRequest( async () => { await form.validateFields(); const values = form.getFieldsValue(); - const res = await wallet.addCustomTestnet(values); + + const res = await wallet.addCustomTestnet(values, { + ga: { + source: 'dapp', + }, + }); if ('error' in res) { form.setFields([ { diff --git a/src/ui/views/Approval/components/CoinbaseWaiting/index.tsx b/src/ui/views/Approval/components/CoinbaseWaiting/index.tsx index dd331e344ae..86b811dc307 100644 --- a/src/ui/views/Approval/components/CoinbaseWaiting/index.tsx +++ b/src/ui/views/Approval/components/CoinbaseWaiting/index.tsx @@ -136,11 +136,12 @@ const CoinbaseWaiting = ({ params }: { params: ApprovalParams }) => { if (!isText && !isSignTriggered) { const explain = explainRef.current; + const chainInfo = findChainByEnum(chain); - if (explain) { + if (explain || chainInfo?.isTestnet) { wallet.reportStats('signTransaction', { type: account.brandName, - chainId: findChainByEnum(chain)?.serverId || '', + chainId: chainInfo?.serverId || '', category: KEYRING_CATEGORY_MAP[account.type], preExecSuccess: explain ? explain?.calcSuccess && explain?.pre_exec.success @@ -148,12 +149,15 @@ const CoinbaseWaiting = ({ params }: { params: ApprovalParams }) => { createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', + networkType: chainInfo?.isTestnet + ? 'Custom Network' + : 'Integrated Network', }); } matomoRequestEvent({ category: 'Transaction', action: 'Submit', - label: account.brandName, + label: chainInfo?.isTestnet ? 'Custom Network' : 'Integrated Network', }); isSignTriggered = true; } diff --git a/src/ui/views/Approval/components/CommonWaiting.tsx b/src/ui/views/Approval/components/CommonWaiting.tsx index 2ec5e3b884e..35f2f7664e4 100644 --- a/src/ui/views/Approval/components/CommonWaiting.tsx +++ b/src/ui/views/Approval/components/CommonWaiting.tsx @@ -122,6 +122,9 @@ export const CommonWaiting = ({ params }: { params: ApprovalParams }) => { createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet + ? 'Custom Network' + : 'Integrated Network', }); } } else { @@ -165,7 +168,7 @@ export const CommonWaiting = ({ params }: { params: ApprovalParams }) => { matomoRequestEvent({ category: 'Transaction', action: 'Submit', - label: brandName, + label: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); setSignFinishedData({ data: sig, diff --git a/src/ui/views/Approval/components/ImKeyHardwareWaiting.tsx b/src/ui/views/Approval/components/ImKeyHardwareWaiting.tsx index 67b801aeee4..baf98a1975c 100644 --- a/src/ui/views/Approval/components/ImKeyHardwareWaiting.tsx +++ b/src/ui/views/Approval/components/ImKeyHardwareWaiting.tsx @@ -136,6 +136,9 @@ export const ImKeyHardwareWaiting = ({ createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet + ? 'Custom Network' + : 'Integrated Network', }); } } else { @@ -181,7 +184,7 @@ export const ImKeyHardwareWaiting = ({ matomoRequestEvent({ category: 'Transaction', action: 'Submit', - label: KEYRING_CLASS.HARDWARE.IMKEY, + label: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); setSignFinishedData({ diff --git a/src/ui/views/Approval/components/LedgerHardwareWaiting.tsx b/src/ui/views/Approval/components/LedgerHardwareWaiting.tsx index 74bbab1db2e..d13998ca2a4 100644 --- a/src/ui/views/Approval/components/LedgerHardwareWaiting.tsx +++ b/src/ui/views/Approval/components/LedgerHardwareWaiting.tsx @@ -132,6 +132,9 @@ const LedgerHardwareWaiting = ({ params }: { params: ApprovalParams }) => { createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet + ? 'Custom Network' + : 'Integrated Network', }); } } else { @@ -179,7 +182,7 @@ const LedgerHardwareWaiting = ({ params }: { params: ApprovalParams }) => { matomoRequestEvent({ category: 'Transaction', action: 'Submit', - label: KEYRING_CLASS.HARDWARE.LEDGER, + label: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); setSignFinishedData({ diff --git a/src/ui/views/Approval/components/PrivatekeyWaiting.tsx b/src/ui/views/Approval/components/PrivatekeyWaiting.tsx index a665a9be52a..4e8fa1cf885 100644 --- a/src/ui/views/Approval/components/PrivatekeyWaiting.tsx +++ b/src/ui/views/Approval/components/PrivatekeyWaiting.tsx @@ -129,6 +129,9 @@ export const PrivatekeyWaiting = ({ params }: { params: ApprovalParams }) => { createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet + ? 'Custom Network' + : 'Integrated Network', }); } } else { @@ -166,7 +169,7 @@ export const PrivatekeyWaiting = ({ params }: { params: ApprovalParams }) => { matomoRequestEvent({ category: 'Transaction', action: 'Submit', - label: type, + label: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); setSignFinishedData({ data: sig, diff --git a/src/ui/views/Approval/components/QRHardWareWaiting/QRHardWareWaiting.tsx b/src/ui/views/Approval/components/QRHardWareWaiting/QRHardWareWaiting.tsx index 2887ccfb7c9..78b5abaf880 100644 --- a/src/ui/views/Approval/components/QRHardWareWaiting/QRHardWareWaiting.tsx +++ b/src/ui/views/Approval/components/QRHardWareWaiting/QRHardWareWaiting.tsx @@ -207,7 +207,7 @@ const QRHardWareWaiting = ({ params }) => { stats.report('signTransaction', { type: account.brandName, - chainId: findChainByEnum(chain)?.serverId || '', + chainId: chainInfo?.serverId || '', category: KEYRING_CATEGORY_MAP[account.type], preExecSuccess: explain ? explain?.calcSuccess && explain?.pre_exec.success @@ -216,6 +216,9 @@ const QRHardWareWaiting = ({ params }) => { source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', signMethod, + networkType: chainInfo?.isTestnet + ? 'Custom Network' + : 'Integrated Network', }); } } else { diff --git a/src/ui/views/Approval/components/SignTestnetTx/index.tsx b/src/ui/views/Approval/components/SignTestnetTx/index.tsx index 02e4e401f69..3f909bba9ef 100644 --- a/src/ui/views/Approval/components/SignTestnetTx/index.tsx +++ b/src/ui/views/Approval/components/SignTestnetTx/index.tsx @@ -36,6 +36,7 @@ import { WaitingSignComponent } from '../map'; import { useLedgerDeviceConnected } from '@/ui/utils/ledger'; import { getAddress } from 'viem'; import IconGnosis from 'ui/assets/walletlogo/safe.svg'; +import { matomoRequestEvent } from '@/utils/matomo-request'; const { TabPane } = Tabs; @@ -232,6 +233,21 @@ export const SignTestnetTx = ({ params, origin }: SignTxProps) => { (item) => item.type === currentAccount.type ) ); + wallet.reportStats('createTransaction', { + type: currentAccount.brandName, + category: KEYRING_CATEGORY_MAP[currentAccount.type], + chainId: chain?.serverId || '', + createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', + source: params?.$ctx?.ga?.source || '', + trigger: params?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', + }); + + matomoRequestEvent({ + category: 'Transaction', + action: 'init', + label: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', + }); if (currentAccount.type === KEYRING_TYPE.GnosisKeyring) { setIsGnosisAccount(true); } @@ -441,22 +457,22 @@ export const SignTestnetTx = ({ params, origin }: SignTxProps) => { // return; // } - // await wallet.reportStats('signTransaction', { - // type: currentAccount.brandName, - // chainId: chain.serverId, - // category: KEYRING_CATEGORY_MAP[currentAccount.type], - // preExecSuccess: - // checkErrors.length > 0 || !txDetail?.pre_exec.success ? false : true, - // createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', - // source: params?.$ctx?.ga?.source || '', - // trigger: params?.$ctx?.ga?.trigger || '', - // }); - - // matomoRequestEvent({ - // category: 'Transaction', - // action: 'Submit', - // label: currentAccount.brandName, - // }); + await wallet.reportStats('signTransaction', { + type: currentAccount.brandName, + chainId: chain?.serverId || '', + category: KEYRING_CATEGORY_MAP[currentAccount.type], + preExecSuccess: true, + createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', + source: params?.$ctx?.ga?.source || '', + trigger: params?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', + }); + + matomoRequestEvent({ + category: 'Transaction', + action: 'Submit', + label: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', + }); resolveApproval({ ...transaction, nonce: realNonce || tx.nonce, @@ -467,8 +483,6 @@ export const SignTestnetTx = ({ params, origin }: SignTxProps) => { }); }; - useMount(() => {}); - if (!chain) { return null; } diff --git a/src/ui/views/Approval/components/SignTx.tsx b/src/ui/views/Approval/components/SignTx.tsx index 68801d2e707..2e43fa2ac3a 100644 --- a/src/ui/views/Approval/components/SignTx.tsx +++ b/src/ui/views/Approval/components/SignTx.tsx @@ -1152,6 +1152,7 @@ const SignTx = ({ params, origin }: SignTxProps) => { createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); if (!isViewGnosisSafe) { const params: any = { @@ -1194,6 +1195,7 @@ const SignTx = ({ params, origin }: SignTxProps) => { createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); let newTx; @@ -1363,12 +1365,13 @@ const SignTx = ({ params, origin }: SignTxProps) => { createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); matomoRequestEvent({ category: 'Transaction', action: 'Submit', - label: currentAccount.brandName, + label: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); resolveApproval({ ...transaction, @@ -1655,12 +1658,13 @@ const SignTx = ({ params, origin }: SignTxProps) => { createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', + networkType: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); matomoRequestEvent({ category: 'Transaction', action: 'init', - label: currentAccount.brandName, + label: chain?.isTestnet ? 'Custom Network' : 'Integrated Network', }); if (currentAccount.type === KEYRING_TYPE.GnosisKeyring) { diff --git a/src/ui/views/Approval/components/SwitchChain/SwitchChain.tsx b/src/ui/views/Approval/components/SwitchChain/SwitchChain.tsx index f653012c018..d77f7ff3fd3 100644 --- a/src/ui/views/Approval/components/SwitchChain/SwitchChain.tsx +++ b/src/ui/views/Approval/components/SwitchChain/SwitchChain.tsx @@ -3,7 +3,7 @@ import { createTestnetChain, } from '@/background/service/customTestnet'; import { CustomTestnetForm } from '@/ui/views/CustomTestnet/components/CustomTestnetForm'; -import { useRequest } from 'ahooks'; +import { useMount, useRequest } from 'ahooks'; import { Button, Spin } from 'antd'; import { useForm } from 'antd/lib/form/Form'; import BigNumber from 'bignumber.js'; @@ -14,6 +14,7 @@ import { useApproval, useWallet } from 'ui/utils'; import { SwitchEthereumChainParams } from './type'; import { LoadingOutlined } from '@ant-design/icons'; import { useThemeMode } from '@/ui/hooks/usePreference'; +import { matomoRequestEvent } from '@/utils/matomo-request'; interface SwitchChainProps { data: SwitchEthereumChainParams[]; @@ -65,11 +66,23 @@ const SwitchChain = ({ params }: { params: SwitchChainProps }) => { } ); + useMount(() => { + matomoRequestEvent({ + category: 'Custom Network', + action: 'Dapp Add Network', + }); + }); + const { loading, runAsync: runAddChain } = useRequest( async () => { await form.validateFields(); const values = form.getFieldsValue(); - const res = await wallet.addCustomTestnet(values); + + const res = await wallet.addCustomTestnet(values, { + ga: { + source: 'dapp', + }, + }); if ('error' in res) { form.setFields([ { diff --git a/src/ui/views/Approval/components/WatchAddressWaiting/index.tsx b/src/ui/views/Approval/components/WatchAddressWaiting/index.tsx index f43030a39a7..1de9eb35a8c 100644 --- a/src/ui/views/Approval/components/WatchAddressWaiting/index.tsx +++ b/src/ui/views/Approval/components/WatchAddressWaiting/index.tsx @@ -208,9 +208,10 @@ const WatchAddressWaiting = ({ params }: { params: ApprovalParams }) => { ) { if (!isText && !isSignTriggered) { const explain = explainRef.current; + const chainInfo = findChainByEnum(chain); // const tx = approval.data?.params; - if (explain) { + if (explain || chainInfo?.isTestnet) { // const { nonce, from, chainId } = tx; // const explain = await wallet.getExplainCache({ // nonce: Number(nonce), @@ -220,7 +221,7 @@ const WatchAddressWaiting = ({ params }: { params: ApprovalParams }) => { wallet.reportStats('signTransaction', { type: account.brandName, - chainId: findChainByEnum(chain)?.serverId || '', + chainId: chainInfo?.serverId || '', category: KEYRING_CATEGORY_MAP[account.type], preExecSuccess: explain ? explain?.calcSuccess && explain?.pre_exec.success @@ -228,12 +229,17 @@ const WatchAddressWaiting = ({ params }: { params: ApprovalParams }) => { createBy: params?.$ctx?.ga ? 'rabby' : 'dapp', source: params?.$ctx?.ga?.source || '', trigger: params?.$ctx?.ga?.trigger || '', + networkType: chainInfo?.isTestnet + ? 'Custom Network' + : 'Integrated Network', }); } matomoRequestEvent({ category: 'Transaction', action: 'Submit', - label: account.brandName, + label: chainInfo?.isTestnet + ? 'Custom Network' + : 'Integrated Network', }); isSignTriggered = true; } diff --git a/src/ui/views/CommonPopup/AssetList/CustomTestnetAssetList/CustomTestnetAssetListContainer.tsx b/src/ui/views/CommonPopup/AssetList/CustomTestnetAssetList/CustomTestnetAssetListContainer.tsx index 3dd24825761..64719074fbb 100644 --- a/src/ui/views/CommonPopup/AssetList/CustomTestnetAssetList/CustomTestnetAssetListContainer.tsx +++ b/src/ui/views/CommonPopup/AssetList/CustomTestnetAssetList/CustomTestnetAssetListContainer.tsx @@ -16,6 +16,7 @@ import { useTranslation } from 'react-i18next'; import { EditCustomTestnetModal } from '@/ui/views/CustomTestnet/components/EditTestnetModal'; import { useThemeMode } from '@/ui/hooks/usePreference'; import { isSameTesnetToken } from '@/utils/chain'; +import { matomoRequestEvent } from '@/utils/matomo-request'; interface Props { className?: string; @@ -120,6 +121,10 @@ export const CustomTestnetAssetListContainer: React.FC = ({ 'flex items-center gap-x-[4px] justify-center' )} onClick={() => { + matomoRequestEvent({ + category: 'Custom Network', + action: 'TokenList Add Network', + }); setIsShowAddTestnetModal(true); }} > @@ -199,6 +204,11 @@ export const CustomTestnetAssetListContainer: React.FC = ({ }} /> { setIsShowAddTestnetModal(false); diff --git a/src/ui/views/CustomTestnet/components/EditTestnetModal.tsx b/src/ui/views/CustomTestnet/components/EditTestnetModal.tsx index 53532967fe5..676f527361d 100644 --- a/src/ui/views/CustomTestnet/components/EditTestnetModal.tsx +++ b/src/ui/views/CustomTestnet/components/EditTestnetModal.tsx @@ -47,6 +47,7 @@ export const EditCustomTestnetModal = ({ onChange, height, maskStyle, + ctx, }: { isEdit?: boolean; data?: TestnetChainBase | null; @@ -57,16 +58,28 @@ export const EditCustomTestnetModal = ({ zIndex?: number; height?: number; maskStyle?: React.CSSProperties; + ctx?: { + ga?: { + source?: string; + }; + }; }) => { const wallet = useWallet(); const [isShowAddFromChainList, setIsShowAddFromChainList] = useState(false); const [form] = Form.useForm(); const { loading, runAsync: runAddTestnet } = useRequest( - (data: TestnetChainBase) => { + ( + data: TestnetChainBase, + ctx?: { + ga?: { + source?: string; + }; + } + ) => { return isEdit ? wallet.updateCustomTestnet(data) - : wallet.addCustomTestnet(data); + : wallet.addCustomTestnet(data, ctx); }, { manual: true, @@ -76,7 +89,7 @@ export const EditCustomTestnetModal = ({ const handleSubmit = async () => { await form.validateFields(); const values = form.getFieldsValue(); - const res = await runAddTestnet(values); + const res = await runAddTestnet(values, ctx); if ('error' in res) { form.setFields([ { @@ -133,9 +146,11 @@ export const EditCustomTestnetModal = ({ )} onClick={() => { setIsShowAddFromChainList(true); + const source = ctx?.ga?.source || 'setting'; matomoRequestEvent({ category: 'Custom Network', action: 'Click Add From ChanList', + label: source, }); }} > @@ -184,10 +199,11 @@ export const EditCustomTestnetModal = ({ onSelect={(item) => { form.setFieldsValue(item); setIsShowAddFromChainList(false); + const source = ctx?.ga?.source || 'setting'; matomoRequestEvent({ category: 'Custom Network', action: 'Choose ChainList Network', - label: String(item.id), + label: `${source}_${String(item.id)}`, }); }} /> diff --git a/src/ui/views/CustomTestnet/index.tsx b/src/ui/views/CustomTestnet/index.tsx index bb172eedb0f..dc94b134599 100644 --- a/src/ui/views/CustomTestnet/index.tsx +++ b/src/ui/views/CustomTestnet/index.tsx @@ -174,6 +174,11 @@ export const CustomTestnet = () => { { +}): Chain | TestnetChain | undefined => { const { enum: chainEnum, id, serverId, hex, networkId } = params; if (chainEnum && chainEnum.startsWith('CUSTOM_')) { return findChain({ From 38e0070a9e2b447d7a649aac9f3efeddf91d40b8 Mon Sep 17 00:00:00 2001 From: heisenberg <110591045+heisenberg-2077@users.noreply.github.com> Date: Wed, 24 Apr 2024 15:25:38 +0800 Subject: [PATCH 03/14] fix: catch onekey error messages (#2230) --- .../keyring/eth-onekey-keyring/eth-onekey-keyring.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/background/service/keyring/eth-onekey-keyring/eth-onekey-keyring.ts b/src/background/service/keyring/eth-onekey-keyring/eth-onekey-keyring.ts index c7e14a19a0b..066b6fcdbe1 100644 --- a/src/background/service/keyring/eth-onekey-keyring/eth-onekey-keyring.ts +++ b/src/background/service/keyring/eth-onekey-keyring/eth-onekey-keyring.ts @@ -344,7 +344,9 @@ class OneKeyKeyring extends EventEmitter { tx.s = Buffer.from(payload.s, 'hex'); return tx; } - ).then(resolve); + ) + .then(resolve) + .catch(reject); } else { this._signTransaction( address, @@ -368,7 +370,9 @@ class OneKeyKeyring extends EventEmitter { freeze: Object.isFrozen(tx), }); } - ).then(resolve); + ) + .then(resolve) + .catch(reject); } // This is necessary to avoid popup collision // between the unlock & sign trezor popups From c9deee455756d2adb6a02c73ea47eeb5d38d1adf Mon Sep 17 00:00:00 2001 From: vvvvvv1vvvvvv <86296331+vvvvvv1vvvvvv@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:47:08 +0800 Subject: [PATCH 04/14] fix: typedata address bypass (#2238) --- src/ui/utils/address.ts | 21 +++++++++++++++++++ .../components/TypedDataActions/utils.ts | 7 +++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/ui/utils/address.ts b/src/ui/utils/address.ts index a66dcfe6d07..9c1b1d1ea57 100644 --- a/src/ui/utils/address.ts +++ b/src/ui/utils/address.ts @@ -9,3 +9,24 @@ export const enum AddressType { CONTRACT = 'CONTRACT', UNKNOWN = 'UNKNOWN', } + +export type Hex = `0x${string}`; + +export function add0x(hexadecimal: string): Hex { + if (hexadecimal.startsWith('0x')) { + return hexadecimal as Hex; + } + + if (hexadecimal.startsWith('0X')) { + return `0x${hexadecimal.substring(2)}`; + } + + return `0x${hexadecimal}`; +} + +export function isStrictHexString(value: unknown): value is Hex { + if (typeof value === 'string') { + return /^0x[0-9a-f]+$/iu.test(value); + } + return false; +} diff --git a/src/ui/views/Approval/components/TypedDataActions/utils.ts b/src/ui/views/Approval/components/TypedDataActions/utils.ts index 85bd63c32d5..3b16ef078a5 100644 --- a/src/ui/views/Approval/components/TypedDataActions/utils.ts +++ b/src/ui/views/Approval/components/TypedDataActions/utils.ts @@ -27,6 +27,7 @@ import { ContextActionData } from '@rabby-wallet/rabby-security-engine/dist/rule import BigNumber from 'bignumber.js'; import { getArrayType, isArrayType } from '@metamask/abi-utils/dist/parsers'; import { BigNumber as EthersBigNumber } from 'ethers'; +import { isStrictHexString, add0x } from 'ui/utils/address'; import i18n from '@/i18n'; import { WalletControllerType, getTimeSpan } from '@/ui/utils'; import { @@ -38,7 +39,7 @@ import { ApproveNFTRequireData, fetchNFTApproveRequiredData, } from '../Actions/utils'; -import { CHAINS, ALIAS_ADDRESS } from 'consts'; +import { ALIAS_ADDRESS } from 'consts'; import { Chain } from 'background/service/openapi'; import { findChain, @@ -1171,8 +1172,10 @@ export function normalizeValue(type: string, value: unknown): any { } if (type === 'address') { - if (typeof value === 'string' && !value.startsWith('0x')) { + if (typeof value === 'string' && !/^(0x|0X)/.test(value)) { return EthersBigNumber.from(value).toHexString(); + } else if (isStrictHexString(value)) { + return add0x(value); } } From 9c94d084d6bf9b9ed4b4cb4422a240eb13b29814 Mon Sep 17 00:00:00 2001 From: heisenberg <110591045+heisenberg-2077@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:52:50 +0800 Subject: [PATCH 05/14] fix: sometimes the wc qr code can't appear (#2225) * fix: sometimes the wc qr code can't appear * fix: wc --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b5ab1d3337a..7267031fe33 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@rabby-wallet/eth-lattice-keyring": "1.1.0", "@rabby-wallet/eth-simple-keyring": "5.0.1", "@rabby-wallet/eth-trezor-keyring": "2.5.1", - "@rabby-wallet/eth-walletconnect-keyring": "2.1.2", + "@rabby-wallet/eth-walletconnect-keyring": "2.1.3", "@rabby-wallet/eth-watch-keyring": "1.0.0", "@rabby-wallet/gnosis-sdk": "1.3.6", "@rabby-wallet/page-provider": "0.3.2", diff --git a/yarn.lock b/yarn.lock index 5525f6a9716..423ae44a299 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4549,10 +4549,10 @@ ethereumjs-util "^7.1.5" hdkey "0.8.0" -"@rabby-wallet/eth-walletconnect-keyring@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@rabby-wallet/eth-walletconnect-keyring/-/eth-walletconnect-keyring-2.1.2.tgz#ff369c5c6418006ff3aaadfe8caffe081f8eed38" - integrity sha512-1UjNJFUb4Xym8HTXIybzhJC4xRnbM5TVQny6KEEFkzvU8eNNy5ZKIi/gRk2UsOApf1LbUdSx9KyML4C9tdDVqA== +"@rabby-wallet/eth-walletconnect-keyring@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@rabby-wallet/eth-walletconnect-keyring/-/eth-walletconnect-keyring-2.1.3.tgz#8ea63178e2fa4c9369ba2ea1df6940d016d32c2a" + integrity sha512-Yvx1uCC/E8Zv53vx0ZjHpXL+udZLgLfnER37O04i6pN2aRFmh9SFPh9nnNn7+Nh/i/Q2gz4UziCu6AjIdq5I1w== dependencies: "@ethereumjs/tx" "^3.5.2" "@rabby-wallet/wc-client" "^1.8.10" From 80bb32f06c467ecfb24197278e91b38c4afda7eb Mon Sep 17 00:00:00 2001 From: Nakochi <109920857+Nakochi-crypto@users.noreply.github.com> Date: Fri, 26 Apr 2024 14:36:01 +0900 Subject: [PATCH 06/14] fix: Japanese font issue (#2201) * Fix Japanese font issue * Rename jp to ja * Revert "Rename jp to ja" This reverts commit 851870ac109da185fba2c6b452d83f877e3cdeea. * Change font-family depending on language * Fix index.less * Fix index.less * Fix index.less * Fix index.less * Fix index.less --- _raw/css/Noto+Sans+JP.css | 63 +++++++++++++++++++++++++++++++ src/i18n.ts | 5 +++ src/ui/app.tsx | 5 +-- src/ui/index.html | 1 + src/ui/models/preference.ts | 4 +- src/ui/notification.html | 1 + src/ui/popup.html | 1 + src/ui/style/index.less | 20 +++++++++- src/ui/views/SwitchLang/index.tsx | 4 +- 9 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 _raw/css/Noto+Sans+JP.css diff --git a/_raw/css/Noto+Sans+JP.css b/_raw/css/Noto+Sans+JP.css new file mode 100644 index 00000000000..90a9f882ec2 --- /dev/null +++ b/_raw/css/Noto+Sans+JP.css @@ -0,0 +1,63 @@ +@font-face { + font-family: 'Noto Sans JP'; + font-style: normal; + font-weight: 100; + font-display: swap; + src: url(https://fonts.gstatic.com/s/notosansjp/v52/-F6jfjtqLzI2JPCgQBnw7HFyzSD-AsregP8VFBEi75s.ttf) format('truetype'); +} +@font-face { + font-family: 'Noto Sans JP'; + font-style: normal; + font-weight: 200; + font-display: swap; + src: url(https://fonts.gstatic.com/s/notosansjp/v52/-F6jfjtqLzI2JPCgQBnw7HFyzSD-AsregP8VFJEj75s.ttf) format('truetype'); +} +@font-face { + font-family: 'Noto Sans JP'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url(https://fonts.gstatic.com/s/notosansjp/v52/-F6jfjtqLzI2JPCgQBnw7HFyzSD-AsregP8VFE8j75s.ttf) format('truetype'); +} +@font-face { + font-family: 'Noto Sans JP'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/notosansjp/v52/-F6jfjtqLzI2JPCgQBnw7HFyzSD-AsregP8VFBEj75s.ttf) format('truetype'); +} +@font-face { + font-family: 'Noto Sans JP'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://fonts.gstatic.com/s/notosansjp/v52/-F6jfjtqLzI2JPCgQBnw7HFyzSD-AsregP8VFCMj75s.ttf) format('truetype'); +} +@font-face { + font-family: 'Noto Sans JP'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/notosansjp/v52/-F6jfjtqLzI2JPCgQBnw7HFyzSD-AsregP8VFM8k75s.ttf) format('truetype'); +} +@font-face { + font-family: 'Noto Sans JP'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/notosansjp/v52/-F6jfjtqLzI2JPCgQBnw7HFyzSD-AsregP8VFPYk75s.ttf) format('truetype'); +} +@font-face { + font-family: 'Noto Sans JP'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url(https://fonts.gstatic.com/s/notosansjp/v52/-F6jfjtqLzI2JPCgQBnw7HFyzSD-AsregP8VFJEk75s.ttf) format('truetype'); +} +@font-face { + font-family: 'Noto Sans JP'; + font-style: normal; + font-weight: 900; + font-display: swap; + src: url(https://fonts.gstatic.com/s/notosansjp/v52/-F6jfjtqLzI2JPCgQBnw7HFyzSD-AsregP8VFLgk75s.ttf) format('truetype'); +} diff --git a/src/i18n.ts b/src/i18n.ts index e3cdc09fe01..6c9ced216e6 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -43,4 +43,9 @@ i18n.on('languageChanged', function (lng) { addResourceBundle(lng); }); +export const changeLanguage = (locale: string) => { + i18n.changeLanguage(locale); + document.documentElement.lang = locale; +}; + export default i18n; diff --git a/src/ui/app.tsx b/src/ui/app.tsx index c537284e4dc..692c3596c0e 100644 --- a/src/ui/app.tsx +++ b/src/ui/app.tsx @@ -6,14 +6,13 @@ import { Message } from '@/utils/message'; import { getUITypeName } from 'ui/utils'; import eventBus from '@/eventBus'; import * as Sentry from '@sentry/react'; -import i18n, { addResourceBundle } from 'src/i18n'; +import i18n, { addResourceBundle, changeLanguage } from 'src/i18n'; import { EVENTS } from 'consts'; import type { WalletControllerType } from 'ui/utils/WalletContext'; import store from './store'; -import '../i18n'; import { getSentryEnv, isManifestV3 } from '@/utils/env'; import { updateChainStore } from '@/utils/chain'; @@ -134,7 +133,7 @@ const main = () => { wallet.getLocale().then((locale) => { addResourceBundle(locale).then(() => { - i18n.changeLanguage(locale); + changeLanguage(locale); ReactDOM.render( diff --git a/src/ui/index.html b/src/ui/index.html index 497a604e2e1..59fe47268f2 100644 --- a/src/ui/index.html +++ b/src/ui/index.html @@ -10,6 +10,7 @@ content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover" /> + Rabby Wallet diff --git a/src/ui/models/preference.ts b/src/ui/models/preference.ts index 10bc55099c1..abb9385ad3e 100644 --- a/src/ui/models/preference.ts +++ b/src/ui/models/preference.ts @@ -7,7 +7,7 @@ import { addedToken, } from 'background/service/preference'; import { CHAINS_ENUM, DARK_MODE_TYPE } from 'consts'; -import i18n from '@/i18n'; +import { changeLanguage } from '@/i18n'; interface PreferenceState { externalLinkAck: boolean; @@ -182,7 +182,7 @@ export const preference = createModel()({ dispatch.preference.setField({ locale, }); - i18n.changeLanguage(locale); + changeLanguage(locale); await store.app.wallet.setLocale(locale); dispatch.preference.getPreference('locale'); }, diff --git a/src/ui/notification.html b/src/ui/notification.html index 294fd1327c0..0ab1912450c 100644 --- a/src/ui/notification.html +++ b/src/ui/notification.html @@ -9,6 +9,7 @@ content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover" /> + Rabby Wallet Notification