accumulate_distribute/events/orders_order_fill.js

'use strict'

const { Config } = require('bfx-api-node-core')
const { DUST } = Config

const scheduleTick = require('../util/schedule_tick')

/**
 * Called when an order fills. Updates the remaining amount & order timeline
 * position (if behind, etc) on the instance state. If the instance is fully
 * filled, the `exec:stop` event is triggered.
 *
 * Otherwise, if `catchUp` is enabled and the instance is behind with order
 * fills the next tick is re-scheduled to occur earlier in order to compensate.
 *
 * @memberOf module:AccumulateDistribute
 * @listens AOHost~event:ordersOrderFill
 * @see module:AccumulateDistribute.scheduleTick
 *
 * @param {AOInstance} instance - AO instance state
 * @param {object} order - the order that filled
 * @returns {Promise} p
 */
const onOrdersOrderFill = async (instance = {}, order) => {
  const { state = {}, h = {} } = instance
  const { args = {}, ordersBehind, timeout, currentOrder } = state
  const { emit, updateState, debug } = h
  const { catchUp } = args

  const newOrdersBehind = Math.max(0, ordersBehind - 1)
  const fillAmount = order.getLastFillAmount()
  const remainingAmount = state.remainingAmount - fillAmount
  const absRem = Math.abs(remainingAmount)

  order.resetFilledAmount()

  debug('updated remaining amount: %f [filled %f]', remainingAmount, fillAmount)

  await updateState(instance, {
    remainingAmount,
    ordersBehind: newOrdersBehind,
    currentOrder: currentOrder + 1
  })

  if (absRem <= DUST) { // stop if finished
    if (absRem < 0) {
      debug('warning: overfill! %f', absRem)
    }

    clearTimeout(timeout)

    return emit('exec:stop')
  }

  if (catchUp && newOrdersBehind > 0) {
    debug('catching up (behind with %d orders)', newOrdersBehind)

    clearTimeout(timeout)
    await scheduleTick.tick(instance, true) // re-schedule early submit
  } else if (ordersBehind > 0 && newOrdersBehind === 0) {
    debug('caught up!')
  }
}

module.exports = onOrdersOrderFill