Skip to content

Commit

Permalink
add recipient_source on tx send | all_done | view (LW-8355) (#534)
Browse files Browse the repository at this point in the history
* feat(extension): add recipient_source LW-8355

* feat(extension): fix find address book exact match
  • Loading branch information
tommayeliog authored Sep 15, 2023
1 parent 1fef96e commit ed00a8c
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ describe('Testing useGetFilteredAddressBook hook', () => {
const { result } = renderHook(() => useGetFilteredAddressBook(), {
wrapper: makeDbContextWrapper(db)
});
expect(result.current.getAddressBookByNameOrAddress).toBeDefined();
expect(result.current.filterAddressesByNameOrAddress).toBeDefined();

await act(async () => {
await result.current.getAddressBookByNameOrAddress({ value: 't' });
await result.current.filterAddressesByNameOrAddress({ value: 't' });
});
expect(result.current.filteredAddresses).toHaveLength(1);
expect(result.current.filteredAddresses).toStrictEqual([
Expand All @@ -95,15 +95,15 @@ describe('Testing useGetFilteredAddressBook hook', () => {
const { result } = renderHook(() => useGetFilteredAddressBook(), {
wrapper: makeDbContextWrapper(db)
});
expect(result.current.getAddressBookByNameOrAddress).toBeDefined();
expect(result.current.filterAddressesByNameOrAddress).toBeDefined();

await act(async () => {
await result.current.getAddressBookByNameOrAddress({ value: 'oth' });
await result.current.filterAddressesByNameOrAddress({ value: 'oth' });
});
expect(result.current.filteredAddresses).toHaveLength(2);

await act(async () => {
await result.current.getAddressBookByNameOrAddress({ value: 'oth', limit: 1 });
await result.current.filterAddressesByNameOrAddress({ value: 'oth', limit: 1 });
});
expect(result.current.filteredAddresses).toHaveLength(1);
});
Expand All @@ -112,10 +112,10 @@ describe('Testing useGetFilteredAddressBook hook', () => {
const { result } = renderHook(() => useGetFilteredAddressBook(), {
wrapper: makeDbContextWrapper(db)
});
expect(result.current.getAddressBookByNameOrAddress).toBeDefined();
expect(result.current.filterAddressesByNameOrAddress).toBeDefined();

await act(async () => {
await result.current.getAddressBookByNameOrAddress({ value: 'addr_test3' });
await result.current.filterAddressesByNameOrAddress({ value: 'addr_test3' });
});
expect(result.current.filteredAddresses).toHaveLength(1);
expect(result.current.filteredAddresses).toStrictEqual([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { cardanoNetworkMap } from '@src/features/address-book/context';

const DEFAULT_QUERY_LIMIT = 5;

interface GetAddressByNameOrAddressArgs {
interface FilterAddressByNameOrAddressArgs {
value: string;
limit?: number;
}
Expand All @@ -20,12 +20,7 @@ interface FilteredAddressList {
walletHandleResolution?: HandleResolution;
}

const getAddressBookByNameOrAddressTransformer = ({
address,
name,
id,
handleResolution
}: AddressBookSchema): FilteredAddressList => ({
const addressTransformer = ({ address, name, id, handleResolution }: AddressBookSchema): FilteredAddressList => ({
walletAddress: address,
walletName: name,
id,
Expand All @@ -34,7 +29,8 @@ const getAddressBookByNameOrAddressTransformer = ({

export const useGetFilteredAddressBook = (): {
filteredAddresses: FilteredAddressList[];
getAddressBookByNameOrAddress: ({ value, limit }: GetAddressByNameOrAddressArgs) => Promise<void>;
filterAddressesByNameOrAddress: ({ value, limit }: FilterAddressByNameOrAddressArgs) => Promise<void>;
getMatchedAddresses: ({ value, limit }: FilterAddressByNameOrAddressArgs) => Promise<FilteredAddressList[]>;
resetAddressList: () => void;
} => {
const { environmentName } = useWalletStore();
Expand All @@ -52,35 +48,45 @@ export const useGetFilteredAddressBook = (): {
executeRef.current = { execute };
}, [execute]);

const getAddressBookByNameOrAddress = useCallback(
async ({ value, limit = DEFAULT_QUERY_LIMIT }: GetAddressByNameOrAddressArgs) => {
const getMatchedAddresses = useCallback(
async ({
value,
limit = DEFAULT_QUERY_LIMIT
}: FilterAddressByNameOrAddressArgs): Promise<FilteredAddressList[]> => {
const network = cardanoNetworkMap[environmentName];

if (value.length <= 0) {
setFilteredAddresses([]);
} else {
await executeRef.current.execute(async () => {
const result = await dbRef.current
.getConnection<AddressBookSchema>(addressBookSchema)
.where('name')
.startsWithIgnoreCase(value)
.or('address')
.equalsIgnoreCase(value)
.filter((item) => item.network === network)
.limit(limit)
.toArray();

const addressList = result.map((element) => getAddressBookByNameOrAddressTransformer(element));
setFilteredAddresses(addressList);
});
if (!value) {
return [];
}

const result = await dbRef.current
.getConnection<AddressBookSchema>(addressBookSchema)
.where('name')
.startsWithIgnoreCase(value)
.or('address')
.equalsIgnoreCase(value)
.filter((item) => item.network === network)
.limit(limit)
.toArray();

return result.map((element) => addressTransformer(element));
},
[environmentName]
);

const filterAddressesByNameOrAddress = useCallback(
async (args: FilterAddressByNameOrAddressArgs) => {
await executeRef.current.execute(async () => {
const addressList = await getMatchedAddresses(args);
setFilteredAddresses(addressList);
});
},
[getMatchedAddresses]
);

const resetAddressList = useCallback(() => {
setFilteredAddresses([]);
}, []);

return { filteredAddresses, getAddressBookByNameOrAddress, resetAddressList };
return { filteredAddresses, getMatchedAddresses, filterAddressesByNameOrAddress, resetAddressList };
};
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const AddressInput = ({ row, currentNetwork, isPopupView }: AddressInputP

const { setSection } = useSections();
const { address, handle, handleStatus, setAddressValue } = useAddressState(row);
const { filteredAddresses, getAddressBookByNameOrAddress } = useGetFilteredAddressBook();
const { filteredAddresses, filterAddressesByNameOrAddress } = useGetFilteredAddressBook();
const { setAddressToEdit } = useAddressBookStore();
const [, setRowId] = useCurrentRow();
const [handleVerificationState, setHandleVerificationState] = useState<HandleVerificationState | undefined>();
Expand Down Expand Up @@ -187,8 +187,8 @@ export const AddressInput = ({ row, currentNetwork, isPopupView }: AddressInputP
]);

useEffect(() => {
getAddressBookByNameOrAddress({ value: handle || address || '' });
}, [address, getAddressBookByNameOrAddress, handle]);
filterAddressesByNameOrAddress({ value: handle || address || '' });
}, [address, filterAddressesByNameOrAddress, handle]);

const validationObject = useMemo(() => {
const isNameValid = address && isWalletNameValid(address);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import {
TokenAnalyticsProperties,
useMetadata
} from '@views/browser/features/send-transaction';
import React, { useEffect, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import styles from './TransactionSuccessView.module.scss';
import { useWalletStore } from '@src/stores';
import { useObservable } from '@lace/common';
import { getTokensProperty } from '../helpers';
import { Wallet } from '@lace/cardano';
import { useGetFilteredAddressBook } from '@src/features/address-book/hooks';

export const TransactionSuccessView = ({ footerSlot }: { footerSlot?: React.ReactElement }): React.ReactElement => {
const { t } = useTranslation();
Expand All @@ -32,6 +33,7 @@ export const TransactionSuccessView = ({ footerSlot }: { footerSlot?: React.Reac
const assets = useObservable(inMemoryWallet.assetInfo$);
const [customAnalyticsProperties, setCustomAnalyticsProperties] = useState<TokenAnalyticsProperties[]>();
const [metadata] = useMetadata();
const { getMatchedAddresses } = useGetFilteredAddressBook();

useEffect(() => {
// run this only when assets value was emitted and customAnalyticsProperties is undefined
Expand All @@ -40,13 +42,23 @@ export const TransactionSuccessView = ({ footerSlot }: { footerSlot?: React.Reac
}
}, [assets, cardanoCoin, customAnalyticsProperties, uiOutputs]);

useEffect(() => {
const sendEventOnDone = useCallback(async () => {
// send analytics event after customAnalyticsProperties was set
if (customAnalyticsProperties) {
const recipientTypes = Object.values(uiOutputs).map((row) =>
const recipients = Object.values(uiOutputs);
const recipientSources = await Promise.all(
recipients.map(async (row) => {
const addressIdentifier = row.handle || row.address;
const bookRecords = await getMatchedAddresses({ value: addressIdentifier });
const exactMatch = bookRecords.find((item) => item.walletAddress === addressIdentifier);
return exactMatch ? 'address book' : 'not on address book';
})
);
const recipientTypes = recipients.map((row) =>
row.handle ? TxRecipientType.AdaHandle : TxRecipientType.RegularAddress
);
const recipientTypesUnique = uniq(recipientTypes);
const recipientSourceUnique = uniq(recipientSources);
analytics.sendEventToPostHog(PostHogAction.SendAllDoneView, {
// eslint-disable-next-line camelcase
trigger_point: triggerPoint,
Expand All @@ -61,12 +73,18 @@ export const TransactionSuccessView = ({ footerSlot }: { footerSlot?: React.Reac
// eslint-disable-next-line camelcase
metadata_defined: !!metadata,
// eslint-disable-next-line camelcase
recipient_type: recipientTypesUnique
recipient_type: recipientTypesUnique,
// eslint-disable-next-line camelcase
recipient_source: recipientSourceUnique
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [customAnalyticsProperties]);

useEffect(() => {
sendEventOnDone();
}, [sendEventOnDone]);

return (
<>
<div className={styles.successTxContainer} data-testid="transaction-success-container">
Expand Down

0 comments on commit ed00a8c

Please sign in to comment.