Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/Emurgo/yoroi-frontend in…
Browse files Browse the repository at this point in the history
…to Ahmed/zendesk
  • Loading branch information
neuodev committed Aug 8, 2022
2 parents ee11fdc + 5ff974b commit 89715c5
Show file tree
Hide file tree
Showing 54 changed files with 603 additions and 181 deletions.
11 changes: 3 additions & 8 deletions .github/workflows/tests.yml
Expand Up @@ -153,16 +153,11 @@ jobs:
- name: Download firmware
working-directory: ../trezor-user-env/src/binaries/firmware/bin/
run: |
sed '/^.*R_LATEST_BUILD.*$/d' download.sh | sed '/^.*trezor_r_master.*$/d' > temp_file.sh
rm download.sh
mv temp_file.sh download.sh
chmod +x download.sh
sudo ./download.sh
run: sudo ./download.sh

- name: Download trezord-go
working-directory: ../trezor-user-env
run: sudo ./src/binaries/trezord-go/bin/download.sh
working-directory: ../trezor-user-env/src/binaries/trezord-go/bin/
run: sudo ./download.sh

- name: Copy the v2-master firmware to the root of the project
working-directory: ../trezor-user-env
Expand Down
4 changes: 4 additions & 0 deletions packages/yoroi-extension/app/App.js
Expand Up @@ -36,6 +36,7 @@ import { ThemeProvider } from '@mui/material/styles';
import { CssBaseline } from '@mui/material';
import { globalStyles } from './styles/globalStyles';
import Support from './components/widgets/Support';
import { trackNavigation } from './api/analytics';

// https://github.com/yahoo/react-intl/wiki#loading-locale-data
addLocaleData([
Expand Down Expand Up @@ -80,6 +81,9 @@ class App extends Component<Props, State> {
this.mergedMessages = _mergedMessages;
});
});
this.props.history.listen(({ pathname }) => {
trackNavigation(pathname);
});
}

state: State = {
Expand Down
Expand Up @@ -353,6 +353,7 @@ export type CatalystRoundInfoRequest = {|

export type CatalystRound = {|
+id: number,
+name: string,
+registrationStart: string,
+registrationEnd: string,
+votingStart: string,
Expand Down
171 changes: 171 additions & 0 deletions packages/yoroi-extension/app/api/analytics/index.js
@@ -0,0 +1,171 @@
// @flow
import cryptoRandomString from 'crypto-random-string';
import querystring from 'querystring';

import LocalStorageApi, {
loadAnalyticsInstanceId,
saveAnalyticsInstanceId,
} from '../localStorage';
import { environment } from '../../environment';
import { TRACKED_ROUTES } from '../../routes-config';
import type { StoresMap } from '../../stores';
import { isTestnet as isTestnetFunc } from '../ada/lib/storage/database/prepackaged/networks';

const MATOMO_URL = 'https://analytics.emurgo-rnd.com/matomo.php';
const SITE_ID = '4';
let INSTANCE_ID;
let stores;

export async function trackStartup(stores_: StoresMap): Promise<void> {
stores = stores_;

let event;
if (await (new LocalStorageApi()).getUserLocale() != null) {
INSTANCE_ID = await loadAnalyticsInstanceId();
if (INSTANCE_ID) {
emitEvent(INSTANCE_ID, 'launch');
return;
}
event = 'pre-existing-instance';
} else {
event = 'new-instance';
}
INSTANCE_ID = generateAnalyticsInstanceId();
await saveAnalyticsInstanceId(INSTANCE_ID);
emitEvent(INSTANCE_ID, event);
}

type NewWalletType = 'hardware' | 'created' | 'restored';

export function trackWalletCreation(newWalletType: NewWalletType): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'new-wallet/' + newWalletType);
}

export function trackNavigation(path: string): void {
if (path.match(TRACKED_ROUTES)) {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'navigate' + path);
}
}

export function trackSend(): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'new-transaction/send');
}

export function trackDelegation(): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'delegation');
}

export function trackWithdrawal(shouldDeregister: boolean): void {
if (INSTANCE_ID == null) {
return;
}
if (shouldDeregister) {
emitEvent(INSTANCE_ID, 'deregister');
} else {
emitEvent(INSTANCE_ID, 'withdrawal');
}
}

export function trackCatalystRegistration(): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'new-transaction/catalyst');
}

export function trackSetLocale(locale: string): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'set-locale/' + locale);
}

export function trackSetUnitOfAccount(unitOfAccount: string): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'unit-of-account/' + unitOfAccount);
}

export function trackUpdateTheme(theme: string): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'update-theme/' + theme);
}

export function trackUriPrompt(choice: 'skip' | 'allow'): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'uri-prompt/' + choice);
}

export function trackBuySellDialog(): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'buy-sell-ada');
}

export function trackExportWallet(): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'export-wallet');
}

export function trackRemoveWallet(): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'remove-wallet');
}

export function trackResyncWallet(): void {
if (INSTANCE_ID == null) {
return;
}
emitEvent(INSTANCE_ID, 'resync-wallet');
}

function generateAnalyticsInstanceId(): string {
// Matomo requires 16 character hex string
return cryptoRandomString({ length: 16 });
}

function emitEvent(instanceId: string, event: string): void {
if (environment.isDev() || environment.isTest()) {
return;
}

const isTestnet = stores.profile.selectedNetwork != null ?
isTestnetFunc(stores.profile.selectedNetwork) :
false;

// https://developer.matomo.org/api-reference/tracking-api
const params = {
idsite: SITE_ID,
rec: '1',
action_name: (isTestnet ? 'testnet/' : '') + event,
url: `yoroi.extension/${isTestnet ? 'testnet/' : ''}${event}`,
_id: INSTANCE_ID,
rand: `${Date.now()}-${Math.random()}`,
apiv: '1'
};
const url = `${MATOMO_URL}?${querystring.stringify(params)}`;

fetch(url);
}
10 changes: 10 additions & 0 deletions packages/yoroi-extension/app/api/localStorage/index.js
Expand Up @@ -32,6 +32,7 @@ const storageKeys = {
TOGGLE_SIDEBAR: networkForLocalStorage + '-TOGGLE-SIDEBAR',
WALLETS_NAVIGATION: networkForLocalStorage + '-WALLETS-NAVIGATION',
SUBMITTED_TRANSACTIONS: 'submittedTransactions',
ANALYTICS_INSTANCE_ID: networkForLocalStorage + '-ANALYTICS',
// ========== CONNECTOR ========== //
ERGO_CONNECTOR_WHITELIST: 'connector_whitelist',
};
Expand Down Expand Up @@ -360,3 +361,12 @@ export function loadSubmittedTransactions(): any {
}
return JSON.parse(dataStr);
}

export async function loadAnalyticsInstanceId(): Promise<?string> {
return getLocalItem(storageKeys.ANALYTICS_INSTANCE_ID);
}

export async function saveAnalyticsInstanceId(id: string): Promise<void> {
await setLocalItem(storageKeys.ANALYTICS_INSTANCE_ID, id);
}

Expand Up @@ -15,6 +15,7 @@ import { ReactComponent as VerifyIcon } from '../../assets/images/verify-icon.i
import VerticalFlexContainer from '../layout/VerticalFlexContainer'
import LoadingSpinner from '../widgets/LoadingSpinner'
import globalMessages from '../../i18n/global-messages';
import { trackBuySellDialog } from '../../api/analytics';

const messages = defineMessages({
dialogTitle: {
Expand Down Expand Up @@ -77,6 +78,7 @@ export default class BuySellDialog extends Component<Props, State> {
}
]
this.setState({ walletList: wallets })
trackBuySellDialog();
}

createRows: ($npm$ReactIntl$IntlFormat, Array<WalletInfo>) => Node = (intl, wallets) => (
Expand Down
Expand Up @@ -20,6 +20,7 @@ import {
} from '../../../../api/ada/lib/storage/models/ConceptualWallet';
import type { SendUsingLedgerParams } from '../../../../actions/ada/ledger-send-actions';
import type { SendUsingTrezorParams } from '../../../../actions/ada/trezor-send-actions';
import { trackSend } from '../../../../api/analytics';

export type GeneratedData = typeof WalletSendPreviewStepContainer.prototype.generated;

Expand Down Expand Up @@ -90,6 +91,7 @@ export default class WalletSendPreviewStepContainer extends Component<Props> {
onSuccess: openTransactionSuccessDialog,
});
}
trackSend()
}

render(): Node {
Expand Down
@@ -0,0 +1,113 @@
// @flow
import type { Node } from 'react';
import { Box } from '@mui/system';
import { CircularProgress, Stack, Typography } from '@mui/material';

type Props = {|
+percentage: number,
+days: string,
+currentEpoch: number,
+startEpochDate: string,
+endEpochDate: string,
|};

export function EpochProgressCard({
percentage,
days,
currentEpoch,
startEpochDate,
endEpochDate,
}: Props): Node {
return (
<Box>
<Stack direction="row" spacing={2} justifyContent="flex-start">
<Graph value={percentage} days={days} />
<Stack direction="column" flexGrow="1">
<Title label="Current Epoch" value={currentEpoch} />
<Stack direction="row" spacing={3} mt="50px" justifyContent="space-between">
<LabelWithValue label="Epoch started at" value={startEpochDate} />
<LabelWithValue label="Epoch ends at" value={endEpochDate} />
</Stack>
</Stack>
</Stack>
</Box>
);
}

type TitleProps = {|
+label: string,
+value: string | number,
|};
const Title = ({ label, value }: TitleProps): Node => {
return (
<Box>
<Typography fontWeight="500" color="var(--yoroi-palette-primary-300)">
{label}: {value}
</Typography>
</Box>
);
};

type InfoColumnProps = {|
+label: string,
+value: string | number,
|};
const LabelWithValue = ({ label, value }: InfoColumnProps): Node => {
return (
<Box>
<Typography
style={{ textTransform: 'uppercase' }}
variant="caption"
mb="4px"
color="var(--yoroi-palette-gray-600)"
>
{label}
</Typography>
<Typography color="var(--yoroi-palette-gray-900)">{value}</Typography>
</Box>
);
};

const Graph = ({ value, days }): Node => {
return (
<Box mr="8px" position="relative" display="flex" justifyContent="center">
<CircularProgress
size={120}
thickness={7}
variant="determinate"
value={value}
sx={{
color: 'var(--yoroi-palette-primary-300)',
animationDuration: '550ms',
position: 'absolute',
zIndex: 1,
}}
/>
<CircularProgress
size={120}
thickness={7}
variant="determinate"
sx={{
color: 'var(--yoroi-palette-gray-50)',
}}
value={100}
/>
<Box
position="absolute"
sx={{
top: '30%',
left: '50%',
transform: 'translate(-50%)',
textAlign: 'center',
}}
>
<Typography variant="h4" color="var(--yoroi-palette-gray-900)">
{value}%
</Typography>
<Typography variant="caption1" fontSize="12px" color="var(--yoroi-palette-gray-600)">
{days} days
</Typography>
</Box>
</Box>
);
};

0 comments on commit 89715c5

Please sign in to comment.