wax-expresstrade
Version:
Promise-based Node API for WAX Expresstrade.
152 lines (122 loc) • 4.05 kB
JavaScript
const EventEmitter = require('events')
const request = require('request-promise')
const speakeasy = require('speakeasy')
const ICase = require('./interfaces/ICase')
const ICaseSite = require('./interfaces/ICaseSite')
const IEthereum = require('./interfaces/IEthereum')
const IItem = require('./interfaces/IItem')
const ITrade = require('./interfaces/ITrade')
const IUser = require('./interfaces/IUser')
const OfferState = require('./interfaces/ITrade/states')
class ExpressTrade extends EventEmitter {
constructor(options) {
super()
// Check for config
if (typeof options !== 'object') {
throw new Error('Options not specified!')
}
if (options.apiKey === undefined) {
throw new Error('apiKey not specified!')
}
if (options.twoFactorSecret === undefined) {
throw new Error('twoFactorSecret not specified!')
}
// Initialize internal settings
this.options = {
apiUrl: 'https://api-trade.wax.io/',
pollInterval: null,
...options
}
this.request = request.defaults({
baseUrl: this.options.apiUrl,
auth: { user: this.options.apiKey },
json: true
})
// Initialize interfaces
this.ICase = new ICase({ request: this.request })
this.ICaseSite = new ICaseSite({ request: this.request })
this.IEthereum = new IEthereum({ request: this.request })
this.IItem = new IItem({ request: this.request })
this.ITrade = new ITrade({ request: this.request, generateToken: () => this.generateToken() })
this.IUser = new IUser({ request: this.request })
// Polling
this.pollData = {}
if (this.options.pollInterval !== null) {
if (this.options.pollInterval < 1000) {
throw new Error('pollInterval minimal value is 1000. Please change it!')
}
this.startPolling(this.options.pollInterval)
}
}
startPolling(interval) {
this.pollInterval = setInterval(() => this.poll(), interval)
}
stopPolling() {
clearInterval(this.pollInterval)
this.pollInterval = undefined
}
async poll() {
let offers
try {
const offersResponse = await this.ITrade.GetOffers({})
offers = offersResponse.offers
} catch (err) {
console.error(`Cannot poll offers - ${err.message}`)
return
}
const pollData = {}
// First-run time poll
if (Object.keys(this.pollData).length === 0) {
for (const offer of offers) {
pollData[offer.id] = offer
}
this.pollData = pollData
return
}
for (const offer of offers) {
const newState = offer.state
pollData[offer.id] = offer
if (this.pollData[offer.id] === undefined) {
const event = offer.sent_by_you ? 'OfferSent' : 'OfferReceived'
this.emit(event, offer)
} else if (newState !== this.pollData[offer.id].state) {
this.emit('OfferChanged', offer)
switch (newState) {
case OfferState.STATE_ACCEPTED:
this.emit('OfferAccepted', offer)
break
case OfferState.STATE_EXPIRED:
this.emit('OfferExpired', offer)
break
case OfferState.STATE_CANCELLED:
this.emit('OfferCancelled', offer)
break
case OfferState.STATE_DECLINED:
this.emit('OfferDeclined', offer)
break
case OfferState.STATE_INVALID_ITEMS:
this.emit('OfferNoLongerValid', offer)
break
case OfferState.STATE_PENDING_CASE_OPEN:
this.emit('OfferCasePending', offer)
break
case OfferState.STATE_EXPIRED_CASE_OPEN:
this.emit('OfferCaseExpired', offer)
break
case OfferState.STATE_FAILED_CASE_OPEN:
this.emit('OfferCaseFailed', offer)
break
}
}
}
// Save new pollData
this.pollData = pollData
}
generateToken() {
return speakeasy.totp({
secret: this.options.twoFactorSecret,
encoding: 'base32'
})
}
}
module.exports = ExpressTrade