Skip to content

Commit

Permalink
Refactors asset ids to include chain id
Browse files Browse the repository at this point in the history
Removed symbols from network base asset ids generation, added chain id
to ids for all asset types. This allows us to use these for indexing
assets across networks in e.g. redux.
  • Loading branch information
hyphenized committed Jul 18, 2023
1 parent 1448c23 commit d9be0a1
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 50 deletions.
10 changes: 5 additions & 5 deletions background/redux-slices/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import {
AssetMainCurrencyAmount,
AssetDecimalAmount,
isBaseAssetForNetwork,
AssetID,
getAssetID,
isSameAsset,
isTrustedAsset,
getFullAssetID,
FullAssetID,
} from "./utils/asset-utils"
import { DomainName, HexString, URI } from "../types"
import { normalizeEVMAddress, sameEVMAddress } from "../lib/utils"
Expand Down Expand Up @@ -61,7 +61,7 @@ export type AccountData = {
address: HexString
network: Network
balances: {
[assetID: AssetID]: AccountBalance
[assetID: FullAssetID]: AccountBalance
}
ens: {
name?: DomainName
Expand Down Expand Up @@ -316,7 +316,7 @@ const accountSlice = createSlice({
network,
assetAmount: { asset },
} = updatedAccountBalance
const assetID = getAssetID(asset)
const assetID = getFullAssetID(asset)

const normalizedAddress = normalizeEVMAddress(address)
const existingAccountData =
Expand Down Expand Up @@ -451,7 +451,7 @@ const accountSlice = createSlice({
if (account !== "loading") {
Object.values(account.balances).forEach(({ assetAmount }) => {
if (isSameAsset(assetAmount.asset, asset)) {
delete account.balances[getAssetID(assetAmount.asset)]
delete account.balances[getFullAssetID(assetAmount.asset)]
}
})
}
Expand Down
49 changes: 49 additions & 0 deletions background/redux-slices/migrations/to-34.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,65 @@
type OldState = {
assets: unknown[]
account: {
accountsData: {
evm: {
[chainID: string]: {
[address: string]:
| "loading"
| {
balances: {
[assetID: string]: unknown
}
[other: string]: unknown
}
}
}
}
[sliceKey: string]: unknown
}
[otherSlice: string]: unknown
}

type NewState = {
assets: unknown[]
account: {
accountsData: {
evm: {
[chainID: string]: {
[address: string]:
| "loading"
| {
balances: {
[assetID: string]: unknown
}
[other: string]: unknown
}
}
}
}
[sliceKey: string]: unknown
}
[otherSlice: string]: unknown
}

export default (prevState: Record<string, unknown>): NewState => {
const typedPrevState = prevState as OldState

const {
account: { accountsData },
} = typedPrevState

Object.keys(accountsData.evm).forEach((chainID) =>
Object.keys(accountsData.evm[chainID]).forEach((address) => {
const account = accountsData.evm[chainID][address]

if (account !== "loading") {
// Clear all accounts cached balances
account.balances = {}
}
})
)

return {
...typedPrevState,
assets: [],
Expand Down
54 changes: 28 additions & 26 deletions background/redux-slices/tests/accounts.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import reducer, {
updateAccountBalance,
updateAssetReferences,
} from "../accounts"
import { getAssetID } from "../utils/asset-utils"
import { getFullAssetID } from "../utils/asset-utils"
import { determineAssetDisplayAndVerify } from "../selectors"

const ADDRESS_MOCK = "0x208e94d5661a73360d9387d3ca169e5c130090cd"
Expand Down Expand Up @@ -74,7 +74,7 @@ describe("Accounts redux slice", () => {
expect(updatedAccountData).not.toEqual("loading")

const updatedBalance = (updatedAccountData as AccountData)?.balances
expect(updatedBalance?.[getAssetID(ETH)].assetAmount.amount).toBe(1n)
expect(updatedBalance?.[getFullAssetID(ETH)].assetAmount.amount).toBe(1n)
expect(updated.combinedData.totalMainCurrencyValue).toBe("")
})

Expand All @@ -94,7 +94,7 @@ describe("Accounts redux slice", () => {
updated.accountsData.evm[ETHEREUM.chainID][ADDRESS_MOCK]
const updatedBalance = (updatedAccountData as AccountData)?.balances

expect(updatedBalance?.[getAssetID(ETH)].assetAmount.amount).toBe(1n)
expect(updatedBalance?.[getFullAssetID(ETH)].assetAmount.amount).toBe(1n)
expect(updated.combinedData.totalMainCurrencyValue).toBe("")
})

Expand Down Expand Up @@ -126,7 +126,7 @@ describe("Accounts redux slice", () => {

const updatedBalance = (updatedAccountData as AccountData)?.balances

expect(updatedBalance?.[getAssetID(ETH)].assetAmount.amount).toBe(0n)
expect(updatedBalance?.[getFullAssetID(ETH)].assetAmount.amount).toBe(0n)
})

it("should update zero balance for account that is loaded", () => {
Expand All @@ -153,7 +153,7 @@ describe("Accounts redux slice", () => {
updated.accountsData.evm[ETHEREUM.chainID][ADDRESS_MOCK]
const updatedBalance = (updatedAccountData as AccountData)?.balances

expect(updatedBalance?.[getAssetID(ETH)].assetAmount.amount).toBe(0n)
expect(updatedBalance?.[getFullAssetID(ETH)].assetAmount.amount).toBe(0n)
})

it("should update positive balance multiple times", () => {
Expand Down Expand Up @@ -188,10 +188,10 @@ describe("Accounts redux slice", () => {
updated.accountsData.evm[ETHEREUM.chainID][ADDRESS_MOCK]
const updatedBalance = (updatedAccountData as AccountData)?.balances

expect(updatedBalance?.[getAssetID(ETH)].assetAmount.amount).toBe(1n)
expect(updatedBalance?.[getAssetID(ASSET_MOCK)].assetAmount.amount).toBe(
10n
)
expect(updatedBalance?.[getFullAssetID(ETH)].assetAmount.amount).toBe(1n)
expect(
updatedBalance?.[getFullAssetID(ASSET_MOCK)].assetAmount.amount
).toBe(10n)
})

it("should support storing balances for assets with the same symbol", () => {
Expand Down Expand Up @@ -232,19 +232,21 @@ describe("Accounts redux slice", () => {
updated.accountsData.evm[ETHEREUM.chainID][ADDRESS_MOCK]
const balances = (updatedAccountData as AccountData)?.balances

expect(balances?.[getAssetID(ETH)].assetAmount.asset).toEqual(ETH)
expect(balances?.[getFullAssetID(ETH)].assetAmount.asset).toEqual(ETH)

expect(balances?.[getAssetID(someToken)].assetAmount.asset).toEqual(
expect(balances?.[getFullAssetID(someToken)].assetAmount.asset).toEqual(
someToken
)
expect(balances?.[getAssetID(someToken)].assetAmount.amount).toEqual(1n)

expect(balances?.[getAssetID(someOtherToken)].assetAmount.asset).toEqual(
someOtherToken
)
expect(balances?.[getAssetID(someOtherToken)].assetAmount.amount).toEqual(
2n
expect(balances?.[getFullAssetID(someToken)].assetAmount.amount).toEqual(
1n
)

expect(
balances?.[getFullAssetID(someOtherToken)].assetAmount.asset
).toEqual(someOtherToken)
expect(
balances?.[getFullAssetID(someOtherToken)].assetAmount.amount
).toEqual(2n)
})

it("updates cached asset data for all accounts", () => {
Expand Down Expand Up @@ -298,12 +300,12 @@ describe("Accounts redux slice", () => {
][otherAccount.address] as AccountData

expect(
firstAccountData.balances[getAssetID(asset)].assetAmount.asset.metadata
?.verified
firstAccountData.balances[getFullAssetID(asset)].assetAmount.asset
.metadata?.verified
).not.toBeDefined()
expect(
secondAccountData.balances[getAssetID(asset)].assetAmount.asset.metadata
?.verified
secondAccountData.balances[getFullAssetID(asset)].assetAmount.asset
.metadata?.verified
).not.toBeDefined()

const updatedAsset = cloneDeep(asset)
Expand All @@ -324,12 +326,12 @@ describe("Accounts redux slice", () => {
][otherAccount.address] as AccountData

expect(
updatedFirstAccountData.balances[getAssetID(asset)].assetAmount.asset
.metadata?.verified
updatedFirstAccountData.balances[getFullAssetID(asset)].assetAmount
.asset.metadata?.verified
).toBe(true)
expect(
updatedSecondAccountData.balances[getAssetID(asset)].assetAmount.asset
.metadata?.verified
updatedSecondAccountData.balances[getFullAssetID(asset)].assetAmount
.asset.metadata?.verified
).toBe(true)
})
})
Expand Down
22 changes: 3 additions & 19 deletions background/redux-slices/utils/asset-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,35 +401,19 @@ export function isUntrustedAsset(asset: AnyAsset): boolean {
return !isTrustedAsset(asset)
}

type AssetType = "base" | "erc20"
type AssetID = "base" | SmartContractFungibleAsset["contractAddress"]
type ChainID = string

export type AssetID = `${AssetType}/${string}`
export type FullAssetID = `${ChainID}/${AssetID}`

/**
* Returns a string that can be used as an identifier for an asset
* TODO: This should be removed in favour of getFullAssetID; Base
* assets should not use symbol in their identifier
*/
export const getAssetID = (
asset: NetworkBaseAsset | SmartContractFungibleAsset
): AssetID => {
if (isNetworkBaseAsset(asset)) {
return `base/${asset.symbol}`
}

return `erc20/${asset.contractAddress}`
}

export const getFullAssetID = (
asset: NetworkBaseAsset | SmartContractFungibleAsset
): FullAssetID => {
if (isNetworkBaseAsset(asset)) {
return `${asset.chainID}/${getAssetID(asset)}`
return `${asset.chainID}/base`
}

return `${asset.homeNetwork.chainID}/${getAssetID(asset)}`
return `${asset.homeNetwork.chainID}/${asset.contractAddress}`
}

// FIXME Unify once asset similarity code is unified.
Expand Down

0 comments on commit d9be0a1

Please sign in to comment.