mirror of
				https://github.com/Xahau/Validation-Ledger-Tx-Store-to-xPOP.git
				synced 2025-11-04 12:25:48 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			135 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { writeFile } from 'fs'
 | 
						|
import { dirExists } from './dirExists.mjs'
 | 
						|
import { ledgerIndexToFolders } from './ledgerIndexToFolders.mjs'
 | 
						|
import { xpopGenerate } from './xpopGenerate.mjs'
 | 
						|
import { createDirectory } from './createDirectory.mjs'
 | 
						|
import { waitForLedgerReady } from './events/ledgerReady.mjs'
 | 
						|
import { emit } from '../bin/webserver.mjs'
 | 
						|
import 'dotenv/config'
 | 
						|
 | 
						|
let txCount = 0
 | 
						|
 | 
						|
const xpopBinaryDir = new URL('../store/xpop', import.meta.url).pathname
 | 
						|
const lastSeenTransactions = []
 | 
						|
 | 
						|
const fields = (process.env?.FIELDSREQUIRED || '')
 | 
						|
  .split(',')
 | 
						|
  .map(f => f.trim())
 | 
						|
  .filter(f => f.match(/^[a-zA-Z0-9]+$/))
 | 
						|
 | 
						|
const fieldsRequired = fields.length === 1 && fields[0] === ''
 | 
						|
  ? [ 'Fee' ]
 | 
						|
  : fields
 | 
						|
 | 
						|
const hasRequiredFields = tx => fieldsRequired.map(f => Object.keys(tx).includes(f)).every(f => !!f)
 | 
						|
 | 
						|
const onTransaction = async ({
 | 
						|
  networkId,
 | 
						|
  transaction,
 | 
						|
}) => {
 | 
						|
    if (transaction?.validated) {
 | 
						|
      const { transaction: tx } = transaction
 | 
						|
  
 | 
						|
      if (tx.hash && lastSeenTransactions.indexOf(tx.hash) < 0) {
 | 
						|
        lastSeenTransactions.unshift(tx.hash)
 | 
						|
        lastSeenTransactions.length = 3000
 | 
						|
  
 | 
						|
        const validTx = hasRequiredFields(tx)
 | 
						|
        if (!process.env?.NOELIGIBLEFULLTXLOG) {
 | 
						|
          console.log('TX', tx.hash, validTx)
 | 
						|
        }
 | 
						|
  
 | 
						|
        if (validTx && transaction?.ledger_index) {
 | 
						|
          const relativeStorDir = 'store/' + networkId + '/' + ledgerIndexToFolders(transaction.ledger_index)
 | 
						|
          const storeDir = new URL('../' + relativeStorDir, import.meta.url).pathname
 | 
						|
          
 | 
						|
          console.log('xPOP eligible', relativeStorDir, process.env?.NOELIGIBLEFULLTXLOG ? tx.hash : tx)
 | 
						|
  
 | 
						|
          if (await dirExists(storeDir)) {
 | 
						|
            const wroteTxFile = await new Promise(resolve => {
 | 
						|
              writeFile(storeDir + '/tx_' + tx.hash + '.json', Buffer.from(JSON.stringify(transaction), 'utf8'), err => {
 | 
						|
                if (err) {
 | 
						|
                  console.log('Error writing file @ ' + storeDir)
 | 
						|
                  resolve(false)
 | 
						|
                }
 | 
						|
                resolve(true)
 | 
						|
              })
 | 
						|
            })
 | 
						|
 | 
						|
            if (wroteTxFile) {
 | 
						|
              await waitForLedgerReady(transaction.ledger_index)
 | 
						|
 | 
						|
              // Make sure IO & validation messages get some time to be processed
 | 
						|
              await new Promise(resolve => setTimeout(resolve, 2_000))
 | 
						|
 | 
						|
              /**
 | 
						|
               * TX all ready, written to filesystem, ...
 | 
						|
               * This is where we start a slight delay to give the `onLedger`
 | 
						|
               * routine some time to fetch & store and then we'll try to
 | 
						|
               * generate an xPOP.
 | 
						|
               */
 | 
						|
              const xpopBinary = await xpopGenerate({
 | 
						|
                ledgerIndex: transaction.ledger_index,
 | 
						|
                networkId,
 | 
						|
                txHash: tx.hash,
 | 
						|
              })
 | 
						|
 | 
						|
              
 | 
						|
              if (!(await dirExists(xpopBinaryDir))) {
 | 
						|
                console.log('(Re-) creating /store/xpop directory')
 | 
						|
                await createDirectory('store/xpop')
 | 
						|
              }
 | 
						|
 | 
						|
              const xpopWritten = await new Promise(resolve => {
 | 
						|
                writeFile(xpopBinaryDir + '/' + tx.hash, Buffer.from(xpopBinary, 'utf8'), err => {
 | 
						|
                  if (err) {
 | 
						|
                    console.log('Error writing binary XPOP', err)
 | 
						|
                    resolve(false)
 | 
						|
                  } else {
 | 
						|
                    console.log('Wrote binary xPOP: ' + xpopBinaryDir + '/' + tx.hash)
 | 
						|
                    resolve(true)
 | 
						|
                  }
 | 
						|
                })
 | 
						|
              })
 | 
						|
              if (xpopWritten) {
 | 
						|
                console.log('   ### EMIT XPOP READY FOR', tx?.Account, Number(tx.Sequence), tx.hash)
 | 
						|
 | 
						|
                txCount++
 | 
						|
 | 
						|
                return await emit({
 | 
						|
                  account: tx?.Account,
 | 
						|
                  sequence: tx.Sequence,
 | 
						|
                  origin: {
 | 
						|
                    tx: tx.hash,
 | 
						|
                    networkId: networkId,
 | 
						|
                    ledgerIndex: transaction.ledger_index,
 | 
						|
                    burn: tx?.Fee,
 | 
						|
                  },
 | 
						|
                  destination: {
 | 
						|
                    networkId: tx?.OperationLimit,
 | 
						|
                  },
 | 
						|
                  ...(
 | 
						|
                    process.env?.URL_PREFIX
 | 
						|
                      ? {
 | 
						|
                          xpop: {
 | 
						|
                            binary: `${process.env.URL_PREFIX}/xpop/${tx.hash}`,
 | 
						|
                            source: `${process.env.URL_PREFIX}/${networkId}/${ledgerIndexToFolders(transaction.ledger_index)}/`,
 | 
						|
                            blob: xpopBinary,
 | 
						|
                          }
 | 
						|
                        }
 | 
						|
                      : {}
 | 
						|
                  )
 | 
						|
                })
 | 
						|
              }
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
export {
 | 
						|
  onTransaction,
 | 
						|
  txCount,
 | 
						|
}
 |