Skip to content

Commit

Permalink
refactor: store local evm transactions in same store as blockscout ev…
Browse files Browse the repository at this point in the history
…m transactions (#2013)

Co-authored-by: Mark Nardi <[email protected]>
  • Loading branch information
nicole-obrien and MarkNerdi authored Feb 29, 2024
1 parent cbe29c2 commit d9d4cb3
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { DEFAULT_ACCOUNT_RECOVERY_CONFIGURATION } from '@core/profile'
import { RecoverAccountsPayload, recoverAccounts } from '@core/profile-manager'
import { checkActiveProfileAuth, getBaseToken, loadAccounts } from '@core/profile/actions'
import { activeAccounts, activeProfile, visibleActiveAccounts } from '@core/profile/stores'
import { activeAccounts, activeProfile, activeProfileId, visibleActiveAccounts } from '@core/profile/stores'
import { formatTokenAmountBestMatch } from '@core/token'
import { refreshAccountTokensForActiveProfile } from '@core/token/actions'
import { closePopup } from '@desktop/auxiliary/popup'
Expand Down Expand Up @@ -141,7 +141,7 @@
onDestroy(async () => {
if (hasUsedWalletFinder) {
await refreshAccountTokensForActiveProfile()
await generateAndStoreActivitiesForAllAccounts()
await generateAndStoreActivitiesForAllAccounts($activeProfileId)
loadNftsForActiveProfile()
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { NetworkId } from '@core/network'
import { setOutgoingAsyncActivitiesToClaimed } from './setOutgoingAsyncActivitiesToClaimed'

export async function generateAndStoreActivitiesForAccount(
profileId: string,
account: IAccountState,
networkId: NetworkId
): Promise<void> {
Expand All @@ -34,7 +35,7 @@ export async function generateAndStoreActivitiesForAccount(
const balanceChangeActivities = await generateActivitiesFromBalanceChanges(account)
activities.push(...balanceChangeActivities)

const chainActivities = await generateActivitiesFromChains(account)
const chainActivities = await generateActivitiesFromChains(profileId, account)
activities.push(...chainActivities)

// Step 4: set account activities with generated activities
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { activeAccounts } from '@core/profile/stores'
import { generateAndStoreActivitiesForAccount } from './generateAndStoreActivitiesForAccount'
import { getActiveNetworkId } from '@core/network'

export async function generateAndStoreActivitiesForAllAccounts(): Promise<void> {
export async function generateAndStoreActivitiesForAllAccounts(profileId: string): Promise<void> {
try {
const networkId = getActiveNetworkId()
const accounts = get(activeAccounts)

await Promise.all(
accounts.map((activeAccount) => generateAndStoreActivitiesForAccount(activeAccount, networkId))
accounts.map((activeAccount) => generateAndStoreActivitiesForAccount(profileId, activeAccount, networkId))
)
} catch (err) {
console.error(err)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { activeProfileId } from '@core/profile/stores'
import { NetworkId } from '@core/network/types'
import { persistent } from '@core/utils/store'
import { get } from 'svelte/store'
import { PersistedEvmTransaction } from '../types'
import { NetworkId } from '@core/network/types'
import { IChain } from '@core/network/interfaces'

type PersistedEvmTransactions = {
[profileId: string]: {
Expand All @@ -14,40 +11,3 @@ type PersistedEvmTransactions = {
}

export const persistedEvmTransactions = persistent<PersistedEvmTransactions>('evmTransactions', {})

export function getPersistedEvmTransactions(accountIndex: number, chain: IChain): PersistedEvmTransaction[] {
const networkId = chain.getConfiguration().id
return get(persistedEvmTransactions)?.[get(activeProfileId)]?.[accountIndex]?.[networkId] ?? []
}

export function addPersistedTransaction(
accountIndex: number,
chain: IChain,
...newTransactions: PersistedEvmTransaction[]
): void {
const networkId = chain.getConfiguration().id
const profileId = get(activeProfileId)
persistedEvmTransactions.update((state) => {
if (!state[profileId]) {
state[profileId] = {}
}
if (!state[profileId][accountIndex]) {
state[profileId][accountIndex] = {
[networkId]: [],
}
}
if (!state[profileId][accountIndex][networkId]) {
state[profileId][accountIndex][networkId] = []
}

state[get(activeProfileId)][accountIndex][networkId]?.push(...newTransactions)
return state
})
}

export function removePersistedEvmTransactionsForProfile(profileId: string): void {
persistedEvmTransactions.update((state) => {
delete state[profileId]
return state
})
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import { IAccountState } from '@core/account'
import { network } from '@core/network'
import { getPersistedTransactionsForChain } from '@core/transactions/stores'
import { get } from 'svelte/store'
import { Activity } from '../types'
import { getPersistedEvmTransactions } from '../stores'
import { generateActivityFromEvmTransaction } from './generateActivityFromEvmTransaction'
import { get } from 'svelte/store'
import { network } from '@core/network'

export async function generateActivitiesFromChains(account: IAccountState): Promise<Activity[]> {
export async function generateActivitiesFromChains(profileId: string, account: IAccountState): Promise<Activity[]> {
const activities: Activity[] = []

const chains = get(network)?.getChains() ?? []
for (const chain of chains) {
const transactions = getPersistedEvmTransactions(account.index, chain)
for (const transaction of transactions) {
const persistedTransactions = getPersistedTransactionsForChain(profileId, account.index, chain)
for (const transaction of persistedTransactions) {
try {
const activity = await generateActivityFromEvmTransaction(transaction, chain, account)
if (activity) {
activities.push(activity)
if (transaction.local) {
// TODO: build activities from persisted transactions
const activity = await generateActivityFromEvmTransaction(transaction.local, chain, account)
if (activity) {
activities.push(activity)
}
}
} catch (error) {
console.error(error)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import { NftOutput, OutputType } from '@iota/sdk/out/types'
import { getAddressFromAccountForNetwork } from '@core/account'
import { IAccountState } from '@core/account/interfaces'
import { activeAccounts } from '@core/profile/stores'
import { ActivityType } from '@core/activity'
import { getNftId } from '@core/activity/utils/outputs'
import { getTransferInfoFromTransactionData } from '@core/layer-2/utils/getTransferInfoFromTransactionData'
import { getActiveNetworkId, getNetwork } from '@core/network'
import { activeAccounts, activeProfileId } from '@core/profile/stores'
import { getPersistedTransactionsForChain } from '@core/transactions/stores'
import { IWrappedOutput } from '@core/wallet/interfaces'
import { NftOutput, OutputType } from '@iota/sdk/out/types'
import { get } from 'svelte/store'
import { Nft } from '../interfaces'
import { buildNftFromNftOutput } from './buildNftFromNftOutput'
import { setAccountNftsInAllAccountNfts } from './setAccountNftsInAllAccountNfts'
import { getActiveNetworkId, getNetwork } from '@core/network'
import { ActivityType, getPersistedEvmTransactions } from '@core/activity'
import { getTransferInfoFromTransactionData } from '@core/layer-2/utils/getTransferInfoFromTransactionData'
import { buildNftFromPersistedErc721Nft, getNftsFromNftIds } from '../utils'
import { addNftsToDownloadQueue } from './addNftsToDownloadQueue'
import { buildNftFromNftOutput } from './buildNftFromNftOutput'
import { getPersistedErc721Nfts } from './getPersistedErc721Nfts'
import { getAddressFromAccountForNetwork } from '@core/account'
import { setAccountNftsInAllAccountNfts } from './setAccountNftsInAllAccountNfts'

export async function loadNftsForActiveProfile(): Promise<void> {
let nftsToDownload: Nft[] = []
const profileId = get(activeProfileId)
const allAccounts = get(activeAccounts)
for (const account of allAccounts) {
const accountNfts = await loadNftsForAccount(account)
const accountNfts = await loadNftsForAccount(profileId, account)
nftsToDownload = [...nftsToDownload, ...accountNfts]
}

nftsToDownload = [...new Set(nftsToDownload)]
void addNftsToDownloadQueue(nftsToDownload)
}

export async function loadNftsForAccount(account: IAccountState): Promise<Nft[]> {
export async function loadNftsForAccount(profileId: string, account: IAccountState): Promise<Nft[]> {
const accountNfts: Nft[] = []
const unspentOutputs = await account.unspentOutputs()
const networkId = getActiveNetworkId()
Expand All @@ -40,10 +42,13 @@ export async function loadNftsForAccount(account: IAccountState): Promise<Nft[]>

for (const chain of getNetwork()?.getChains() ?? []) {
// Wrapped L1 NFTs
const transactionsOnChain = getPersistedEvmTransactions(account.index, chain)
const transactionsOnChain = getPersistedTransactionsForChain(profileId, account.index, chain)
const nftIdsOnChain = []
for (const transaction of transactionsOnChain) {
const transferInfo = getTransferInfoFromTransactionData(transaction, chain)
if (!transaction.local) {
continue
}
const transferInfo = getTransferInfoFromTransactionData(transaction.local, chain)
if (transferInfo?.type !== ActivityType.Nft) {
continue
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export async function login(loginOptions?: ILoginOptions): Promise<void> {

// Step 5: generate and store activities for all accounts
incrementLoginProgress()
await generateAndStoreActivitiesForAllAccounts()
await generateAndStoreActivitiesForAllAccounts(_activeProfile.id)

if (type === ProfileType.Software) {
// Step 6: set initial stronghold status
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import {
removeClaimedActivitiesForProfile,
removeHiddenActivitiesForProfile,
removePersistedBalanceChangesForProfile,
removePersistedEvmTransactionsForProfile,
} from '@core/activity/stores'
import { removePersistedNftsForProfile } from '@core/nfts/stores'
import { removePersistedProfile } from '@core/profile/stores'
import { removePersistedTokensForProfile } from '@core/token/stores'
import { removePersistedTransactionsForProfile } from '@core/transactions/stores'

export function removeAllProfileData(profileId: string): void {
removePersistedProfile(profileId)
removePersistedEvmTransactionsForProfile(profileId)
removePersistedTransactionsForProfile(profileId)
removePersistedBalanceChangesForProfile(profileId)
removeClaimedActivitiesForProfile(profileId)
removePersistedNftsForProfile(profileId)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { addAccountActivity, addPersistedTransaction } from '@core/activity/stores'
import { EvmTransactionData } from '@core/layer-2'
import { IChain } from '@core/network'
import { signEvmTransaction } from '../signEvmTransaction'
import { generateActivityFromEvmTransaction } from '@core/activity/utils/generateActivityFromEvmTransaction'
import { IAccountState } from '@core/account'
import {
Activity,
ActivityDirection,
ActivityType,
PersistedEvmTransaction,
calculateAndAddPersistedNftBalanceChange,
} from '@core/activity'
import { IAccountState } from '@core/account'
import { updateL2BalanceWithoutActivity } from '../updateL2BalanceWithoutActivity'
import { addAccountActivity } from '@core/activity/stores'
import { generateActivityFromEvmTransaction } from '@core/activity/utils/generateActivityFromEvmTransaction'
import { EvmTransactionData } from '@core/layer-2'
import { EvmNetworkId, IChain } from '@core/network'
import { addLocalTransactionToPersistedTransaction } from '@core/transactions/stores'
import { sendSignedEvmTransaction } from '@core/wallet/actions/sendSignedEvmTransaction'
import { signEvmTransaction } from '../signEvmTransaction'
import { updateL2BalanceWithoutActivity } from '../updateL2BalanceWithoutActivity'

export async function signAndSendTransactionFromEvm(
preparedTransaction: EvmTransactionData,
chain: IChain,
account: IAccountState,
signAndSend: boolean
signAndSend: boolean,
profileId: string
): Promise<unknown> {
const signedTransaction = await signEvmTransaction(preparedTransaction, chain, account)
if (!signedTransaction) {
Expand All @@ -40,16 +42,18 @@ export async function signAndSendTransactionFromEvm(
...transactionReceipt,
timestamp: Date.now(),
}
await persistEvmTransaction(evmTransaction, chain, account)
await persistEvmTransaction(profileId, account, chain, evmTransaction)
return transactionReceipt.transactionHash
}

async function persistEvmTransaction(
evmTransaction: PersistedEvmTransaction,
profileId: string,
account: IAccountState,
chain: IChain,
account: IAccountState
evmTransaction: PersistedEvmTransaction
): Promise<void> {
addPersistedTransaction(account.index, chain, evmTransaction)
const networkId = chain.getConfiguration().id as EvmNetworkId
addLocalTransactionToPersistedTransaction(profileId, account.index, networkId, [evmTransaction])

const activity = await generateActivityFromEvmTransaction(evmTransaction, chain, account)
if (!activity) {
Expand All @@ -62,7 +66,7 @@ async function persistEvmTransaction(

if (activity.recipient?.type === 'account') {
const recipientAccount = activity.recipient.account
addPersistedTransaction(recipientAccount.index, chain, evmTransaction)
addLocalTransactionToPersistedTransaction(profileId, recipientAccount.index, networkId, [evmTransaction])
const receiveActivity = await generateActivityFromEvmTransaction(evmTransaction, chain, recipientAccount)
if (!receiveActivity) {
return
Expand Down

0 comments on commit d9d4cb3

Please sign in to comment.