Skip to content

Commit

Permalink
feat(jumpstart): add analytics to the reclaim flow (#5163)
Browse files Browse the repository at this point in the history
### Description

As title says, it adds analytics to the reclaim flow

### Test plan

Unit test

### Related issues

- Fixes RET-1003

### Backwards compatibility

Y

---------

Co-authored-by: Kathy Luo <kathyluo18@gmail.com>
  • Loading branch information
dievazqu and kathaypacific committed Mar 28, 2024
1 parent 8678ced commit 69c85cc
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 33 deletions.
8 changes: 8 additions & 0 deletions src/analytics/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,14 @@ export enum JumpstartEvents {
jumpstart_claim_loading_dismissed = 'jumpstart_claim_loading_dismissed',
jumpstart_claim_error_dismissed = 'jumpstart_claim_error_dismissed',
jumpstart_claim_error_contact_support = 'jumpstart_claim_error_contact_support',
jumpstart_reclaim_press = 'jumpstart_reclaim_press',
jumpstart_reclaim_start = 'jumpstart_reclaim_start',
jumpstart_reclaim_failed = 'jumpstart_reclaim_failed',
jumpstart_reclaim_succeeded = 'jumpstart_reclaim_succeeded',
jumpstart_reclaim_dismiss_error = 'jumpstart_reclaim_dismiss_error',
jumpstart_reclaim_contact_support = 'jumpstart_reclaim_contact_support',
jumpstart_claim_status_fetch_success = 'jumpstart_claim_status_fetch_success',
jumpstart_claim_status_fetch_error = 'jumpstart_claim_status_fetch_error',
}

export enum PointsEvents {
Expand Down
20 changes: 18 additions & 2 deletions src/analytics/Properties.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
OnboardingEvents,
PerformanceEvents,
PhoneVerificationEvents,
PointsEvents,
QrScreenEvents,
RewardsEvents,
SendEvents,
Expand All @@ -42,7 +43,6 @@ import {
TransactionEvents,
WalletConnectEvents,
WebViewEvents,
PointsEvents,
} from 'src/analytics/Events'
import {
BackQuizProgress,
Expand All @@ -67,13 +67,13 @@ import { LocalCurrencyCode } from 'src/localCurrency/consts'
import { NftOrigin } from 'src/nfts/types'
import { NotificationReceiveState } from 'src/notifications/types'
import { AdventureCardName } from 'src/onboarding/types'
import { PointsActivity } from 'src/points/types'
import { RecipientType } from 'src/recipients/recipient'
import { QrCode } from 'src/send/types'
import { Field } from 'src/swap/types'
import { TokenDetailsActionName } from 'src/tokens/types'
import { NetworkId, TokenTransactionTypeV2, TransactionStatus } from 'src/transactions/types'
import { Currency } from 'src/utils/currencies'
import { PointsActivity } from 'src/points/types'

type Web3LibraryProps = { web3Library: 'contract-kit' | 'viem' }

Expand Down Expand Up @@ -1511,6 +1511,10 @@ interface JumpstartSendProperties extends JumpstartDepositProperties {
tokenSymbol: string
tokenAmount: string | null
}
interface JumpstartReclaimProperties {
networkId: NetworkId
depositTxHash: string
}
export enum JumpstartShareOrigin {
QrScreen = 'qrScreen',
MainScreen = 'mainScreen',
Expand Down Expand Up @@ -1553,6 +1557,18 @@ interface JumpstartEventsProperties {
[JumpstartEvents.jumpstart_claim_loading_dismissed]: undefined
[JumpstartEvents.jumpstart_claim_error_dismissed]: undefined
[JumpstartEvents.jumpstart_claim_error_contact_support]: undefined
[JumpstartEvents.jumpstart_reclaim_press]: JumpstartReclaimProperties
[JumpstartEvents.jumpstart_reclaim_start]: JumpstartReclaimProperties
[JumpstartEvents.jumpstart_reclaim_failed]: JumpstartReclaimProperties
[JumpstartEvents.jumpstart_reclaim_succeeded]: JumpstartReclaimProperties & {
reclaimTxHash: string
}
[JumpstartEvents.jumpstart_reclaim_dismiss_error]: JumpstartReclaimProperties
[JumpstartEvents.jumpstart_reclaim_contact_support]: undefined
[JumpstartEvents.jumpstart_claim_status_fetch_success]: JumpstartReclaimProperties & {
claimed: boolean
}
[JumpstartEvents.jumpstart_claim_status_fetch_error]: JumpstartReclaimProperties
}

interface PointsEventsProperties {
Expand Down
20 changes: 18 additions & 2 deletions src/analytics/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import {
AssetsEvents,
AuthenticationEvents,
BuilderHooksEvents,
CICOEvents,
CeloExchangeEvents,
CeloNewsEvents,
CICOEvents,
CoinbasePayEvents,
ContractKitEvents,
DappExplorerEvents,
Expand All @@ -26,6 +26,7 @@ import {
OnboardingEvents,
PerformanceEvents,
PhoneVerificationEvents,
PointsEvents,
QrScreenEvents,
RewardsEvents,
SendEvents,
Expand All @@ -36,7 +37,6 @@ import {
TransactionEvents,
WalletConnectEvents,
WebViewEvents,
PointsEvents,
} from 'src/analytics/Events'

/**
Expand Down Expand Up @@ -336,6 +336,22 @@ export const eventDocs: Record<AnalyticsEventType, string> = {
[JumpstartEvents.jumpstart_claim_loading_dismissed]: `When user dismisses Wallet Jumpstart claim loading toast`,
[JumpstartEvents.jumpstart_claim_error_dismissed]: `When user dismisses Wallet Jumpstart claim error toast`,
[JumpstartEvents.jumpstart_claim_error_contact_support]: `When user taps "Contact Support" CTA on Wallet Jumpstart claim error toast`,
[JumpstartEvents.jumpstart_reclaim_press]:
'When user taps on "Reclaim" button on the Jumpstart screen',
[JumpstartEvents.jumpstart_reclaim_start]:
'When user taps on "Confirm" button on the transaction confirmation bottom sheet to start sending the reclaim transaction to the network',
[JumpstartEvents.jumpstart_reclaim_failed]:
'When the reclaim transaction fails to send, or is reverted by the network',
[JumpstartEvents.jumpstart_reclaim_succeeded]:
'When the reclaim transaction was successful on the network',
[JumpstartEvents.jumpstart_reclaim_contact_support]:
'When the user taps "contact support" from any of the error toasts',
[JumpstartEvents.jumpstart_claim_status_fetch_success]:
'When fetching whether a jumpstart link has been claimed is successful',
[JumpstartEvents.jumpstart_claim_status_fetch_error]:
'When fetching whether a jumpstart link has been claimed fails',
[JumpstartEvents.jumpstart_reclaim_dismiss_error]:
'When user dismisses the error toast for when the reclaim transaction failed',
// Events for the QR screen redesign
[QrScreenEvents.qr_screen_copy_address]: ``,
[QrScreenEvents.qr_scanner_open]: `When unique "QR scanner" button is pressed`,
Expand Down
1 change: 1 addition & 0 deletions src/jumpstart/JumpstartTransactionDetailsScreen.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ describe('JumpstartTransactionDetailsScreen', () => {
reclaimTx: getSerializablePreparedTransaction(mockReclaimTx),
networkId: mockTransaction.networkId,
tokenAmount: mockTransaction.amount,
depositTxHash: mockTransaction.transactionHash,
}),
])
})
Expand Down
49 changes: 44 additions & 5 deletions src/jumpstart/JumpstartTransactionDetailsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { Trans, useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import walletJumpstart from 'src/abis/IWalletJumpstart'
import { JumpstartEvents } from 'src/analytics/Events'
import ValoraAnalytics from 'src/analytics/ValoraAnalytics'
import BackButton from 'src/components/BackButton'
import BottomSheet, { BottomSheetRefType } from 'src/components/BottomSheet'
import Button, { BtnSizes, BtnTypes } from 'src/components/Button'
Expand Down Expand Up @@ -72,7 +74,7 @@ function JumpstartTransactionDetailsScreen({ route }: Props) {
const fetchClaimData = useAsync(
async () => {
if (!isDeposit) {
return
return null
}
const { claimed, beneficiary, index } = await fetchClaimStatus(
jumpstartContractAddress as Address,
Expand Down Expand Up @@ -114,31 +116,70 @@ function JumpstartTransactionDetailsScreen({ route }: Props) {
},
[],
{
onSuccess: (result) => {
if (result) {
ValoraAnalytics.track(JumpstartEvents.jumpstart_claim_status_fetch_success, {
networkId,
depositTxHash: transaction.transactionHash,
claimed: result.claimed,
})
}
},
onError: (error) => {
ValoraAnalytics.track(JumpstartEvents.jumpstart_claim_status_fetch_error, {
networkId,
depositTxHash: transaction.transactionHash,
})
Logger.warn(TAG, 'Failed to fetch escrow data', error)
},
}
)

const handleReclaimPress = () => {
ValoraAnalytics.track(JumpstartEvents.jumpstart_reclaim_press, {
networkId,
depositTxHash: transaction.transactionHash,
})

if (reclaimStatus === 'error') {
dispatch(jumpstartReclaimErrorDismissed())
}
bottomSheetRef.current?.snapToIndex(0)
}

const handleConfirmReclaim = () => {
ValoraAnalytics.track(JumpstartEvents.jumpstart_reclaim_start, {
networkId,
depositTxHash: transaction.transactionHash,
})

if (!reclaimTx) {
Logger.warn(TAG, 'Reclaim transaction is not set')
return
}
dispatch(jumpstartReclaimStarted({ reclaimTx, networkId, tokenAmount }))
dispatch(
jumpstartReclaimStarted({
reclaimTx,
networkId,
tokenAmount,
depositTxHash: transaction.transactionHash,
})
)
}

const handleContactSupport = () => {
ValoraAnalytics.track(JumpstartEvents.jumpstart_reclaim_contact_support)
navigate(Screens.SupportContact)
}

const handleDismissReclaimError = () => {
ValoraAnalytics.track(JumpstartEvents.jumpstart_reclaim_dismiss_error, {
networkId,
depositTxHash: transaction.transactionHash,
})
dispatch(jumpstartReclaimErrorDismissed())
}

const reclaimTx = fetchClaimData.result?.preparedTransaction
const isClaimed = fetchClaimData.result?.claimed || reclaimStatus === 'success'
const title =
Expand Down Expand Up @@ -282,9 +323,7 @@ function JumpstartTransactionDetailsScreen({ route }: Props) {
title={t('jumpstartReclaim.reclaimError.title')}
description={t('jumpstartReclaim.reclaimError.description')}
ctaLabel2={t('dismiss')}
onPressCta2={() => {
dispatch(jumpstartReclaimErrorDismissed())
}}
onPressCta2={handleDismissReclaimError}
ctaLabel={t('contactSupport')}
onPressCta={handleContactSupport}
/>
Expand Down
54 changes: 32 additions & 22 deletions src/jumpstart/saga.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,14 +460,17 @@ describe('sendJumpstartTransactions', () => {
})

describe('jumpstartReclaim', () => {
const mockSerializablePreparedTransaction = getSerializablePreparedTransaction({
from: '0xa',
to: '0xb',
value: BigInt(0),
data: '0x0',
gas: BigInt(59_480),
})
const networkId = NetworkId['celo-alfajores']
const depositTxHash = '0xaaa'

it('should send the reclaim transaction and dispatch the success action on success', async () => {
const serializablePreparedTransaction = getSerializablePreparedTransaction({
from: '0xa',
to: '0xb',
value: BigInt(0),
data: '0x0',
gas: BigInt(59_480),
})
await expectSaga(jumpstartReclaim, {
type: jumpstartReclaimStarted.type,
payload: {
Expand All @@ -476,8 +479,9 @@ describe('jumpstartReclaim', () => {
tokenAddress: '0x123',
tokenId: 'celo-alfajores:0x123',
},
networkId: NetworkId['celo-alfajores'],
reclaimTx: serializablePreparedTransaction,
networkId,
reclaimTx: mockSerializablePreparedTransaction,
depositTxHash,
},
})
.provide([
Expand All @@ -488,20 +492,21 @@ describe('jumpstartReclaim', () => {
.run()

expect(sendPreparedTransactions).toHaveBeenCalledWith(
[serializablePreparedTransaction],
'celo-alfajores',
[mockSerializablePreparedTransaction],
networkId,
expect.any(Array)
)
expect(ValoraAnalytics.track).toHaveBeenCalledWith(
JumpstartEvents.jumpstart_reclaim_succeeded,
{
networkId,
depositTxHash,
reclaimTxHash: '0x1',
}
)
})

it('should dispatch an error if the reclaim transaction is reverted', async () => {
const serializablePreparedTransaction = getSerializablePreparedTransaction({
from: '0xa',
to: '0xb',
value: BigInt(0),
data: '0x0',
gas: BigInt(59_480),
})
await expectSaga(jumpstartReclaim, {
type: jumpstartReclaimStarted.type,
payload: {
Expand All @@ -510,8 +515,9 @@ describe('jumpstartReclaim', () => {
tokenAddress: '0x123',
tokenId: 'celo-alfajores:0x123',
},
networkId: NetworkId['celo-alfajores'],
reclaimTx: serializablePreparedTransaction,
networkId,
reclaimTx: mockSerializablePreparedTransaction,
depositTxHash,
},
})
.provide([
Expand All @@ -525,9 +531,13 @@ describe('jumpstartReclaim', () => {
.put(jumpstartReclaimFailed())
.run()

expect(ValoraAnalytics.track).toHaveBeenCalledWith(JumpstartEvents.jumpstart_reclaim_failed, {
networkId,
depositTxHash,
})
expect(sendPreparedTransactions).toHaveBeenCalledWith(
[serializablePreparedTransaction],
'celo-alfajores',
[mockSerializablePreparedTransaction],
networkId,
expect.any(Array)
)
})
Expand Down
9 changes: 7 additions & 2 deletions src/jumpstart/saga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,8 @@ export function* sendJumpstartTransactions(
}

export function* jumpstartReclaim(action: PayloadAction<JumpstarReclaimAction>) {
const { reclaimTx, networkId, tokenAmount, depositTxHash } = action.payload
try {
const { reclaimTx, networkId, tokenAmount } = action.payload

const createStandbyReclaimTransaction = (
transactionHash: string,
_feeCurrencyId?: string
Expand Down Expand Up @@ -391,8 +390,14 @@ export function* jumpstartReclaim(action: PayloadAction<JumpstarReclaimAction>)
}

yield* put(jumpstartReclaimSucceeded())
ValoraAnalytics.track(JumpstartEvents.jumpstart_reclaim_succeeded, {
networkId,
depositTxHash,
reclaimTxHash: txHash,
})
} catch (err) {
Logger.warn(TAG, 'Error reclaiming jumpstart transaction', err)
ValoraAnalytics.track(JumpstartEvents.jumpstart_reclaim_failed, { networkId, depositTxHash })
yield* put(jumpstartReclaimFailed())
}
}
Expand Down
1 change: 1 addition & 0 deletions src/jumpstart/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface JumpstarReclaimAction {
reclaimTx: SerializableTransactionRequest
networkId: NetworkId
tokenAmount: TokenAmount
depositTxHash: string
}
export interface JumpstartTransactionStartedAction {
serializablePreparedTransactions: SerializableTransactionRequest[]
Expand Down

0 comments on commit 69c85cc

Please sign in to comment.