Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fathom Analytics #510

Merged
merged 5 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
<script lang="ts">
import { getAntelope } from 'src/antelope';
import { defineComponent } from 'vue';

import { getAntelope, useChainStore } from 'src/antelope';
import { TELOS_NETWORK_NAMES } from 'src/antelope/mocks/chain-constants';

export const isTodayBeforeTelosCloudDown = new Date().getTime() < new Date('2023-12-31').getTime();

export default defineComponent({
name: 'App',
mounted() {
const network = useChainStore().currentChain.settings.getNetwork();
if (TELOS_NETWORK_NAMES.includes(network)) {
const script = document.createElement('script');
script.src = 'https://cdn.usefathom.com/script.js';
script.dataset.site = 'PDKJSBKL';
script.dataset.spa = 'auto';
script.defer = true;
document.body.appendChild(script);
}

if (isTodayBeforeTelosCloudDown) {
getAntelope().config.notifyRememberInfoHandler(
this.$t('temporal.telos_cloud_discontinued_title'),
Expand Down
4 changes: 2 additions & 2 deletions src/antelope/mocks/AccountStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ class AccountStore {
} as AccountModel;
}

async loginEVM({ authenticator, network }: LoginEVMActionData): Promise<boolean> {
async loginEVM({ authenticator, network }: LoginEVMActionData, trackAnalyticsEvents: boolean): Promise<boolean> {
currentAuthenticator = authenticator;
currentAccount = await authenticator.login(network);
currentAccount = await authenticator.login(network, trackAnalyticsEvents);
const account = useAccountStore().getAccount(authenticator.label);
getAntelope().events.onLoggedIn.next(account);
return true;
Expand Down
11 changes: 10 additions & 1 deletion src/antelope/mocks/ChainStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
// Mocking ChainStore -----------------------------------
declare const fathom: { trackGoal: (eventId: string, value: 0) => void };

import { RpcEndpoint } from 'universal-authenticator-library';
import { NativeCurrencyAddress, TokenClass } from 'src/antelope/types';
Expand All @@ -23,7 +24,15 @@ export interface EVMChainSettings {
const settings = {
getChainId: () => process.env.NETWORK_EVM_CHAIN_ID,
getDisplay: () => process.env.NETWORK_EVM_DISPLAY,
trackAnalyticsEvent: () => void 0,
trackAnalyticsEvent(params: Record<string, unknown>): void {
if (typeof fathom === 'undefined') {
console.warn(`Failed to track event with ID ${params.id}: Fathom Analytics not loaded`);
return;
}

const id = params.id as string;
fathom.trackGoal(id, 0);
},
getRPCEndpoint: () => {
// extract the url parts
const regex = /^(https?):\/\/([^:/]+)(?::(\d+))?(\/.*)?$/;
Expand Down
2 changes: 1 addition & 1 deletion src/antelope/mocks/EVMStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class EVMStore {
if (!authenticator) {
console.error('Inconsistency: logged account authenticator is null', authenticator);
} else {
useAccountStore().loginEVM({ authenticator, network });
useAccountStore().loginEVM({ authenticator, network }, false);
}
}
} else {
Expand Down
4 changes: 3 additions & 1 deletion src/antelope/wallets/authenticators/EVMAuthenticator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ export abstract class EVMAuthenticator {
return (useChainStore().getChain(this.label).settings as EVMChainSettings);
}

async login(network: string): Promise<addressString | null> {
async login(network: string, trackAnalyticsEvents?: boolean): Promise<addressString | null> {
this.trace('login', network);
this.trace('Login analytics enabled =', trackAnalyticsEvents);

const chain = useChainStore();
try {
chain.setChain(CURRENT_CONTEXT, network);
Expand Down
20 changes: 12 additions & 8 deletions src/antelope/wallets/authenticators/InjectedProviderAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,20 +132,23 @@ export abstract class InjectedProviderAuth extends EVMAuthenticator {
});
}

async login(network: string): Promise<addressString | null> {
async login(network: string, trackAnalyticsEvents?: boolean): Promise<addressString | null> {
const chainSettings = this.getChainSettings();
const authName = this.getName();
const isTelos = TELOS_NETWORK_NAMES.includes(network);

this.trace('login', network);
useFeedbackStore().setLoading(`${this.getName()}.login`);

this.trace('login', 'trackAnalyticsEvent -> login started');
chainSettings.trackAnalyticsEvent(
{ id: TELOS_ANALYTICS_EVENT_IDS.loginStarted },
);
if (isTelos && trackAnalyticsEvents) {
this.trace('login', 'trackAnalyticsEvent -> login started');
chainSettings.trackAnalyticsEvent(
{ id: TELOS_ANALYTICS_EVENT_IDS.loginStarted },
);
}

const response = await super.login(network).then((res) => {
if (TELOS_NETWORK_NAMES.includes(network)) {
const response = await super.login(network, trackAnalyticsEvents).then((res) => {
if (isTelos && trackAnalyticsEvents && TELOS_NETWORK_NAMES.includes(network)) {
let successfulLoginEventId = '';

if (authName === MetamaskAuthName) {
Expand All @@ -171,7 +174,8 @@ export abstract class InjectedProviderAuth extends EVMAuthenticator {
}).catch((error) => {
// if the user rejects the connection, we don't want to track it as an error
if (
TELOS_NETWORK_NAMES.includes(network) &&
trackAnalyticsEvents &&
isTelos &&
error.message !== 'antelope.evm.error_connect_rejected'
) {
let failedLoginEventId = '';
Expand Down
94 changes: 51 additions & 43 deletions src/antelope/wallets/authenticators/WalletConnectAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import {
import { EVMAuthenticator } from 'src/antelope/wallets';
import { RpcEndpoint } from 'universal-authenticator-library';
import { toRaw } from 'vue';
import { TELOS_ANALYTICS_EVENT_IDS } from 'src/antelope/mocks/chain-constants';
import { TELOS_ANALYTICS_EVENT_IDS, TELOS_NETWORK_NAMES } from 'src/antelope/mocks/chain-constants';

const name = 'WalletConnect';

Expand Down Expand Up @@ -81,9 +81,10 @@ export class WalletConnectAuth extends EVMAuthenticator {
return new WalletConnectAuth(this.options, this.wagmiClient, label);
}

async walletConnectLogin(network: string): Promise<addressString | null> {
async walletConnectLogin(network: string, trackAnalyticsEvents: boolean): Promise<addressString | null> {
this.trace('walletConnectLogin');
const chainSettings = this.getChainSettings();
const isOnTelos = TELOS_NETWORK_NAMES.includes(chainSettings.getNetwork());

try {
this.clearAuthenticator();
Expand Down Expand Up @@ -113,70 +114,77 @@ export class WalletConnectAuth extends EVMAuthenticator {
console.error(e);
}

this.trace(
'login',
'trackAnalyticsEvent -> login successful',
'WalletConnect',
TELOS_ANALYTICS_EVENT_IDS.loginSuccessfulWalletConnect,
);
chainSettings.trackAnalyticsEvent(
{ id: TELOS_ANALYTICS_EVENT_IDS.loginSuccessfulWalletConnect },
);
this.trace(
'login',
'trackAnalyticsEvent -> generic login successful',
TELOS_ANALYTICS_EVENT_IDS.loginSuccessful,
);
chainSettings.trackAnalyticsEvent(
{ id: TELOS_ANALYTICS_EVENT_IDS.loginSuccessful },
);
if (isOnTelos && trackAnalyticsEvents) {
this.trace(
'login',
'trackAnalyticsEvent -> login successful',
'WalletConnect',
TELOS_ANALYTICS_EVENT_IDS.loginSuccessfulWalletConnect,
);
chainSettings.trackAnalyticsEvent(
{ id: TELOS_ANALYTICS_EVENT_IDS.loginSuccessfulWalletConnect },
);
this.trace(
'login',
'trackAnalyticsEvent -> generic login successful',
TELOS_ANALYTICS_EVENT_IDS.loginSuccessful,
);
chainSettings.trackAnalyticsEvent(
{ id: TELOS_ANALYTICS_EVENT_IDS.loginSuccessful },
);
}

return address;
} catch (e) {
// This is a non-expected error
console.error(e);
this.trace(
'walletConnectLogin',
'trackAnalyticsEvent -> login failed',
'WalletConnect',
TELOS_ANALYTICS_EVENT_IDS.loginFailedWalletConnect,
);
const chainSettings = this.getChainSettings();
chainSettings.trackAnalyticsEvent(
{ id: TELOS_ANALYTICS_EVENT_IDS.loginFailedWalletConnect },
);
if (isOnTelos && trackAnalyticsEvents) {
this.trace(
'walletConnectLogin',
'trackAnalyticsEvent -> login failed',
'WalletConnect',
TELOS_ANALYTICS_EVENT_IDS.loginFailedWalletConnect,
);
const chainSettings = this.getChainSettings();
chainSettings.trackAnalyticsEvent(
{ id: TELOS_ANALYTICS_EVENT_IDS.loginFailedWalletConnect },
);
}
throw new AntelopeError('antelope.evm.error_login');
} finally {
useFeedbackStore().unsetLoading(`${this.getName()}.login`);
}
}

async login(network: string): Promise<addressString | null> {
async login(network: string, trackAnalyticsEvents: boolean): Promise<addressString | null> {
this.trace('login', network);
const wagmiConnected = () => localStorage.getItem('wagmi.connected');
const chainSettings = this.getChainSettings();
const isOnTelos = TELOS_NETWORK_NAMES.includes(chainSettings.getNetwork());

useFeedbackStore().setLoading(`${this.getName()}.login`);
if (wagmiConnected()) {
// We are in auto-login process. So log loginStarted before calling the walletConnectLogin method
this.trace(
'login',
'trackAnalyticsEvent -> login started',
'WalletConnect',
TELOS_ANALYTICS_EVENT_IDS.loginStarted,
);
chainSettings.trackAnalyticsEvent(
{ id: TELOS_ANALYTICS_EVENT_IDS.loginStarted },
);
return this.walletConnectLogin(network);
if (isOnTelos && trackAnalyticsEvents) {
this.trace(
'login',
'trackAnalyticsEvent -> login started',
'WalletConnect',
TELOS_ANALYTICS_EVENT_IDS.loginStarted,
);
chainSettings.trackAnalyticsEvent(
{ id: TELOS_ANALYTICS_EVENT_IDS.loginStarted },
);
}
return this.walletConnectLogin(network, trackAnalyticsEvents);
} else {
return new Promise((resolve) => {
this.trace('login', 'web3Modal.openModal()');

this.unsubscribeWeb3Modal = this.web3Modal.subscribeModal(async (newState: {open:boolean}) => {
this.trace('login', 'web3Modal.subscribeModal ', toRaw(newState), wagmiConnected);

if (newState.open === true) {
if (isOnTelos && newState.open === true && trackAnalyticsEvents) {
this.trace(
'login',
'trackAnalyticsEvent -> login started',
Expand All @@ -191,7 +199,7 @@ export class WalletConnectAuth extends EVMAuthenticator {
if (newState.open === false) {
useFeedbackStore().unsetLoading(`${this.getName()}.login`);

if (!wagmiConnected()) {
if (isOnTelos && !wagmiConnected() && trackAnalyticsEvents) {
this.trace(
'login',
'trackAnalyticsEvent -> login failed',
Expand All @@ -212,7 +220,7 @@ export class WalletConnectAuth extends EVMAuthenticator {
}

if (wagmiConnected()) {
resolve(this.walletConnectLogin(network));
resolve(this.walletConnectLogin(network, true));
}
});
this.web3Modal.openModal();
Expand Down
2 changes: 1 addition & 1 deletion src/components/LoginModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ export default defineComponent({
}
const authenticator = auth.newInstance(label);
const network = useChainStore().currentChain.settings.getNetwork();
useAccountStore().loginEVM({ authenticator, network }).then(() => {
useAccountStore().loginEVM({ authenticator, network }, true).then(() => {
const address = useAccountStore().getAccount(label).account;
this.setLogin({ address });
localStorage.setItem(LOGIN_DATA_KEY, JSON.stringify({
Expand Down
Loading