Skip to content

Commit

Permalink
feat: update watchAssetHandler for erc721 (#1712)
Browse files Browse the repository at this point in the history
* update watchAssetHandler for erc721

* update translations

* improve locales

* address to lowercase

---------

Co-authored-by: Nicole O'Brien <[email protected]>
  • Loading branch information
MarkNerdi and nicole-obrien authored Jan 17, 2024
1 parent a75f913 commit 0c1729b
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,23 @@
validateEthereumAddress(_tokenAddress)
const erc20TokenMetadata = (await getEvmTokenMetadata(_tokenAddress, networkId)) as IErc20Metadata
if (erc20TokenMetadata) {
addNewTrackedTokenToActiveProfile(
networkId,
_tokenAddress,
erc20TokenMetadata,
TokenTrackingStatus.ManuallyTracked
)
showNotification({
variant: 'success',
text: localize('popups.importToken.success', {
values: { tokenSymbol: erc20TokenMetadata.symbol },
}),
})
closePopup()
if (!erc20TokenMetadata) {
return
}
addNewTrackedTokenToActiveProfile(
networkId,
_tokenAddress,
erc20TokenMetadata,
TokenTrackingStatus.ManuallyTracked
)
showNotification({
variant: 'success',
text: localize('popups.importToken.success', {
values: { tokenSymbol: erc20TokenMetadata.symbol },
}),
})
closePopup()
} catch (err) {
tokenAddressError = err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@
import PopupTemplate from '../PopupTemplate.svelte'
import { closePopup } from '@desktop/auxiliary/popup'
import { showNotification } from '@auxiliary/notification'
import { persistErc721Nft, updateAllAccountNftsForAccount } from '@core/nfts/actions'
import {
addNewTrackedNftToActiveProfile,
persistErc721Nft,
updateAllAccountNftsForAccount,
} from '@core/nfts/actions'
import { buildNftFromPersistedErc721Nft } from '@core/nfts/utils'
import { activeAccounts } from '@core/profile/stores'
import { getAddressFromAccountForNetwork } from '@core/account'
import { TokenTrackingStatus } from '@core/token'
let busy = false
Expand All @@ -30,21 +35,26 @@
busy = true
try {
validateEthereumAddress(tokenAddress)
const persistedErc721Nft = await persistErc721Nft(tokenAddress, tokenId, networkId)
if (!persistedErc721Nft) {
const persistedNft = await persistErc721Nft(tokenAddress, tokenId, networkId)
if (!persistedNft) {
throw new Error(localize('popups.importTokens.errors.alreadyAdded'))
}
addNewTrackedNftToActiveProfile(
networkId,
`${persistedNft.contractMetadata.address}:${persistedNft.tokenId}`,
TokenTrackingStatus.ManuallyTracked
)
for (const account of $activeAccounts) {
const l2Address = getAddressFromAccountForNetwork(account, networkId)
const nft = buildNftFromPersistedErc721Nft(persistedErc721Nft, l2Address)
const nft = buildNftFromPersistedErc721Nft(persistedNft, l2Address)
updateAllAccountNftsForAccount(account.index, nft)
}
showNotification({
variant: 'success',
text: localize('popups.importToken.success', {
values: { tokenSymbol: persistedErc721Nft.contractMetadata.symbol },
values: { tokenSymbol: persistedNft.contractMetadata.symbol },
}),
})
closePopup()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,108 +1,95 @@
import { PopupId, openPopup } from '../../../../../../desktop/lib/auxiliary/popup'
import { PopupId, closePopup, openPopup } from '../../../../../../desktop/lib/auxiliary/popup'
import { IChain, NetworkId } from '@core/network'
import { CallbackParameters } from '@auxiliary/wallet-connect/types'
import { ContractType, EvmAssetStandard } from '@core/layer-2'
import { getEvmTokenMetadata } from '@core/layer-2'
import { getSdkError } from '@walletconnect/utils'
import { addNewTrackedTokenToActiveProfile } from '@core/wallet/actions'
import { TokenStandard, TokenTrackingStatus } from '@core/token/enums'
import { IConnectedDapp } from '../interface'
import { localize } from '@core/i18n'
import { NftStandard } from '@core/nfts/enums'
import { addNewTrackedNftToActiveProfile, persistErc721Nft } from '@core/nfts/actions'
import { IErc20Metadata } from '@core/token'

interface WatchAssetParams {
type: EvmAssetStandard
options: {
address: string
name?: string
decimals?: number
symbol?: string
}
}
type WatchAssetParams =
| {
type: TokenStandard.Erc20
options: {
address: string
name?: string
decimals?: number
symbol?: string
}
}
| {
type: NftStandard.Erc721
options: {
address: string
tokenId: string
}
}

export async function handleWatchAsset(
export function handleWatchAsset(
params: WatchAssetParams,
dapp: IConnectedDapp | undefined,
chain: IChain,
responseCallback: (params: CallbackParameters) => void
): Promise<void> {
): void {
if (params.type !== TokenStandard.Erc20 && params.type !== NftStandard.Erc721) {
responseCallback({ error: getSdkError('UNSUPPORTED_METHODS') })
return
}

const assetInfo = await getAssetInfo(params.type, params.options, chain)
if (!assetInfo) {
responseCallback({ error: getSdkError('UNSUPPORTED_METHODS') })
return
}

openPopup({
id: PopupId.Confirmation,
props: {
title: localize('popups.confirmAssetTracking.title'),
description: localize('popups.confirmAssetTracking.description', {
title: localize(`popups.confirmAssetTracking.${params.type}.title`),
description: localize(`popups.confirmAssetTracking.${params.type}.description`, {
dappName: dapp?.metadata?.name,
assetName: assetInfo.name,
assetName: params.type === TokenStandard.Erc20 ? params.options.name : undefined,
tokenId: params.type === NftStandard.Erc721 ? params.options.tokenId : undefined,
address: params.options.address,
}),
onConfirm: () => {
void trackAsset(params.type, params.options.address, assetInfo, chain.getConfiguration().id)
void trackAsset(params, chain.getConfiguration().id)
responseCallback({ result: null })
},
onCancel: () => responseCallback({ error: getSdkError('USER_REJECTED') }),
onCancel: () => {
responseCallback({ error: getSdkError('USER_REJECTED') })
closePopup()
},
},
})
}

async function getAssetInfo(
type: EvmAssetStandard,
options: {
address: string
name?: string
decimals?: number
symbol?: string
},
chain: IChain
): Promise<{ name: string; decimals: number; symbol: string } | undefined> {
async function trackAsset(params: WatchAssetParams, networkId: NetworkId): Promise<void> {
const { type, options } = params
switch (type) {
case TokenStandard.Erc20: {
const { address } = options
const contract = chain.getContract(ContractType.Erc20, address)
const name = options.name ? options.name : await contract?.methods.name().call()
const decimals = options.decimals ? options.decimals : await contract?.methods.decimals().call()
const symbol = options.symbol ? options.symbol : await contract?.methods.symbol().call()

return { name: name, decimals, symbol }
}
case NftStandard.Erc721:
// TODO
break
default:
break
}
}

function trackAsset(
type: EvmAssetStandard,
address: string,
assetInfo: {
name: string
decimals: number
symbol: string
},
networkId: NetworkId
): void {
switch (type) {
case TokenStandard.Erc20:
const erc20TokenMetadata = await getEvmTokenMetadata(options.address, networkId)
if (!erc20TokenMetadata) {
return
}
addNewTrackedTokenToActiveProfile(
networkId,
address,
{ ...assetInfo, standard: TokenStandard.Erc20 },
options.address,
erc20TokenMetadata as IErc20Metadata,
TokenTrackingStatus.ManuallyTracked
)
break
case NftStandard.Erc721:
// TODO
}
case NftStandard.Erc721: {
const persistedNft = await persistErc721Nft(options.address, options.tokenId, networkId)
if (!persistedNft) {
return
}
addNewTrackedNftToActiveProfile(
networkId,
`${persistedNft.contractMetadata.address.toLowerCase()}:${persistedNft.tokenId}`,
TokenTrackingStatus.ManuallyTracked
)
break
}
default:
break
}
Expand Down

This file was deleted.

1 change: 0 additions & 1 deletion packages/shared/src/lib/core/layer-2/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export * from './abi.type'
export * from './contract.type'
export * from './evm-asset-standard.type'
export * from './evm-chain-gas-prices.type'
export * from './evm-transaction-options.type'
export * from './evm-transaction-data.type'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { updateAllAccountNftsForAccount } from './updateAllAccountNfts'
import { buildNftFromPersistedErc721Nft } from '../utils'
import { addNftsToDownloadQueue } from './addNftsToDownloadQueue'
import { Nft } from '../interfaces'
import { addNewTrackedNftToActiveProfile } from './addNewTrackedNftToActiveProfile'
import { TokenTrackingStatus } from '@core/token'

export async function checkForUntrackedNfts(account: IAccountState): Promise<void> {
if (!features?.collectibles?.erc721?.enabled) {
Expand Down Expand Up @@ -66,6 +68,12 @@ async function persistNftsFromExplorerAsset(
return undefined
}

addNewTrackedNftToActiveProfile(
networkId,
`${persistedNft.contractMetadata.address}:${persistedNft.tokenId}`,
TokenTrackingStatus.AutomaticallyTracked
)

const nft = buildNftFromPersistedErc721Nft(persistedNft, evmAddress)
updateAllAccountNftsForAccount(account.index, nft)
return nft
Expand Down
24 changes: 13 additions & 11 deletions packages/shared/src/lib/core/nfts/actions/persistErc721Nft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,20 @@ export async function persistErc721Nft(
const chain = network?.getChain(networkId)
const expectedOwner = getSelectedAccount().evmAddresses[chain?.getConfiguration()?.coinType ?? '0']
const contract = chain?.getContract(ContractType.Erc721, tokenAddress)
if (contract) {
const metadata = (await getEvmTokenMetadata(
tokenAddress,
networkId,
ContractType.Erc721
)) as IErc721ContractMetadata
let owner = await contract.methods.ownerOf(tokenId).call()
owner = owner.toLowerCase()
if (!contract) {
return
}

const metadata = (await getEvmTokenMetadata(
tokenAddress,
networkId,
ContractType.Erc721
)) as IErc721ContractMetadata
let owner = await contract.methods.ownerOf(tokenId).call()
owner = owner.toLowerCase()

if (owner === expectedOwner) {
return persistNftWithContractMetadata(owner, networkId, metadata, tokenId, contract)
}
if (owner !== expectedOwner) {
throw new Error(localize('popups.importToken.errors.otherOwner'))
}
return persistNftWithContractMetadata(owner, networkId, metadata, tokenId, contract)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { Contract } from '@core/layer-2'
import { NetworkId } from '@core/network'
import { TokenTrackingStatus } from '@core/token'
import { IErc721ContractMetadata, IPersistedErc721Nft } from '../interfaces'
import { addPersistedNft } from '../stores'
import { buildPersistedErc721Nft } from '../utils'
import { addNewTrackedNftToActiveProfile } from './addNewTrackedNftToActiveProfile'
import { isNftPersisted } from './isNftPersisted'

export async function persistNftWithContractMetadata(
Expand All @@ -21,6 +19,5 @@ export async function persistNftWithContractMetadata(
}
const persistedNft = await buildPersistedErc721Nft(ownerAddress, networkId, tokenId, contract, contractMetadata)
addPersistedNft(nftId, persistedNft)
addNewTrackedNftToActiveProfile(networkId, nftId, TokenTrackingStatus.AutomaticallyTracked)
return persistedNft
}
10 changes: 8 additions & 2 deletions packages/shared/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -778,8 +778,14 @@
"body": "Are you sure you want to clear {url} as the primary node?"
},
"confirmAssetTracking": {
"title": "Add a new token",
"description": "\"{dappName}\" wants to add \"{assetName}\" to your wallet."
"ERC721": {
"title": "Add new NFT",
"description": "\"{dappName}\" wants to add an NFT with id \"{tokenId}\" and address \"{address}\" to your wallet."
},
"ERC20": {
"title": "Add new token",
"description": "\"{dappName}\" wants to add {assetName, select, undefined { a token with address \"{address}\" } other { {assetName} }} to your wallet."
}
},
"node": {
"titleAdd": "Add a node",
Expand Down

0 comments on commit 0c1729b

Please sign in to comment.