import { uniqBy } from 'lodash-unified' ; import type { JsonRpcPayload } from 'web3-core-helpers' ; import { WalletMessages } from '@masknet/plugin-wallet' ; import { ChainId , formatEthereumAddress } from '@masknet/web3-shared-evm' ; import { currentChainIdSettings } from '../../settings' ; import { PluginDB } from '../../database/Plugin.db' ; export const MAX_RECENT_TRANSACTIONS_SIZE = 20 ; export interface RecentTransaction { at : Date ; hash : string ; hashReplacement ? : string ; payload : JsonRpcPayload ; payloadReplacement ? : JsonRpcPayload ; } export interface RecentTransactionChunk { id : string ; chainId : ChainId ; address : string ; type : 'recent-transactions' ; transactions : RecentTransaction [ ] ; createdAt : Date ; updatedAt : Date ; } function getRecordId ( chainId , address ) { return `${ chainId }_${ formatEthereumAddress ( address ) }` ; } export async function addRecentTransaction ( chainId , address , hash , payload ) { const now = new Date ( ) ; const recordId = getRecordId ( chainId , address ) ; const chunk = await PluginDB . get ( 'recent-transactions' , recordId ) ; await PluginDB . add ( { type : 'recent-transactions' , id : recordId , chainId , address : formatEthereumAddress ( address ) , transactions : uniqBy ( [ { at : now , hash , payload , } , ... ( chunk ?. transactions ?? [ ] ) , ] , ( x ) => x . hash ) . slice ( 0 , MAX_RECENT_TRANSACTIONS_SIZE ) , createdAt : chunk ?. createdAt ?? now , updatedAt : now , } ) ; WalletMessages . events . transactionsUpdated . sendToAll ( ) ; } export async function replaceRecentTransaction ( chainId , address , oldHash , newHash , newPayload ? ) { const now = new Date ( ) ; const recordId = getRecordId ( chainId , address ) ; const chunk = await PluginDB . get ( 'recent-transactions' , recordId ) ; const transaction = chunk ?. transactions . find ( ( x ) => x . hash === oldHash ) ; if ( ! transaction ) throw new Error ( 'Failed to find the old transaction.' ) ; if ( transaction . hash === newHash ) return ; transaction . hashReplacement = newHash ; if ( newPayload ) { transaction . payloadReplacement = newPayload ; } await PluginDB . add ( { type : 'recent-transactions' , id : recordId , chainId , address : formatEthereumAddress ( address ) , transactions : chunk ?. transactions ?? [ ] , createdAt : chunk ?. createdAt ?? now , updatedAt : now , } ) ; WalletMessages . events . transactionsUpdated . sendToAll ( ) ; } export async function removeRecentTransaction ( chainId , address , hash ) { const now = new Date ( ) ; const recordId = getRecordId ( chainId , address ) ; const chunk = await PluginDB . get ( 'recent-transactions' , recordId ) ; if ( ! chunk ) return ; await PluginDB . add ( { type : 'recent-transactions' , id : recordId , chainId : currentChainIdSettings . value , address : formatEthereumAddress ( address ) , transactions : chunk . transactions . filter ( ( x ) => x . hash !== hash ) , createdAt : chunk . createdAt , updatedAt : now , } ) ; WalletMessages . events . transactionsUpdated . sendToAll ( ) ; } export async function getRecentTransactions ( chainId , address ) { const recordId = getRecordId ( chainId , address ) ; const chunk = await PluginDB . get ( 'recent-transactions' , recordId ) ; return chunk ?. transactions ?? [ ] ; } export async function clearRecentTransactions ( chainId , address ) { const recordId = getRecordId ( chainId , address ) ; await PluginDB . remove ( 'recent-transactions' , recordId ) ; WalletMessages . events . transactionsUpdated . sendToAll ( ) ; }