Skip to content

Commit

Permalink
feat(wallet-dashboard): Add amplitude events (#5010)
Browse files Browse the repository at this point in the history
* feat(dashboard): Integrate Amplitude

* manypkg

* prettier fix dashboard

* missing header

* feat(wallet-dashboard): Add more amplitude events

* fix: format code

* chore: Add `walletDashboardRev`

* chore: bring back disabled check

* fix(dashboard): modify the license header in the prepend file

* fix(dashboard): remove isTimelock for migration amplitude event

* fix(dashboard): lint

* fix(dashboard): remove duplicate file

---------

Co-authored-by: cpl121 <[email protected]>
Co-authored-by: cpl121 <[email protected]>
Co-authored-by: Begoña Álvarez de la Cruz <[email protected]>
  • Loading branch information
4 people authored Jan 30, 2025
1 parent 345082a commit 6caf3cb
Show file tree
Hide file tree
Showing 16 changed files with 495 additions and 29 deletions.
4 changes: 2 additions & 2 deletions apps/wallet-dashboard/ampli.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"WorkspaceId": "72fb85fc-aed9-46ef-83a2-9345888a1678",
"SourceId": "ca44ad20-3cfd-4618-aa11-4b8befb0b123",
"Branch": "main",
"Version": "1.0.0",
"VersionId": "954386e3-441d-4aa5-b9ad-1f01e0a20e55",
"Version": "3.0.0",
"VersionId": "fd563f8a-ce76-4f47-a8f5-296a8ac394f8",
"Runtime": "browser:typescript-ampli-v2",
"Platform": "Browser",
"Language": "TypeScript",
Expand Down
7 changes: 7 additions & 0 deletions apps/wallet-dashboard/app/(protected)/assets/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Warning } from '@iota/apps-ui-icons';

import { AssetTileLink, Loading } from '@/components';
import { AssetDialog } from '@/components/dialogs/assets';
import { ampli } from '@/lib/utils/analytics';

const ASSET_CATEGORIES: { label: string; value: AssetCategory }[] = [
{
Expand Down Expand Up @@ -63,6 +64,12 @@ export default function AssetsDashboardPage(): React.JSX.Element {

function onAssetClick(asset: IotaObjectData) {
setSelectedAsset(asset);
if (selectedAssetCategory === AssetCategory.Visual) {
ampli.clickedCollectibleCard({
objectId: asset.objectId,
collectibleType: asset.type!,
});
}
}

return (
Expand Down
2 changes: 2 additions & 0 deletions apps/wallet-dashboard/app/(protected)/vesting/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import { useEffect, useState } from 'react';
import { StakedTimelockObject } from '@/components';
import { IotaSignAndExecuteTransactionOutput } from '@iota/wallet-standard';
import toast from 'react-hot-toast';
import { ampli } from '@/lib/utils/analytics';

export default function VestingDashboardPage(): JSX.Element {
const [timelockedObjectsToUnstake, setTimelockedObjectsToUnstake] =
Expand Down Expand Up @@ -180,6 +181,7 @@ export default function VestingDashboardPage(): JSX.Element {
{
onSuccess: (tx) => {
handleOnSuccess(tx.digest);
ampli.timelockCollect();
},
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { AssetsDialogView } from './constants';
import { TransactionDetailsView } from '../send-token';
import { DialogLayout } from '../layout';
import toast from 'react-hot-toast';
import { ampli } from '@/lib/utils/analytics';

interface AssetsDialogProps {
onClose: () => void;
Expand Down Expand Up @@ -80,6 +81,9 @@ export function AssetDialog({ onClose, asset, refetchAssets }: AssetsDialogProps
refetchAssets();
toast.success('Transfer transaction successful');
setView(AssetsDialogView.TransactionDetails);
ampli.sentCollectible({
objectId,
});
} catch {
toast.error('Transfer transaction failed');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import toast from 'react-hot-toast';
import { TransactionDialogView } from '../TransactionDialog';
import { MigrationDialogView } from './enums';
import { ConfirmMigrationView } from './views';
import { ampli } from '@/lib/utils/analytics';

interface MigrationDialogProps {
handleClose: () => void;
Expand Down Expand Up @@ -54,6 +55,10 @@ export function MigrationDialog({
onSuccess(tx.digest);
setTxDigest(tx.digest);
setView(MigrationDialogView.TransactionDetails);
ampli.migration({
basicOutputObjects: basicOutputObjects.length,
nftOutputObjects: nftOutputObjects.length,
});
},
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { INITIAL_VALUES } from './constants';
import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils';
import { useTransferTransactionMutation } from '@/hooks';
import toast from 'react-hot-toast';
import { ampli } from '@/lib/utils/analytics';
import { useQueryClient } from '@tanstack/react-query';

interface SendCoinDialogProps {
Expand Down Expand Up @@ -69,6 +70,9 @@ function SendTokenDialogBody({

setStep(FormStep.TransactionDetails);
toast.success('Transfer transaction has been sent');
ampli.sentCoins({
coinType: selectedCoin.coinType,
});
},
onError: () => {
setOpen(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { Dialog } from '@iota/apps-ui-kit';
import { DetailsView } from './views';
import { TransactionDialogView } from '../TransactionDialog';
import { StakeDialogView } from './enums/view.enums';
import { ampli } from '@/lib/utils/analytics';

const INITIAL_VALUES = {
amount: '',
Expand Down Expand Up @@ -92,6 +93,10 @@ export function StakeDialog({

function handleValidatorSelect(validator: string): void {
setSelectedValidator?.(validator);

ampli.selectValidator({
validatorAddress: validator,
});
}

function setViewBasedOnStakingType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { useState } from 'react';
import { ExtendedDelegatedStake } from '@iota/core';
import { StakeDialogView } from '../enums/view.enums';
import { ampli } from '@/lib/utils/analytics';

export function useStakeDialog() {
const [stakeDialogView, setStakeDialogView] = useState<StakeDialogView | undefined>();
Expand All @@ -21,6 +22,9 @@ export function useStakeDialog() {
function handleNewStake() {
setSelectedStake(null);
setStakeDialogView(StakeDialogView.SelectValidator);
ampli.clickedStakeIota({
isCurrentlyStaking: true,
});
}

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
// SPDX-License-Identifier: Apache-2.0

import { useFormatCoin, useBalance, CoinFormat, parseAmount, useCoinMetadata } from '@iota/core';
import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils';
import { IOTA_TYPE_ARG, NANOS_PER_IOTA } from '@iota/iota-sdk/utils';
import { useFormikContext } from 'formik';
import { useSignAndExecuteTransaction } from '@iota/dapp-kit';
import { useNewStakeTransaction } from '@/hooks';
import { EnterAmountDialogLayout } from './EnterAmountDialogLayout';
import toast from 'react-hot-toast';
import { ampli } from '@/lib/utils/analytics';

export interface FormValues {
amount: string;
Expand Down Expand Up @@ -75,6 +76,9 @@ export function EnterAmountView({
onSuccess(tx.digest);
toast.success('Stake transaction has been sent');
resetForm();
ampli.stakedIota({
stakedAmount: Number(BigInt(values.amount) / NANOS_PER_IOTA),
});
},
onError: () => {
toast.error('Stake transaction was not sent');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@

import { useMemo } from 'react';
import { useFormatCoin, CoinFormat, useGetAllOwnedObjects, TIMELOCK_IOTA_TYPE } from '@iota/core';
import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils';
import { IOTA_TYPE_ARG, NANOS_PER_IOTA } from '@iota/iota-sdk/utils';
import { useFormikContext } from 'formik';
import { useSignAndExecuteTransaction } from '@iota/dapp-kit';
import { useGetCurrentEpochStartTimestamp, useNewStakeTimelockedTransaction } from '@/hooks';
import {
getAmountFromGroupedTimelockObjects,
useGetCurrentEpochStartTimestamp,
useNewStakeTimelockedTransaction,
} from '@/hooks';
import { prepareObjectsForTimelockedStakingTransaction } from '@/lib/utils';
import { EnterAmountDialogLayout } from './EnterAmountDialogLayout';
import toast from 'react-hot-toast';
import { ampli } from '@/lib/utils/analytics';

interface FormValues {
amount: string;
Expand Down Expand Up @@ -42,20 +47,19 @@ export function EnterTimelockedAmountView({
StructType: TIMELOCK_IOTA_TYPE,
});
const groupedTimelockObjects = useMemo(() => {
if (timelockedObjects && currentEpochMs) {
return prepareObjectsForTimelockedStakingTransaction(
timelockedObjects,
amountWithoutDecimals,
currentEpochMs,
);
} else {
return [];
}
if (!timelockedObjects || !currentEpochMs) return [];
return prepareObjectsForTimelockedStakingTransaction(
timelockedObjects,
amountWithoutDecimals,
currentEpochMs,
);
}, [timelockedObjects, currentEpochMs, amountWithoutDecimals]);

const { data: newStakeData, isLoading: isTransactionLoading } =
useNewStakeTimelockedTransaction(selectedValidator, senderAddress, groupedTimelockObjects);

const stakedAmount = getAmountFromGroupedTimelockObjects(groupedTimelockObjects);

const hasGroupedTimelockObjects = groupedTimelockObjects.length > 0;

const [maxTokenFormatted, maxTokenFormattedSymbol] = useFormatCoin(
Expand Down Expand Up @@ -85,6 +89,10 @@ export function EnterTimelockedAmountView({
onSuccess: (tx) => {
onSuccess?.(tx.digest);
toast.success('Stake transaction has been sent');
ampli.timelockStake({
stakedAmount: Number(stakedAmount / NANOS_PER_IOTA),
validatorAddress: senderAddress,
});
resetForm();
},
onError: () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
import { useCurrentAccount, useSignAndExecuteTransaction } from '@iota/dapp-kit';
import { IotaSignAndExecuteTransactionOutput } from '@iota/wallet-standard';
import toast from 'react-hot-toast';
import { ampli } from '@/lib/utils/analytics';

interface UnstakeTimelockedObjectsViewProps {
onClose: () => void;
Expand Down Expand Up @@ -84,6 +85,9 @@ export function UnstakeTimelockedObjectsView({
onSuccess: (tx) => {
toast.success('Unstake transaction has been sent');
onSuccess(tx);
ampli.timelockUnstake({
validatorAddress: groupedTimelockedObjects.validatorAddress,
});
},
},
).catch(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { DialogLayout, DialogLayoutFooter, DialogLayoutBody } from '../../layout
import { useNewUnstakeTransaction } from '@/hooks';
import { IotaSignAndExecuteTransactionOutput } from '@iota/wallet-standard';
import toast from 'react-hot-toast';
import { ampli } from '@/lib/utils/analytics';

interface UnstakeDialogProps {
extendedStake: ExtendedDelegatedStake;
Expand Down Expand Up @@ -84,6 +85,10 @@ export function UnstakeView({
onSuccess: (tx) => {
toast.success('Unstake transaction has been sent');
onSuccess(tx);

ampli.unstakedIota({
validatorAddress: extendedStake.validatorAddress,
});
},
},
).catch(() => {
Expand Down
14 changes: 10 additions & 4 deletions apps/wallet-dashboard/hooks/useNewStakeTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,21 @@ export function useNewStakeTransaction(validator: string, amount: bigint, sender
});
}

export function getAmountFromGroupedTimelockObjects(
groupedTimelockObjects: GroupedTimelockObject[],
): bigint {
return groupedTimelockObjects.reduce(
(acc, obj) => acc + (obj.totalLockedAmount - (obj.splitAmount ?? 0n)),
0n,
);
}

export function useNewStakeTimelockedTransaction(
validator: string,
senderAddress: string,
groupedTimelockObjects: GroupedTimelockObject[],
) {
const amount = groupedTimelockObjects.reduce(
(acc, obj) => acc + (obj.totalLockedAmount - (obj.splitAmount ?? 0n)),
0n,
);
const amount = getAmountFromGroupedTimelockObjects(groupedTimelockObjects);
const client = useIotaClient();
return useQuery({
// eslint-disable-next-line @tanstack/query/exhaustive-deps
Expand Down
4 changes: 4 additions & 0 deletions apps/wallet-dashboard/hooks/usePersistedNetwork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { NetworkConfiguration } from '@iota/iota-sdk/client';
import { useLocalStorage } from '@iota/core';
import toast from 'react-hot-toast';
import { useEffect } from 'react';
import { ampli } from '@/lib/utils/analytics';

export function usePersistedNetwork() {
const clientContext = useIotaClientContext();
Expand All @@ -26,6 +27,9 @@ export function usePersistedNetwork() {
clientContext.selectNetwork(network.id);
setPersistedNetwork(network.id);
toast.success(`Switched to ${network.name}`);
ampli.switchedNetwork({
toNetwork: network.name,
});
}

useEffect(() => {
Expand Down
Loading

0 comments on commit 6caf3cb

Please sign in to comment.