From d400b9094dfe5035f9d1002652c790134d53ca1e Mon Sep 17 00:00:00 2001 From: Greg Bugyis Date: Wed, 2 Nov 2022 23:21:02 +0200 Subject: [PATCH] feat: Buy Bag events (#5062) * Add activity boolean to Collection page event * Log add-to-bag events * WIP * Bag update events * Log pay event * Bag success event * Add bag signed event * Move formatting function out to util * Format event properties with utility function * Remove console log and fix event on details page * Remove commented code * Fix event names to follow convention * Move priceChangedAssets logging to useEffect * Add modal constant and useTrace * Fix typo --- src/analytics/constants.ts | 8 + src/nft/components/bag/Bag.tsx | 15 +- src/nft/components/bag/BagContent.tsx | 39 +- src/nft/components/bag/BagFooter.tsx | 54 ++- .../components/collection/ActivityCells.tsx | 13 + .../components/collection/CollectionAsset.tsx | 12 + .../collection/TransactionCompleteModal.tsx | 450 ++++++++++-------- src/nft/components/details/AssetDetails.tsx | 17 +- .../components/details/AssetPriceDetails.tsx | 16 +- src/nft/hooks/useSendTransaction.ts | 3 + src/nft/pages/collection/index.tsx | 2 +- src/nft/utils/formatEventProperties.ts | 7 + src/nft/utils/index.ts | 1 + 13 files changed, 395 insertions(+), 242 deletions(-) create mode 100644 src/nft/utils/formatEventProperties.ts diff --git a/src/analytics/constants.ts b/src/analytics/constants.ts index b1b652eb4d..71410f67ac 100644 --- a/src/analytics/constants.ts +++ b/src/analytics/constants.ts @@ -16,6 +16,12 @@ export enum EventName { NAVBAR_SEARCH_SELECTED = 'Navbar Search Selected', NAVBAR_SEARCH_EXITED = 'Navbar Search Exited', NFT_ACTIVITY_SELECTED = 'NFT Activity Selected', + NFT_BUY_ADDED = 'NFT Buy Bag Added', + NFT_BUY_BAG_CHANGED = 'NFT Buy Bag Changed', + NFT_BUY_BAG_PAY = 'NFT Buy Bag Pay Clicked', + NFT_BUY_BAG_REFUNDED = 'NFT Buy Bag Refunded', + NFT_BUY_BAG_SIGNED = 'NFT Buy Bag Signed', + NFT_BUY_BAG_SUCCEEDED = 'NFT Buy Bag Succeeded', NFT_FILTER_OPENED = 'NFT Collection Filter Opened', NFT_FILTER_SELECTED = 'NFT Filter Selected', NFT_TRENDING_ROW_SELECTED = 'Trending Row Selected', @@ -106,6 +112,7 @@ export enum SectionName { /** Known modals for analytics purposes. */ export enum ModalName { CONFIRM_SWAP = 'confirm-swap-modal', + NFT_TX_COMPLETE = 'nft-tx-complete-modal', TOKEN_SELECTOR = 'token-selector-modal', // alphabetize additional modal names. } @@ -125,6 +132,7 @@ export enum ElementName { MAX_TOKEN_AMOUNT_BUTTON = 'max-token-amount-button', NAVBAR_SEARCH_INPUT = 'navbar-search-input', NFT_ACTIVITY_TAB = 'nft-activity-tab', + NFT_BUY_BAG_PAY_BUTTON = 'nft-buy-bag-pay-button', NFT_FILTER_BUTTON = 'nft-filter-button', NFT_FILTER_OPTION = 'nft-filter-option', NFT_TRENDING_ROW = 'nft-trending-row', diff --git a/src/nft/components/bag/Bag.tsx b/src/nft/components/bag/Bag.tsx index 2e1d7e8790..7ab2387f23 100644 --- a/src/nft/components/bag/Bag.tsx +++ b/src/nft/components/bag/Bag.tsx @@ -20,11 +20,14 @@ import { } from 'nft/hooks' import { fetchRoute } from 'nft/queries' import { BagItemStatus, BagStatus, ProfilePageStateType, RouteResponse, TxStateType } from 'nft/types' -import { buildSellObject } from 'nft/utils/buildSellObject' -import { recalculateBagUsingPooledAssets } from 'nft/utils/calcPoolPrice' -import { fetchPrice } from 'nft/utils/fetchPrice' +import { + buildSellObject, + fetchPrice, + formatAssetEventProperties, + recalculateBagUsingPooledAssets, + sortUpdatedAssets, +} from 'nft/utils' import { combineBuyItemsWithTxRoute } from 'nft/utils/txRoute/combineItemsWithTxRoute' -import { sortUpdatedAssets } from 'nft/utils/updatedAssets' import { useEffect, useMemo, useRef, useState } from 'react' import { useQuery, useQueryClient } from 'react-query' import { useLocation } from 'react-router-dom' @@ -283,6 +286,10 @@ const Bag = () => { bagStatus={bagStatus} fetchAssets={fetchAssets} assetsAreInReview={itemsInBag.some((item) => item.status === BagItemStatus.REVIEWING_PRICE_CHANGE)} + eventProperties={{ + usd_value: totalUsdPrice, + ...formatAssetEventProperties(itemsInBag.map((item) => item.asset)), + }} /> )} {isSellingAssets && isProfilePage && ( diff --git a/src/nft/components/bag/BagContent.tsx b/src/nft/components/bag/BagContent.tsx index 43c4689b4e..03f40edba6 100644 --- a/src/nft/components/bag/BagContent.tsx +++ b/src/nft/components/bag/BagContent.tsx @@ -1,9 +1,13 @@ +import { sendAnalyticsEvent } from 'analytics' +import { EventName } from 'analytics/constants' +import { Trace } from 'analytics/Trace' import { BagRow, PriceChangeBagRow, UnavailableAssetsHeaderRow } from 'nft/components/bag/BagRow' import { Column } from 'nft/components/Flex' import { useBag, useIsMobile } from 'nft/hooks' import { BagItemStatus, BagStatus } from 'nft/types' import { recalculateBagUsingPooledAssets } from 'nft/utils/calcPoolPrice' import { fetchPrice } from 'nft/utils/fetchPrice' +import { formatAssetEventProperties } from 'nft/utils/formatEventProperties' import { useEffect, useMemo } from 'react' import { useQuery } from 'react-query' @@ -44,24 +48,41 @@ export const BagContent = () => { const hasAssetsInReview = priceChangedAssets.length > 0 const hasAssets = itemsInBag.length > 0 + if (hasAssetsInReview) + sendAnalyticsEvent(EventName.NFT_BUY_BAG_CHANGED, { + usd_value: fetchedPriceData, + bag_quantity: itemsInBag, + ...formatAssetEventProperties(priceChangedAssets), + }) + if (bagStatus === BagStatus.IN_REVIEW && !hasAssetsInReview) { if (hasAssets) setBagStatus(BagStatus.CONFIRM_REVIEW) else setBagStatus(BagStatus.ADDING_TO_BAG) } - }, [bagStatus, itemsInBag, priceChangedAssets, setBagStatus]) + }, [bagStatus, itemsInBag, priceChangedAssets, setBagStatus, fetchedPriceData]) return ( <> 0 || unavailableAssets.length > 0 ? 'flex' : 'none'}> {unavailableAssets.length > 0 && ( - setItemsInBag(availableItems)} - didOpenUnavailableAssets={didOpenUnavailableAssets} - setDidOpenUnavailableAssets={setDidOpenUnavailableAssets} - isMobile={isMobile} - /> + + setItemsInBag(availableItems)} + didOpenUnavailableAssets={didOpenUnavailableAssets} + setDidOpenUnavailableAssets={setDidOpenUnavailableAssets} + isMobile={isMobile} + /> + )} {priceChangedAssets.map((asset, index) => ( void assetsAreInReview: boolean + eventProperties: Record } const PENDING_BAG_STATUSES = [ @@ -65,6 +68,7 @@ export const BagFooter = ({ bagStatus, fetchAssets, assetsAreInReview, + eventProperties, }: BagFooterProps) => { const toggleWalletModal = useToggleWalletModal() const walletModalIsOpen = useModalIsOpen(ApplicationModal.WALLET) @@ -102,28 +106,36 @@ export const BagFooter = ({ )} )} - { - if (!isConnected) { - toggleWalletModal() - } else { - fetchAssets() - } - }} + - {isPending && } - {!isConnected || walletModalIsOpen - ? 'Connect wallet' - : bagStatus === BagStatus.FETCHING_FINAL_ROUTE || bagStatus === BagStatus.CONFIRMING_IN_WALLET - ? 'Proceed in wallet' - : bagStatus === BagStatus.PROCESSING_TRANSACTION - ? 'Transaction pending' - : 'Pay'} - + { + if (!isConnected) { + toggleWalletModal() + } else { + fetchAssets() + } + }} + > + {isPending && } + {!isConnected || walletModalIsOpen + ? 'Connect wallet' + : bagStatus === BagStatus.FETCHING_FINAL_ROUTE || bagStatus === BagStatus.CONFIRMING_IN_WALLET + ? 'Proceed in wallet' + : bagStatus === BagStatus.PROCESSING_TRANSACTION + ? 'Transaction pending' + : 'Pay'} + + ) diff --git a/src/nft/components/collection/ActivityCells.tsx b/src/nft/components/collection/ActivityCells.tsx index 40c6c4f562..61e5f0eb57 100644 --- a/src/nft/components/collection/ActivityCells.tsx +++ b/src/nft/components/collection/ActivityCells.tsx @@ -1,4 +1,7 @@ import { ChainId } from '@uniswap/smart-order-router' +import { sendAnalyticsEvent } from 'analytics' +import { EventName, PageName } from 'analytics/constants' +import { useTrace } from 'analytics/Trace' import { MouseoverTooltip } from 'components/Tooltip' import { Box } from 'nft/components/Box' import { Column, Row } from 'nft/components/Flex' @@ -96,6 +99,15 @@ export const BuyCell = ({ return itemsInBag.some((item) => asset.tokenId === item.asset.tokenId && asset.address === item.asset.address) }, [asset, itemsInBag]) + const trace = useTrace({ page: PageName.NFT_COLLECTION_PAGE }) + + const eventProperties = { + collection_address: asset.address, + token_id: asset.tokenId, + token_type: asset.tokenType, + ...trace, + } + return ( {event.eventType === ActivityEventType.Listing && event.orderStatus ? ( @@ -106,6 +118,7 @@ export const BuyCell = ({ e.preventDefault() isSelected ? removeAsset([asset]) : selectAsset([asset]) !isSelected && !cartExpanded && !isMobile && toggleCart() + !isSelected && sendAnalyticsEvent(EventName.NFT_BUY_ADDED, { eventProperties }) }} disabled={event.orderStatus !== OrderStatus.VALID} > diff --git a/src/nft/components/collection/CollectionAsset.tsx b/src/nft/components/collection/CollectionAsset.tsx index 0bcc348769..9acedad3b9 100644 --- a/src/nft/components/collection/CollectionAsset.tsx +++ b/src/nft/components/collection/CollectionAsset.tsx @@ -1,4 +1,7 @@ import { BigNumber } from '@ethersproject/bignumber' +import { sendAnalyticsEvent } from 'analytics' +import { EventName, PageName } from 'analytics/constants' +import { useTrace } from 'analytics/Trace' import { useBag } from 'nft/hooks' import { GenieAsset, Markets, UniformHeight } from 'nft/types' import { formatWeiToDecimal, isAudio, isVideo, rarityProviderLogo } from 'nft/utils' @@ -36,6 +39,7 @@ export const CollectionAsset = ({ const itemsInBag = useBag((state) => state.itemsInBag) const bagExpanded = useBag((state) => state.bagExpanded) const toggleBag = useBag((state) => state.toggleBag) + const trace = useTrace({ page: PageName.NFT_COLLECTION_PAGE }) const { quantity, isSelected } = useMemo(() => { return { @@ -72,6 +76,13 @@ export const CollectionAsset = ({ } }, [asset]) + const eventProperties = { + collection_address: asset.address, + token_id: asset.tokenId, + token_type: asset.tokenType, + ...trace, + } + return ( { addAssetsToBag([asset]) !bagExpanded && !isMobile && toggleBag() + sendAnalyticsEvent(EventName.NFT_BUY_ADDED, { ...eventProperties }) }} removeAssetFromBag={() => { removeAssetsFromBag([asset]) diff --git a/src/nft/components/collection/TransactionCompleteModal.tsx b/src/nft/components/collection/TransactionCompleteModal.tsx index 6746dc276d..0bd7747a4c 100644 --- a/src/nft/components/collection/TransactionCompleteModal.tsx +++ b/src/nft/components/collection/TransactionCompleteModal.tsx @@ -1,3 +1,6 @@ +import { EventName, ModalName } from 'analytics/constants' +import { Trace } from 'analytics/Trace' +import { useTrace } from 'analytics/Trace' import clsx from 'clsx' import { Box } from 'nft/components/Box' import { Portal } from 'nft/components/common/Portal' @@ -16,6 +19,7 @@ import { parseTransactionResponse, shortenTxHash, } from 'nft/utils' +import { formatAssetEventProperties } from 'nft/utils/formatEventProperties' import { useEffect, useMemo, useRef, useState } from 'react' import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' @@ -33,6 +37,7 @@ const TxCompleteModal = () => { const isMobile = useIsMobile() const txHashUrl = getExplorerLink(1, txHash, ExplorerDataType.TRANSACTION) const shouldShowModal = (txState === TxStateType.Success || txState === TxStateType.Failed) && txState + const trace = useTrace({ modal: ModalName.NFT_TX_COMPLETE }) const { nftsPurchased, nftsNotPurchased, @@ -73,229 +78,264 @@ const TxCompleteModal = () => { {/* Successfully purchased NFTs */} {showPurchasedModal && ( - - - -

Complete!

-

Uniswap has granted your wish!

+ + + + +

Complete!

+

Uniswap has granted your wish!

+
+ 32 ? (isMobile ? '172px' : '292px') : 'min-content', + }} + > + {[...nftsPurchased].map((nft, index) => ( + 1 && styles.successAssetImageGrid + )} + style={{ + maxHeight: `${getSuccessfulImageSize(nftsPurchased.length, isMobile)}px`, + maxWidth: `${getSuccessfulImageSize(nftsPurchased.length, isMobile)}px`, + }} + src={nft.imageUrl} + alt={nft.name} + key={index} + /> + ))} + + {nftsPurchased.length > 32 && } + + + + {nftsPurchased.length} NFT{nftsPurchased.length === 1 ? '' : 's'} + + {formatEthPrice(totalPurchaseValue.toString())} ETH + + + + {shortenTxHash(txHash, 2, 2)} + + + - 32 ? (isMobile ? '172px' : '292px') : 'min-content', - }} - > - {[...nftsPurchased].map((nft, index) => ( - 1 && styles.successAssetImageGrid - )} - style={{ - maxHeight: `${getSuccessfulImageSize(nftsPurchased.length, isMobile)}px`, - maxWidth: `${getSuccessfulImageSize(nftsPurchased.length, isMobile)}px`, - }} - src={nft.imageUrl} - alt={nft.name} - key={index} - /> - ))} - - {nftsPurchased.length > 32 && } - - - - {nftsPurchased.length} NFT{nftsPurchased.length === 1 ? '' : 's'} - - {formatEthPrice(totalPurchaseValue.toString())} ETH - - - - {shortenTxHash(txHash, 2, 2)} - - - - +
)} {/* NFTs that were not purchased ie Refunds */} {showRefundModal && /* Showing both purchases & refunds */ (showPurchasedModal ? ( - - - -

Instant Refund

-

- Uniswap returned{' '} - {formatEthPrice(totalRefundValue.toString())} ETH back - to your wallet for unavailable items. -

+ + -

- {formatEthPrice(totalRefundValue.toString())} ETH -

-

{formatUSDPriceWithCommas(totalUSDRefund)}

-

- for {nftsNotPurchased.length} unavailable item - {nftsNotPurchased.length === 1 ? '' : 's'}. + +

Instant Refund

+

+ Uniswap returned{' '} + {formatEthPrice(totalRefundValue.toString())} ETH{' '} + back to your wallet for unavailable items.

- - - {shortenTxHash(txHash, 2, 2)} - - +

+ {formatEthPrice(totalRefundValue.toString())} ETH +

+

{formatUSDPriceWithCommas(totalUSDRefund)}

+

+ for {nftsNotPurchased.length} unavailable item + {nftsNotPurchased.length === 1 ? '' : 's'}. +

+ + + + {shortenTxHash(txHash, 2, 2)} + + +
-
- - {nftsNotPurchased.map((nft, index) => ( - - {nft.name} - - ))} - - - - ) : ( - // Only showing when all assets are unavailable - - - {txState === TxStateType.Success ? ( - <> - -

Instant Refund

- - ) : ( -

Failed Transaction

- )} -
-

- {txState === TxStateType.Success && - `Selected item${ - nftsPurchased.length === 1 ? ' is' : 's are' - } no longer available. Uniswap instantly refunded you for this incomplete transaction. `} - {formatUsdPrice(txFeeFiat)} was used for gas in attempt to complete this transaction. For support, - please visit our Discord -

- - {nftsNotPurchased.length >= 3 && ( - toggleShowUnavailable()}> - {!showUnavailable && ( - - {nftsNotPurchased.slice(0, 3).map((asset, index) => ( - {asset.name} - ))} - - )} - - Unavailable - - {nftsNotPurchased.length} item{nftsNotPurchased.length === 1 ? '' : 's'} - - - - - )} - {(showUnavailable || nftsNotPurchased.length < 3) && - nftsNotPurchased.map((asset, index) => ( - - - {asset.name} - - - -

- {formatEthPrice( - asset.updatedPriceInfo ? asset.updatedPriceInfo.ETHPrice : asset.priceInfo.ETHPrice - )}{' '} - ETH -

-
- - {txState === TxStateType.Success ? 'Refunded' : asset.name} - -
+ + {nftsNotPurchased.map((nft, index) => ( + + {nft.name} ))} + + - {showUnavailable && } -

- {formatEthPrice(totalRefundValue.toString())} ETH -

-

{formatUSDPriceWithCommas(totalUSDRefund)}

- - - {shortenTxHash(txHash, 2, 2)} - +
+ ) : ( + // Only showing when all assets are unavailable + + + + {txState === TxStateType.Success ? ( + <> + +

Instant Refund

+ + ) : ( +

Failed Transaction

+ )} +
+

+ {txState === TxStateType.Success && + `Selected item${ + nftsPurchased.length === 1 ? ' is' : 's are' + } no longer available. Uniswap instantly refunded you for this incomplete transaction. `} + {formatUsdPrice(txFeeFiat)} was used for gas in attempt to complete this transaction. For support, + please visit our Discord +

+ + {nftsNotPurchased.length >= 3 && ( + toggleShowUnavailable()}> + {!showUnavailable && ( + + {nftsNotPurchased.slice(0, 3).map((asset, index) => ( + {asset.name} + ))} + + )} + + Unavailable + + {nftsNotPurchased.length} item{nftsNotPurchased.length === 1 ? '' : 's'} + + + + + )} + {(showUnavailable || nftsNotPurchased.length < 3) && + nftsNotPurchased.map((asset, index) => ( + + + {asset.name} + + + +

+ {formatEthPrice( + asset.updatedPriceInfo ? asset.updatedPriceInfo.ETHPrice : asset.priceInfo.ETHPrice + )}{' '} + ETH +

+
+ + {txState === TxStateType.Success ? 'Refunded' : asset.name} + +
+
+ ))} +
+ {showUnavailable && } +

+ {formatEthPrice(totalRefundValue.toString())} ETH +

+

{formatUSDPriceWithCommas(totalUSDRefund)}

+ + + {shortenTxHash(txHash, 2, 2)} + + +

+ for {nftsNotPurchased.length} unavailable item + {nftsNotPurchased.length === 1 ? '' : 's'}. +

+ closeTxCompleteScreen()} + > + + Return to Marketplace +
-

- for {nftsNotPurchased.length} unavailable item - {nftsNotPurchased.length === 1 ? '' : 's'}. -

- closeTxCompleteScreen()} - > - - Return to Marketplace - -
+
))}
diff --git a/src/nft/components/details/AssetDetails.tsx b/src/nft/components/details/AssetDetails.tsx index 74a146ab3e..a85ea46410 100644 --- a/src/nft/components/details/AssetDetails.tsx +++ b/src/nft/components/details/AssetDetails.tsx @@ -1,4 +1,7 @@ import { useWeb3React } from '@web3-react/core' +import { sendAnalyticsEvent } from 'analytics' +import { EventName, PageName } from 'analytics/constants' +import { useTrace } from 'analytics/Trace' import clsx from 'clsx' import { MouseoverTooltip } from 'components/Tooltip/index' import useENSName from 'hooks/useENSName' @@ -132,6 +135,15 @@ export const AssetDetails = ({ asset, collection }: AssetDetailsProps) => { const [isOwned, setIsOwned] = useState(false) const { account: address, provider } = useWeb3React() + const trace = useTrace({ page: PageName.NFT_DETAILS_PAGE }) + + const eventProperties = { + collection_address: asset.address, + token_id: asset.tokenId, + token_type: asset.tokenType, + ...trace, + } + const { rarityProvider, rarityLogo } = useMemo( () => asset.rarity @@ -394,7 +406,10 @@ export const AssetDetails = ({ asset, collection }: AssetDetailsProps) => { onClick={() => { if (isSelected) { removeAssetsFromBag([asset]) - } else addAssetsToBag([asset]) + } else { + addAssetsToBag([asset]) + sendAnalyticsEvent(EventName.NFT_BUY_ADDED, { ...eventProperties }) + } setSelected((x) => !x) }} > diff --git a/src/nft/components/details/AssetPriceDetails.tsx b/src/nft/components/details/AssetPriceDetails.tsx index ba974079c0..5af1a8f198 100644 --- a/src/nft/components/details/AssetPriceDetails.tsx +++ b/src/nft/components/details/AssetPriceDetails.tsx @@ -1,4 +1,7 @@ import { useWeb3React } from '@web3-react/core' +import { sendAnalyticsEvent } from 'analytics' +import { EventName, PageName } from 'analytics/constants' +import { useTrace } from 'analytics/Trace' import { CancelListingIcon, MinusIcon, PlusIcon } from 'nft/components/icons' import { useBag } from 'nft/hooks' import { CollectionInfoForAsset, GenieAsset, TokenType } from 'nft/types' @@ -196,6 +199,14 @@ export const AssetPriceDetails = ({ asset, collection }: AssetPriceDetailsProps) const USDPrice = useUsdPrice(asset) const isErc1555 = asset.tokenType === TokenType.ERC1155 + const trace = useTrace({ page: PageName.NFT_DETAILS_PAGE }) + const eventProperties = { + collection_address: asset.address, + token_id: asset.tokenId, + token_type: asset.tokenType, + ...trace, + } + const { quantity, assetInBag } = useMemo(() => { return { quantity: itemsInBag.filter( @@ -242,7 +253,10 @@ export const AssetPriceDetails = ({ asset, collection }: AssetPriceDetailsProps) assetInBag={assetInBag} margin={true} useAccentColor={true} - onClick={() => (assetInBag ? removeAssetsFromBag([asset]) : addAssetsToBag([asset]))} + onClick={() => { + assetInBag ? removeAssetsFromBag([asset]) : addAssetsToBag([asset]) + !assetInBag && sendAnalyticsEvent(EventName.NFT_BUY_ADDED, { ...eventProperties }) + }} > {assetInBag ? 'Remove' : 'Buy Now'} diff --git a/src/nft/hooks/useSendTransaction.ts b/src/nft/hooks/useSendTransaction.ts index f284e81033..0e828dd6c3 100644 --- a/src/nft/hooks/useSendTransaction.ts +++ b/src/nft/hooks/useSendTransaction.ts @@ -3,6 +3,8 @@ import { BigNumber } from '@ethersproject/bignumber' import { hexStripZeros } from '@ethersproject/bytes' import { ContractReceipt } from '@ethersproject/contracts' import type { JsonRpcSigner } from '@ethersproject/providers' +import { sendAnalyticsEvent } from 'analytics' +import { EventName } from 'analytics/constants' import create from 'zustand' import { devtools } from 'zustand/middleware' @@ -48,6 +50,7 @@ export const useSendTransaction = create()( const res = await signer.sendTransaction(tx) set({ state: TxStateType.Confirming }) set({ txHash: res.hash }) + sendAnalyticsEvent(EventName.NFT_BUY_BAG_SIGNED, { transaction_hash: res.hash }) const txReceipt = await res.wait() diff --git a/src/nft/pages/collection/index.tsx b/src/nft/pages/collection/index.tsx index cbcfc4cde4..da4673c49e 100644 --- a/src/nft/pages/collection/index.tsx +++ b/src/nft/pages/collection/index.tsx @@ -91,7 +91,7 @@ const Collection = () => { <> diff --git a/src/nft/utils/formatEventProperties.ts b/src/nft/utils/formatEventProperties.ts new file mode 100644 index 0000000000..1da170b52f --- /dev/null +++ b/src/nft/utils/formatEventProperties.ts @@ -0,0 +1,7 @@ +import { GenieAsset } from 'nft/types' + +export const formatAssetEventProperties = (assets: GenieAsset[]) => ({ + collection_addresses: assets.map((asset) => asset.address), + token_ids: assets.map((asset) => asset.tokenId), + token_types: assets.map((asset) => asset.tokenType), +}) diff --git a/src/nft/utils/index.ts b/src/nft/utils/index.ts index 71adee57d2..1ebaffef4f 100644 --- a/src/nft/utils/index.ts +++ b/src/nft/utils/index.ts @@ -5,6 +5,7 @@ export * from './calcPoolPrice' export * from './carousel' export * from './currency' export * from './fetchPrice' +export * from './formatEventProperties' export * from './isAudio' export * from './isVideo' export * from './listNfts'