bfx-api-node-models
Version:
Object models for usage with the Bitfinex node API
212 lines (193 loc) • 5.7 kB
JavaScript
'use strict'
const _flatten = require('lodash/flatten')
const _isEmpty = require('lodash/isEmpty')
const _compact = require('lodash/compact')
const { prepareAmount, preparePrice } = require('bfx-api-node-util')
const numberValidator = require('./validators/number')
const dateValidator = require('./validators/date')
const amountValidator = require('./validators/amount')
const boolValidator = require('./validators/bool')
const stringValidator = require('./validators/string')
const symbolValidator = require('./validators/symbol')
const Model = require('./model')
const statuses = ['ACTIVE', 'EXECUTED', 'PARTIALLY FILLED', 'CANCELED']
const boolFields = ['notify', 'hidden', 'renew']
const fields = {
id: 0,
symbol: 1,
mtsCreate: 2,
mtsUpdate: 3,
amount: 4,
amountOrig: 5,
type: 6,
flags: 9,
status: 10,
rate: 14,
period: 15,
notify: 16,
hidden: 17,
renew: 19,
rateReal: 20
}
/**
* Funding Offer model
*/
class FundingOffer extends Model {
/**
* @param {object|Array} data - funding offer data
* @param {number} data.id - id
* @param {string} data.symbol - symbol
* @param {number} data.mtsCreate - creation timestamp
* @param {number} data.mtsUpdate - last update timestamp
* @param {string} data.amount - remaining amount
* @param {string} data.amountOrig - original amount
* @param {string} data.type - funding offer type
* @param {number} data.flags - flags
* @param {string} data.status - current status
* @param {number} data.rate - rate
* @param {number} data.rateReal - rate real
* @param {number} data.period - period for the offer
* @param {number|boolean} data.notify - notify flag
* @param {number|boolean} data.hidden - hidden flag
* @param {number|boolean} data.renew - renew flag
* @param {object} [apiInterface] - rest or websocket object capable of
* submitting funding offers
*/
constructor (data = {}, apiInterface) {
super({ data, fields, boolFields })
this._apiInterface = apiInterface
}
/**
* @param {object[]|object|Array[]|Array} data - data to convert to POJO
* @returns {object} pojo
*/
static unserialize (data) {
return super.unserialize({ data, fields, boolFields })
}
/**
* Creates an order map that can be used in either the websocket `on`
* command or a rest request body
*
* @returns {object} on
*/
toNewOfferPacket () {
return {
type: this.type,
symbol: this.symbol,
amount: prepareAmount(+this.amount),
rate: prepareAmount(+this.rate),
period: this.period,
flags: this.flags
}
}
/**
* Submit the funding offer
*
* @param {RESTv2} apiInterface - optional rest instance
* @returns {Promise} p
*/
async submit (apiInterface = this._apiInterface) {
if (!apiInterface) {
throw new Error('no API interface provided')
}
return apiInterface.submitFundingOffer({ offer: this }).then((offerArray) => {
Object.assign(this, FundingOffer.unserialize(offerArray))
return this
})
}
/**
* Cancel the funding offer
*
* @param {RESTv2} apiInterface - optional rest instance
* @returns {Promise} p
*/
async cancel (apiInterface = this._apiInterface) {
if (!apiInterface) {
throw new Error('no API interface provided')
}
return apiInterface.cancelFundingOffer({ id: this.id }).then((offerArray) => {
Object.assign(this, FundingOffer.unserialize(offerArray))
return this
})
}
/**
* Close the funding offer
*
* @param {RESTv2} apiInterface - optional rest instance
* @returns {Promise} p
*/
async close (apiInterface = this._apiInterface) {
if (!apiInterface) {
throw new Error('no API interface provided')
}
return apiInterface.closeFunding({
id: this.id,
type: this.type
}).then((offerArray) => {
Object.assign(this, FundingOffer.unserialize(offerArray))
return this
})
}
/**
* Returns a string representation of the position
*
* @returns {string} desc
*/
toString () {
const {
id, symbol, status, amount, amountOrig, rate, period, renew
} = this
return _compact(_flatten([
id && `(id: ${id})`,
'funding offer for',
symbol.substring(1),
!_isEmpty(status) && `(${status})`,
'for',
prepareAmount(amount),
(!!amountOrig && amountOrig !== amount) && `(${prepareAmount(amountOrig)})`,
'@',
preparePrice(rate),
`(period ${period})`,
`[renew ${renew ? 'Y' : 'N'}]`
])).join(' ')
}
/**
* Validates a given funding offer instance
*
* @param {object[]|object|FundingOffer[]|FundingOffer|Array} data - instance to validate
* @returns {string} error - null if instance is valid
*/
static validate (data) {
return super.validate({
data,
fields,
validators: {
mtsCreate: dateValidator,
mtsUpdate: dateValidator,
mtsOpening: dateValidator,
mtsLastPayout: dateValidator,
amountOrig: amountValidator,
amount: amountValidator,
flags: numberValidator,
rate: numberValidator,
period: numberValidator,
rateReal: numberValidator,
notify: boolValidator,
hidden: boolValidator,
renew: boolValidator,
noClose: boolValidator,
status: stringValidator,
symbol: symbolValidator,
type: stringValidator,
id: numberValidator
}
})
}
}
FundingOffer.status = {}
FundingOffer.type = {
LEND: 'lend',
LOAN: 'loan'
}
statuses.forEach(s => (FundingOffer.status[s.split(' ').join('_')] = s))
module.exports = FundingOffer