mirror of
https://github.com/Xahau/Validation-Ledger-Tx-Store-to-xPOP.git
synced 2025-11-04 20:35:49 +00:00
156 lines
5.9 KiB
JavaScript
156 lines
5.9 KiB
JavaScript
import { writeFile } from 'fs'
|
|
import { ledgerIndexToFolders } from './ledgerIndexToFolders.mjs'
|
|
import { computeBinaryTransactionHash } from './computeBinaryTransactionHash.mjs'
|
|
import { dirExists } from './dirExists.mjs'
|
|
import { ledgerReady, waitForLedgerReady } from './events/ledgerReady.mjs'
|
|
import { onTransaction } from './onTransaction.mjs'
|
|
import 'dotenv/config'
|
|
|
|
const obtainedHumanReadableLedgers = []
|
|
const obtainedBinaryTxLedgers = []
|
|
|
|
let lastLedger
|
|
|
|
const onLedger = async ({
|
|
networkId,
|
|
ledger,
|
|
connection,
|
|
}) => {
|
|
if ((ledger?.type || '').toUpperCase() === 'LEDGERCLOSED') {
|
|
if (ledger?.txn_count > 0 && ledger?.ledger_index) {
|
|
const relativeStoreDir = 'store/' + networkId + '/' + ledgerIndexToFolders(ledger.ledger_index)
|
|
const storeDir = new URL('../' + relativeStoreDir, import.meta.url).pathname
|
|
|
|
lastLedger = ledger.ledger_index
|
|
|
|
if (await dirExists(storeDir)) {
|
|
const ledgerData = [
|
|
...(
|
|
obtainedBinaryTxLedgers.indexOf(ledger.ledger_index) < 0
|
|
? [
|
|
connection.send({
|
|
command: 'ledger',
|
|
ledger_index: ledger.ledger_index,
|
|
transactions: true,
|
|
expand: true,
|
|
binary: true,
|
|
})
|
|
]
|
|
: []),
|
|
...(
|
|
obtainedHumanReadableLedgers.indexOf(ledger.ledger_index) < 0
|
|
? [
|
|
connection.send({
|
|
command: 'ledger',
|
|
ledger_index: ledger.ledger_index,
|
|
transactions: true,
|
|
expand: true,
|
|
binary: false,
|
|
})
|
|
]
|
|
: []),
|
|
].map(query => query.then(results => {
|
|
if (results?.validated && results?.ledger_index === ledger?.ledger_index && results?.ledger_hash === ledger?.ledger_hash) {
|
|
if (
|
|
results?.ledger?.transactions
|
|
&& Array.isArray(results.ledger.transactions)
|
|
&& results.ledger.transactions.length > 0
|
|
&& obtainedBinaryTxLedgers.indexOf(ledger.ledger_index) < 0
|
|
) {
|
|
/**
|
|
* Store in array, so if more ledger events come in and they
|
|
* also result in a response here, it won't be saved again.
|
|
* So yes: events will come in multiple times if multiple
|
|
* nodes are connected, and yes, multiple promises will be
|
|
* fired to fetch the ledger information, but then only
|
|
* the first one will be stored.
|
|
*/
|
|
obtainedBinaryTxLedgers.unshift(results.ledger_index)
|
|
obtainedBinaryTxLedgers.length = 250
|
|
|
|
console.log('Obtained ledger (binary)', relativeStoreDir, results.ledger_index, 'TX#', results.ledger.transactions.length)
|
|
|
|
/**
|
|
* Merge transaction hashes with the raw tx data
|
|
*/
|
|
;(results?.ledger?.transactions || []).map(t => {
|
|
return Object.assign(t, { tx_id: computeBinaryTransactionHash(t.tx_blob), })
|
|
})
|
|
|
|
writeFile(storeDir + '/ledger_binary_transactions.json', Buffer.from(JSON.stringify(results.ledger), 'utf8'), err => {
|
|
if (err) {
|
|
console.log('Error writing file @ ' + storeDir)
|
|
} else {
|
|
ledgerReady(results.ledger_index, 'ledger_binary_transactions')
|
|
}
|
|
})
|
|
}
|
|
if (
|
|
results?.ledger?.parent_hash
|
|
&& obtainedHumanReadableLedgers.indexOf(ledger.ledger_index) < 0
|
|
&& results?.ledger?.ledger_hash === ledger?.ledger_hash
|
|
) {
|
|
/**
|
|
* See comment above "Store in array" ... - first one will be stored
|
|
*/
|
|
obtainedHumanReadableLedgers.unshift(results.ledger_index)
|
|
obtainedHumanReadableLedgers.length = 250
|
|
|
|
console.log('Obtained ledger (JSON object)', relativeStoreDir, results.ledger_index, 'Hash', results.ledger.ledger_hash)
|
|
|
|
writeFile(storeDir + '/ledger_info.json', Buffer.from(JSON.stringify({ ...results.ledger, transactions: undefined, }), 'utf8'), err => {
|
|
if (err) {
|
|
console.log('Error writing file @ ' + storeDir)
|
|
} else {
|
|
ledgerReady(ledger.ledger_index, 'ledger_info')
|
|
}
|
|
})
|
|
|
|
}
|
|
}
|
|
|
|
return results.ledger
|
|
}))
|
|
|
|
/**
|
|
* Deal with transactions & fire events
|
|
*/
|
|
waitForLedgerReady(ledger.ledger_index)?.then(async () => {
|
|
if (ledgerData.length > 0) {
|
|
const [binary, json] = await Promise.all(ledgerData)
|
|
const sequetiallyMappedLedgerTxEvents = (json?.transactions || []).map(tx => {
|
|
return {
|
|
validated: true,
|
|
ledger_index: ledger.ledger_index,
|
|
transaction: tx,
|
|
}
|
|
})
|
|
.sort((a, b) => a.transaction.Sequence - b.transaction.Sequence)
|
|
.reduce((promiseChain, current) => {
|
|
return promiseChain.then(() => {
|
|
// console.log(' » Tx events: Processing', current.transaction.Sequence)
|
|
return onTransaction({
|
|
networkId,
|
|
transaction: current,
|
|
connection,
|
|
})
|
|
}).then(() => {
|
|
// console.log(' » Tx events: Done ', current.transaction.Sequence)
|
|
})
|
|
}, Promise.resolve())
|
|
|
|
sequetiallyMappedLedgerTxEvents.then(() => {
|
|
// console.log(' « « « « All transactions in ledger processed', ledger.ledger_index)
|
|
});
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export {
|
|
onLedger,
|
|
lastLedger,
|
|
}
|