Skip to content

Commit

Permalink
chore: remove balance changes for evm assets (#2054)
Browse files Browse the repository at this point in the history
* cleanup L2 balance fetches

* generate balance changes only if IRC is sent

* fix name

* cleanup old balance changes

* improve erc detection

* add prod migration
  • Loading branch information
MarkNerdi authored Mar 5, 2024
1 parent 8da63da commit a0fef6c
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@ import {
import { selectedAccountNfts } from '@core/nfts/stores'
import { getActiveProfile } from '@core/profile/stores'
import { getOrRequestTokenFromPersistedTokens } from '@core/token/actions'
import { TOKEN_ID_BYTE_LENGTH } from '@core/token/constants'
import { Converter } from '@core/utils/convert'
import { ISC_MAGIC_CONTRACT_ADDRESS } from '../constants'
import { evmAddressToAgentId, getAgentBalanceParameters, getSmartContractHexName } from '../helpers'
import { setLayer2AccountBalanceForChain } from '../stores'
import { isTrackedTokenAddress } from '@core/wallet'
import { TokenTrackingStatus } from '@core/token'
import { BASE_TOKEN_ID, TokenTrackingStatus } from '@core/token'
import features from '@features/features'
import { KeyValue } from '@ui/types'

Expand All @@ -37,45 +35,37 @@ export function fetchL2BalanceForAccount(account: IAccountState): void {
return
}

await fetchLayer2Nfts(evmAddress, chain, account)
await fetchL2Irc27Nfts(evmAddress, chain, account)
if (features.collectibles.erc721.enabled) {
void updateErc721NftsOwnership(account)
}

const balances = await getLayer2BalanceForAddress(evmAddress, chain)
if (!balances) {
const l2Balance: { [tokenId: string]: bigint } = {}

const l2BaseAndIrc30Balances = await getL2NativeTokenBalancesForAddress(evmAddress, chain)
const erc20Balances = await getErc20BalancesForAddress(evmAddress, chain)
if (erc20Balances.length === 0 && l2BaseAndIrc30Balances.length === 0) {
return
}

const layer2Balance: { [tokenId: string]: bigint } = {}

for (const { balance, tokenId } of balances) {
for (const { balance, tokenId } of l2BaseAndIrc30Balances) {
const adjustedBalance = Number.isNaN(Number(balance)) ? BigInt(0) : balance
const isNativeToken = Converter.hexToBytes(tokenId).length === TOKEN_ID_BYTE_LENGTH
const isErc20TrackedToken = isTrackedTokenAddress(networkId, tokenId)
if (isNativeToken || isErc20TrackedToken) {
if (tokenId !== BASE_TOKEN_ID) {
await getOrRequestTokenFromPersistedTokens(tokenId, networkId)
await calculateAndAddPersistedTokenBalanceChange(account, networkId, tokenId, adjustedBalance)
}
await calculateAndAddPersistedTokenBalanceChange(account, networkId, tokenId, adjustedBalance)
layer2Balance[tokenId] = adjustedBalance
l2Balance[tokenId] = adjustedBalance
}
setLayer2AccountBalanceForChain(index, networkId, layer2Balance)
})
}

async function getLayer2BalanceForAddress(
evmAddress: string,
chain: IChain
): Promise<ILayer2TokenBalance[] | undefined> {
const layer2BaseAndIrc30Balances = await getLayer2NativeTokenBalancesForAddress(evmAddress, chain)
const erc20Balances = await getLayer2Erc20BalancesForAddress(evmAddress, chain)
return [...layer2BaseAndIrc30Balances, ...erc20Balances]
for (const { balance, tokenId } of erc20Balances) {
await getOrRequestTokenFromPersistedTokens(tokenId, networkId)
l2Balance[tokenId] = Number.isNaN(Number(balance)) ? BigInt(0) : balance
}
setLayer2AccountBalanceForChain(index, networkId, l2Balance)
})
}

async function getLayer2NativeTokenBalancesForAddress(
evmAddress: string,
chain: IChain
): Promise<ILayer2TokenBalance[]> {
async function getL2NativeTokenBalancesForAddress(evmAddress: string, chain: IChain): Promise<ILayer2TokenBalance[]> {
const accountsCoreContract = getSmartContractHexName('accounts')
const getBalanceFunc = getSmartContractHexName('balance')
const agentID = evmAddressToAgentId(evmAddress, chain.getConfiguration())
Expand All @@ -86,18 +76,19 @@ async function getLayer2NativeTokenBalancesForAddress(
.callView(accountsCoreContract, getBalanceFunc, parameters)
.call()) as { items: KeyValue<string>[] }

const nativeTokens = nativeTokenResult.items.map((item) => ({
tokenId: item.key,
balance: Converter.bigIntLikeToBigInt(item.value),
}))
const nativeTokens =
nativeTokenResult.items?.map((item) => ({
tokenId: item.key,
balance: Converter.bigIntLikeToBigInt(item.value),
})) ?? []

return nativeTokens
} catch (e) {
return []
}
}

async function getLayer2Erc20BalancesForAddress(evmAddress: string, chain: IChain): Promise<ILayer2TokenBalance[]> {
async function getErc20BalancesForAddress(evmAddress: string, chain: IChain): Promise<ILayer2TokenBalance[]> {
const networkId = chain.getConfiguration().id
const trackedTokens = getActiveProfile()?.trackedTokens?.[networkId] ?? {}
const erc20TokenBalances = []
Expand All @@ -122,7 +113,7 @@ async function getLayer2Erc20BalancesForAddress(evmAddress: string, chain: IChai
return erc20TokenBalances
}

async function fetchLayer2Nfts(evmAddress: string, chain: IChain, account: IAccountState): Promise<void> {
async function fetchL2Irc27Nfts(evmAddress: string, chain: IChain, account: IAccountState): Promise<void> {
const accountsCoreContract = getSmartContractHexName('accounts')
const getBalanceFunc = getSmartContractHexName('accountNFTs')
const agentID = evmAddressToAgentId(evmAddress, chain.getConfiguration())
Expand Down
1 change: 1 addition & 0 deletions packages/shared/src/lib/core/layer-2/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from './getErc721TransferSmartContractData'
export * from './getEvmTransactionFromHexString'
export * from './getHexEncodedTransaction'
export * from './getMethodNameForEvmTransaction'
export * from './isErcAsset'
export * from './lookupMethodSignature'
export * from './parseLayer2Metadata'
export * from './parseLayer2MetadataForTransfer'
Expand Down
7 changes: 7 additions & 0 deletions packages/shared/src/lib/core/layer-2/utils/isErcAsset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { isValidEthereumAddress } from '@core/utils/crypto/utils/isValidEthereumAddress'

export function isErcAsset(assetId: string): boolean {
const [address] = assetId.split(':')

return isValidEthereumAddress(address)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { IErc721Nft } from '../interfaces'
import { getAllAccountNfts, persistedNftForActiveProfile, updatePersistedNft } from '../stores'
import { getOwnerOfErc721Nft } from '../utils'
import { get } from 'svelte/store'
import { calculateAndAddPersistedNftBalanceChange } from '@core/activity'

export async function updateErc721NftsOwnership(account: IAccountState): Promise<void> {
try {
Expand All @@ -26,8 +25,6 @@ export async function updateErc721NftsOwnership(account: IAccountState): Promise
const l2Address = getAddressFromAccountForNetwork(account, nft.networkId)
const isSpendable = updatedOwner === l2Address?.toLowerCase()
updateAllAccountNftsForAccount(account.index, { ...nft, isSpendable })

calculateAndAddPersistedNftBalanceChange(account, nft.networkId, nft.id, isSpendable)
})
await Promise.allSettled(promises)
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AppStage } from '@core/app/enums'

export const PROFILE_VERSION: Record<AppStage, number> = {
[AppStage.ALPHA]: 6,
[AppStage.ALPHA]: 7,
[AppStage.BETA]: 0,
[AppStage.PROD]: 3,
[AppStage.PROD]: 4,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { persistedBalanceChanges } from '@core/activity'
import { isErcAsset } from '@core/layer-2'
import { NetworkId } from '@core/network'
import { BASE_TOKEN_ID } from '@core/token'

export function removeEvmBalanceChanges(profileId: string): void {
persistedBalanceChanges.update((state) => {
const profileBalanceChanges = state[profileId]
if (!profileBalanceChanges) {
return state
}

for (const accountId of Object.keys(profileBalanceChanges)) {
const accountBalanceChanges = profileBalanceChanges[accountId]

for (const networkId of Object.keys(accountBalanceChanges)) {
const networkBalanceChanges = accountBalanceChanges[networkId as NetworkId]
if (!networkBalanceChanges) {
continue
}
const tokens = networkBalanceChanges.tokens
const nfts = networkBalanceChanges.nfts

for (const nftId of Object.keys(nfts ?? {})) {
if (isErcAsset(nftId)) {
delete nfts[nftId]
}
}

for (const tokenId of Object.keys(tokens ?? {})) {
if (tokenId === BASE_TOKEN_ID || isErcAsset(tokenId)) {
delete tokens[tokenId]
}
}

accountBalanceChanges[networkId as NetworkId] = networkBalanceChanges
}
profileBalanceChanges[accountId] = accountBalanceChanges
}

state[profileId] = profileBalanceChanges
return state
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { removeEvmBalanceChanges } from '../actions/removeEvmBalanceChanges'

export function alphaProfileMigration6To7(existingProfile: unknown): Promise<void> {
const profile = existingProfile as { id: string }

try {
removeEvmBalanceChanges(profile.id)
} catch (error) {
return Promise.reject()
}

return Promise.resolve()
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { alphaProfileMigration2To3 } from './alpha-profile-migration-2-to-3'
import { alphaProfileMigration3To4 } from './alpha-profile-migration-3-to-4'
import { alphaProfileMigration4To5 } from './alpha-profile-migration-4-to-5'
import { alphaProfileMigration5To6 } from './alpha-profile-migration-5-to-6'
import { alphaProfileMigration6To7 } from './alpha-profile-migration-6-to-7'

export const ALPHA_PROFILE_MIGRATION_MAP: ProfileMigrationMap = {
0: alphaProfileMigration0To1,
Expand All @@ -13,4 +14,5 @@ export const ALPHA_PROFILE_MIGRATION_MAP: ProfileMigrationMap = {
3: alphaProfileMigration3To4,
4: alphaProfileMigration4To5,
5: alphaProfileMigration5To6,
6: alphaProfileMigration6To7,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { removeEvmBalanceChanges } from '../actions/removeEvmBalanceChanges'

export function prodProfileMigration3To4(existingProfile: unknown): Promise<void> {
const profile = existingProfile as { id: string }

try {
removeEvmBalanceChanges(profile.id)
} catch (error) {
return Promise.reject()
}

return Promise.resolve()
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { ProfileMigrationMap } from '../../types'
import { prodProfileMigration0To1 } from './prod-profile-migration-0-to-1'
import { prodProfileMigration1To2 } from './prod-profile-migration-1-to-2'
import { prodProfileMigration2To3 } from './prod-profile-migration-2-to-3'
import { prodProfileMigration3To4 } from './prod-profile-migration-3-to-4'

export const PROD_PROFILE_MIGRATION_MAP: ProfileMigrationMap = {
0: prodProfileMigration0To1,
1: prodProfileMigration1To2,
2: prodProfileMigration2To3,
3: prodProfileMigration3To4,
}
1 change: 0 additions & 1 deletion packages/shared/src/lib/core/wallet/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export * from './mintNft'
export * from './mintNftCollection'
export * from './rejectActivity'
export * from './sendOutput'
export * from './updateL2BalanceWithoutActivity'
export * from './signEvmTransaction'
export * from './signMessage'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import {
StardustActivity,
StardustActivityType,
calculateAndAddPersistedNftBalanceChange,
calculateAndAddPersistedTokenBalanceChange,
} from '@core/activity'
import { addAccountActivity } from '@core/activity/stores'
import { generateActivityFromEvmTransaction } from '@core/activity/utils/evm'
import { EvmTransactionData } from '@core/layer-2'
import { EvmTransactionData, isErcAsset } from '@core/layer-2'
import { EvmNetworkId, IChain } from '@core/network'
import { LocalEvmTransaction } from '@core/transactions'
import { addLocalTransactionToPersistedTransaction } from '@core/transactions/stores'
import { sendSignedEvmTransaction } from '@core/wallet/actions/sendSignedEvmTransaction'
import { updateL2BalanceWithoutActivity } from '../updateL2BalanceWithoutActivity'
import { updateLayer2AccountBalanceForTokenOnChain } from '@core/layer-2/stores'

export async function sendAndPersistTransactionFromEvm(
preparedTransaction: EvmTransactionData,
Expand Down Expand Up @@ -73,18 +74,15 @@ async function createHiddenBalanceChange(account: IAccountState, activity: Stard
const received = activity.direction === ActivityDirection.Incoming
const networkId = activity.sourceNetworkId

if (activity.type === StardustActivityType.Nft) {
if (activity.type === StardustActivityType.Nft && !isErcAsset(activity.nftId)) {
const owned = received ? true : false
calculateAndAddPersistedNftBalanceChange(account, networkId, activity.nftId, owned, true)
}
if (activity.tokenTransfer) {
const rawAmount = activity.tokenTransfer.rawAmount
const amount = received ? rawAmount : BigInt(-1) * rawAmount
await updateL2BalanceWithoutActivity(amount, activity.tokenTransfer.tokenId, account, networkId)
}
if (activity.tokenTransfer && !isErcAsset(activity.tokenTransfer.tokenId)) {
const tokenId = activity.tokenTransfer.tokenId
const amount = received ? activity.tokenTransfer.rawAmount : BigInt(-1) * activity.tokenTransfer.rawAmount

const rawBaseTokenAmount = received
? activity.baseTokenTransfer.rawAmount
: BigInt(-1) * (activity.baseTokenTransfer.rawAmount + BigInt(activity.transactionFee ?? 0))
await updateL2BalanceWithoutActivity(rawBaseTokenAmount, activity.baseTokenTransfer.tokenId, account, networkId)
const newBalance = updateLayer2AccountBalanceForTokenOnChain(account.index, networkId, tokenId, amount)
await calculateAndAddPersistedTokenBalanceChange(account, networkId, tokenId, newBalance, true)
}
}

This file was deleted.

0 comments on commit a0fef6c

Please sign in to comment.