Skip to content

Commit

Permalink
feat: store indexed data in persisted transactions (#2869)
Browse files Browse the repository at this point in the history
* feat: poll noves indexer data

* feat: store indexed data in persisted transactions

* feat: adds latest block fetched logic and store for noves
  • Loading branch information
jeeanribeiro authored Oct 15, 2024
1 parent 8f2e3ed commit 21c2bd4
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 32 deletions.
1 change: 1 addition & 0 deletions packages/shared/src/lib/auxiliary/noves/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './apis'
export * from './constants'
export * from './interfaces'
export * from './types'
1 change: 0 additions & 1 deletion packages/shared/src/lib/core/network/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,3 @@ export * from './network-status-poll-interval.constant'
export * from './noves-translate-api-url.constant'
export * from './seconds-per-milestone.constant'
export * from './supported-network-id.constant'
export * from '../../../auxiliary/noves/constants/supported-network-id-to-noves-chain.constant'
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ import { IAccountState, getAddressFromAccountForNetwork } from '@core/account'
import {
addBlockscoutTokenTransferToPersistedTransactions,
addBlockscoutTransactionToPersistedTransactions,
addNovesTransactionToPersistedTransactions,
getLatestBlockForPersistedNovesTransactionsForAccountNetwork,
getPersistedTransactionsForChain,
isBlockscoutTokenTransferPersisted,
isBlockscoutTransactionPersisted,
updateLatestBlockForPersistedNovesTransactionsForAccountNetwork,
} from '../stores'
import { BlockscoutApi } from '@auxiliary/blockscout/api'
import { EvmNetworkId, IEvmNetwork, SUPPORTED_NETWORK_ID_TO_NOVES_CHAIN, getEvmNetworks } from '@core/network'
import { EvmNetworkId, IEvmNetwork, getEvmNetworks } from '@core/network'
import { BlockscoutTokenTransfer } from '@auxiliary/blockscout/types'
import { generateEvmActivityFromPersistedTransaction } from '@core/activity/utils'
import { EvmActivity, addAccountActivities, allAccountActivities } from '@core/activity'
import { get } from 'svelte/store'
import { NovesApi, NovesTxResponse } from '@auxiliary/noves'
import { SUPPORTED_NETWORK_ID_TO_NOVES_CHAIN, NovesApi, NovesTxResponse } from '@auxiliary/noves'

export async function fetchAndPersistTransactionsForAccounts(
profileId: string,
Expand All @@ -38,12 +41,11 @@ export async function fetchAndPersistTransactionsForNetwork(
try {
const [blockscoutTransactionsPromise, novesTransactionsPromise] = await Promise.allSettled([
fetchBlockscoutTransactionsForAccount(profileId, account, network),
fetchNovesTransactionsForAccount(account, network),
fetchNovesTransactionsForAccount(profileId, account, network),
])

const blockscoutTransactions =
blockscoutTransactionsPromise.status === 'fulfilled' && blockscoutTransactionsPromise.value
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const novesTransactions = novesTransactionsPromise.status === 'fulfilled' && novesTransactionsPromise.value

blockscoutTransactions &&
Expand All @@ -54,6 +56,20 @@ export async function fetchAndPersistTransactionsForNetwork(
blockscoutTransactions
)

if (novesTransactions && novesTransactions.length > 0) {
addNovesTransactionToPersistedTransactions(profileId, account.index, network.id, novesTransactions)

// Transactions are in reverse-chronological order
// So first transaction will be the latest one
const latestBlock = novesTransactions[0].rawTransactionData.blockNumber
updateLatestBlockForPersistedNovesTransactionsForAccountNetwork(
profileId,
account.index,
network.id,
latestBlock
)
}

const blockscoutTokenTransfers = await fetchBlockscoutTokenTransfersForAccount(profileId, account, network)
blockscoutTokenTransfers &&
addBlockscoutTokenTransferToPersistedTransactions(
Expand Down Expand Up @@ -130,6 +146,7 @@ async function fetchBlockscoutTransactionsForAccount(
}

async function fetchNovesTransactionsForAccount(
profileId: string,
account: IAccountState,
network: IEvmNetwork
): Promise<NovesTxResponse[]> {
Expand All @@ -139,8 +156,16 @@ async function fetchNovesTransactionsForAccount(
return []
}

const latestBlock = getLatestBlockForPersistedNovesTransactionsForAccountNetwork(
profileId,
account.index,
network.id
)

const novesApi = new NovesApi()
const transactions = await novesApi.translate.getTransactionsFromAddress(address, novesChain)
const transactions = await novesApi.translate.getTransactionsFromAddress(address, novesChain, {
startBlock: latestBlock,
})
return transactions
}

Expand Down
1 change: 1 addition & 0 deletions packages/shared/src/lib/core/transactions/stores/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './latest-block-persisted-for-noves-transactions.store'
export * from './transactions.store'
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { NetworkId } from '@core/network'
import { get, writable } from 'svelte/store'

type LatestBlockPersistedForAccountNetwork = {
[profileId: string]: {
[accountId: number]: {
[networkId in NetworkId]?: {
latestBlock?: number
}
}
}
}

export const latestBlockPersistedForNovesTransactions = writable<LatestBlockPersistedForAccountNetwork>({})

export function getLatestBlockForPersistedNovesTransactionsForAccountNetwork(
profileId: string,
accountId: number,
networkId: NetworkId
): number | undefined {
return get(latestBlockPersistedForNovesTransactions)[profileId]?.[accountId]?.[networkId]?.latestBlock
}

export function updateLatestBlockForPersistedNovesTransactionsForAccountNetwork(
profileId: string,
accountId: number,
networkId: NetworkId,
latestBlock: number
): void {
latestBlockPersistedForNovesTransactions.update((state) => {
if (!state[profileId]) {
state[profileId] = {}
}

if (!state[profileId][accountId]) {
state[profileId][accountId] = {}
}

if (!state[profileId][accountId][networkId]) {
state[profileId][accountId][networkId] = {}
}

const obj = state[profileId][accountId][networkId] ?? {}

obj.latestBlock = latestBlock

state[profileId][accountId][networkId] = obj

return state
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { persistent } from '@core/utils/store'
import { get } from 'svelte/store'
import { LocalEvmTransaction, PersistedTransaction } from '../types/'
import { BlockscoutTokenTransfer } from '@auxiliary/blockscout/types'
import { NovesTxResponse } from '@auxiliary/noves'

type PersistedTransactions = {
[profileId: string]: {
Expand Down Expand Up @@ -147,6 +148,40 @@ export function addBlockscoutTransactionToPersistedTransactions(
})
}

export function addNovesTransactionToPersistedTransactions(
profileId: string,
accountIndex: number,
networkId: NetworkId,
newTransactions: NovesTxResponse[]
): void {
persistedTransactions.update((state) => {
if (!state[profileId]) {
state[profileId] = {}
}
if (!state[profileId][accountIndex]) {
state[profileId][accountIndex] = {
[networkId]: {},
}
}
if (!state[profileId][accountIndex][networkId]) {
state[profileId][accountIndex][networkId] = {}
}

const _transactions = state[profileId][accountIndex][networkId] ?? {}
for (const transaction of newTransactions) {
const existingTransaction = _transactions?.[transaction.rawTransactionData.transactionHash.toLowerCase()]
const updatedTransaction: PersistedTransaction = {
...existingTransaction,
noves: transaction,
}
_transactions[transaction.rawTransactionData.transactionHash.toLowerCase()] = updatedTransaction
}
state[profileId][accountIndex][networkId] = _transactions

return state
})
}

export function addBlockscoutTokenTransferToPersistedTransactions(
profileId: string,
accountIndex: number,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,12 @@
import { IBlockscoutTransaction } from '@auxiliary/blockscout/interfaces'
import { LocalEvmTransaction } from './local-evm-transaction.interface'
import { BlockscoutTokenTransfer } from '@auxiliary/blockscout/types'
import { NovesTxResponse } from '@auxiliary/noves'
import { AtLeastOne } from '@core/utils/types'

export type PersistedTransaction =
| {
blockscout: IBlockscoutTransaction
tokenTransfer: BlockscoutTokenTransfer
local: LocalEvmTransaction
}
| {
blockscout?: IBlockscoutTransaction
tokenTransfer: BlockscoutTokenTransfer
local: LocalEvmTransaction
}
| {
blockscout: IBlockscoutTransaction
tokenTransfer: BlockscoutTokenTransfer
local?: LocalEvmTransaction
}
| {
blockscout?: IBlockscoutTransaction
tokenTransfer: BlockscoutTokenTransfer
local?: LocalEvmTransaction
}
| {
blockscout?: IBlockscoutTransaction
tokenTransfer?: BlockscoutTokenTransfer
local: LocalEvmTransaction
}
export type PersistedTransaction = AtLeastOne<{
blockscout: IBlockscoutTransaction
noves: NovesTxResponse
tokenTransfer: BlockscoutTokenTransfer
local: LocalEvmTransaction
}>
4 changes: 4 additions & 0 deletions packages/shared/src/lib/core/utils/types/types.type.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export type PartiallyOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>

export type AtLeastOne<T, Keys extends keyof T = keyof T> = Keys extends keyof T
? Required<Pick<T, Keys>> & Partial<Omit<T, Keys>>
: never

0 comments on commit 21c2bd4

Please sign in to comment.