Skip to content

Commit

Permalink
feat(earn): consistent analytics props for deposit (#6044)
Browse files Browse the repository at this point in the history
### Description

As the title

### Test plan

Unit tests

### Related issues

- Fixes ACT-1358

### Backwards compatibility

Yes

### Network scalability

If a new NetworkId and/or Network are added in the future, the changes
in this PR will:

- [x] Continue to work without code changes, OR trigger a compilation
error (guaranteeing we find it when a new network is added)
  • Loading branch information
satish-ravi authored Sep 19, 2024
1 parent fbd0547 commit b9cb0fc
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 108 deletions.
11 changes: 6 additions & 5 deletions src/analytics/Properties.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1552,7 +1552,12 @@ interface EarnCommonProperties {
}

interface EarnDepositProperties extends EarnCommonProperties {
tokenAmount: string
depositTokenAmount: string
mode: EarnDepositMode
// the below are mainly for swap-deposit. For deposit, this would just be
// same as the depositTokenAmount and depositTokenId
fromTokenAmount: string
fromTokenId: string
}

interface EarnWithdrawProperties extends EarnCommonProperties {
Expand Down Expand Up @@ -1601,10 +1606,6 @@ interface EarnEventsProperties {
[EarnEvents.earn_enter_amount_continue_press]: {
amountInUsd: string
amountEnteredIn: AmountEnteredIn
// TODO(ACT-1358): these could be moved to EarnDepositProperties
depositTokenAmount: string
sourceTokenId: string
mode: EarnDepositMode
} & EarnDepositProperties
[EarnEvents.earn_enter_amount_info_more_pools]: undefined
[EarnEvents.earn_exit_pool_press]: {
Expand Down
212 changes: 120 additions & 92 deletions src/earn/EarnDepositBottomSheet.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ const mockSwapDepositProps = {
}

describe('EarnDepositBottomSheet', () => {
const expectedAnalyticsProperties = {
const commonAnalyticsProperties = {
depositTokenId: mockArbUsdcTokenId,
tokenAmount: '100',
depositTokenAmount: '100',
networkId: NetworkId['arbitrum-sepolia'],
providerId: mockEarnPositions[0].appId,
poolId: mockEarnPositions[0].positionId,
Expand Down Expand Up @@ -186,103 +186,131 @@ describe('EarnDepositBottomSheet', () => {
expect(getByTestId('EarnDeposit/SecondaryCta')).toBeTruthy()
})

it('pressing complete submits action and fires analytics event', () => {
const store = createMockStore({ tokens: { tokenBalances: mockTokenBalances } })
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)

fireEvent.press(getByTestId('EarnDeposit/PrimaryCta'))
expect(AppAnalytics.track).toHaveBeenCalledWith(
EarnEvents.earn_deposit_complete,
expectedAnalyticsProperties
)
expect(store.getActions()).toEqual([
{
type: depositStart.type,
payload: {
amount: '100',
pool: mockEarnPositions[0],
preparedTransactions: getSerializablePreparedTransactions(
mockPreparedTransaction.transactions
),
describe.each([
{
mode: 'deposit',
props: mockDepositProps,
fromTokenAmount: '100',
fromTokenId: mockArbUsdcTokenId,
depositTokenAmount: '100',
},
{
mode: 'swap-deposit',
props: mockSwapDepositProps,
fromTokenAmount: '0.041',
fromTokenId: mockArbEthTokenId,
depositTokenAmount: '99.999',
},
])('$mode', ({ mode, props, fromTokenAmount, fromTokenId, depositTokenAmount }) => {
const expectedAnalyticsProperties = {
...commonAnalyticsProperties,
mode,
fromTokenAmount,
fromTokenId,
depositTokenAmount,
}

it('pressing complete submits action and fires analytics event', () => {
const store = createMockStore({ tokens: { tokenBalances: mockTokenBalances } })
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet {...props} />
</Provider>
)

fireEvent.press(getByTestId('EarnDeposit/PrimaryCta'))
expect(AppAnalytics.track).toHaveBeenCalledWith(
EarnEvents.earn_deposit_complete,
expectedAnalyticsProperties
)
expect(store.getActions()).toEqual([
{
type: depositStart.type,
payload: {
amount: depositTokenAmount,
pool: mockEarnPositions[0],
preparedTransactions: getSerializablePreparedTransactions(
mockPreparedTransaction.transactions
),
mode,
fromTokenAmount,
fromTokenId,
},
},
},
])
})

it('pressing cancel fires analytics event', () => {
const { getByTestId } = render(
<Provider store={createMockStore({ tokens: { tokenBalances: mockTokenBalances } })}>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)

fireEvent.press(getByTestId('EarnDeposit/SecondaryCta'))
expect(AppAnalytics.track).toHaveBeenCalledWith(
EarnEvents.earn_deposit_cancel,
expectedAnalyticsProperties
)
})

it('pressing provider info opens the terms and conditions', () => {
const store = createMockStore({ tokens: { tokenBalances: mockTokenBalances } })
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)

fireEvent.press(getByTestId('EarnDeposit/ProviderInfo'))
expect(AppAnalytics.track).toHaveBeenCalledWith(
EarnEvents.earn_deposit_provider_info_press,
expectedAnalyticsProperties
)
expect(store.getActions()).toEqual([openUrl('termsUrl', true)])
})
])
})

it('pressing terms and conditions opens the terms and conditions', () => {
const store = createMockStore({ tokens: { tokenBalances: mockTokenBalances } })
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)
it('pressing cancel fires analytics event', () => {
const { getByTestId } = render(
<Provider store={createMockStore({ tokens: { tokenBalances: mockTokenBalances } })}>
<EarnDepositBottomSheet {...props} />
</Provider>
)

fireEvent.press(getByTestId('EarnDeposit/SecondaryCta'))
expect(AppAnalytics.track).toHaveBeenCalledWith(
EarnEvents.earn_deposit_cancel,
expectedAnalyticsProperties
)
})

fireEvent.press(getByTestId('EarnDeposit/TermsAndConditions'))
expect(AppAnalytics.track).toHaveBeenCalledWith(
EarnEvents.earn_deposit_terms_and_conditions_press,
expectedAnalyticsProperties
)
expect(store.getActions()).toEqual([openUrl('termsUrl', true)])
})
it('pressing provider info opens the terms and conditions', () => {
const store = createMockStore({ tokens: { tokenBalances: mockTokenBalances } })
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet {...props} />
</Provider>
)

fireEvent.press(getByTestId('EarnDeposit/ProviderInfo'))
expect(AppAnalytics.track).toHaveBeenCalledWith(
EarnEvents.earn_deposit_provider_info_press,
expectedAnalyticsProperties
)
expect(store.getActions()).toEqual([openUrl('termsUrl', true)])
})

it('shows loading state and buttons are disabled when deposit is submitted', () => {
const store = createMockStore({
tokens: { tokenBalances: mockTokenBalances },
earn: { depositStatus: 'loading' },
it('pressing terms and conditions opens the terms and conditions', () => {
const store = createMockStore({ tokens: { tokenBalances: mockTokenBalances } })
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet {...props} />
</Provider>
)

fireEvent.press(getByTestId('EarnDeposit/TermsAndConditions'))
expect(AppAnalytics.track).toHaveBeenCalledWith(
EarnEvents.earn_deposit_terms_and_conditions_press,
expectedAnalyticsProperties
)
expect(store.getActions()).toEqual([openUrl('termsUrl', true)])
})
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)

expect(getByTestId('EarnDeposit/PrimaryCta')).toBeDisabled()
expect(getByTestId('EarnDeposit/SecondaryCta')).toBeDisabled()
expect(getByTestId('EarnDeposit/PrimaryCta')).toContainElement(getByTestId('Button/Loading'))
})
it('shows loading state and buttons are disabled when deposit is submitted', () => {
const store = createMockStore({
tokens: { tokenBalances: mockTokenBalances },
earn: { depositStatus: 'loading' },
})
const { getByTestId } = render(
<Provider store={store}>
<EarnDepositBottomSheet {...props} />
</Provider>
)

expect(getByTestId('EarnDeposit/PrimaryCta')).toBeDisabled()
expect(getByTestId('EarnDeposit/SecondaryCta')).toBeDisabled()
expect(getByTestId('EarnDeposit/PrimaryCta')).toContainElement(getByTestId('Button/Loading'))
})

it('shows gas subsidized copy if feature gate is set', () => {
jest.spyOn(earnUtils, 'isGasSubsidizedForNetwork').mockReturnValue(true)
const { getByTestId } = render(
<Provider store={createMockStore({ tokens: { tokenBalances: mockTokenBalances } })}>
<EarnDepositBottomSheet {...mockDepositProps} />
</Provider>
)
it('shows gas subsidized copy if feature gate is set', () => {
jest.spyOn(earnUtils, 'isGasSubsidizedForNetwork').mockReturnValue(true)
const { getByTestId } = render(
<Provider store={createMockStore({ tokens: { tokenBalances: mockTokenBalances } })}>
<EarnDepositBottomSheet {...props} />
</Provider>
)

expect(getByTestId('EarnDeposit/GasSubsidized')).toBeTruthy()
expect(getByTestId('EarnDeposit/GasSubsidized')).toBeTruthy()
})
})
})
8 changes: 7 additions & 1 deletion src/earn/EarnDepositBottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,12 @@ export default function EarnDepositBottomSheet({
const commonAnalyticsProperties = {
providerId: pool.appId,
depositTokenId: pool.dataProps.depositTokenId,
tokenAmount: inputAmount.toString(),
depositTokenAmount: depositAmount.toString(),
fromTokenId: inputTokenId,
fromTokenAmount: inputAmount.toString(),
networkId: pool.networkId,
poolId: pool.positionId,
mode,
}

const { estimatedFeeAmount, feeCurrency } = getFeeCurrencyAndAmounts(preparedTransaction)
Expand Down Expand Up @@ -95,6 +98,9 @@ export default function EarnDepositBottomSheet({
amount: depositAmount.toString(),
pool,
preparedTransactions: getSerializablePreparedTransactions(preparedTransaction.transactions),
mode,
fromTokenId: inputTokenId,
fromTokenAmount: inputAmount.toString(),
})
)
AppAnalytics.track(EarnEvents.earn_deposit_complete, commonAnalyticsProperties)
Expand Down
8 changes: 4 additions & 4 deletions src/earn/EarnEnterAmount.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,11 @@ describe('EarnEnterAmount', () => {
amountEnteredIn: 'token',
amountInUsd: '8.00',
networkId: NetworkId['arbitrum-sepolia'],
tokenAmount: '8',
depositTokenId: mockArbUsdcTokenId,
providerId: mockEarnPositions[0].appId,
poolId: mockEarnPositions[0].positionId,
sourceTokenId: mockArbUsdcTokenId,
fromTokenId: mockArbUsdcTokenId,
fromTokenAmount: '8',
depositTokenAmount: '8',
mode: 'deposit',
})
Expand Down Expand Up @@ -360,11 +360,11 @@ describe('EarnEnterAmount', () => {
amountEnteredIn: 'token',
amountInUsd: '0.62',
networkId: NetworkId['arbitrum-sepolia'],
tokenAmount: '0.00041',
fromTokenAmount: '0.00041',
depositTokenId: mockArbUsdcTokenId,
providerId: mockEarnPositions[0].appId,
poolId: mockEarnPositions[0].positionId,
sourceTokenId: mockArbEthTokenId,
fromTokenId: mockArbEthTokenId,
depositTokenAmount: '0.99999',
mode: 'swap-deposit',
})
Expand Down
4 changes: 2 additions & 2 deletions src/earn/EarnEnterAmount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -298,14 +298,14 @@ function EarnEnterAmount({ route }: Props) {
return
}
AppAnalytics.track(EarnEvents.earn_enter_amount_continue_press, {
tokenAmount: tokenAmount.toString(),
amountInUsd: tokenAmount.multipliedBy(token.priceUsd ?? 0).toFixed(2),
amountEnteredIn: enteredIn,
depositTokenId: pool.dataProps.depositTokenId,
networkId: token.networkId,
providerId: pool.appId,
poolId: pool.positionId,
sourceTokenId: token.tokenId,
fromTokenId: token.tokenId,
fromTokenAmount: tokenAmount.toString(),
mode,
depositTokenAmount: swapTransaction
? getSwapToAmountInDecimals({ swapTransaction, fromAmount: tokenAmount }).toString()
Expand Down
20 changes: 19 additions & 1 deletion src/earn/saga.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,13 @@ describe('depositSubmitSaga', () => {

const expectedAnalyticsProps = {
depositTokenId: mockArbUsdcTokenId,
tokenAmount: '100',
depositTokenAmount: '100',
networkId: NetworkId['arbitrum-sepolia'],
providerId: mockEarnPositions[0].appId,
poolId: mockEarnPositions[0].positionId,
mode: 'deposit',
fromTokenAmount: '100',
fromTokenId: mockArbUsdcTokenId,
}

const expectedApproveStandbyTx = {
Expand Down Expand Up @@ -231,6 +234,9 @@ describe('depositSubmitSaga', () => {
amount: '100',
pool: mockEarnPositions[0],
preparedTransactions: [serializableApproveTx, serializableDepositTx],
mode: 'deposit',
fromTokenAmount: '100',
fromTokenId: mockArbUsdcTokenId,
},
})
.withState(createMockStore({ tokens: { tokenBalances: mockTokenBalances } }).getState())
Expand Down Expand Up @@ -274,6 +280,9 @@ describe('depositSubmitSaga', () => {
amount: '100',
pool: mockEarnPositions[0],
preparedTransactions: [serializableDepositTx],
mode: 'deposit',
fromTokenAmount: '100',
fromTokenId: mockArbUsdcTokenId,
},
})
.withState(createMockStore({ tokens: { tokenBalances: mockTokenBalances } }).getState())
Expand Down Expand Up @@ -315,6 +324,9 @@ describe('depositSubmitSaga', () => {
amount: '100',
pool: mockEarnPositions[0],
preparedTransactions: [serializableDepositTx],
mode: 'deposit',
fromTokenAmount: '100',
fromTokenId: mockArbUsdcTokenId,
},
})
.withState(createMockStore({ tokens: { tokenBalances: mockTokenBalances } }).getState())
Expand Down Expand Up @@ -348,6 +360,9 @@ describe('depositSubmitSaga', () => {
amount: '100',
pool: mockEarnPositions[0],
preparedTransactions: [serializableDepositTx],
mode: 'deposit',
fromTokenAmount: '100',
fromTokenId: mockArbUsdcTokenId,
},
})
.withState(createMockStore({ tokens: { tokenBalances: mockTokenBalances } }).getState())
Expand Down Expand Up @@ -383,6 +398,9 @@ describe('depositSubmitSaga', () => {
amount: '100',
pool: mockEarnPositions[0],
preparedTransactions: [serializableApproveTx, serializableDepositTx],
mode: 'deposit',
fromTokenAmount: '100',
fromTokenId: mockArbUsdcTokenId,
},
})
.withState(createMockStore({ tokens: { tokenBalances: mockTokenBalances } }).getState())
Expand Down
Loading

0 comments on commit b9cb0fc

Please sign in to comment.