daemon/indexing/listener/listener.js
async function handleLog(log, rule, contractVersion, context) {
  log.decoded = web3.eth.abi.decodeLog(
    rule.eventAbi.inputs,
    log.data,
    log.topics.slice(1)
  )
  log.contractName = contractVersion.contractName
  log.eventName = rule.eventName
  log.contractVersionKey = contractVersion.versionKey
  log.networkId = context.networkId

  console.log(
    `Processing log \
    blockNumber=${log.blockNumber} \
    transactionIndex=${log.transactionIndex} \
    eventName=${log.eventName} \
    contractName=${log.contractName}`
  )

  // Note: we run the rule with a retry since we've seen in production cases where we fail loading
  // from smart contracts the data pointed to by the event. This may occur due to load balancing
  // across ethereum nodes and if some nodes are lagging. For example the ethereum node we
  // end up connecting to for reading the data may lag compared to the node received the event from.
  let ruleResults = undefined
  await withRetrys(async () => {
    ruleResults = await rule.ruleFn(log)
  })

  const output = {
    log: log,
    related: ruleResults
  }

  const json = JSON.stringify(output, null, 2)
  if (context.config.verbose) {
    console.log(json)
    console.log('\n----\n')
  }

  const userAddress = log.decoded.party
  const ipfsHash = log.decoded.ipfsHash

  //TODO: remove binary data from pictures in a proper way.
  const listing = output.related.listing
  delete listing.ipfs.data.pictures
  const listingId = listing.id

  // Data consistency: check  listingId from the JSON stored in IPFS
  // matches with listingID emitted in the event.
  // TODO: use method utils/id.js:parseListingId
  // DVF: this should really be handled in origin js - origin.js should throw
  // an error if this happens.
  const ipfsListingId = listingId.split('-')[2]
  if (ipfsListingId !== log.decoded.listingID) {
    throw `ListingId mismatch: ${ipfsListingId} !== ${log.decoded.listingID}`
  }

  // TODO: This kind of verification logic should live in origin.js
  if(output.related.listing.ipfs.data.price === undefined){
    return
  }

  if (context.config.elasticsearch) {
    console.log('INDEXING ', listingId)
    await withRetrys(async () => {
      await search.Listing.index(
        listingId,
        userAddress,
        ipfsHash,
        listing
      )
    })
    if (output.related.offer !== undefined) {
      const offer = output.related.offer
      await withRetrys(async () => {
        await search.Offer.index(offer, listing)
      })
    }
    if (output.related.seller !== undefined) {
      await withRetrys(async () => {
        await search.User.index(output.related.seller)
      })
    }
    if (output.related.buyer !== undefined) {
      await withRetrys(async () => {
        await search.User.index(output.related.buyer)
      })
    }
  }

  if (context.config.db) {
    await withRetrys(async () => {
      await db.Listing.insert(
        listingId,
        userAddress,
        ipfsHash,
        listing.ipfs.data
      )
    })
  }

  if (context.config.webhook) {
    console.log('\n-- WEBHOOK to ' + context.config.webhook + ' --\n')
    await withRetrys(async () => {
      await postToWebhook(context.config.webhook, json)
    })
  }
}
async function handleLog(log, rule, contractVersion, context) {
  log.decoded = web3.eth.abi.decodeLog(
    rule.eventAbi.inputs,
    log.data,
    log.topics.slice(1)
  )
  log.contractName = contractVersion.contractName
  log.eventName = rule.eventName
  log.contractVersionKey = contractVersion.versionKey
  log.networkId = context.networkId

  console.log(
    `Processing log \
    blockNumber=${log.blockNumber} \
    transactionIndex=${log.transactionIndex} \
    eventName=${log.eventName} \
    contractName=${log.contractName}`
  )

  // Note: we run the rule with a retry since we've seen in production cases where we fail loading
  // from smart contracts the data pointed to by the event. This may occur due to load balancing
  // across ethereum nodes and if some nodes are lagging. For example the ethereum node we
  // end up connecting to for reading the data may lag compared to the node received the event from.
  let ruleResults = undefined
  await withRetrys(async () => {
    ruleResults = await rule.ruleFn(log)
  })

  const output = {
    log: log,
    related: ruleResults
  }

  const json = JSON.stringify(output, null, 2)
  if (context.config.verbose) {
    console.log(json)
    console.log('\n----\n')
  }

  const userAddress = log.decoded.party
  const ipfsHash = log.decoded.ipfsHash

  //TODO: remove binary data from pictures in a proper way.
  const listing = output.related.listing
  delete listing.ipfs.data.pictures
  const listingId = listing.id

  // Data consistency: check  listingId from the JSON stored in IPFS
  // matches with listingID emitted in the event.
  // TODO: use method utils/id.js:parseListingId
  // DVF: this should really be handled in origin js - origin.js should throw
  // an error if this happens.
  const ipfsListingId = listingId.split('-')[2]
  if (ipfsListingId !== log.decoded.listingID) {
    throw `ListingId mismatch: ${ipfsListingId} !== ${log.decoded.listingID}`
  }

  // TODO: This kind of verification logic should live in origin.js
  if(output.related.listing.ipfs.data.price === undefined){
    return
  }

  if (context.config.elasticsearch) {
    console.log('INDEXING ', listingId)
    await withRetrys(async () => {
      await search.Listing.index(
        listingId,
        userAddress,
        ipfsHash,
        listing
      )
    })
    if (output.related.offer !== undefined) {
      const offer = output.related.offer
      await withRetrys(async () => {
        await search.Offer.index(offer, listing)
      })
    }
    if (output.related.seller !== undefined) {
      await withRetrys(async () => {
        await search.User.index(output.related.seller)
      })
    }
    if (output.related.buyer !== undefined) {
      await withRetrys(async () => {
        await search.User.index(output.related.buyer)
      })
    }
  }

  if (context.config.db) {
    await withRetrys(async () => {
      await db.Listing.insert(
        listingId,
        userAddress,
        ipfsHash,
        listing.ipfs.data
      )
    })
  }

  if (context.config.webhook) {
    console.log('\n-- WEBHOOK to ' + context.config.webhook + ' --\n')
    await withRetrys(async () => {
      await postToWebhook(context.config.webhook, json)
    })
  }
}
async function handleLog ( log , rule , contractVersion , context ) { log . decoded = web3 . eth . abi . decodeLog ( rule . eventAbi . inputs , log . data , log . topics . slice ( 1 ) ) log . contractName = contractVersion . contractName log . eventName = rule . eventName log . contractVersionKey = contractVersion . versionKey log . networkId = context . networkId console . log ( ` \
 ${ log . blockNumber } \
 ${ log . transactionIndex } \
 ${ log . eventName } \
 ${ log . contractName } ` ) // Note: we run the rule with a retry since we've seen in production cases where we fail loading // from smart contracts the data pointed to by the event. This may occur due to load balancing // across ethereum nodes and if some nodes are lagging. For example the ethereum node we // end up connecting to for reading the data may lag compared to the node received the event from. let ruleResults = undefined await withRetrys ( async ( ) => { ruleResults = await rule . ruleFn ( log ) } ) const output = { log : log , related : ruleResults } const json = JSON . stringify ( output , null , 2 ) if ( context . config . verbose ) { console . log ( json ) console . log ( '\n----\n' ) } const userAddress = log . decoded . party const ipfsHash = log . decoded . ipfsHash //TODO: remove binary data from pictures in a proper way. const listing = output . related . listing delete listing . ipfs . data . pictures const listingId = listing . id // Data consistency: check  listingId from the JSON stored in IPFS // matches with listingID emitted in the event. // TODO: use method utils/id.js:parseListingId // DVF: this should really be handled in origin js - origin.js should throw // an error if this happens. const ipfsListingId = listingId . split ( '-' ) [ 2 ] if ( ipfsListingId !== log . decoded . listingID ) { throw ` ${ ipfsListingId } ${ log . decoded . listingID } ` } // TODO: This kind of verification logic should live in origin.js if ( output . related . listing . ipfs . data . price === undefined ) { return } if ( context . config . elasticsearch ) { console . log ( 'INDEXING ' , listingId ) await withRetrys ( async ( ) => { await search . Listing . index ( listingId , userAddress , ipfsHash , listing ) } ) if ( output . related . offer !== undefined ) { const offer = output . related . offer await withRetrys ( async ( ) => { await search . Offer . index ( offer , listing ) } ) } if ( output . related . seller !== undefined ) { await withRetrys ( async ( ) => { await search . User . index ( output . related . seller ) } ) } if ( output . related . buyer !== undefined ) { await withRetrys ( async ( ) => { await search . User . index ( output . related . buyer ) } ) } } if ( context . config . db ) { await withRetrys ( async ( ) => { await db . Listing . insert ( listingId , userAddress , ipfsHash , listing . ipfs . data ) } ) } if ( context . config . webhook ) { console . log ( '\n-- WEBHOOK to ' + context . config . webhook + ' --\n' ) await withRetrys ( async ( ) => { await postToWebhook ( context . config . webhook , json ) } ) } }
handleLog - annotates, runs rule, and ouputs a particular log
handleLog - annotates runs rule and ouputs a particular log