Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
4.0.15
- WSv2: submitFundingOffer function
- WSv2: cancelFundingOffer function
- WSv2: closeFundingLoan function
- WSv2: closeFundingCredit function

4.0.14
- fix: README docs reference

Expand Down
4 changes: 2 additions & 2 deletions docs/WS2Manager.html

Large diffs are not rendered by default.

3,898 changes: 2,671 additions & 1,227 deletions docs/WSv2.html

Large diffs are not rendered by default.

240 changes: 238 additions & 2 deletions docs/global.html

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions docs/index.html

Large diffs are not rendered by default.

174 changes: 163 additions & 11 deletions docs/transports_ws2.js.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/util_precision.js.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/util_ws2.js.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/ws2_manager.js.html

Large diffs are not rendered by default.

154 changes: 154 additions & 0 deletions lib/transports/ws2.js
Original file line number Diff line number Diff line change
Expand Up @@ -1931,6 +1931,160 @@ class WSv2 extends EventEmitter {
return this._getEventPromise(`order-new-${packet.cid}`)
}

/**
* @typedef {object} FundingOffer
* @property {string} type - offer type i.e. LIMIT, FRRDELTAVAR
* @property {string} symbol - symbol i.e. fUSD, fBTC
* @property {string} amount - positive for buy, negative for sell i.e. '50'
* @property {string} rate - rate of the offer
* @property {number} period - Time period of offer. Min:2, Max:30 days
* @property {number} flags - flags
*/

/**
* Sends a new funding offer to the server. Emits an error if not
* authenticated. The funding offer can be either key/value pair object
* literal, an instance of FundingOffer class or an array
*
* @see WSv2#cancelFundingOffer
* @see WSv2#closeFundingCredit
* @see WSv2#closeFundingLoan
*
* @param {FundingOffer|Array} payload - funding offer object model or array
* @throws an error if not authenticated
* @example
* const fo = new FundingOffer({
* type: 'LIMIT',
* symbol: 'fUSD',
* amount: '50',
* rate: '0.001',
* period: 2,
* flags: 0
* }, ws)
*
* ws.submitFundingOffer(fo)
*
* ws.onFundingOfferNew({ symbol: 'fUSD' }, (resp) => {
* console.log('Funding offer status: ', resp.status)
* })
*/
async submitFundingOffer (payload) {
if (!this._isAuthenticated) {
throw new Error('not authenticated')
}

const packet = (
payload instanceof FundingOffer
? payload
: new FundingOffer(payload)
).toNewOfferPacket()

if (this._affCode) {
packet.meta.aff_code = packet.meta.aff_code || this._affCode
}

this.send([0, 'fon', null, packet])
}

/**
* Cancels funding offer by ID. Emits an error if not authenticated.
* The ID can be passed as a number, key/value pair object literal,
* an instance of FundingOffer class or an array
*
* @see WSv2#submitFundingOffer
* @see WSv2#closeFundingCredit
* @see WSv2#closeFundingLoan
*
* @param {FundingOffer|object|Array|number} payload - funding offer model,
* array or ID to cancel
* @throws an error if not authenticated
* @example
* ws.cancelFundingOffer({ id: 1234 })
*
* ws.onFundingOfferClose({ symbol: 'fUSD' }, (resp) => {
* console.log('Funding offer status: ', resp.status)
* })
*/
cancelFundingOffer (payload) {
if (!this._isAuthenticated) {
throw new Error('not authenticated')
}

const id = _isNumber(payload)
? payload
: Array.isArray(payload)
? payload[0]
: payload.id

this.send([0, 'foc', null, { id }])
}

/**
* Cancels funding loan by ID. Emits an error if not authenticated.
* The ID can be passed as a number, key/value pair object literal,
* an instance of FundingLoan class or an array
*
* @see WSv2#submitFundingOffer
* @see WSv2#cancelFundingOffer
* @see WSv2#closeFundingCredit
*
* @param {FundingLoan|object|Array|number} payload - funding loan class,
* object literal, array or ID to cancel
* @throws an error if not authenticated
* @example
* ws.closeFundingLoan({ id: 1234 })
*
* ws.onFundingLoanClose({ symbol: 'fUSD' }, (resp) => {
* console.log('Funding loan status: ', resp.status)
* })
*/
closeFundingLoan (payload) {
if (!this._isAuthenticated) {
throw new Error('not authenticated')
}

const id = _isNumber(payload)
? payload
: Array.isArray(payload)
? payload[0]
: payload.id

this.send([0, 'flc', null, { id }])
}

/**
* Cancels funding credit by ID. Emits an error if not authenticated.
* The ID can be passed as a number, key/value pair object literal,
* an instance of FundingCredit class or an array
*
* @see WSv2#submitFundingOffer
* @see WSv2#cancelFundingOffer
* @see WSv2#closeFundingLoan
*
* @param {FundingCredit|object|Array|number} payload - funding credit class,
* object literal, array or ID to cancel
* @throws an error if not authenticated
* @example
* ws.closeFundingCredit({ id: 1234 })
*
* ws.onFundingCreditClose({ symbol: 'fUSD' }, (resp) => {
* console.log('Funding credit status: ', resp.status)
* })
*/
closeFundingCredit (payload) {
if (!this._isAuthenticated) {
throw new Error('not authenticated')
}

const id = _isNumber(payload)
? payload
: Array.isArray(payload)
? payload[0]
: payload.id

this.send([0, 'fcc', null, { id }])
}

/**
* Send a changeset to update an order in-place while maintaining position in
* the price queue. The changeset must contain the order ID, and supports a
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bitfinex-api-node",
"version": "4.0.14",
"version": "4.0.15",
"description": "Node reference library for Bitfinex API",
"engines": {
"node": ">=8.3.0"
Expand Down
204 changes: 203 additions & 1 deletion test/lib/transports/ws2-integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
const assert = require('assert')
const Promise = require('bluebird')
const WSv2 = require('../../../lib/transports/ws2')
const { Order } = require('bfx-api-node-models')
const { Order, FundingOffer } = require('bfx-api-node-models')
const { MockWSv2Server } = require('bfx-api-mock-srv')

const API_KEY = 'dummy'
Expand Down Expand Up @@ -224,6 +224,208 @@ describe('WSv2 integration', () => {
})
})

describe('submitFundingOffer', () => {
const testCases = {
'as class instance': {
payload: new FundingOffer({
type: 'LIMIT',
symbol: 'fUSD',
amount: '50',
rate: '0.001',
period: 2,
flags: 0
}),
expectedResult: {
type: 'LIMIT',
symbol: 'fUSD',
amount: '50.00000000',
rate: '0.00100000',
period: 2,
flags: 0
}
},
'as object literal': {
payload: {
type: 'LIMIT',
symbol: 'fUSD',
amount: '60',
rate: '0.003',
period: 7,
flags: 0
},
expectedResult: {
type: 'LIMIT',
symbol: 'fUSD',
amount: '60.00000000',
rate: '0.00300000',
period: 7,
flags: 0
}
},
'as array': {
payload: [
null, 'fUSD', null, null, '55', null, 'LIMIT', null, null, 0,
null, null, null, null, '0.002', 4
],
expectedResult: {
type: 'LIMIT',
symbol: 'fUSD',
amount: '55.00000000',
rate: '0.00200000',
period: 4,
flags: 0
}
}
}

Object.keys(testCases).forEach((scenario) => {
it(scenario, async () => {
let sentPackets = 0
wss = new MockWSv2Server()
ws = createTestWSv2Instance()

await ws.open()
await ws.auth()

ws._ws.send = (msgJSON) => {
const msg = JSON.parse(msgJSON)
assert.strictEqual(msg[1], 'fon')
assert.deepStrictEqual(msg[3], testCases[scenario].expectedResult)
sentPackets++
}

ws.submitFundingOffer(testCases[scenario].payload)
assert.strictEqual(sentPackets, 1)
})
})
})

describe('cancelFundingOffer', () => {
const testCases = {
'as class instance': {
payload: new FundingOffer({ id: 123 }),
expectedResult: { id: 123 }
},
'as object literal': {
payload: { id: 124 },
expectedResult: { id: 124 }
},
'as number': {
payload: 125,
expectedResult: { id: 125 }
},
'as array': {
payload: [126],
expectedResult: { id: 126 }
}
}

Object.keys(testCases).forEach((scenario) => {
it(scenario, async () => {
let sentPackets = 0
wss = new MockWSv2Server()
ws = createTestWSv2Instance()

await ws.open()
await ws.auth()

ws._ws.send = (msgJSON) => {
const msg = JSON.parse(msgJSON)
assert.strictEqual(msg[1], 'foc')
assert.deepStrictEqual(msg[3], testCases[scenario].expectedResult)
sentPackets++
}

ws.cancelFundingOffer(testCases[scenario].payload)
assert.strictEqual(sentPackets, 1)
})
})
})

describe('closeFundingLoan', () => {
const testCases = {
'as class instance': {
payload: new FundingOffer({ id: 123 }),
expectedResult: { id: 123 }
},
'as object literal': {
payload: { id: 124 },
expectedResult: { id: 124 }
},
'as number': {
payload: 125,
expectedResult: { id: 125 }
},
'as array': {
payload: [126],
expectedResult: { id: 126 }
}
}

Object.keys(testCases).forEach((scenario) => {
it(scenario, async () => {
let sentPackets = 0
wss = new MockWSv2Server()
ws = createTestWSv2Instance()

await ws.open()
await ws.auth()

ws._ws.send = (msgJSON) => {
const msg = JSON.parse(msgJSON)
assert.strictEqual(msg[1], 'flc')
assert.deepStrictEqual(msg[3], testCases[scenario].expectedResult)
sentPackets++
}

ws.closeFundingLoan(testCases[scenario].payload)
assert.strictEqual(sentPackets, 1)
})
})
})

describe('closeFundingCredit', () => {
const testCases = {
'as class instance': {
payload: new FundingOffer({ id: 123 }),
expectedResult: { id: 123 }
},
'as object literal': {
payload: { id: 124 },
expectedResult: { id: 124 }
},
'as number': {
payload: 125,
expectedResult: { id: 125 }
},
'as array': {
payload: [126],
expectedResult: { id: 126 }
}
}

Object.keys(testCases).forEach((scenario) => {
it(scenario, async () => {
let sentPackets = 0
wss = new MockWSv2Server()
ws = createTestWSv2Instance()

await ws.open()
await ws.auth()

ws._ws.send = (msgJSON) => {
const msg = JSON.parse(msgJSON)
assert.strictEqual(msg[1], 'fcc')
assert.deepStrictEqual(msg[3], testCases[scenario].expectedResult)
sentPackets++
}

ws.closeFundingCredit(testCases[scenario].payload)
assert.strictEqual(sentPackets, 1)
})
})
})

describe('listeners', () => {
it('manages listeners by cbGID', () => {
ws = createTestWSv2Instance()
Expand Down