classic-ui/modules/account/store/actions/decryptNotes/encryptFormatTx.js

210 lines
5.4 KiB
JavaScript

import { decrypt } from 'eth-sig-util'
import { isAddress } from 'web3-utils'
import { eventsType } from '@/constants'
import { parseHexNote, getInstanceByAddress, unpackEncryptedMessage } from '@/utils'
export async function _encryptFormatTx({ dispatch, getters, rootGetters }, { events, privateKey }) {
let result = []
const netId = rootGetters['metamask/netId']
const eventsInterface = rootGetters['application/eventsInterface']
dispatch('loading/changeText', { message: this.app.i18n.t('decryptingNotes') }, { root: true })
const encryptedEvents = decryptEvents({ events, privateKey })
dispatch(
'loading/changeText',
{ message: this.app.i18n.t('getAndValidateEvents', { name: this.app.i18n.t('deposit') }) },
{ root: true }
)
const instances = encryptedEvents.reduce((acc, curr) => {
const instance = getInstanceByAddress({ netId, address: curr.address })
if (!instance) {
return acc
}
const name = `${netId}${instance.amount}${instance.currency}`
if (!acc[name]) {
const service = eventsInterface.getService({ netId, ...instance })
acc[name] = { ...instance, service }
}
return acc
}, {})
await Promise.all(
[].concat(
Object.values(instances).map((instance) => instance.service.updateEvents(eventsType.DEPOSIT)),
Object.values(instances).map((instance) => instance.service.updateEvents(eventsType.WITHDRAWAL))
)
)
const eventBatches = getBatches(encryptedEvents)
for await (const batch of eventBatches) {
try {
const depositPromises = batch.map((event) => {
const instance = getInstanceByAddress({ netId, address: event.address })
if (!instance) {
return
}
const { service } = instances[`${netId}${instance.amount}${instance.currency}`]
return getDeposit({ event, netId, service, instance })
})
const proceedDeposits = await Promise.all(depositPromises)
console.log({ proceedDeposits })
dispatch(
'loading/changeText',
{ message: this.app.i18n.t('getAndValidateEvents', { name: this.app.i18n.t('withdrawal') }) },
{ root: true }
)
const proceedEvents = await Promise.all(
proceedDeposits.map(([event, deposit]) => proceedEvent({ event, getters, deposit, netId, dispatch }))
)
result = result.concat(proceedEvents)
} catch (e) {
console.error('_encryptFormatTx', e)
}
}
dispatch('loading/disable', {}, { root: true })
return formattingEvents(result)
}
function decryptEvents({ privateKey, events }) {
const encryptEvents = []
for (const event of events) {
try {
const unpackedMessage = unpackEncryptedMessage(event.encryptedNote)
const [address, note] = decrypt(unpackedMessage, privateKey).split('-')
encryptEvents.push({ address, note, ...event })
} catch {
// decryption may fail for foreign notes
continue
}
}
return encryptEvents
}
function formattingEvents(proceedEvents) {
const result = []
const statistic = []
let unSpent = 0
proceedEvents.forEach((transaction) => {
if (transaction) {
if (!transaction.isSpent) {
unSpent += 1
statistic.push({
amount: transaction.amount,
currency: transaction.currency
})
}
result.push(transaction)
}
})
return {
unSpent,
statistic,
transactions: result
}
}
async function getDeposit({ netId, event, service, instance }) {
const { commitmentHex, nullifierHex } = parseHexNote(event.note)
const foundEvent = await service.findEvent({
eventName: 'commitment',
eventToFind: commitmentHex,
type: eventsType.DEPOSIT
})
if (!foundEvent) {
return
}
const isSpent = await service.findEvent({
eventName: 'nullifierHash',
eventToFind: nullifierHex,
type: eventsType.WITHDRAWAL
})
const deposit = {
leafIndex: foundEvent.leafIndex,
timestamp: foundEvent.timestamp,
txHash: foundEvent.transactionHash,
depositBlock: foundEvent.blockNumber
}
return [
event,
{
nullifierHex,
commitmentHex,
amount: instance.amount,
isSpent: Boolean(isSpent),
currency: instance.currency,
prefix: `tornado-${instance.currency}-${instance.amount}-${netId}`,
...deposit
}
]
}
async function proceedEvent({ dispatch, getters, deposit, netId, event: { note, address, ...event } }) {
const { encrypt, backup } = getters.accounts
try {
const { depositBlock, ...rest } = deposit
const transaction = {
...rest,
netId,
status: 2,
type: 'Deposit',
txHash: event.txHash,
owner: isAddress(encrypt) ? encrypt : '',
backupAccount: isAddress(backup) ? backup : '',
index: deposit.leafIndex,
storeType: 'encryptedTxs',
blockNumber: event.blockNumber,
note: event.encryptedNote
}
if (deposit && deposit.isSpent) {
const withdrawEvent = await dispatch(
'application/loadWithdrawalEvent',
{ withdrawNote: `${deposit.prefix}-${note}` },
{ root: true }
)
if (withdrawEvent) {
transaction.txHash = withdrawEvent.txHash
transaction.depositBlock = depositBlock
transaction.blockNumber = withdrawEvent.blockNumber
}
}
return transaction
} catch (err) {
console.log('err', err.message)
}
}
function getBatches(arr, batchSize = 100) {
const batches = []
while (arr.length) {
batches.push(arr.splice(0, batchSize))
}
return batches
}