├── .github ├── ISSUE_TEMPLATE └── PULL_REQUEST_TEMPLATE ├── .gitignore ├── .husky └── pre-commit ├── .jsdoc.json ├── .npmignore ├── .travis.yml ├── CHANGELOG ├── DOCUMENTATION.md ├── LICENSE.md ├── README.md ├── docs ├── AccountSummary.html ├── Alert.html ├── AuthPermission.html ├── BalanceInfo.html ├── Candle.html ├── ChangeLog.html ├── CoreSettings.html ├── Currency.html ├── FundingCredit.html ├── FundingInfo.html ├── FundingLoan.html ├── FundingOffer.html ├── FundingTicker.html ├── FundingTickerHist.html ├── FundingTrade.html ├── Invoice.html ├── LedgerEntry.html ├── Liquidations.html ├── Login.html ├── MarginInfo.html ├── Model.html ├── Movement.html ├── MovementInfo.html ├── Notification.html ├── Order.html ├── OrderBook.html ├── Position.html ├── PublicTrade.html ├── StatusMessagesDeriv.html ├── SymbolDetails.html ├── Trade.html ├── TradingTicker.html ├── TradingTickerHist.html ├── TransactionFee.html ├── UserInfo.html ├── Wallet.html ├── WalletHist.html ├── WeightedAverages.html ├── account_summary.js.html ├── alert.js.html ├── auth_permission.js.html ├── balance_info.js.html ├── candle.js.html ├── change_log.js.html ├── core_settings.js.html ├── currency.js.html ├── fonts │ ├── Montserrat │ │ ├── Montserrat-Bold.eot │ │ ├── Montserrat-Bold.ttf │ │ ├── Montserrat-Bold.woff │ │ ├── Montserrat-Bold.woff2 │ │ ├── Montserrat-Regular.eot │ │ ├── Montserrat-Regular.ttf │ │ ├── Montserrat-Regular.woff │ │ └── Montserrat-Regular.woff2 │ └── Source-Sans-Pro │ │ ├── sourcesanspro-light-webfont.eot │ │ ├── sourcesanspro-light-webfont.svg │ │ ├── sourcesanspro-light-webfont.ttf │ │ ├── sourcesanspro-light-webfont.woff │ │ ├── sourcesanspro-light-webfont.woff2 │ │ ├── sourcesanspro-regular-webfont.eot │ │ ├── sourcesanspro-regular-webfont.svg │ │ ├── sourcesanspro-regular-webfont.ttf │ │ ├── sourcesanspro-regular-webfont.woff │ │ └── sourcesanspro-regular-webfont.woff2 ├── funding_credit.js.html ├── funding_info.js.html ├── funding_loan.js.html ├── funding_offer.js.html ├── funding_ticker.js.html ├── funding_ticker_hist.js.html ├── funding_trade.js.html ├── global.html ├── index.html ├── invoice.js.html ├── ledger_entry.js.html ├── liquidations.js.html ├── login.js.html ├── margin_info.js.html ├── model.js.html ├── movement.js.html ├── movement_info.js.html ├── notification.js.html ├── order.js.html ├── order_book.js.html ├── position.js.html ├── public_trade.js.html ├── scripts │ ├── collapse.js │ ├── commonNav.js │ ├── linenumber.js │ ├── nav.js │ ├── polyfill.js │ ├── prettify │ │ ├── Apache-License-2.0.txt │ │ ├── lang-css.js │ │ └── prettify.js │ └── search.js ├── status_messages_deriv.js.html ├── styles │ ├── jsdoc.css │ └── prettify.css ├── symbol_details.js.html ├── trade.js.html ├── trading_ticker.js.html ├── trading_ticker_hist.js.html ├── transaction_fee.js.html ├── user_info.js.html ├── util_assign_from_collection_or_instance.js.html ├── util_is_collection.js.html ├── validators_amount.js.html ├── validators_array.js.html ├── validators_bool.js.html ├── validators_currency.js.html ├── validators_date.js.html ├── validators_number.js.html ├── validators_object.js.html ├── validators_price.js.html ├── validators_string.js.html ├── validators_symbol.js.html ├── wallet.js.html ├── wallet_hist.js.html └── weighted_averages.js.html ├── examples └── order.js ├── index.js ├── lib ├── account_summary.js ├── alert.js ├── auth_permission.js ├── balance_info.js ├── candle.js ├── change_log.js ├── core_settings.js ├── currency.js ├── funding_credit.js ├── funding_info.js ├── funding_loan.js ├── funding_offer.js ├── funding_ticker.js ├── funding_ticker_hist.js ├── funding_trade.js ├── index.js ├── invoice.js ├── ledger_entry.js ├── liquidations.js ├── login.js ├── margin_info.js ├── model.js ├── movement.js ├── movement_info.js ├── notification.js ├── order.js ├── order_book.js ├── position.js ├── public_trade.js ├── status_messages_deriv.js ├── symbol_details.js ├── trade.js ├── trading_ticker.js ├── trading_ticker_hist.js ├── transaction_fee.js ├── user_info.js ├── util │ ├── arr_fill_empty.js │ ├── assign_from_collection_or_instance.js │ └── is_collection.js ├── validators │ ├── amount.js │ ├── array.js │ ├── bool.js │ ├── currency.js │ ├── date.js │ ├── number.js │ ├── object.js │ ├── price.js │ ├── string.js │ └── symbol.js ├── wallet.js ├── wallet_hist.js └── weighted_averages.js ├── package.json └── test ├── helpers ├── test_model.js └── test_model_validation.js └── lib ├── models ├── account_summary.js ├── alert.js ├── auth_permission.js ├── balance_info.js ├── candle.js ├── change_logs.js ├── core_settings.js ├── currency.js ├── funding_credit.js ├── funding_info.js ├── funding_loan.js ├── funding_offer.js ├── funding_ticker.js ├── funding_ticker_hist.js ├── funding_trade.js ├── invoice.js ├── ledger_entry.js ├── liquidations.js ├── login.js ├── margin_info.js ├── model.js ├── movement.js ├── movement_info.js ├── notification.js ├── order.js ├── order_book.js ├── position.js ├── public_trade.js ├── status_messages_deriv.js ├── symbol_details.js ├── trade.js ├── trading_ticker.js ├── trading_ticker_hist.js ├── transaction_fee.js ├── user_info.js ├── wallet.js ├── wallet_hist.js └── weighted_averages.js ├── util ├── arr_fill_empty.js ├── assign_from_collection_or_instance.js └── is_collection.js └── validators ├── amount.js ├── bool.js ├── currency.js ├── date.js ├── number.js ├── price.js ├── string.js └── symbol.js /.github/ISSUE_TEMPLATE: -------------------------------------------------------------------------------- 1 | #### Issue type 2 | - [ ] bug 3 | - [ ] missing functionality 4 | - [ ] performance 5 | - [ ] feature request 6 | 7 | #### Brief description 8 | 9 | #### Steps to reproduce 10 | - 11 | 12 | ##### Additional Notes: 13 | - 14 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE: -------------------------------------------------------------------------------- 1 | ### Description: 2 | ... 3 | 4 | ### Breaking changes: 5 | - [ ] 6 | 7 | ### New features: 8 | - [ ] 9 | 10 | ### Fixes: 11 | - [ ] 12 | 13 | ### PR status: 14 | - [ ] Version bumped 15 | - [ ] Change-log updated 16 | - [ ] Tests added or updated 17 | - [ ] Documentation updated 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | /test/test_api_keys.json 4 | /build 5 | npm-debug.log 6 | source/images 7 | .DS_Store 8 | todo 9 | package-lock.json 10 | .env 11 | /dist 12 | coverage 13 | .nyc_output 14 | tags 15 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # only run on added/modified files 4 | git diff --name-only --cached --diff-filter=AM -- "*.js" | \ 5 | while read -r file 6 | do 7 | if [ -f "$file" ]; then # don't run on deleted files 8 | npx standard "$file" 9 | fi 10 | done 11 | -------------------------------------------------------------------------------- /.jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": false, 4 | "dictionaries": ["jsdoc"] 5 | }, 6 | "source": { 7 | "include": ["lib", "DOCUMENTATION.md"], 8 | "includePattern": ".js$", 9 | "excludePattern": "(node_modules/|docs)" 10 | }, 11 | "plugins": [ 12 | "plugins/markdown" 13 | ], 14 | "templates": { 15 | "cleverLinks": false, 16 | "monospaceLinks": true, 17 | "smallSourceLink": true, 18 | "hideAuthor": true 19 | }, 20 | "opts": { 21 | "destination": "./docs/", 22 | "encoding": "utf8", 23 | "private": false, 24 | "recurse": true, 25 | "template": "./node_modules/docdash" 26 | }, 27 | "package": "", 28 | "docdash": { 29 | "static": true, 30 | "sort": true, 31 | "search": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | docs 3 | coverage 4 | examples 5 | .github 6 | .nyc_output 7 | .travis.yml 8 | .jsdoc.json 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: node_js 4 | node_js: 5 | - "stable" 6 | 7 | install: 8 | - npm install --ignore-scripts 9 | 10 | script: 11 | - npm run lint 12 | - npm run unit 13 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | # 2.1.0 2 | - feature: add isUserMerchant flag into user info model 3 | 4 | # 2.0.1 5 | - chore: bump bfx-api-node-rest to 6.0.0 6 | 7 | # 2.0.0 8 | - chore: deprecated support for pulse endpoints 9 | 10 | # 1.8.2 11 | - feat: add IOC order type 12 | 13 | # 1.8.1 14 | - fix: Add extra Weighted Averages fields for trades timestamps 15 | 16 | # 1.8.0 17 | - feature: Weighted Averages model 18 | 19 | # 1.7.1 20 | - fix: Change FundingOffer, Order, Position model to support new rest api signature 21 | - fix: Test coverage to support new rest api signature 22 | 23 | # 1.7.0 24 | - feature: Currency Movement Info model 25 | 26 | # 1.6.3 27 | - fix: public trade unserializing from snapshot 28 | 29 | # 1.6.2 30 | - feature: visible on hit option supported for hidden orders 31 | 32 | # 1.6.0 33 | - feature: Core settings model 34 | 35 | # 1.5.0 36 | - feature: added isPaperTradeEnabled info in user info model 37 | 38 | # 1.4.1 39 | - fix: validate inputs on updateWith method in order book model 40 | 41 | # 1.4.0 42 | - chore: standard upgrade 43 | - chore: remove babel 44 | 45 | # 1.3.3 46 | - feature: add extra keys to account summary model 47 | 48 | # 1.3.2 49 | - feature: add note to movement model 50 | 51 | # 1.3.1 52 | - feature: enriched pulse message model to include pulse comments 53 | 54 | # 1.3.0 55 | - feature: add multi level parser to base model class 56 | - feature: add symbol details model 57 | - feature: add transaction fee model 58 | - feature: add account summary model 59 | - feature: add auth permission model 60 | 61 | # 1.2.11 62 | - feature: add clampMin to StatusMessagesDeriv model 63 | - feature: add clampMax to StatusMessagesDeriv model 64 | 65 | # 1.2.10 66 | - feature: add walletFx to currency model 67 | - fix: currencies explorer is an array not a string 68 | 69 | # 1.2.9 70 | - feature: add Invoice model 71 | 72 | # 1.2.8 73 | - feature: enriched pulse message model to include pulse profile 74 | 75 | # 1.2.7 76 | - feature: add pulse model 77 | 78 | # 1.2.6 79 | - feature: add public pulse profile model 80 | 81 | # 1.2.5 82 | - feature: add change log model 83 | 84 | # 1.2.4 85 | - meta: added JSDoc-generated HTML docs 86 | - meta: standardized linter config 87 | 88 | # 1.2.3 89 | - fix: index lookup in validation of array-format models 90 | 91 | # 1.2.2 92 | - fix: make bfx-api-node-rest dev-dep to break circular dependency 93 | 94 | # 1.2.1 95 | - fix: move bfx-hf-util and bfx-api-node-rest to deps from dev deps 96 | 97 | # 1.2.0 98 | - meta: bumped dependencies 99 | - meta: added husky pre-commit test hook 100 | - feature: add validation support to models 101 | - refactor: core Model() class method signatures to reduce boilerplate 102 | - Position feature: orderToClose() method 103 | - Model fix: toJS() unserialize method invocation parameters 104 | 105 | # 1.1.10 106 | - feature: add ability to specify lev in new Order object 107 | 108 | # 1.1.9 109 | - feature: Add type to FundingCredit and FundingLoan 110 | 111 | # 1.1.8 112 | - Order feature: add toString() method 113 | 114 | # 1.1.7 115 | - fix: increase test timeout in a few places 116 | 117 | # 1.1.6 118 | - fix: generate orderbook checksum using strings to prevent 119 | https://github.com/bitfinexcom/bitfinex-api-node/issues/511 120 | 121 | # 1.1.5 122 | 123 | - feature: support affiliateCode field in Order class 124 | 125 | # 1.1.4 126 | - feature: Login model 127 | 128 | # 1.1.3 129 | - models/Order: fix OCO field population on on packets 130 | 131 | # 1.1.2 132 | - models/order: add fields hidden, routing and meta 133 | 134 | # 1.1.1 135 | - docs: create/update 136 | 137 | # 1.1.0 138 | - adds function Position.claim 139 | - adds function FundingOffer.submit 140 | - adds function FundingOffer.close 141 | - adds function FundingOffer.cancel 142 | 143 | # 1.0.13 144 | - fix: (Model bool field handling) un-quote key in indexOf call 145 | - manifest: add build script 146 | - manifest: update dependencies 147 | - meta: standardize travis conig 148 | - meta: add github issue/pr templates 149 | - meta: init changelog 150 | 151 | # 1.0.12 152 | - Order fix: prepare prices & amounts in new order packet 153 | - Order refactor: require gid to match to apply an update 154 | 155 | # 1.0.11 156 | - Order fix: init reduce-only flag in constructor 157 | - Position fix: add missing fields 158 | - feature: StatusMessagesDeriv model 159 | - feature: Liquidation model 160 | 161 | # 1.0.10 162 | - feature: make all model collections iterable 163 | 164 | # 1.0.9 165 | - Currency: add symbol field 166 | 167 | # 1.0.8 168 | - feature: populate tif & mtsTIF on Order 169 | 170 | # 1.0.7 171 | - refactor: convert PositionHist to Position 172 | 173 | # 1.0.6 174 | - feature: WalletHistory model 175 | - feature: PositionHistory model 176 | - feature: TradingTickerHist model 177 | - feature: FundingTickerHist model 178 | - fix: tests for FundingTicker & TradingTicker 179 | 180 | # 1.0.5 181 | - OrderBook refactor: assumy OB snapshots are sorted in update method 182 | - OrderBook fix: support update with empty snapshot 183 | - feature: add live REST tests where possible 184 | 185 | # 1.0.4 186 | - OrderBook fix: guard against empty array OB updates in updateArrayOBWith 187 | 188 | # 1.0.3 189 | - fix: update FundingTicker & TradingTicker formats 190 | 191 | # 1.0.2 192 | - fix: allow creating orders w/ amount or amountOrig 0 193 | 194 | # 1.0.1 195 | - feature: Currency model 196 | - feature: UserInfo model 197 | - LedgerEntry feature: add wallet field 198 | 199 | # 1.0.0 200 | * Initial version 201 | -------------------------------------------------------------------------------- /DOCUMENTATION.md: -------------------------------------------------------------------------------- 1 | # Bitfinex Data Models for Node.JS 2 | 3 | This repo contains model classes for working with the data structures returned 4 | by the Bitfinex REST & WebSocket APIs. The models can all be initialized with 5 | an array-format payload as returned by an API call, and can be unserialized 6 | back to the array format when needed. 7 | 8 | Some models, such as {@link Order} and {@link OrderBook} provide higher level 9 | methods which operate on the underlying data sets. 10 | 11 | All models provide `serialize()` and `unserialize()` methods, which convert 12 | to/from array-format payloads respectively. All model constructors can take 13 | either array-format payloads, or objects/other model instances. A helper 14 | `toJS()` method is also provided for converting models to plain JS objects 15 | (POJOs). 16 | 17 | ### Features 18 | 19 | * Convert between array, object, and class representations of API data 20 | * Class methods for operating on model data where applicable (i.e. `OrderBook`) 21 | 22 | Classes for the following Bitfinex API data types: 23 | * {@link Alert} 24 | * {@link BalanceInfo} 25 | * {@link Candle} 26 | * {@link Currency} 27 | * {@link FundingCredit} 28 | * {@link FundingInfo} 29 | * {@link FundingLoan} 30 | * {@link FundingOffer} 31 | * {@link FundingTickerHist} 32 | * {@link FundingTicker} 33 | * {@link FundingTrade} 34 | * {@link LedgerEntry} 35 | * {@link Liquidations} 36 | * {@link MarginInfo} 37 | * {@link Movement} 38 | * {@link Notification} 39 | * {@link OrderBook} 40 | * {@link Order} 41 | * {@link Position} 42 | * {@link PublicTrade} 43 | * {@link StatusMessagesDeriv} 44 | * {@link Trade} 45 | * {@link TradingTicker} 46 | * {@link TradingTickerHist} 47 | * {@link UserInfo} 48 | * {@link Wallet} 49 | * {@link WalletHist} 50 | * {@link Currency} 51 | * {@link SymbolDetails} 52 | * {@link TransactionFee} 53 | * {@link AccountSummary} 54 | * {@link AuthPermission} 55 | 56 | ### Installation 57 | 58 | ```js 59 | npm i --save bfx-api-node-models 60 | ``` 61 | 62 | ### Quickstart 63 | 64 | ```js 65 | const { Order } = require('bfx-api-node-models') 66 | 67 | const o = new Order({ 68 | cid: Date.now(), 69 | symbol: 'tBTCUSD', 70 | price: 7000.0, 71 | amount: -0.02, 72 | type: Order.type.EXCHANGE_LIMIT 73 | }) 74 | 75 | // Generate an API-compatible order creation packet for later submit 76 | console.log(o.toNewOrderPacket()) 77 | ``` 78 | 79 | ### Examples 80 | 81 | The order model provides helper methods for order submission, updates, and cancellation. These methods are compatible with version 2.0.0 of `bitfinex-api-node`, and return promises which resolve upon receival of the relevant success/error notifications. 82 | 83 | Orders are matched with their API packets by one/all of `id`, `gid`, and `cid`. 84 | 85 | Example usage: 86 | ```js 87 | const { Order } = require('bfx-api-node-models') 88 | const ws = ... // setup WSv2 instance for order updates/submission 89 | 90 | // Build new order 91 | const o = new Order({ 92 | cid: Date.now(), 93 | symbol: 'tBTCUSD', 94 | price: 7000.0, 95 | amount: -0.02, 96 | type: Order.type.EXCHANGE_LIMIT 97 | }, ws) // note WSv2 client passed in here 98 | 99 | let closed = false 100 | 101 | // Enable automatic updates 102 | o.registerListeners() 103 | 104 | o.on('update', () => { 105 | debug('order updated: %j', o.serialize()) 106 | }) 107 | 108 | o.on('close', () => { 109 | debug('order closed: %s', o.status) 110 | closed = true 111 | }) 112 | 113 | debug('submitting order %d', o.cid) 114 | 115 | o.submit().then(() => { 116 | debug('got submit confirmation for order %d [%d]', o.cid, o.id) 117 | }).catch((err) => { 118 | debug('failed to submit order: %s', err.message) 119 | }) 120 | ``` 121 | 122 | The order book model constructor takes either entire book snapshots as returned by the WSv2 API, or individual update packets with single bids/asks. Once constructed, order books may be updated either with complete snapshots via `updateFromSnapshot(snapshot)` or individual update packets via `updateWidth(entry)`. 123 | 124 | Static helpers are also provided for working with array-format order books, in the form of `updateArrayOBWith(ob, entry, raw)`, `arrayOBMidPrice(ob, raw)`, and `checksumArr(ob, raw)`. 125 | 126 | Checksums may be calculated for normal books via `checksum()`, for comparison with the checksums reported by the WSv2 API. 127 | 128 | Example usage: 129 | ```js 130 | const ob = new OrderBook([ 131 | [140, 1, 10], 132 | [145, 1, 10], 133 | [148, 1, 10], 134 | [149, 1, 10], 135 | [151, 1, -10], 136 | [152, 1, -10], 137 | [158, 1, -10], 138 | [160, 1, -10] 139 | ]) 140 | 141 | ob.updateWith([145, 3, 15]) // update bid 142 | ob.updateWith([158, 3, -15]) // update ask 143 | 144 | console.log(ob.serialize()) 145 | ``` 146 | 147 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 bitfinexcom 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bitfinex Data Models for Node.JS 2 | 3 | [![Build Status](https://travis-ci.org/bitfinexcom/bfx-api-node-models.svg?branch=master)](https://travis-ci.org/bitfinexcom/bfx-api-node-models) 4 | 5 | This repo contains model classes for working with the data structures returned by the Bitfinex REST & WebSocket APIs. The models can all be initialized with an array-format payload as returned by an API call, and can be unserialized back to the array format when needed. 6 | 7 | Some models, such as `Order` and `OrderBook` provide higher level methods which operate on the underlying data sets. 8 | 9 | All models provide `serialize()` and `unserialize()` methods, which convert to/from array-format payloads respectively. All model constructors can take either array-format payloads, or objects/other model instances. A helper `toJS()` method is also provided for converting models to plain JS objects (POJOs). 10 | 11 | ### Features 12 | 13 | * Convert between array, object, and class representations of API data 14 | * Class methods for operating on model data where applicable (i.e. `OrderBook`) 15 | 16 | Classes for the following Bitfinex API data types: 17 | * Alert 18 | * BalanceInfo 19 | * Candle 20 | * Currency 21 | * FundingCredit 22 | * FundingInfo 23 | * FundingLoan 24 | * FundingOffer 25 | * FundingTickerHist 26 | * FundingTicker 27 | * FundingTrade 28 | * LedgerEntry 29 | * Liquidations 30 | * MarginInfo 31 | * Movement 32 | * Notification 33 | * OrderBook 34 | * Order 35 | * Position 36 | * PublicTrade 37 | * StatusMessagesDeriv 38 | * Trade 39 | * TradingTicker 40 | * TradingTickerHist 41 | * UserInfo 42 | * Wallet 43 | * WalletHist 44 | * Currency 45 | * SymbolDetails 46 | * TransactionFee 47 | * AccountSummary 48 | * AuthPermission 49 | 50 | ### Installation 51 | 52 | ```js 53 | npm i --save bfx-api-node-models 54 | ``` 55 | 56 | ### Quickstart 57 | 58 | ```js 59 | const { Order } = require('bfx-api-node-models') 60 | 61 | const o = new Order({ 62 | cid: Date.now(), 63 | symbol: 'tBTCUSD', 64 | price: 7000.0, 65 | amount: -0.02, 66 | type: Order.type.EXCHANGE_LIMIT 67 | }) 68 | 69 | // Generate an API-compatible order creation packet for later submit 70 | console.log(o.toNewOrderPacket()) 71 | ``` 72 | 73 | ### Docs 74 | 75 | Refer to the [docs/](https://cdn.statically.io/gh/bitfinexcom/bfx-api-node-models/master/docs/index.html) 76 | folder for JSDoc-generated API documentation covering each model class. 77 | 78 | ### Examples 79 | 80 | The order model provides helper methods for order submission, updates, and cancellation. These methods are compatible with version 2.0.0 of `bitfinex-api-node`, and return promises which resolve upon receival of the relevant success/error notifications. 81 | 82 | Orders are matched with their API packets by one/all of `id`, `gid`, and `cid`. 83 | 84 | Example usage: 85 | ```js 86 | const { Order } = require('bfx-api-node-models') 87 | const ws = ... // setup WSv2 instance for order updates/submission 88 | 89 | // Build new order 90 | const o = new Order({ 91 | cid: Date.now(), 92 | symbol: 'tBTCUSD', 93 | price: 7000.0, 94 | amount: -0.02, 95 | type: Order.type.EXCHANGE_LIMIT 96 | }, ws) // note WSv2 client passed in here 97 | 98 | let closed = false 99 | 100 | // Enable automatic updates 101 | o.registerListeners() 102 | 103 | o.on('update', () => { 104 | debug('order updated: %j', o.serialize()) 105 | }) 106 | 107 | o.on('close', () => { 108 | debug('order closed: %s', o.status) 109 | closed = true 110 | }) 111 | 112 | debug('submitting order %d', o.cid) 113 | 114 | o.submit().then(() => { 115 | debug('got submit confirmation for order %d [%d]', o.cid, o.id) 116 | }).catch((err) => { 117 | debug('failed to submit order: %s', err.message) 118 | }) 119 | ``` 120 | 121 | The order book model constructor takes either entire book snapshots as returned by the WSv2 API, or individual update packets with single bids/asks. Once constructed, order books may be updated either with complete snapshots via `updateFromSnapshot(snapshot)` or individual update packets via `updateWidth(entry)`. 122 | 123 | Static helpers are also provided for working with array-format order books, in the form of `updateArrayOBWith(ob, entry, raw)`, `arrayOBMidPrice(ob, raw)`, and `checksumArr(ob, raw)`. 124 | 125 | Checksums may be calculated for normal books via `checksum()`, for comparison with the checksums reported by the WSv2 API. 126 | 127 | Example usage: 128 | ```js 129 | const ob = new OrderBook([ 130 | [140, 1, 10], 131 | [145, 1, 10], 132 | [148, 1, 10], 133 | [149, 1, 10], 134 | [151, 1, -10], 135 | [152, 1, -10], 136 | [158, 1, -10], 137 | [160, 1, -10] 138 | ]) 139 | 140 | ob.updateWith([145, 3, 15]) // update bid 141 | ob.updateWith([158, 3, -15]) // update ask 142 | 143 | console.log(ob.serialize()) 144 | ``` 145 | 146 | ### Contributing 147 | 148 | 1. Fork it 149 | 2. Create your feature branch (`git checkout -b my-new-feature`) 150 | 3. Commit your changes (`git commit -am 'Add some feature'`) 151 | 4. Push to the branch (`git push origin my-new-feature`) 152 | 5. Create a new Pull Request 153 | -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Montserrat/Montserrat-Bold.eot -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Montserrat/Montserrat-Bold.ttf -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Montserrat/Montserrat-Bold.woff -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Montserrat/Montserrat-Bold.woff2 -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Montserrat/Montserrat-Regular.eot -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Montserrat/Montserrat-Regular.ttf -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Montserrat/Montserrat-Regular.woff -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Montserrat/Montserrat-Regular.woff2 -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitfinexcom/bfx-api-node-models/e4d7c771648e903161df520f4e8714de816ddde4/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 -------------------------------------------------------------------------------- /docs/scripts/collapse.js: -------------------------------------------------------------------------------- 1 | function hideAllButCurrent(){ 2 | //by default all submenut items are hidden 3 | //but we need to rehide them for search 4 | document.querySelectorAll("nav > ul").forEach(function(parent) { 5 | if (parent.className.indexOf("collapse_top") !== -1) { 6 | parent.style.display = "none"; 7 | } 8 | }); 9 | document.querySelectorAll("nav > ul > li > ul li").forEach(function(parent) { 10 | parent.style.display = "none"; 11 | }); 12 | document.querySelectorAll("nav > h3").forEach(function(section) { 13 | if (section.className.indexOf("collapsed_header") !== -1) { 14 | section.addEventListener("click", function(){ 15 | if (section.nextSibling.style.display === "none") { 16 | section.nextSibling.style.display = "block"; 17 | } else { 18 | section.nextSibling.style.display = "none"; 19 | } 20 | }); 21 | } 22 | }); 23 | 24 | //only current page (if it exists) should be opened 25 | var file = window.location.pathname.split("/").pop().replace(/\.html/, ''); 26 | document.querySelectorAll("nav > ul > li > a").forEach(function(parent) { 27 | var href = parent.attributes.href.value.replace(/\.html/, ''); 28 | if (file === href) { 29 | if (parent.parentNode.parentNode.className.indexOf("collapse_top") !== -1) { 30 | parent.parentNode.parentNode.style.display = "block"; 31 | } 32 | parent.parentNode.querySelectorAll("ul li").forEach(function(elem) { 33 | elem.style.display = "block"; 34 | }); 35 | } 36 | }); 37 | } 38 | 39 | hideAllButCurrent(); -------------------------------------------------------------------------------- /docs/scripts/commonNav.js: -------------------------------------------------------------------------------- 1 | if (typeof fetch === 'function') { 2 | const init = () => { 3 | if (typeof scrollToNavItem !== 'function') return false 4 | scrollToNavItem() 5 | // hideAllButCurrent not always loaded 6 | if (typeof hideAllButCurrent === 'function') hideAllButCurrent() 7 | return true 8 | } 9 | fetch('./nav.inc.html') 10 | .then(response => response.ok ? response.text() : `${response.url} => ${response.status} ${response.statusText}`) 11 | .then(body => { 12 | document.querySelector('nav').innerHTML += body 13 | // nav.js should be quicker to load than nav.inc.html, a fallback just in case 14 | return init() 15 | }) 16 | .then(done => { 17 | if (done) return 18 | let i = 0 19 | ;(function waitUntilNavJs () { 20 | if (init()) return 21 | if (i++ < 100) return setTimeout(waitUntilNavJs, 300) 22 | console.error(Error('nav.js not loaded after 30s waiting for it')) 23 | })() 24 | }) 25 | .catch(error => console.error(error)) 26 | } else { 27 | console.error(Error('Browser too old to display commonNav (remove commonNav docdash option)')) 28 | } 29 | -------------------------------------------------------------------------------- /docs/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | /*global document */ 2 | (function() { 3 | var source = document.getElementsByClassName('prettyprint source linenums'); 4 | var i = 0; 5 | var lineNumber = 0; 6 | var lineId; 7 | var lines; 8 | var totalLines; 9 | var anchorHash; 10 | 11 | if (source && source[0]) { 12 | anchorHash = document.location.hash.substring(1); 13 | lines = source[0].getElementsByTagName('li'); 14 | totalLines = lines.length; 15 | 16 | for (; i < totalLines; i++) { 17 | lineNumber++; 18 | lineId = 'line' + lineNumber; 19 | lines[i].id = lineId; 20 | if (lineId === anchorHash) { 21 | lines[i].className += ' selected'; 22 | } 23 | } 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /docs/scripts/nav.js: -------------------------------------------------------------------------------- 1 | function scrollToNavItem() { 2 | var path = window.location.href.split('/').pop().replace(/\.html/, ''); 3 | document.querySelectorAll('nav a').forEach(function(link) { 4 | var href = link.attributes.href.value.replace(/\.html/, ''); 5 | if (path === href) { 6 | link.scrollIntoView({block: 'center'}); 7 | return; 8 | } 9 | }) 10 | } 11 | 12 | scrollToNavItem(); 13 | -------------------------------------------------------------------------------- /docs/scripts/polyfill.js: -------------------------------------------------------------------------------- 1 | //IE Fix, src: https://www.reddit.com/r/programminghorror/comments/6abmcr/nodelist_lacks_foreach_in_internet_explorer/ 2 | if (typeof(NodeList.prototype.forEach)!==typeof(alert)){ 3 | NodeList.prototype.forEach=Array.prototype.forEach; 4 | } -------------------------------------------------------------------------------- /docs/scripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /docs/scripts/search.js: -------------------------------------------------------------------------------- 1 | 2 | var searchAttr = 'data-search-mode'; 3 | function contains(a,m){ 4 | return (a.textContent || a.innerText || "").toUpperCase().indexOf(m) !== -1; 5 | }; 6 | 7 | //on search 8 | document.getElementById("nav-search").addEventListener("keyup", function(event) { 9 | var search = this.value.toUpperCase(); 10 | 11 | if (!search) { 12 | //no search, show all results 13 | document.documentElement.removeAttribute(searchAttr); 14 | 15 | document.querySelectorAll("nav > ul > li:not(.level-hide)").forEach(function(elem) { 16 | elem.style.display = "block"; 17 | }); 18 | 19 | if (typeof hideAllButCurrent === "function"){ 20 | //let's do what ever collapse wants to do 21 | hideAllButCurrent(); 22 | } else { 23 | //menu by default should be opened 24 | document.querySelectorAll("nav > ul > li > ul li").forEach(function(elem) { 25 | elem.style.display = "block"; 26 | }); 27 | } 28 | } else { 29 | //we are searching 30 | document.documentElement.setAttribute(searchAttr, ''); 31 | 32 | //show all parents 33 | document.querySelectorAll("nav > ul > li").forEach(function(elem) { 34 | elem.style.display = "block"; 35 | }); 36 | document.querySelectorAll("nav > ul").forEach(function(elem) { 37 | elem.style.display = "block"; 38 | }); 39 | //hide all results 40 | document.querySelectorAll("nav > ul > li > ul li").forEach(function(elem) { 41 | elem.style.display = "none"; 42 | }); 43 | //show results matching filter 44 | document.querySelectorAll("nav > ul > li > ul a").forEach(function(elem) { 45 | if (!contains(elem.parentNode, search)) { 46 | return; 47 | } 48 | elem.parentNode.style.display = "block"; 49 | }); 50 | //hide parents without children 51 | document.querySelectorAll("nav > ul > li").forEach(function(parent) { 52 | var countSearchA = 0; 53 | parent.querySelectorAll("a").forEach(function(elem) { 54 | if (contains(elem, search)) { 55 | countSearchA++; 56 | } 57 | }); 58 | 59 | var countUl = 0; 60 | var countUlVisible = 0; 61 | parent.querySelectorAll("ul").forEach(function(ulP) { 62 | // count all elements that match the search 63 | if (contains(ulP, search)) { 64 | countUl++; 65 | } 66 | 67 | // count all visible elements 68 | var children = ulP.children 69 | for (i=0; i ul.collapse_top").forEach(function(parent) { 86 | var countVisible = 0; 87 | parent.querySelectorAll("li").forEach(function(elem) { 88 | if (elem.style.display !== "none") { 89 | countVisible++; 90 | } 91 | }); 92 | 93 | if (countVisible == 0) { 94 | //has no child at all and does not contain text 95 | parent.style.display = "none"; 96 | } 97 | }); 98 | } 99 | }); -------------------------------------------------------------------------------- /docs/styles/prettify.css: -------------------------------------------------------------------------------- 1 | .pln { 2 | color: #ddd; 3 | } 4 | 5 | /* string content */ 6 | .str { 7 | color: #61ce3c; 8 | } 9 | 10 | /* a keyword */ 11 | .kwd { 12 | color: #fbde2d; 13 | } 14 | 15 | /* a comment */ 16 | .com { 17 | color: #aeaeae; 18 | } 19 | 20 | /* a type name */ 21 | .typ { 22 | color: #8da6ce; 23 | } 24 | 25 | /* a literal value */ 26 | .lit { 27 | color: #fbde2d; 28 | } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #ddd; 33 | } 34 | 35 | /* lisp open bracket */ 36 | .opn { 37 | color: #000000; 38 | } 39 | 40 | /* lisp close bracket */ 41 | .clo { 42 | color: #000000; 43 | } 44 | 45 | /* a markup tag name */ 46 | .tag { 47 | color: #8da6ce; 48 | } 49 | 50 | /* a markup attribute name */ 51 | .atn { 52 | color: #fbde2d; 53 | } 54 | 55 | /* a markup attribute value */ 56 | .atv { 57 | color: #ddd; 58 | } 59 | 60 | /* a declaration */ 61 | .dec { 62 | color: #EF5050; 63 | } 64 | 65 | /* a variable name */ 66 | .var { 67 | color: #c82829; 68 | } 69 | 70 | /* a function name */ 71 | .fun { 72 | color: #4271ae; 73 | } 74 | 75 | /* Specify class=linenums on a pre to get line numbering */ 76 | ol.linenums { 77 | margin-top: 0; 78 | margin-bottom: 0; 79 | padding-bottom: 2px; 80 | } 81 | -------------------------------------------------------------------------------- /examples/order.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.DEBUG = '*' 4 | 5 | const debug = require('debug')('bfx:api:models:examples:order') 6 | const { Order } = require('../') 7 | const o = new Order({ 8 | type: Order.type.EXCHANGE_LIMIT, 9 | symbol: 'tBTCUSD', 10 | amount: 0.05, 11 | price: 10000, 12 | hidden: true 13 | }) 14 | 15 | debug('generated ws2 compatible new order packet:') 16 | debug(JSON.stringify(o.toNewOrderPacket(), null, 2)) 17 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = require('./lib') 4 | -------------------------------------------------------------------------------- /lib/account_summary.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const arrayValidator = require('./validators/array') 5 | const objectValidator = require('./validators/object') 6 | 7 | const Model = require('./model') 8 | const fields = { 9 | trade_vol_30d: [5, 0], 10 | fees_trading_30d: [5, 1], 11 | fees_trading_total_30d: [5, 2], 12 | fees_funding_30d: [6, 1], 13 | fees_funding_total_30d: [6, 2], 14 | makerFee: [4, 0, 0], 15 | derivMakerRebate: [4, 0, 5], 16 | takerFeeToCrypto: [4, 1, 0], 17 | takerFeeToStable: [4, 1, 1], 18 | takerFeeToFiat: [4, 1, 2], 19 | derivTakerFee: [4, 1, 5], 20 | leoLev: [9, 'leo_lev'], 21 | leoAmountAvg: [9, 'leo_amount_avg'] 22 | } 23 | 24 | /** 25 | * Account Summary model 26 | */ 27 | class AccountSummary extends Model { 28 | /** 29 | * @param {object|Array} data - account summary data 30 | * @param {Array} data.trade_vol_30d - traded volume over the past 30 days detailed by currency 31 | * @param {object} data.fees_trading_30d - trading fees charged over the past 30 days detailed by currency 32 | * @param {number} data.fees_trading_total_30d - USD equivalent of the trading fees charged over the past 30 days 33 | * @param {object} data.fees_funding_30d - funding returns over the past 30 days detailed by currency 34 | * @param {number} data.fees_funding_total_30d - USD equivalent of the funding returns over the past 30 days 35 | * @param {number} data.makerFee - maker fee rate for the account 36 | * @param {number} data.derivMakerRebate - maker rebate for derivative trades on the account 37 | * @param {number} data.takerFeeToCrypto - taker fee rate for crypto to crypto trades on the account 38 | * @param {number} data.takerFeeToStable - taker fee rate for crypto to stable coin trades on the account 39 | * @param {number} data.takerFeeToFiat - taker fee rate for crypto to stable coin trades on the account 40 | * @param {number} data.derivTakerFee - taker fee rate for derivative trades on the account 41 | * @param {number} data.leoLev - current LEO discount level of the account 42 | * @param {number} data.leoAmountAvg - average amount of LEO held in the account over the past 30 days. 43 | */ 44 | constructor (data = {}) { 45 | super({ data, fields }) 46 | } 47 | 48 | /** 49 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 50 | * @returns {object} pojo 51 | */ 52 | static unserialize (data) { 53 | return super.unserialize({ data, fields }) 54 | } 55 | 56 | serialize () { 57 | const arr = super.serialize() 58 | 59 | arr[4][0][1] = this.makerFee 60 | arr[4][0][2] = this.makerFee 61 | 62 | return arr 63 | } 64 | 65 | /** 66 | * Validates a given account summary instance 67 | * 68 | * @param {object[]|object|AccountSummary[]|AccountSummary|Array} data - instance to validate 69 | * @returns {string} error - null if instance is valid 70 | */ 71 | static validate (data) { 72 | return super.validate({ 73 | data, 74 | fields, 75 | validators: { 76 | trade_vol_30d: arrayValidator, 77 | fees_trading_30d: objectValidator, 78 | fees_trading_total_30d: numberValidator, 79 | fees_funding_30d: objectValidator, 80 | fees_funding_total_30d: numberValidator, 81 | makerFee: numberValidator, 82 | derivMakerRebate: numberValidator, 83 | takerFeeToCrypto: numberValidator, 84 | takerFeeToStable: numberValidator, 85 | takerFeeToFiat: numberValidator, 86 | derivTakerFee: numberValidator, 87 | leoLev: numberValidator, 88 | leoAmountAvg: numberValidator 89 | } 90 | }) 91 | } 92 | } 93 | 94 | module.exports = AccountSummary 95 | -------------------------------------------------------------------------------- /lib/alert.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const priceValidator = require('./validators/price') 4 | const symbolValidator = require('./validators/symbol') 5 | const Model = require('./model') 6 | const fields = { 7 | key: 0, 8 | type: 1, 9 | symbol: 2, 10 | price: 3 11 | } 12 | 13 | /** 14 | * Price alert model 15 | */ 16 | class Alert extends Model { 17 | /** 18 | * @param {object|Array} data - alert data 19 | * @param {string} data.key - alert key 20 | * @param {string} data.type - alert type 21 | * @param {string} data.symbol - configured symbol 22 | * @param {string} data.price - configured price 23 | */ 24 | constructor (data = {}) { 25 | super({ data, fields }) 26 | } 27 | 28 | /** 29 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 30 | * @returns {object} pojo 31 | */ 32 | static unserialize (data) { 33 | return super.unserialize({ data, fields }) 34 | } 35 | 36 | /** 37 | * Validates a given alert instance 38 | * 39 | * TODO: validate type (get a list) 40 | * 41 | * @param {object[]|object|Alert[]|Alert|Array} data - instance to validate 42 | * @returns {string} error - null if instance is valid 43 | */ 44 | static validate (data) { 45 | return super.validate({ 46 | data, 47 | fields, 48 | validators: { 49 | price: priceValidator, 50 | symbol: symbolValidator 51 | } 52 | }) 53 | } 54 | } 55 | 56 | module.exports = Alert 57 | -------------------------------------------------------------------------------- /lib/auth_permission.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const boolValidator = require('./validators/bool') 4 | const stringValidator = require('./validators/string') 5 | const Model = require('./model') 6 | const fields = { 7 | key: 0, 8 | read: 1, 9 | write: 2 10 | } 11 | const boolFields = ['read', 'write'] 12 | 13 | /** 14 | * Auth permission model 15 | */ 16 | class AuthPermission extends Model { 17 | /** 18 | * @param {object|Array} data - auth permission data 19 | * @param {string} data.key - operation key 20 | * @param {boolean} data.read - read permission 21 | * @param {boolean} data.write - write permission 22 | */ 23 | constructor (data = {}) { 24 | super({ data, fields, boolFields }) 25 | } 26 | 27 | /** 28 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 29 | * @returns {object} pojo 30 | */ 31 | static unserialize (data) { 32 | return super.unserialize({ data, fields, boolFields }) 33 | } 34 | 35 | /** 36 | * Validates a given auth permission setting instance 37 | * 38 | * @param {object[]|object|AuthPermission[]|AuthPermission|Array} data - instance to validate 39 | * @returns {string} error - null if instance is valid 40 | */ 41 | static validate (data) { 42 | return super.validate({ 43 | data, 44 | fields, 45 | validators: { 46 | key: stringValidator, 47 | read: boolValidator, 48 | write: boolValidator 49 | } 50 | }) 51 | } 52 | } 53 | 54 | module.exports = AuthPermission 55 | -------------------------------------------------------------------------------- /lib/balance_info.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const amountValidator = require('./validators/amount') 4 | const Model = require('./model') 5 | const fields = { 6 | amount: 0, 7 | amountNet: 1 8 | } 9 | 10 | /** 11 | * Wallet balance information model 12 | */ 13 | class BalanceInfo extends Model { 14 | /** 15 | * @param {object|Array} data - balance info data 16 | * @param {number} data.amount - total balance 17 | * @param {number} data.amountNet - available balance 18 | */ 19 | constructor (data = {}) { 20 | super({ data, fields }) 21 | } 22 | 23 | /** 24 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 25 | * @returns {object} pojo 26 | */ 27 | static unserialize (data) { 28 | return super.unserialize({ data, fields }) 29 | } 30 | 31 | /** 32 | * Validates a given balance info instance 33 | * 34 | * @param {object[]|object|BalanceInfo[]|BalanceInfo|Array} data - instance 35 | * to validate 36 | * @returns {string} error - null if instance is valid 37 | */ 38 | static validate (data) { 39 | return super.validate({ 40 | data, 41 | fields, 42 | validators: { 43 | amount: amountValidator, 44 | amountNet: amountValidator 45 | } 46 | }) 47 | } 48 | } 49 | 50 | module.exports = BalanceInfo 51 | -------------------------------------------------------------------------------- /lib/candle.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const dateValidator = require('./validators/date') 5 | const Model = require('./model') 6 | const fields = { 7 | mts: 0, 8 | open: 1, 9 | close: 2, 10 | high: 3, 11 | low: 4, 12 | volume: 5 13 | } 14 | 15 | /** 16 | * OHLCV Candle model 17 | */ 18 | class Candle extends Model { 19 | /** 20 | * @param {object|Array} data - source payloud 21 | * @param {number} data.mts - timestamp 22 | * @param {number} data.open - open price 23 | * @param {number} data.close - close price 24 | * @param {number} data.high - highest price in the period 25 | * @param {number} data.low - lowest price in the period 26 | * @param {number} data.volume - total volume for the period 27 | */ 28 | constructor (data = {}) { 29 | super({ data, fields }) 30 | } 31 | 32 | /** 33 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 34 | * @returns {object} pojo 35 | */ 36 | static unserialize (data) { 37 | return super.unserialize({ data, fields }) 38 | } 39 | 40 | /** 41 | * Validates a given Candle instance 42 | * 43 | * @param {object[]|object|Candle[]|Candle|Array} data - instance to validate 44 | * @returns {string} error - null if instance is valid 45 | */ 46 | static validate (data) { 47 | return super.validate({ 48 | data, 49 | fields, 50 | validators: { 51 | mts: dateValidator, 52 | open: numberValidator, 53 | high: numberValidator, 54 | low: numberValidator, 55 | close: numberValidator, 56 | volume: numberValidator 57 | } 58 | }) 59 | } 60 | } 61 | 62 | module.exports = Candle 63 | -------------------------------------------------------------------------------- /lib/change_log.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const stringValidator = require('./validators/string') 4 | const dateValidator = require('./validators/date') 5 | const Model = require('./model') 6 | 7 | const fields = { 8 | mtsCreate: 0, 9 | log: 2, 10 | ip: 5, 11 | userAgent: 6 12 | } 13 | 14 | /** 15 | * ChangeLog model 16 | */ 17 | class ChangeLog extends Model { 18 | /** 19 | * @param {object|Array} data - log data 20 | * @param {number} data.mtsCreate - timestamp 21 | * @param {string} data.log - log data 22 | * @param {string} data.ip - ip 23 | * @param {string} data.userAgent - user agent 24 | */ 25 | constructor (data = {}) { 26 | super({ data, fields }) 27 | } 28 | 29 | /** 30 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 31 | * @returns {object} pojo 32 | */ 33 | static unserialize (data) { 34 | return super.unserialize({ data, fields }) 35 | } 36 | 37 | /** 38 | * Validates a given wallet instance 39 | * 40 | * @param {object[]|object|ChangeLog[]|ChangeLog|Array} data - instance to validate 41 | * @returns {string} error - null if instance is valid 42 | */ 43 | static validate (data) { 44 | return super.validate({ 45 | data, 46 | fields, 47 | 48 | validators: { 49 | mtsCreate: dateValidator, 50 | log: stringValidator, 51 | ip: stringValidator, 52 | userAgent: stringValidator 53 | } 54 | }) 55 | } 56 | } 57 | 58 | module.exports = ChangeLog 59 | -------------------------------------------------------------------------------- /lib/core_settings.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const Model = require('./model') 4 | const stringValidator = require('./validators/string') 5 | 6 | const fields = { 7 | key: 0, 8 | value: 1 9 | } 10 | 11 | /** 12 | * Core Settings model 13 | */ 14 | 15 | class CoreSettings extends Model { 16 | /** 17 | * @param {object|Array} data - core settings data 18 | * @param {string} data.key - settings key 19 | * @param {string | Array} [data.value] - settings value 20 | */ 21 | constructor (data = {}) { 22 | super({ data, fields }) 23 | } 24 | 25 | /** 26 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 27 | * @returns {object} pojo 28 | */ 29 | static unserialize (data) { 30 | return super.unserialize({ data, fields }) 31 | } 32 | 33 | /** 34 | * Validates a given core settings instance 35 | * 36 | * @param {object[]|object|CoreSettings[]|CoreSettings|Array} data - instance to validate 37 | * @returns {string} error - null if instance is valid 38 | */ 39 | static validate (data) { 40 | return super.validate({ 41 | data, 42 | fields, 43 | validators: { 44 | key: stringValidator 45 | } 46 | }) 47 | } 48 | } 49 | 50 | module.exports = CoreSettings 51 | -------------------------------------------------------------------------------- /lib/currency.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const stringValidator = require('./validators/string') 5 | const arrayValidator = require('./validators/array') 6 | const currencyValidator = require('./validators/currency') 7 | const Model = require('./model') 8 | 9 | const fields = { 10 | id: 0, 11 | name: 1, 12 | pool: 2, 13 | explorer: 3, 14 | symbol: 4, 15 | walletFx: 5 16 | } 17 | 18 | /** 19 | * Currency model 20 | */ 21 | class Currency extends Model { 22 | /** 23 | * @param {object|Array} data - currency data 24 | * @param {string} data.id - id 25 | * @param {string} data.name - currency name ('Ethereum') 26 | * @param {string} data.pool - pool 27 | * @param {string} data.exporer - explorer URL 28 | * @param {string} data.symbol - symbol ('ETH') 29 | */ 30 | constructor (data = {}) { 31 | super({ data, fields }) 32 | } 33 | 34 | /** 35 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 36 | * @returns {object} pojo 37 | */ 38 | static unserialize (data) { 39 | return super.unserialize({ data, fields }) 40 | } 41 | 42 | /** 43 | * Validates a given currency instance 44 | * 45 | * @param {object[]|object|Currency[]|Currency|Array} data - instance to validate 46 | * @returns {string} error - null if instance is valid 47 | */ 48 | static validate (data) { 49 | return super.validate({ 50 | data, 51 | fields, 52 | 53 | validators: { 54 | id: numberValidator, 55 | name: stringValidator, 56 | pool: stringValidator, 57 | explorer: arrayValidator, 58 | currency: currencyValidator, 59 | walletFx: arrayValidator 60 | } 61 | }) 62 | } 63 | } 64 | 65 | module.exports = Currency 66 | -------------------------------------------------------------------------------- /lib/funding_credit.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const amountValidator = require('./validators/amount') 5 | const symbolValidator = require('./validators/symbol') 6 | const stringValidator = require('./validators/string') 7 | const dateValidator = require('./validators/date') 8 | const boolValidator = require('./validators/bool') 9 | const Model = require('./model') 10 | 11 | const statuses = ['ACTIVE', 'EXECUTED', 'PARTIALLY FILLED', 'CANCELED'] 12 | const boolFields = ['notify', 'hidden', 'renew', 'noClose'] 13 | const fields = { 14 | id: 0, 15 | symbol: 1, 16 | side: 2, 17 | mtsCreate: 3, 18 | mtsUpdate: 4, 19 | amount: 5, 20 | flags: 6, 21 | status: 7, 22 | type: 8, 23 | rate: 11, 24 | period: 12, 25 | mtsOpening: 13, 26 | mtsLastPayout: 14, 27 | notify: 15, 28 | hidden: 16, 29 | renew: 18, 30 | rateReal: 19, 31 | noClose: 20, 32 | positionPair: 21 33 | } 34 | 35 | /** 36 | * Funding Credit model 37 | */ 38 | class FundingCredit extends Model { 39 | /** 40 | * @param {object|Array} data - funding credit data 41 | * @param {number} data.id - id 42 | * @param {string} data.symbol - symbol 43 | * @param {number} data.side - side 44 | * @param {number} data.mtsCreate - creation timestamp 45 | * @param {number} data.mtsUpdate - last update timestamp 46 | * @param {number} data.mtsOpening - open timestamp 47 | * @param {number} data.mtsLastPayout - last payout timestamp 48 | * @param {number} data.amount - remaining amount 49 | * @param {number} data.flags - flags 50 | * @param {number} data.status - current status 51 | * @param {number} data.rate - rate 52 | * @param {number} data.rateReal - rate 53 | * @param {number} data.period - period 54 | * @param {string} data.positionPair - position pair 55 | * @param {number|boolean} data.notify - notify flag 56 | * @param {number|boolean} data.hidden - hidden flag 57 | * @param {number|boolean} data.renew - renew flag 58 | * @param {number|boolean} data.noClose - no-close flag 59 | */ 60 | constructor (data = {}) { 61 | super({ data, fields, boolFields }) 62 | } 63 | 64 | /** 65 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 66 | * @returns {object} pojo 67 | */ 68 | static unserialize (data) { 69 | return super.unserialize({ data, fields, boolFields }) 70 | } 71 | 72 | /** 73 | * Validates a given fuding credit instance 74 | * 75 | * @param {object[]|object|FundingCredit[]|FundingCredit|Array} data - instance to validate 76 | * @returns {string} error - null if instance is valid 77 | */ 78 | static validate (data) { 79 | return super.validate({ 80 | data, 81 | fields, 82 | validators: { 83 | mtsCreate: dateValidator, 84 | mtsUpdate: dateValidator, 85 | mtsOpening: dateValidator, 86 | mtsLastPayout: dateValidator, 87 | amount: amountValidator, 88 | flags: numberValidator, 89 | rate: numberValidator, 90 | period: numberValidator, 91 | rateReal: numberValidator, 92 | notify: boolValidator, 93 | hidden: boolValidator, 94 | renew: boolValidator, 95 | noClose: boolValidator, 96 | status: stringValidator, 97 | symbol: symbolValidator, 98 | id: numberValidator 99 | } 100 | }) 101 | } 102 | } 103 | 104 | FundingCredit.status = {} 105 | statuses.forEach(s => (FundingCredit.status[s.split(' ').join('_')] = s)) 106 | 107 | module.exports = FundingCredit 108 | -------------------------------------------------------------------------------- /lib/funding_info.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _isArray = require('lodash/isArray') 4 | 5 | const numberValidator = require('./validators/number') 6 | const amountValidator = require('./validators/amount') 7 | const symbolValidator = require('./validators/symbol') 8 | const isCollection = require('./util/is_collection') 9 | const Model = require('./model') 10 | 11 | /** 12 | * Account Funding Info model 13 | */ 14 | class FundingInfo extends Model { 15 | /** 16 | * Create a new instance from a data payload 17 | * 18 | * @param {object[]|object|Array[]|Array} data - funding info data 19 | */ 20 | constructor (data) { 21 | super({ data }) 22 | } 23 | 24 | /** 25 | * Return an array representation of this model 26 | * 27 | * @returns {Array} arr 28 | */ 29 | serialize () { 30 | const { symbol, yieldLoan, yieldLend, durationLoan, durationLend } = this 31 | 32 | return [ 33 | 'sym', 34 | symbol, 35 | [ 36 | yieldLoan, 37 | yieldLend, 38 | durationLoan, 39 | durationLend 40 | ] 41 | ] 42 | } 43 | 44 | /** 45 | * TODO: Figure out a better object key for 'payload', as we need to support 46 | * both arrays and POJOs 47 | * 48 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 49 | * @returns {object} pojo 50 | */ 51 | static unserialize (data) { 52 | if (isCollection(data)) { 53 | return data.map(FundingInfo.unserialize) 54 | } 55 | 56 | const symbol = _isArray(data) ? data[1] : data.symbol 57 | const payload = (_isArray(data) ? data[2] : data.payload) || [] 58 | const [yieldLoan, yieldLend, durationLoan, durationLend] = payload 59 | 60 | return { 61 | symbol, 62 | yieldLoan, 63 | yieldLend, 64 | durationLoan, 65 | durationLend 66 | } 67 | } 68 | 69 | /** 70 | * Validates a given funding info instance 71 | * 72 | * @param {object[]|object|FundingInfo[]|FundingInfo|Array} data - instance to validate 73 | * @returns {string} error - null if instance is valid 74 | */ 75 | static validate (data) { 76 | const { symbol, yieldLoan, yieldLend, durationLoan, durationLend } = this 77 | 78 | return ( 79 | symbolValidator(symbol) || 80 | amountValidator(yieldLoan) || 81 | amountValidator(yieldLend) || 82 | numberValidator(durationLoan) || 83 | numberValidator(durationLend) 84 | ) 85 | } 86 | } 87 | 88 | module.exports = FundingInfo 89 | -------------------------------------------------------------------------------- /lib/funding_loan.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const dateValidator = require('./validators/date') 5 | const amountValidator = require('./validators/amount') 6 | const boolValidator = require('./validators/bool') 7 | const stringValidator = require('./validators/string') 8 | const symbolValidator = require('./validators/symbol') 9 | const Model = require('./model') 10 | 11 | const statuses = ['ACTIVE', 'EXECUTED', 'PARTIALLY FILLED', 'CANCELED'] 12 | const boolFields = ['notify', 'hidden', 'renew', 'noClose'] 13 | const fields = { 14 | id: 0, 15 | symbol: 1, 16 | side: 2, 17 | mtsCreate: 3, 18 | mtsUpdate: 4, 19 | amount: 5, 20 | flags: 6, 21 | status: 7, 22 | type: 8, 23 | rate: 11, 24 | period: 12, 25 | mtsOpening: 13, 26 | mtsLastPayout: 14, 27 | notify: 15, 28 | hidden: 16, 29 | renew: 18, 30 | rateReal: 19, 31 | noClose: 20 32 | } 33 | 34 | /** 35 | * Funding Loan model 36 | */ 37 | class FundingLoan extends Model { 38 | /** 39 | * @param {object|Array} data - funding loan data 40 | * @param {number} data.id - id 41 | * @param {string} data.symbol - symbol 42 | * @param {number} data.side - side 43 | * @param {number} data.mtsCreate - creation timestamp 44 | * @param {number} data.mtsUpdate - last update timestamp 45 | * @param {number} data.mtsOpening - open timestamp 46 | * @param {number} data.mtsLastPayout - last payout timestamp 47 | * @param {number} data.amount - amount 48 | * @param {number} data.flags - flags 49 | * @param {number} data.status - status 50 | * @param {number} data.rate - rate 51 | * @param {number} data.rateReal - rate real 52 | * @param {number} data.period - period flag 53 | * @param {number|boolean} data.notify - notify flag 54 | * @param {number|boolean} data.hidden - hidden flag 55 | * @param {number|boolean} data.renew - renew flag 56 | * @param {number|boolean} data.noClose - no-close flag 57 | */ 58 | constructor (data = {}) { 59 | super({ data, fields, boolFields }) 60 | } 61 | 62 | /** 63 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 64 | * @returns {object} pojo 65 | */ 66 | static unserialize (data) { 67 | return super.unserialize({ data, fields, boolFields }) 68 | } 69 | 70 | /** 71 | * Validates a given funding loan instance 72 | * 73 | * @param {object[]|object|FundingLoan[]|FundingLoan|Array} data - instance to validate 74 | * @returns {string} error - null if instance is valid 75 | */ 76 | static validate (data) { 77 | return super.validate({ 78 | data, 79 | fields, 80 | validators: { 81 | mtsCreate: dateValidator, 82 | mtsUpdate: dateValidator, 83 | mtsOpening: dateValidator, 84 | mtsLastPayout: dateValidator, 85 | amount: amountValidator, 86 | flags: numberValidator, 87 | rate: numberValidator, 88 | period: numberValidator, 89 | rateReal: numberValidator, 90 | notify: boolValidator, 91 | hidden: boolValidator, 92 | renew: boolValidator, 93 | noClose: boolValidator, 94 | status: stringValidator, 95 | symbol: symbolValidator, 96 | id: numberValidator 97 | } 98 | }) 99 | } 100 | } 101 | 102 | FundingLoan.status = {} 103 | FundingLoan.side = { 104 | LEND: 'Lend', 105 | LOAN: 'Loan' 106 | } 107 | 108 | statuses.forEach(s => (FundingLoan.status[s.split(' ').join('_')] = s)) 109 | 110 | module.exports = FundingLoan 111 | -------------------------------------------------------------------------------- /lib/funding_ticker.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const amountValidator = require('./validators/amount') 5 | const symbolValidator = require('./validators/symbol') 6 | const priceValidator = require('./validators/price') 7 | const boolValidator = require('./validators/bool') 8 | const Model = require('./model') 9 | const fields = { 10 | symbol: 0, 11 | frr: 1, 12 | bid: 2, 13 | bidSize: 3, 14 | bidPeriod: 4, 15 | ask: 5, 16 | askSize: 6, 17 | askPeriod: 7, 18 | dailyChange: 8, 19 | dailyChangePerc: 9, 20 | lastPrice: 10, 21 | volume: 11, 22 | high: 12, 23 | low: 13 24 | } 25 | 26 | /** 27 | * Funding Ticker model 28 | */ 29 | class FundingTicker extends Model { 30 | /** 31 | * @param {object|Array} data - funding ticker data 32 | * @param {string} data.symbol - symbol 33 | * @param {number|boolean} data.frr - current FRR 34 | * @param {number} data.bid - best bid 35 | * @param {number} data.bidSize - total bid amount 36 | * @param {number} data.bidPeriod - bid period 37 | * @param {number} data.ask - best ask 38 | * @param {number} data.askSize - total ask amount 39 | * @param {number} data.askPeriod - ask period 40 | * @param {number} data.dailyChange - net 24h period change 41 | * @param {number} data.dailyChangePerc - net 24h period change as percent 42 | * @param {number} data.lastPrice - last price 43 | * @param {number} data.volume - total volume in last 24h period 44 | * @param {number} data.high - highest rate in last 24h period 45 | * @param {number} data.low - lowest rate in last 24h period 46 | */ 47 | constructor (data = {}) { 48 | super({ data, fields }) 49 | } 50 | 51 | /** 52 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 53 | * @returns {object} pojo 54 | */ 55 | static unserialize (data) { 56 | return super.unserialize({ data, fields }) 57 | } 58 | 59 | /** 60 | * Get the quote currency for the ticker. 61 | * 62 | * @returns {string} quoteCurrency 63 | */ 64 | quote () { 65 | return this.symbol.substring(4) 66 | } 67 | 68 | /** 69 | * Get the base currency for the ticker. 70 | * 71 | * @returns {string} baseCurrency 72 | */ 73 | base () { 74 | return this.symbol.substring(1, 4) 75 | } 76 | 77 | /** 78 | * Validates a given funding ticker instance 79 | * 80 | * @param {object[]|object|FundingTicker[]|FundingTicker|Array} data - instance to validate 81 | * @returns {string} error - null if instance is valid 82 | */ 83 | static validate (data) { 84 | return super.validate({ 85 | data, 86 | fields, 87 | validators: { 88 | symbol: symbolValidator, 89 | frr: boolValidator, 90 | bid: priceValidator, 91 | bidSize: amountValidator, 92 | bidPeriod: numberValidator, 93 | ask: priceValidator, 94 | askSize: amountValidator, 95 | askPeriod: numberValidator, 96 | dailyChange: numberValidator, 97 | dailyChangePerc: numberValidator, 98 | lastPrice: priceValidator, 99 | volume: numberValidator, 100 | high: priceValidator, 101 | low: priceValidator 102 | } 103 | }) 104 | } 105 | } 106 | 107 | module.exports = FundingTicker 108 | -------------------------------------------------------------------------------- /lib/funding_ticker_hist.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const dateValidator = require('./validators/date') 5 | const symbolValidator = require('./validators/symbol') 6 | const priceValidator = require('./validators/price') 7 | const Model = require('./model') 8 | const fields = { 9 | symbol: 0, 10 | bid: 2, 11 | bidPeriod: 4, 12 | ask: 5, 13 | mtsUpdate: 15 14 | } 15 | 16 | /** 17 | * Historical Funding Ticker model 18 | */ 19 | class FundingTickerHist extends Model { 20 | /** 21 | * @param {object|Array} data - historical funding ticker data 22 | * @param {string} data.symbol - symbol 23 | * @param {number} data.bid - bid 24 | * @param {number} data.bidPeriod - bid period 25 | * @param {number} data.ask - ask 26 | * @param {number} data.mtsUpdate - timestamp 27 | */ 28 | constructor (data = {}) { 29 | super({ data, fields }) 30 | } 31 | 32 | /** 33 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 34 | * @returns {object} pojo 35 | */ 36 | static unserialize (data) { 37 | return super.unserialize({ data, fields }) 38 | } 39 | 40 | /** 41 | * Get the quote currency for the historical ticker. 42 | * 43 | * @returns {string} quoteCurrency 44 | */ 45 | quote () { 46 | return this.symbol.substring(4) 47 | } 48 | 49 | /** 50 | * Get the base currency for the historical ticker. 51 | * 52 | * @returns {string} baseCurrency 53 | */ 54 | base () { 55 | return this.symbol.substring(1, 4) 56 | } 57 | 58 | /** 59 | * Validates a given historical funding ticker instance. 60 | * 61 | * @param {object[]|object|FundingTickerHist[]|FundingTickerHist|Array} data - instance to validate 62 | * @returns {string} error - null if instance is valid 63 | */ 64 | static validate (data) { 65 | return super.validate({ 66 | data, 67 | fields, 68 | validators: { 69 | symbol: symbolValidator, 70 | bid: priceValidator, 71 | bidPeriod: numberValidator, 72 | ask: priceValidator, 73 | mtsUpdate: dateValidator 74 | } 75 | }) 76 | } 77 | } 78 | 79 | module.exports = FundingTickerHist 80 | -------------------------------------------------------------------------------- /lib/funding_trade.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const dateValidator = require('./validators/date') 5 | const symbolValidator = require('./validators/symbol') 6 | const priceValidator = require('./validators/price') 7 | const amountValidator = require('./validators/amount') 8 | const boolValidator = require('./validators/bool') 9 | const _isUndefined = require('lodash/isUndefined') 10 | const _flatten = require('lodash/flatten') 11 | const _compact = require('lodash/compact') 12 | const Model = require('./model') 13 | const fields = { 14 | id: 0, 15 | symbol: 1, 16 | mtsCreate: 2, 17 | offerID: 3, 18 | amount: 4, 19 | rate: 5, 20 | period: 6, 21 | maker: 7 22 | } 23 | 24 | /** 25 | * Funding Trade model 26 | */ 27 | class FundingTrade extends Model { 28 | /** 29 | * @param {object|Array} data - funding trade data 30 | * @param {number} data.id - id 31 | * @param {string} data.symbol - symbol 32 | * @param {number} data.mtsCreate - creation timestamp 33 | * @param {number} data.offerID - taken offer ID 34 | * @param {number} data.amount - amount 35 | * @param {number} data.rate - rate 36 | * @param {number} data.period - period 37 | * @param {number|boolean} data.maker - maker flag 38 | */ 39 | constructor (data = {}) { 40 | super({ data, fields }) 41 | } 42 | 43 | /** 44 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 45 | * @returns {object} pojo 46 | */ 47 | static unserialize (data) { 48 | return super.unserialize({ data, fields }) 49 | } 50 | 51 | /** 52 | * Returns a string representation of the model, containing pertinent 53 | * information. 54 | * 55 | * @returns {string} str 56 | */ 57 | toString () { 58 | const { 59 | id, symbol, mtsCreate, amount, rate, period, maker 60 | } = this 61 | 62 | return _compact(_flatten([ 63 | `(${id})`, 64 | symbol, 65 | new Date(mtsCreate).toLocaleString(), 66 | [amount, '@', rate], 67 | ['period', period], 68 | !_isUndefined(maker) && maker ? 'maker' : 'taker' 69 | ])).join(' ') 70 | } 71 | 72 | /** 73 | * Validates a given funding trade instance 74 | * 75 | * @param {object[]|object|FundingTrade[]|FundingTrade|Array} data - instance to validate 76 | * @returns {string} error - null if instance is valid 77 | */ 78 | static validate (data) { 79 | return super.validate({ 80 | data, 81 | fields, 82 | validators: { 83 | id: numberValidator, 84 | symbol: symbolValidator, 85 | mtsCreate: dateValidator, 86 | offerID: numberValidator, 87 | amount: amountValidator, 88 | rate: priceValidator, 89 | period: numberValidator, 90 | maker: boolValidator 91 | } 92 | }) 93 | } 94 | } 95 | 96 | module.exports = FundingTrade 97 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = { 4 | OrderBook: require('./order_book'), 5 | BalanceInfo: require('./balance_info'), 6 | FundingCredit: require('./funding_credit'), 7 | FundingInfo: require('./funding_info'), 8 | FundingLoan: require('./funding_loan'), 9 | FundingOffer: require('./funding_offer'), 10 | FundingTrade: require('./funding_trade'), 11 | MarginInfo: require('./margin_info'), 12 | Notification: require('./notification'), 13 | Order: require('./order'), 14 | Position: require('./position'), 15 | Trade: require('./trade'), 16 | Wallet: require('./wallet'), 17 | WalletHist: require('./wallet_hist'), 18 | Alert: require('./alert'), 19 | TradingTicker: require('./trading_ticker'), 20 | TradingTickerHist: require('./trading_ticker_hist'), 21 | FundingTicker: require('./funding_ticker'), 22 | FundingTickerHist: require('./funding_ticker_hist'), 23 | PublicTrade: require('./public_trade'), 24 | Candle: require('./candle'), 25 | LedgerEntry: require('./ledger_entry'), 26 | Liquidations: require('./liquidations'), 27 | Movement: require('./movement'), 28 | MovementInfo: require('./movement_info'), 29 | UserInfo: require('./user_info'), 30 | Currency: require('./currency'), 31 | StatusMessagesDeriv: require('./status_messages_deriv'), 32 | Login: require('./login'), 33 | ChangeLog: require('./change_log'), 34 | Invoice: require('./invoice'), 35 | SymbolDetails: require('./symbol_details'), 36 | TransactionFee: require('./transaction_fee'), 37 | AccountSummary: require('./account_summary'), 38 | AuthPermission: require('./auth_permission'), 39 | CoreSettings: require('./core_settings'), 40 | WeightedAverages: require('./weighted_averages'), 41 | 42 | isCollection: require('./util/is_collection') 43 | } 44 | -------------------------------------------------------------------------------- /lib/invoice.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const stringValidator = require('./validators/string') 4 | const Model = require('./model') 5 | 6 | const fields = { 7 | invoiceHash: 0, 8 | invoice: 1, 9 | // PLACEHOLDER 10 | // PLACEHOLDER 11 | amount: 4 12 | } 13 | 14 | /** 15 | * Deposit Invoice model 16 | */ 17 | class Invoice extends Model { 18 | /** 19 | * @param {object|Array} data - deposit invoice 20 | * @param {string} data.invoiceHash - Hashed invoice 21 | * @param {string} data.invoice - Requested invoice 22 | * @param {string} data.amount - Amount of invoice 23 | */ 24 | constructor (data = {}) { 25 | super({ data, fields }) 26 | } 27 | 28 | /** 29 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 30 | * @returns {object} pojo 31 | */ 32 | static unserialize (data) { 33 | return super.unserialize({ data, fields }) 34 | } 35 | 36 | /** 37 | * @returns {string} str 38 | */ 39 | toString () { 40 | const { invoiceHash, invoice, amount } = this 41 | 42 | return [ 43 | `amount: ${amount}`, 44 | `invoice: ${invoice}`, 45 | `invoiceHash: ${invoiceHash}` 46 | ].join(' ') 47 | } 48 | 49 | /** 50 | * Validates a given invoice instance 51 | * 52 | * @param {object[]|object|Invoice[]|Invoice|Array} data - instance to validate 53 | * @returns {string} error - null if instance is valid 54 | */ 55 | static validate (data) { 56 | return super.validate({ 57 | data, 58 | fields, 59 | validators: { 60 | invoiceHash: stringValidator, 61 | invoice: stringValidator, 62 | amount: stringValidator 63 | } 64 | }) 65 | } 66 | } 67 | 68 | module.exports = Invoice 69 | -------------------------------------------------------------------------------- /lib/ledger_entry.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const dateValidator = require('./validators/date') 5 | const amountValidator = require('./validators/amount') 6 | const currencyValidator = require('./validators/currency') 7 | const stringValidator = require('./validators/string') 8 | const _isString = require('lodash/isString') 9 | const _isEmpty = require('lodash/isEmpty') 10 | 11 | const Model = require('./model') 12 | const fields = { 13 | id: 0, 14 | currency: 1, 15 | mts: 3, 16 | amount: 5, 17 | balance: 6, 18 | description: 8, 19 | wallet: null 20 | } 21 | 22 | /** 23 | * Ledger Entry model; wallet field is automatically populated if a description 24 | * is provided. 25 | */ 26 | class LedgerEntry extends Model { 27 | /** 28 | * @param {object|Array} data - ledger entry data 29 | * @param {number} data.id - id 30 | * @param {string} data.currency - currency 31 | * @param {number} data.mts - transaction timestamp 32 | * @param {number} data.amount - transaction amount 33 | * @param {number} data.balance - balance at time of transaction 34 | * @param {string} data.description - transaction description 35 | */ 36 | constructor (data = {}) { 37 | super({ data, fields }) 38 | 39 | this.wallet = null 40 | 41 | if (_isString(this.description) && !_isEmpty(this.description)) { 42 | const spl = this.description.split('wallet') 43 | this.wallet = (spl && spl.length > 1) ? spl[spl.length - 1].trim() : null 44 | } 45 | } 46 | 47 | /** 48 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 49 | * @returns {object} pojo 50 | */ 51 | static unserialize (data) { 52 | return super.unserialize({ data, fields }) 53 | } 54 | 55 | /** 56 | * Validates a given ledger entry instance 57 | * 58 | * @param {object[]|object|LedgerEntry[]|LedgerEntry|Array} data - instance to validate 59 | * @returns {string} error - null if instance is valid 60 | */ 61 | static validate (data) { 62 | return super.validate({ 63 | data, 64 | fields, 65 | validators: { 66 | id: numberValidator, 67 | currency: currencyValidator, 68 | mts: dateValidator, 69 | amount: amountValidator, 70 | balance: amountValidator, 71 | description: stringValidator 72 | } 73 | }) 74 | } 75 | } 76 | 77 | module.exports = LedgerEntry 78 | -------------------------------------------------------------------------------- /lib/liquidations.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const dateValidator = require('./validators/date') 5 | const amountValidator = require('./validators/amount') 6 | const symbolValidator = require('./validators/symbol') 7 | const priceValidator = require('./validators/price') 8 | const boolValidator = require('./validators/bool') 9 | const _flatten = require('lodash/flatten') 10 | const _compact = require('lodash/compact') 11 | const Model = require('./model') 12 | const fields = { 13 | posId: 1, 14 | mtsUpdated: 2, 15 | symbol: 4, 16 | amount: 5, 17 | basePrice: 6, 18 | isMatch: 8, 19 | isMarketSold: 9 20 | } 21 | 22 | /** 23 | * Liquidation Info model 24 | */ 25 | class Liquidations extends Model { 26 | /** 27 | * @param {object|Array} data - liquidation data 28 | * @param {number} data.posId - position ID 29 | * @param {number} data.mtsUpdated - timestamp 30 | * @param {string} data.symbol - symbol 31 | * @param {number} data.amount - amount 32 | * @param {number} data.basePrice - base price 33 | * @param {number|boolean} data.isMatch - matched flag 34 | * @param {number|boolean} data.isMarketSold - sold flag 35 | */ 36 | constructor (data = {}) { 37 | super({ data, fields }) 38 | } 39 | 40 | /** 41 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 42 | * @returns {object} pojo 43 | */ 44 | static unserialize (data) { 45 | return super.unserialize({ data, fields }) 46 | } 47 | 48 | /** 49 | * @returns {string} str 50 | */ 51 | toString () { 52 | const { 53 | mtsUpdated, symbol, amount, basePrice, isMatch, isMarketSold 54 | } = this 55 | 56 | return _compact(_flatten([ 57 | new Date(mtsUpdated).toLocaleString(), 58 | symbol, 59 | [amount, '@', basePrice], 60 | isMatch && 'matched', 61 | isMarketSold && 'sold' 62 | ])).join(' ') 63 | } 64 | 65 | /** 66 | * Validates a given liquidation instance 67 | * 68 | * @param {object[]|object|Liquidations[]|Liquidations|Array} data - instance to validate 69 | * @returns {string} error - null if instance is valid 70 | */ 71 | static validate (data) { 72 | return super.validate({ 73 | data, 74 | fields, 75 | validators: { 76 | posId: numberValidator, 77 | mtsUpdated: dateValidator, 78 | symbol: symbolValidator, 79 | amount: amountValidator, 80 | basePrice: priceValidator, 81 | isMatch: boolValidator, 82 | isMarketSold: boolValidator 83 | } 84 | }) 85 | } 86 | } 87 | 88 | module.exports = Liquidations 89 | -------------------------------------------------------------------------------- /lib/login.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const dateValidator = require('./validators/date') 5 | const stringValidator = require('./validators/string') 6 | const Model = require('./model') 7 | const fields = { 8 | id: 0, 9 | time: 2, 10 | ip: 4, 11 | extraData: 7 12 | } 13 | 14 | /** 15 | * Login event model 16 | */ 17 | class Login extends Model { 18 | /** 19 | * @param {object|Array} data - login event data 20 | * @param {number} data.id - id 21 | * @param {number} data.time - timestamp 22 | * @param {string} data.ip - client IP address 23 | * @param {object} data.extraData - metadata 24 | */ 25 | constructor (data = {}) { 26 | super({ data, fields }) 27 | } 28 | 29 | /** 30 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 31 | * @returns {object} pojo 32 | */ 33 | static unserialize (data) { 34 | return super.unserialize({ data, fields }) 35 | } 36 | 37 | /** 38 | * Validates a given login instance 39 | * 40 | * @param {object[]|object|Login[]|Login|Array} data - instance to validate 41 | * @returns {string} error - null if instance is valid 42 | */ 43 | static validate (data) { 44 | return super.validate({ 45 | data, 46 | fields, 47 | validators: { 48 | id: numberValidator, 49 | time: dateValidator, 50 | ip: stringValidator 51 | } 52 | }) 53 | } 54 | } 55 | 56 | module.exports = Login 57 | -------------------------------------------------------------------------------- /lib/margin_info.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _isArray = require('lodash/isArray') 4 | 5 | const numberValidator = require('./validators/number') 6 | const amountValidator = require('./validators/amount') 7 | const symbolValidator = require('./validators/symbol') 8 | const stringValidator = require('./validators/string') 9 | const isCollection = require('./util/is_collection') 10 | const Model = require('./model') 11 | 12 | /** 13 | * Margin Info model 14 | */ 15 | class MarginInfo extends Model { 16 | /** 17 | * Create a new instance from a data payload 18 | * 19 | * @param {object[]|object|Array[]|Array} data - margin info data 20 | */ 21 | constructor (data) { 22 | super({ data }) 23 | } 24 | 25 | /** 26 | * Return an array representation of this model 27 | * 28 | * @returns {Array} arr 29 | */ 30 | serialize () { 31 | const { type } = this 32 | 33 | if (type === 'base') { 34 | const { userPL, userSwaps, marginBalance, marginNet } = this 35 | 36 | return [ 37 | type, 38 | [ 39 | userPL, 40 | userSwaps, 41 | marginBalance, 42 | marginNet 43 | ] 44 | ] 45 | } 46 | 47 | const { symbol, tradableBalance, grossBalance, buy, sell } = this 48 | 49 | return [ 50 | type, 51 | symbol, 52 | [ 53 | tradableBalance, 54 | grossBalance, 55 | buy, 56 | sell 57 | ] 58 | ] 59 | } 60 | 61 | /** 62 | * TODO: Figure out a better object key for 'payload', as we need to support 63 | * both arrays and POJOs 64 | * 65 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 66 | * @returns {object} pojo 67 | */ 68 | static unserialize (data) { 69 | if (isCollection(data)) { 70 | return data.map(MarginInfo.unserialize) 71 | } 72 | 73 | const type = _isArray(data) ? data[0] : data.type 74 | 75 | if (type === 'base') { 76 | const payload = (_isArray(data) ? data[1] : data.payload) || [] 77 | const [userPL, userSwaps, marginBalance, marginNet] = payload 78 | 79 | return { 80 | type, 81 | userPL, 82 | userSwaps, 83 | marginBalance, 84 | marginNet 85 | } 86 | } 87 | 88 | const symbol = _isArray(data) ? data[1] : data.symbol 89 | const payload = (_isArray(data) ? data[2] : data.payload) || [] 90 | const [tradableBalance, grossBalance, buy, sell] = payload 91 | 92 | return { 93 | type, 94 | symbol, 95 | tradableBalance, 96 | grossBalance, 97 | buy, 98 | sell 99 | } 100 | } 101 | 102 | /** 103 | * Validates a given margin info instance 104 | * 105 | * @param {object[]|object|MarginInfo[]|MarginInfo|Array} data - instance to validate 106 | * @returns {string} error - null if instance is valid 107 | */ 108 | static validate (data) { 109 | const { type, symbol, tradableBalance, grossBalance, buy, sell } = this 110 | 111 | return ( 112 | stringValidator(type) || 113 | symbolValidator(symbol) || 114 | amountValidator(tradableBalance) || 115 | amountValidator(grossBalance) || 116 | numberValidator(buy) || 117 | numberValidator(sell) 118 | ) 119 | } 120 | } 121 | 122 | module.exports = MarginInfo 123 | -------------------------------------------------------------------------------- /lib/movement.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const dateValidator = require('./validators/date') 5 | const amountValidator = require('./validators/amount') 6 | const currencyValidator = require('./validators/currency') 7 | const stringValidator = require('./validators/string') 8 | const Model = require('./model') 9 | const fields = { 10 | id: 0, 11 | currency: 1, 12 | currencyName: 2, 13 | mtsStarted: 5, 14 | mtsUpdated: 6, 15 | status: 9, 16 | amount: 12, 17 | fees: 13, 18 | destinationAddress: 16, 19 | transactionId: 20, 20 | note: 21 21 | } 22 | 23 | /** 24 | * Currency Movement model 25 | */ 26 | class Movement extends Model { 27 | /** 28 | * @param {object|Array} data - movement data 29 | * @param {number} data.id - id 30 | * @param {string} data.currency - currency 31 | * @param {string} data.currencyName - currency name 32 | * @param {number} data.mtsStarted - movement start timestamp 33 | * @param {number} data.mtsUpdated - last update timestamp 34 | * @param {string} data.status - status 35 | * @param {number} data.amount - moved amount 36 | * @param {number} data.fees - paid fees 37 | * @param {string} data.destinationAddress - destination address 38 | * @param {number} data.transactionId - transaction ID 39 | * @param {string} data.note - note 40 | */ 41 | constructor (data = {}) { 42 | super({ data, fields }) 43 | } 44 | 45 | /** 46 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 47 | * @returns {object} pojo 48 | */ 49 | static unserialize (data) { 50 | return super.unserialize({ data, fields }) 51 | } 52 | 53 | /** 54 | * Validates a given movement instance 55 | * 56 | * @param {object[]|object|Movement[]|Movement|Array} data - instance to validate 57 | * @returns {string} error - null if instance is valid 58 | */ 59 | static validate (data) { 60 | return super.validate({ 61 | data, 62 | fields, 63 | validators: { 64 | id: numberValidator, 65 | currency: currencyValidator, 66 | currencyName: stringValidator, 67 | mtsStarted: dateValidator, 68 | mtsUpdated: dateValidator, 69 | status: stringValidator, 70 | amount: amountValidator, 71 | fees: numberValidator, 72 | destinationAddress: stringValidator, 73 | transactionId: stringValidator, 74 | note: stringValidator 75 | } 76 | }) 77 | } 78 | } 79 | 80 | module.exports = Movement 81 | -------------------------------------------------------------------------------- /lib/movement_info.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const dateValidator = require('./validators/date') 5 | const amountValidator = require('./validators/amount') 6 | const currencyValidator = require('./validators/currency') 7 | const stringValidator = require('./validators/string') 8 | const objectValidator = require('./validators/object') 9 | const Model = require('./model') 10 | const fields = { 11 | id: 0, 12 | currency: 1, 13 | currencyName: 2, 14 | remark: 4, 15 | mtsStarted: 5, 16 | mtsUpdated: 6, 17 | status: 9, 18 | amount: 12, 19 | fees: 13, 20 | destinationAddress: 16, 21 | memo: 17, 22 | transactionId: 20, 23 | note: 21, 24 | bankFees: 24, 25 | bankRouterId: 25, 26 | externalBankMovId: 28, 27 | externalBankMovStatus: 29, 28 | externalBankMovDescription: 30, 29 | externalBankAccInfo: 31 30 | } 31 | 32 | /** 33 | * Currency Movement Info model 34 | */ 35 | class MovementInfo extends Model { 36 | /** 37 | * @param {object|Array} data - movement data 38 | * @param {number} data.id - id 39 | * @param {string} data.currency - currency 40 | * @param {string} data.currencyName - currency name 41 | * @param {string} data.remark - remarks related to movement 42 | * @param {number} data.mtsStarted - movement start timestamp 43 | * @param {number} data.mtsUpdated - last update timestamp 44 | * @param {string} data.status - status 45 | * @param {number} data.amount - moved amount 46 | * @param {number} data.fees - paid fees 47 | * @param {string} data.destinationAddress - destination address 48 | * @param {string} data.memo - memo/tag related to transaction 49 | * @param {string} data.transactionId - transaction ID 50 | * @param {string} data.note - transaction note 51 | * @param {number} data.bankFees - wire bank fees 52 | * @param {number} data.bankRouterId - identifier of bank router 53 | * @param {string} data.externalBankMovId - external provider movement id 54 | * @param {string} data.externalBankMovStatus - external provider movement status 55 | * @param {string} data.externalBankMovDescription - external provider movement info 56 | * @param {object} data.externalBankAccInfo - external provider bank account information for user 57 | */ 58 | constructor (data = {}) { 59 | super({ data, fields }) 60 | } 61 | 62 | /** 63 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 64 | * @returns {object} pojo 65 | */ 66 | static unserialize (data) { 67 | return super.unserialize({ data, fields }) 68 | } 69 | 70 | /** 71 | * Validates a given MovementInfo instance 72 | * 73 | * @param {object[]|object|MovementInfo[]|MovementInfo|Array} data - instance to validate 74 | * @returns {string} error - null if instance is valid 75 | */ 76 | static validate (data) { 77 | return super.validate({ 78 | data, 79 | fields, 80 | validators: { 81 | id: numberValidator, 82 | currency: currencyValidator, 83 | currencyName: stringValidator, 84 | remark: stringValidator, 85 | mtsStarted: dateValidator, 86 | mtsUpdated: dateValidator, 87 | status: stringValidator, 88 | amount: amountValidator, 89 | fees: numberValidator, 90 | destinationAddress: stringValidator, 91 | memo: stringValidator, 92 | transactionId: stringValidator, 93 | note: stringValidator, 94 | bankFees: numberValidator, 95 | bankRouterId: numberValidator, 96 | externalBankMovId: stringValidator, 97 | externalBankMovStatus: stringValidator, 98 | externalBankMovDescription: stringValidator, 99 | externalBankAccInfo: objectValidator 100 | } 101 | }) 102 | } 103 | } 104 | 105 | module.exports = MovementInfo 106 | -------------------------------------------------------------------------------- /lib/notification.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const dateValidator = require('./validators/date') 5 | const stringValidator = require('./validators/string') 6 | const Model = require('./model') 7 | const fields = { 8 | mts: 0, 9 | type: 1, 10 | messageID: 2, 11 | notifyInfo: 4, 12 | code: 5, 13 | status: 6, 14 | text: 7 15 | } 16 | 17 | /** 18 | * Notification model 19 | */ 20 | class Notification extends Model { 21 | /** 22 | * @param {object|Array} data - notification data 23 | * @param {number} data.mts - timestamp 24 | * @param {string} data.type - type (i.e. 'ucm-*' for broadcasts) 25 | * @param {number} data.messageID - message ID 26 | * @param {object} data.notifyInfo - metadata, set by client for broadcasts 27 | * @param {number} data.code - code 28 | * @param {string} data.status - status (i.e. 'error') 29 | * @param {string} data.text - notification text to display to user 30 | */ 31 | constructor (data = {}) { 32 | super({ data, fields }) 33 | } 34 | 35 | /** 36 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 37 | * @returns {object} pojo 38 | */ 39 | static unserialize (data) { 40 | return super.unserialize({ data, fields }) 41 | } 42 | 43 | /** 44 | * Validates a given notification instance 45 | * 46 | * @param {object[]|object|Notification[]|Notification|Array} data - instance to validate 47 | * @returns {string} error - null if instance is valid 48 | */ 49 | static validate (data) { 50 | return super.validate({ 51 | data, 52 | fields, 53 | validators: { 54 | mts: dateValidator, 55 | type: stringValidator, 56 | messageID: numberValidator, 57 | code: numberValidator, 58 | status: stringValidator, 59 | text: stringValidator 60 | } 61 | }) 62 | } 63 | } 64 | 65 | module.exports = Notification 66 | -------------------------------------------------------------------------------- /lib/public_trade.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _flatten = require('lodash/flatten') 4 | const _isArray = require('lodash/isArray') 5 | const _isObject = require('lodash/isObject') 6 | const _isFinite = require('lodash/isFinite') 7 | 8 | const numberValidator = require('./validators/number') 9 | const dateValidator = require('./validators/date') 10 | const amountValidator = require('./validators/amount') 11 | const priceValidator = require('./validators/price') 12 | const Model = require('./model') 13 | 14 | const TRADING_FIELDS = { 15 | id: 0, 16 | mts: 1, 17 | amount: 2, 18 | price: 3 19 | } 20 | 21 | const FUNDING_FIELDS = { 22 | id: 0, 23 | mts: 1, 24 | amount: 2, 25 | rate: 3, 26 | period: 4 27 | } 28 | 29 | /** 30 | * Public Trade model, supporting both funding & ordinary trades 31 | */ 32 | class PublicTrade extends Model { 33 | /** 34 | * @param {object|Array} data - public trade data 35 | */ 36 | constructor (data = {}) { 37 | if (_isArray(data)) { 38 | if (data.length === 5) { 39 | super({ data, fields: FUNDING_FIELDS }) 40 | } else { 41 | super({ data, fields: TRADING_FIELDS }) 42 | } 43 | } else if (_isObject(data)) { 44 | if (data.rate) { 45 | super({ data, fields: FUNDING_FIELDS }) 46 | } else { 47 | super({ data, fields: TRADING_FIELDS }) 48 | } 49 | } else { 50 | throw new Error('unknown data type') 51 | } 52 | } 53 | 54 | /** 55 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 56 | * @returns {object} pojo 57 | */ 58 | static unserialize (data) { 59 | if ((_isArray(data[0]) && data[0].length === 5) || (_isObject(data[0]) && data[0].rate) || data.length === 5) { 60 | return super.unserialize({ data, fields: FUNDING_FIELDS }) 61 | } else { 62 | return super.unserialize({ data, fields: TRADING_FIELDS }) 63 | } 64 | } 65 | 66 | /** 67 | * @returns {string} str 68 | */ 69 | toString () { 70 | const { id, mts, amount, price } = this 71 | 72 | return _flatten([ 73 | `(${id})`, 74 | new Date(mts).toLocaleString(), 75 | [amount, '@', price] 76 | ]).join(' ') 77 | } 78 | 79 | /** 80 | * Validates a given public trade instance 81 | * 82 | * @param {object[]|object|PublicTrade[]|PublicTrade|Array} data - instance to validate 83 | * @returns {string} error - null if instance is valid 84 | */ 85 | static validate (data) { 86 | const { rate } = data 87 | 88 | return super.validate({ 89 | data, 90 | fields: _isFinite(rate) ? FUNDING_FIELDS : TRADING_FIELDS, 91 | validators: _isFinite(rate) 92 | ? { 93 | id: numberValidator, 94 | mts: dateValidator, 95 | amount: amountValidator, 96 | rate: priceValidator, 97 | period: numberValidator 98 | } 99 | : { 100 | id: numberValidator, 101 | mts: dateValidator, 102 | amount: amountValidator, 103 | price: priceValidator 104 | } 105 | }) 106 | } 107 | } 108 | 109 | module.exports = PublicTrade 110 | module.exports.TRADING_FIELDS = TRADING_FIELDS 111 | module.exports.FUNDING_FIELDS = FUNDING_FIELDS 112 | -------------------------------------------------------------------------------- /lib/status_messages_deriv.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const stringValidator = require('./validators/string') 4 | const priceValidator = require('./validators/price') 5 | const Model = require('./model') 6 | 7 | const fields = { 8 | key: 0, 9 | timestamp: 1, 10 | price: 3, 11 | priceSpot: 4, 12 | fundBal: 6, 13 | fundingAccrued: 9, 14 | fundingStep: 10, 15 | clampMin: 22, 16 | clampMax: 23 17 | } 18 | 19 | /** 20 | * Derivatives Status Message model 21 | */ 22 | class StatusMessagesDeriv extends Model { 23 | /** 24 | * @param {object|Array} data - derivatives status message data 25 | * @param {string} data.key - key 26 | * @param {number} data.timestamp - timestamp 27 | * @param {string} data.price - price 28 | * @param {string} data.priceSpot - spot price 29 | * @param {string} data.fundBal - funding balance 30 | * @param {string} data.fundingAccrued - accrued funding 31 | * @param {string} data.fundingStep - funding step 32 | * @param {number} data.clampMin - min clamp 33 | * @param {number} data.clampMax - max clamp 34 | */ 35 | constructor (data = {}) { 36 | super({ data, fields }) 37 | } 38 | 39 | /** 40 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 41 | * @returns {object} pojo 42 | */ 43 | static unserialize (data) { 44 | return super.unserialize({ data, fields }) 45 | } 46 | 47 | /** 48 | * Validates a given public trade instance 49 | * 50 | * @param {object[]|object|PublicTrade[]|PublicTrade|Array} data - instance to validate 51 | * @returns {string} error - null if instance is valid 52 | */ 53 | static validate (data) { 54 | return super.validate({ 55 | data, 56 | fields, 57 | validators: { 58 | key: stringValidator, 59 | timestamp: stringValidator, 60 | price: priceValidator, 61 | priceSpot: priceValidator, 62 | fundBal: priceValidator, 63 | fundingAccrued: priceValidator, 64 | fundingStep: priceValidator, 65 | clampMin: priceValidator, 66 | clampMax: priceValidator 67 | } 68 | }) 69 | } 70 | } 71 | 72 | module.exports = StatusMessagesDeriv 73 | -------------------------------------------------------------------------------- /lib/symbol_details.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const isNil = require('lodash/isNil') 4 | const numberValidator = require('./validators/number') 5 | const stringValidator = require('./validators/string') 6 | const Model = require('./model') 7 | const fields = { 8 | pair: 0, 9 | initialMargin: [1, 8], 10 | minimumMargin: [1, 9], 11 | maximumOrderSize: [1, 4], 12 | minimumOrderSize: [1, 3] 13 | } 14 | 15 | /** 16 | * Symbol Details model 17 | */ 18 | class SymbolDetails extends Model { 19 | /** 20 | * @param {object|Array} data - symbol details data 21 | * @param {string} data.pair - pairs 22 | * @param {number} data.initialMargin - inital margin 23 | * @param {number} data.minimumMargin - minimum margin 24 | * @param {string} data.maximumOrderSize - maximum order size 25 | * @param {string} data.minimumOrderSize - minimum order size 26 | * @param {boolean} data.margin - flag specifying if margin trading supported for pair 27 | */ 28 | constructor (data = {}) { 29 | super({ data, fields }) 30 | } 31 | 32 | /** 33 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 34 | * @returns {object} pojo 35 | */ 36 | static unserialize (data) { 37 | const obj = super.unserialize({ data, fields }) 38 | obj.margin = !isNil(obj.initialMargin) && !isNil(obj.minimumMargin) 39 | 40 | return obj 41 | } 42 | 43 | /** 44 | * Validates a given symbol details instance 45 | * 46 | * @param {object[]|object|SymbolDetails[]|SymbolDetails|Array} data - instance to validate 47 | * @returns {string} error - null if instance is valid 48 | */ 49 | static validate (data) { 50 | return super.validate({ 51 | data, 52 | fields, 53 | validators: { 54 | pair: stringValidator, 55 | initialMargin: numberValidator, 56 | minimumMargin: numberValidator, 57 | maximumOrderSize: stringValidator, 58 | minimumOrderSize: stringValidator 59 | } 60 | }) 61 | } 62 | } 63 | 64 | module.exports = SymbolDetails 65 | -------------------------------------------------------------------------------- /lib/trade.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _isUndefined = require('lodash/isUndefined') 4 | const _isFinite = require('lodash/isFinite') 5 | const _flatten = require('lodash/flatten') 6 | const _compact = require('lodash/compact') 7 | 8 | const numberValidator = require('./validators/number') 9 | const dateValidator = require('./validators/date') 10 | const amountValidator = require('./validators/amount') 11 | const currencyValidator = require('./validators/currency') 12 | const stringValidator = require('./validators/string') 13 | const priceValidator = require('./validators/price') 14 | const boolValidator = require('./validators/bool') 15 | const symbolValidator = require('./validators/symbol') 16 | const Order = require('./order') 17 | const Model = require('./model') 18 | 19 | const boolFields = ['maker'] 20 | const fields = { 21 | id: 0, 22 | symbol: 1, 23 | mtsCreate: 2, 24 | orderID: 3, 25 | execAmount: 4, 26 | execPrice: 5, 27 | orderType: 6, 28 | orderPrice: 7, 29 | maker: 8, 30 | fee: 9, 31 | feeCurrency: 10 32 | } 33 | 34 | /** 35 | * Private Trade model 36 | */ 37 | class Trade extends Model { 38 | /** 39 | * @param {object|Array} data - trade data 40 | * @param {number} data.id - id 41 | * @param {string} data.symbol - symbol 42 | * @param {number} data.mtsCreate - creation timestamp 43 | * @param {number} data.orderID - order ID 44 | * @param {string} data.execAmount - executed amount 45 | * @param {string} data.execPrice - execution price 46 | * @param {string} data.orderType - order type 47 | * @param {string} data.orderPrice - order price 48 | * @param {number|boolean} data.maker - maker flag 49 | * @param {string} data.fee - fee amount 50 | * @param {string} data.feeCurrency - fee currency 51 | */ 52 | constructor (data = {}) { 53 | super({ data, fields, boolFields }) 54 | } 55 | 56 | /** 57 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 58 | * @returns {object} pojo 59 | */ 60 | static unserialize (data) { 61 | return super.unserialize({ data, fields, boolFields }) 62 | } 63 | 64 | /** 65 | * @returns {string} str 66 | */ 67 | toString () { 68 | const { 69 | id, symbol, mtsCreate, execAmount, execPrice, maker, fee, feeCurrency 70 | } = this 71 | 72 | return _compact(_flatten([ 73 | `(${id})`, 74 | symbol, 75 | new Date(mtsCreate).toLocaleString(), 76 | [execAmount, '@', execPrice], 77 | (!_isUndefined(maker)) && maker ? 'maker' : 'taker', 78 | _isFinite(fee) && [fee, feeCurrency] 79 | ])).join(' ') 80 | } 81 | 82 | /** 83 | * Validates a given trade instance 84 | * 85 | * @param {object[]|object|PublicTrade[]|PublicTrade|Array} data - instance to validate 86 | * @returns {string} error - null if instance is valid 87 | */ 88 | static validate (data) { 89 | return super.validate({ 90 | data, 91 | fields, 92 | validators: { 93 | id: numberValidator, 94 | symbol: symbolValidator, 95 | mtsCreate: dateValidator, 96 | orderID: stringValidator, 97 | execAmount: amountValidator, 98 | execPrice: priceValidator, 99 | orderType: v => stringValidator(v, Object.values(Order.type)), 100 | orderPrice: priceValidator, 101 | maker: boolValidator, 102 | fee: numberValidator, 103 | feeCurrency: currencyValidator 104 | } 105 | }) 106 | } 107 | } 108 | 109 | module.exports = Trade 110 | -------------------------------------------------------------------------------- /lib/trading_ticker.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const amountValidator = require('./validators/amount') 5 | const priceValidator = require('./validators/price') 6 | const symbolValidator = require('./validators/symbol') 7 | const Model = require('./model') 8 | const fields = { 9 | symbol: 0, 10 | bid: 1, 11 | bidSize: 2, 12 | ask: 3, 13 | askSize: 4, 14 | dailyChange: 5, 15 | dailyChangePerc: 6, 16 | lastPrice: 7, 17 | volume: 8, 18 | high: 9, 19 | low: 10 20 | } 21 | 22 | /** 23 | * Trading Ticker model 24 | */ 25 | class TradingTicker extends Model { 26 | /** 27 | * @param {object|Array} data - trading ticker data 28 | * @param {string} data.symbol - symbol 29 | * @param {number} data.bid - best bid 30 | * @param {number} data.bidSize - total bid size 31 | * @param {number} data.ask - best ask 32 | * @param {number} data.askSize - total ask size 33 | * @param {number} data.dailyChange - change in last 24h period 34 | * @param {number} data.dailyChangePerc - change in last 24h period as percent 35 | * @param {number} data.lastPrice - last price 36 | * @param {number} data.volume - volume in last 24h period 37 | * @param {number} data.high - highest price in last 24h period 38 | * @param {number} data.low - lowest price in last 24h period 39 | */ 40 | constructor (data = {}) { 41 | super({ data, fields }) 42 | } 43 | 44 | /** 45 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 46 | * @returns {object} pojo 47 | */ 48 | static unserialize (data) { 49 | return super.unserialize({ data, fields }) 50 | } 51 | 52 | /** 53 | * Quote currency of the ticker 54 | * 55 | * @returns {string} quoteCurrency 56 | */ 57 | quote () { 58 | return (this.symbol || '').substring(4) 59 | } 60 | 61 | /** 62 | * Base currency of the ticker 63 | * 64 | * @returns {string} baseCurrency 65 | */ 66 | base () { 67 | return (this.symbol || '').substring(1, 4) 68 | } 69 | 70 | /** 71 | * Validates a given trading ticker instance 72 | * 73 | * @param {object[]|object|PublicTrade[]|PublicTrade|Array} data - instance to validate 74 | * @returns {string} error - null if instance is valid 75 | */ 76 | static validate (data) { 77 | return super.validate({ 78 | data, 79 | fields, 80 | validators: { 81 | symbol: symbolValidator, 82 | bid: priceValidator, 83 | bidSize: amountValidator, 84 | ask: priceValidator, 85 | askSize: amountValidator, 86 | dailyChange: numberValidator, 87 | dailyChangePerc: numberValidator, 88 | lastPrice: priceValidator, 89 | volume: numberValidator, 90 | high: priceValidator, 91 | low: priceValidator 92 | } 93 | }) 94 | } 95 | } 96 | 97 | module.exports = TradingTicker 98 | -------------------------------------------------------------------------------- /lib/trading_ticker_hist.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const symbolValidator = require('./validators/symbol') 4 | const priceValidator = require('./validators/price') 5 | const dateValidator = require('./validators/date') 6 | const Model = require('./model') 7 | const fields = { 8 | symbol: 0, 9 | bid: 1, 10 | ask: 3, 11 | mtsUpdate: 12 12 | } 13 | 14 | /** 15 | * Historical Trading Ticker model 16 | */ 17 | class TradingTickerHist extends Model { 18 | /** 19 | * @param {object|Array} data - historical trading ticker data 20 | * @param {string} data.symbol - symbol 21 | * @param {string} data.bid - best bid 22 | * @param {string} data.ask - best ask 23 | * @param {number} data.mtsUpdate - timestamp 24 | */ 25 | constructor (data = {}) { 26 | super({ data, fields }) 27 | } 28 | 29 | /** 30 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 31 | * @returns {object} pojo 32 | */ 33 | static unserialize (data) { 34 | return super.unserialize({ data, fields }) 35 | } 36 | 37 | /** 38 | * Quote currency for the ticker 39 | * 40 | * @returns {string} quoteCurrency 41 | */ 42 | quote () { 43 | return (this.symbol || '').substring(4) 44 | } 45 | 46 | /** 47 | * Base currency for the ticker. 48 | * 49 | * @returns {string} baseCurrency 50 | */ 51 | base () { 52 | return (this.symbol || '').substring(1, 4) 53 | } 54 | 55 | /** 56 | * Validates a given historical trading ticker instance 57 | * 58 | * @param {object[]|object|TradingTickerHist[]|TradingTickerHist|Array} data - instance to validate 59 | * @returns {string} error - null if instance is valid 60 | */ 61 | static validate (data) { 62 | return super.validate({ 63 | data, 64 | fields, 65 | validators: { 66 | symbol: symbolValidator, 67 | bid: priceValidator, 68 | ask: priceValidator, 69 | mtsUpdated: dateValidator 70 | } 71 | }) 72 | } 73 | } 74 | 75 | module.exports = TradingTickerHist 76 | -------------------------------------------------------------------------------- /lib/transaction_fee.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const stringValidator = require('./validators/string') 5 | const Model = require('./model') 6 | const fields = { 7 | symbol: 0, 8 | fee: [1, 1] 9 | } 10 | 11 | /** 12 | * Transaction Fee model 13 | */ 14 | class TransactionFee extends Model { 15 | /** 16 | * @param {object|Array} data - transaction fee data 17 | * @param {string} data.symbol - currency symbol 18 | * @param {number} data.fee - withdrawal fee 19 | */ 20 | constructor (data = {}) { 21 | super({ data, fields }) 22 | 23 | this.emptyFill = 0 24 | } 25 | 26 | /** 27 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 28 | * @returns {object} pojo 29 | */ 30 | static unserialize (data) { 31 | return super.unserialize({ data, fields }) 32 | } 33 | 34 | /** 35 | * Validates a given transaction fee instance 36 | * 37 | * @param {object[]|object|TransactionFee[]|TransactionFee|Array} data - instance to validate 38 | * @returns {string} error - null if instance is valid 39 | */ 40 | static validate (data) { 41 | return super.validate({ 42 | data, 43 | fields, 44 | validators: { 45 | symbol: stringValidator, 46 | fee: numberValidator 47 | } 48 | }) 49 | } 50 | } 51 | 52 | module.exports = TransactionFee 53 | -------------------------------------------------------------------------------- /lib/user_info.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const boolValidator = require('./validators/bool') 4 | const numberValidator = require('./validators/number') 5 | const stringValidator = require('./validators/string') 6 | const Model = require('./model') 7 | const fields = { 8 | id: 0, 9 | email: 1, 10 | username: 2, 11 | timezone: 7, 12 | isPaperTradeEnabled: 21, 13 | isUserMerchant: 22 14 | } 15 | const boolFields = ['isPaperTradeEnabled', 'isUserMerchant'] 16 | 17 | /** 18 | * User Info model 19 | */ 20 | class UserInfo extends Model { 21 | /** 22 | * @param {object|Array} data - user info data 23 | * @param {number} data.id - id 24 | * @param {string} data.email - email 25 | * @param {string} data.username - username 26 | * @param {number} data.timezone - timezone as UTC offset 27 | * @param {number} data.isPaperTradeEnabled - flag indicating paper trading account 28 | * @param {number} data.isUserMerchant - flag indicating merchant account 29 | */ 30 | constructor (data = {}) { 31 | super({ data, fields, boolFields }) 32 | } 33 | 34 | /** 35 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 36 | * @returns {object} pojo 37 | */ 38 | static unserialize (data) { 39 | return super.unserialize({ data, fields }) 40 | } 41 | 42 | /** 43 | * Validates a given historical trading ticker instance 44 | * 45 | * @param {object[]|object|UserInfo[]|UserInfo|Array} data - instance to validate 46 | * @returns {Error|null} error - null if instance is valid 47 | */ 48 | static validate (data) { 49 | return super.validate({ 50 | data, 51 | fields, 52 | validators: { 53 | id: numberValidator, 54 | email: stringValidator, 55 | username: stringValidator, 56 | timezone: stringValidator, 57 | isPaperTradeEnabled: boolValidator, 58 | isUserMerchant: boolValidator 59 | } 60 | }) 61 | } 62 | } 63 | 64 | module.exports = UserInfo 65 | -------------------------------------------------------------------------------- /lib/util/arr_fill_empty.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const arrFillEmpty = (arr, fill = null) => { 4 | for (let i = 0; i < arr.length; i++) { 5 | if (arr[i] === undefined) { 6 | arr[i] = fill 7 | } 8 | 9 | if (Array.isArray(arr[i])) { 10 | arrFillEmpty(arr[i], fill) 11 | } 12 | } 13 | } 14 | 15 | module.exports = arrFillEmpty 16 | -------------------------------------------------------------------------------- /lib/util/assign_from_collection_or_instance.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _isArray = require('lodash/isArray') 4 | const _isObject = require('lodash/isObject') 5 | 6 | /** 7 | * Merges provided data onto the target model class, supporting both normal 8 | * object/array format packets and arrays of them. If given an array of 9 | * packets, the destination model will become iterable. 10 | * 11 | * @param {object} args - arguments 12 | * @param {object[]|object|Array[]|Array} args.data - data 13 | * @param {object} [args.fields] - index map in the form { [fieldName]: index } 14 | * @param {Array} [args.boolFields] - array of boolean field names 15 | * @param {object} args.target - model class 16 | */ 17 | const assignFromCollectionOrInstance = ({ data, fields, boolFields, target }) => { 18 | // Use/assign passed in data 19 | if (!_isArray(data) && _isObject(data)) { 20 | Object.assign(target, data) 21 | } else if (_isArray(data) && data.length > 0) { 22 | // Initialize iterator/setup array-like access if passed an array of models 23 | let toParse = data 24 | 25 | // Don't make an iterable collection if given an array of 1 item 26 | if (_isArray(data[0]) && data.length === 1) { 27 | toParse = data[0] 28 | } 29 | 30 | if (_isArray(toParse[0]) || _isObject(toParse[0])) { 31 | const collection = target.constructor.unserialize(toParse) 32 | target._collection = collection 33 | 34 | Object.assign(target, collection) // needed for [] access 35 | target.length = collection.length 36 | 37 | target[Symbol.iterator] = function () { 38 | return { 39 | _i: -1, 40 | next: function () { 41 | this._i++ 42 | 43 | return this._i === collection.length 44 | ? { done: true } 45 | : { value: collection[this._i], done: false } 46 | } 47 | } 48 | } 49 | } else { 50 | Object.assign(target, target.constructor.unserialize(toParse)) 51 | } 52 | } 53 | } 54 | 55 | module.exports = assignFromCollectionOrInstance 56 | -------------------------------------------------------------------------------- /lib/util/is_collection.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _isArray = require('lodash/isArray') 4 | const _isObject = require('lodash/isObject') 5 | 6 | /** 7 | * Checks if the provided data is a collection of models 8 | * 9 | * @param {object[]|object|Array[]|Array} data - packet to analyse 10 | * @returns {boolean} isCollection 11 | */ 12 | module.exports = (data) => ( 13 | _isArray(data) && (_isArray(data[0]) || _isObject(data[0])) 14 | ) 15 | -------------------------------------------------------------------------------- /lib/validators/amount.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./number') 4 | 5 | /** 6 | * Validates an amount 7 | * 8 | * @param {*} v - value 9 | * @returns {string} error - null if valid 10 | */ 11 | module.exports = (v) => numberValidator(v) 12 | -------------------------------------------------------------------------------- /lib/validators/array.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /** 4 | * Validates a bool 5 | * 6 | * @param {*} v - value 7 | * @returns {string} error - null if valid 8 | */ 9 | module.exports = (v) => (!Array.isArray(v) 10 | ? 'must be an array' 11 | : null 12 | ) 13 | -------------------------------------------------------------------------------- /lib/validators/bool.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _isBoolean = require('lodash/isBoolean') 4 | 5 | /** 6 | * Validates a bool 7 | * 8 | * @param {*} v - value 9 | * @returns {string} error - null if valid 10 | */ 11 | module.exports = (v) => (!_isBoolean(v) 12 | ? 'must be a bool' 13 | : null 14 | ) 15 | -------------------------------------------------------------------------------- /lib/validators/currency.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _includes = require('lodash/includes') 4 | const { CURRENCIES } = require('bfx-hf-util') 5 | const VALID_CURRENCIES = Object.values(CURRENCIES) 6 | 7 | /** 8 | * Validates a currency 9 | * 10 | * @param {*} v - value 11 | * @returns {string} error - null if valid 12 | */ 13 | module.exports = (v) => (!_includes(VALID_CURRENCIES, v) 14 | ? 'must be a currency currently tradable on Bitfinex' 15 | : null 16 | ) 17 | -------------------------------------------------------------------------------- /lib/validators/date.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _isFinite = require('lodash/isFinite') 4 | 5 | /** 6 | * Validates a date 7 | * 8 | * @param {*} v - value 9 | * @returns {string} error - null if valid 10 | */ 11 | module.exports = (v) => (!_isFinite(+v) || +v < 0 12 | ? 'must be a date or positive number' 13 | : null 14 | ) 15 | -------------------------------------------------------------------------------- /lib/validators/number.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _isFinite = require('lodash/isFinite') 4 | 5 | /** 6 | * Validates a number 7 | * 8 | * @param {*} v - value 9 | * @returns {string} error - null if valid 10 | */ 11 | module.exports = (v) => (!_isFinite(v) 12 | ? 'must be a number' 13 | : null 14 | ) 15 | -------------------------------------------------------------------------------- /lib/validators/object.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _isObject = require('lodash/isObject') 4 | 5 | /** 6 | * Validates a object 7 | * 8 | * @param {*} v - value 9 | * @returns {string} error - null if valid 10 | */ 11 | module.exports = (v) => (!_isObject(v) 12 | ? 'must be an object' 13 | : null 14 | ) 15 | -------------------------------------------------------------------------------- /lib/validators/price.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./number') 4 | 5 | /** 6 | * Validates a price 7 | * 8 | * @param {*} v - value 9 | * @returns {string} error - null if valid 10 | */ 11 | module.exports = (v) => (numberValidator(v) || v < 0 12 | ? 'must be a number greater than zero' 13 | : null 14 | ) 15 | -------------------------------------------------------------------------------- /lib/validators/string.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _includes = require('lodash/includes') 4 | const _isString = require('lodash/isString') 5 | 6 | /** 7 | * Validates a string 8 | * 9 | * @param {*} v - value 10 | * @param {string[]} validOptions - optional 11 | * @returns {string} error - null if valid 12 | */ 13 | module.exports = (v, validOptions) => ( 14 | !_isString(v) || (validOptions && !_includes(validOptions, v)) 15 | ? 'must be a string' 16 | : null 17 | ) 18 | -------------------------------------------------------------------------------- /lib/validators/symbol.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const _includes = require('lodash/includes') 4 | const { SYMBOLS } = require('bfx-hf-util') 5 | const VALID_SYMBOLS = Object.values(SYMBOLS) 6 | 7 | /** 8 | * Validates a symbol 9 | * 10 | * @param {*} v - value 11 | * @returns {string} error - null if valid 12 | */ 13 | module.exports = (v) => (!_includes(VALID_SYMBOLS, v) 14 | ? 'must be a symbol currently traded on Bitfinex' 15 | : null 16 | ) 17 | -------------------------------------------------------------------------------- /lib/wallet.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const amountValidator = require('./validators/amount') 4 | const currencyValidator = require('./validators/currency') 5 | const stringValidator = require('./validators/string') 6 | const { WALLET_TYPES } = require('bfx-hf-util') 7 | const Model = require('./model') 8 | 9 | const VALID_TYPES = Object.values(WALLET_TYPES) 10 | const fields = { 11 | type: 0, 12 | currency: 1, 13 | balance: 2, 14 | unsettledInterest: 3, 15 | balanceAvailable: 4, 16 | description: 5, 17 | meta: 6 18 | } 19 | 20 | /** 21 | * Wallet model 22 | */ 23 | class Wallet extends Model { 24 | /** 25 | * @param {object|Array} data - wallet data 26 | * @param {string} data.type - wallet type (i.e. deposit) 27 | * @param {string} data.currency - wallet currency 28 | * @param {number} data.balance - total balance 29 | * @param {number} data.unsettledInterest - unsettled interest 30 | * @param {number} data.balanceAvailable - available balance 31 | */ 32 | constructor (data = {}) { 33 | super({ data, fields }) 34 | } 35 | 36 | /** 37 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 38 | * @returns {object} pojo 39 | */ 40 | static unserialize (data) { 41 | return super.unserialize({ data, fields }) 42 | } 43 | 44 | /** 45 | * Validates a given wallet instance 46 | * 47 | * @param {object[]|object|Wallet[]|Wallet|Array} data - instance to validate 48 | * @returns {string} error - null if instance is valid 49 | */ 50 | static validate (data) { 51 | return super.validate({ 52 | data, 53 | fields, 54 | 55 | validators: { 56 | type: v => stringValidator(v, VALID_TYPES), 57 | currency: currencyValidator, 58 | balance: amountValidator, 59 | unsettledInterest: amountValidator, 60 | balanceAvailable: amountValidator, 61 | description: stringValidator 62 | } 63 | }) 64 | } 65 | } 66 | 67 | module.exports = Wallet 68 | -------------------------------------------------------------------------------- /lib/wallet_hist.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const amountValidator = require('./validators/amount') 4 | const currencyValidator = require('./validators/currency') 5 | const stringValidator = require('./validators/string') 6 | const dateValidator = require('./validators/date') 7 | const { WALLET_TYPES } = require('bfx-hf-util') 8 | const Model = require('./model') 9 | 10 | const types = Object.values(WALLET_TYPES) 11 | const fields = { 12 | type: 0, 13 | currency: 1, 14 | balance: 2, 15 | unsettledInterest: 3, 16 | balanceAvailable: 4, 17 | mtsUpdate: 6 18 | } 19 | 20 | /** 21 | * Historical Wallet Update model 22 | */ 23 | class WalletHist extends Model { 24 | /** 25 | * @param {object|Array} data - historical wallet update data 26 | * @param {string} data.type - type (i.e. deposit) 27 | * @param {string} data.currency - currency 28 | * @param {number} data.balance - balance 29 | * @param {number} data.unsettledInterest - unsettled interest 30 | * @param {number} data.balanceAvailable - available balance 31 | * @param {number} data.mtsUpdate - timestamp 32 | */ 33 | constructor (data = {}) { 34 | super({ data, fields }) 35 | } 36 | 37 | /** 38 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 39 | * @returns {object} pojo 40 | */ 41 | static unserialize (data) { 42 | return super.unserialize({ data, fields }) 43 | } 44 | 45 | /** 46 | * Validates a given historical wallet instance 47 | * 48 | * @param {object[]|object|WalletHist[]|WalletHist|Array} data - instance to validate 49 | * @returns {string} error - null if instance is valid 50 | */ 51 | static validate (data) { 52 | return super.validate({ 53 | data, 54 | fields, 55 | 56 | validators: { 57 | type: v => stringValidator(v, types), 58 | currency: currencyValidator, 59 | balance: amountValidator, 60 | unsettledInterest: amountValidator, 61 | balanceAvailable: amountValidator, 62 | mtsUpdate: dateValidator 63 | } 64 | }) 65 | } 66 | } 67 | 68 | WalletHist.type = {} 69 | 70 | types.forEach(t => (WalletHist.type[t.toUpperCase()] = t)) 71 | 72 | module.exports = WalletHist 73 | -------------------------------------------------------------------------------- /lib/weighted_averages.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const numberValidator = require('./validators/number') 4 | const Model = require('./model') 5 | const fields = { 6 | tradeCount: 0, 7 | sumBuyingSpent: 1, 8 | sumBuyingAmount: 2, 9 | sumSellingSpent: 4, 10 | sumSellingAmount: 5, 11 | buyingWeightedPrice: 7, 12 | sellingWeightedPrice: 8, 13 | firstTradeMts: 10, 14 | lastTradeMts: 11 15 | } 16 | 17 | /** 18 | * Weighted Averages model 19 | */ 20 | class WeightedAverages extends Model { 21 | /** 22 | * @param {object|Array} data - weighted averages data 23 | * @param {number} data.tradeCount - trade count 24 | * @param {number} data.sumBuyingSpent - sum buying spent 25 | * @param {number} data.sumBuyingAmount - sum buying amount 26 | * @param {number} data.sumSellingSpent - sum selling spent 27 | * @param {number} data.sumSellingAmount - sum selling amount 28 | * @param {number} data.buyingWeightedPrice - buying weighted price 29 | * @param {number} data.sellingWeightedPrice - selling weighted price 30 | * @param {number} data.firstTradeMts - first trade ms timestamp 31 | * @param {number} data.lastTradeMts - last trade ms timestamp 32 | */ 33 | constructor (data = {}) { 34 | super({ data, fields }) 35 | } 36 | 37 | /** 38 | * @param {object[]|object|Array[]|Array} data - data to convert to POJO 39 | * @returns {object} pojo 40 | */ 41 | static unserialize (data) { 42 | return super.unserialize({ data, fields }) 43 | } 44 | 45 | /** 46 | * Validates a given WeightedAverages instance 47 | * 48 | * @param {object[]|object|WeightedAverages[]|WeightedAverages|Array} data - instance to validate 49 | * @returns {string} error - null if instance is valid 50 | */ 51 | static validate (data) { 52 | return super.validate({ 53 | data, 54 | fields, 55 | validators: { 56 | tradeCount: numberValidator, 57 | sumBuyingSpent: numberValidator, 58 | sumBuyingAmount: numberValidator, 59 | sumSellingSpent: numberValidator, 60 | sumSellingAmount: numberValidator, 61 | buyingWeightedPrice: numberValidator, 62 | sellingWeightedPrice: numberValidator, 63 | firstTradeMts: numberValidator, 64 | lastTradeMts: numberValidator 65 | } 66 | }) 67 | } 68 | } 69 | 70 | module.exports = WeightedAverages 71 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bfx-api-node-models", 3 | "version": "2.1.0", 4 | "description": "Object models for usage with the Bitfinex node API", 5 | "engines": { 6 | "node": ">=18.0.0" 7 | }, 8 | "main": "index.js", 9 | "husky": { 10 | "hooks": { 11 | "pre-commit": "npm test" 12 | } 13 | }, 14 | "scripts": { 15 | "lint": "standard", 16 | "lint:fix": "standard --fix", 17 | "test": "npm run lint && npm run unit", 18 | "unit": "NODE_ENV=test nyc --check-coverage --lines 90 --branches 60 --functions 90 --statements 90 --reporter=lcov --reporter=html mocha -b --recursive", 19 | "docs": "rm -rf docs && node_modules/.bin/jsdoc --configure .jsdoc.json --verbose", 20 | "prepare": "husky install" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "https://github.com/bitfinexcom/bfx-api-node-models.git" 25 | }, 26 | "keywords": [ 27 | "bitfinex", 28 | "bitcoin", 29 | "BTC" 30 | ], 31 | "author": "Bitfinex", 32 | "contributors": [ 33 | "Jacob Plaster (https://www.bitfinex.com)", 34 | "Ezequiel Wernicke (https://www.bitfinex.com)", 35 | "Cris Mihalache (https://www.bitfinex.com)", 36 | "Paolo Ardoino (https://www.bitfinex.com)", 37 | "Vigan Abdurrahmani (https://www.bitfinex.com)", 38 | "Abhishek Shrestha (https://www.bitfinex.com)" 39 | ], 40 | "license": "MIT", 41 | "bugs": { 42 | "url": "https://github.com/bitfinexcom/bfx-api-node-models/issues" 43 | }, 44 | "homepage": "http://bitfinexcom.github.io/bfx-api-node-models/", 45 | "devDependencies": { 46 | "bfx-api-node-rest": "^6.0.0", 47 | "docdash": "^2.0.2", 48 | "husky": "^9.1.6", 49 | "jsdoc-to-markdown": "^9.0.1", 50 | "mocha": "^10.7.3", 51 | "nyc": "^17.0.0", 52 | "standard": "^17.1.2" 53 | }, 54 | "dependencies": { 55 | "bfx-api-node-util": "^1.0.10", 56 | "bfx-hf-util": "git+https://github.com/bitfinexcom/bfx-hf-util.git#v1.0.12", 57 | "bluebird": "3.7.2", 58 | "crc-32": "1.2.0", 59 | "debug": "4.3.3", 60 | "lodash": "^4.17.15" 61 | }, 62 | "standard": { 63 | "ignore": [ 64 | "/docs/**/*.js" 65 | ] 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test/helpers/test_model.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _includes = require('lodash/includes') 6 | 7 | const testModel = ({ values = {}, model, orderedFields, boolFields = [] }) => { 8 | const Model = model 9 | const fields = orderedFields 10 | const fieldValues = fields.slice() 11 | 12 | // Apply overrides 13 | for (let i = 0; i < fields.length; i++) { 14 | if (values[fields[i]]) { 15 | fieldValues[i] = values[fields[i]] 16 | } 17 | 18 | if (_includes(boolFields, fields[i])) { 19 | fieldValues[i] = false 20 | } 21 | } 22 | 23 | const checkModelFields = (m) => { 24 | fields.forEach((f) => { 25 | checkField(m, f) 26 | }) 27 | } 28 | 29 | const checkField = (m, f) => { 30 | if (f === null) return 31 | 32 | if (_includes(boolFields, f)) { 33 | assert.strictEqual(m[f], false) 34 | } else if (values[f]) { 35 | assert.strictEqual(m[f], values[f]) 36 | } else { 37 | assert.strictEqual(m[f], f) 38 | } 39 | } 40 | 41 | it('constructs from an array source', () => { 42 | const m = new Model(fieldValues) 43 | checkModelFields(m) 44 | }) 45 | 46 | it('constructs from an object source', () => { 47 | const data = {} 48 | fields.forEach(f => (f !== null) && (data[f] = f)) 49 | boolFields.forEach((f) => { data[f] = false }) 50 | Object.assign(data, values) 51 | 52 | const m = new Model(data) 53 | checkModelFields(m) 54 | }) 55 | 56 | it('constructs from an array of arrays', () => { 57 | const m = new Model([fieldValues, fieldValues, fieldValues]) 58 | const mArr = [...m] 59 | 60 | // test [] access 61 | for (let i = 0; i < m.length; i += 1) { 62 | checkModelFields(m[i]) 63 | } 64 | 65 | // test iterator 66 | for (let i = 0; i < mArr.length; i += 1) { 67 | checkModelFields(mArr[i]) 68 | } 69 | 70 | assert.strictEqual(m.length, mArr.length) 71 | 72 | // test equality 73 | for (let i = 0; i < m.length; i += 1) { 74 | assert.deepStrictEqual(m[i], mArr[i]) 75 | } 76 | }) 77 | 78 | it('constructs from an array of objects', () => { 79 | const data = {} 80 | fields.forEach(f => (f !== null) && (data[f] = f)) 81 | boolFields.forEach((f) => { data[f] = false }) 82 | Object.assign(data, values) 83 | 84 | const m = new Model([data, data, data]) 85 | const mArr = [...m] 86 | 87 | // test [] access 88 | for (let i = 0; i < m.length; i += 1) { 89 | checkModelFields(m[i]) 90 | } 91 | 92 | // test iterator 93 | for (let i = 0; i < mArr.length; i += 1) { 94 | checkModelFields(mArr[i]) 95 | } 96 | 97 | assert.strictEqual(m.length, mArr.length) 98 | 99 | // test equality 100 | for (let i = 0; i < m.length; i += 1) { 101 | assert.deepStrictEqual(m[i], mArr[i]) 102 | } 103 | }) 104 | 105 | it('serializes correctly', () => { 106 | const data = {} 107 | fields.forEach(f => (f !== null) && (data[f] = f)) 108 | boolFields.forEach((f) => { data[f] = false }) 109 | Object.assign(data, values) 110 | 111 | const m = new Model(data) 112 | const arr = m.serialize() 113 | 114 | arr.forEach((v, i) => { 115 | checkField(m, fields[i]) 116 | }) 117 | }) 118 | 119 | it('unserializes correctly', () => { 120 | const m = model.unserialize(fieldValues) 121 | checkModelFields(m) 122 | }) 123 | } 124 | 125 | module.exports = testModel 126 | -------------------------------------------------------------------------------- /test/helpers/test_model_validation.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _min = require('lodash/min') 6 | const _sample = require('lodash/sample') 7 | const _isArray = require('lodash/isArray') 8 | const _isError = require('lodash/isError') 9 | const _isFunction = require('lodash/isFunction') 10 | const _flattenDeep = require('lodash/flattenDeep') 11 | 12 | /** 13 | * Runs basic checks on a model's validate method 14 | * 15 | * @param {object} args - arguments 16 | * @param {object} args.model - class 17 | * @param {object} args.validData - map of arrays for each key containing valid values 18 | */ 19 | module.exports = ({ model, validData }) => { 20 | it('validate: is provided', () => { 21 | _isFunction(model.validate) 22 | }) 23 | 24 | // Generate valid/invalid param sets for fuzzing 25 | const valid = [] 26 | const invalid = [] 27 | const minDatasetLength = _min(Object.values(validData).map(arr => arr.length)) 28 | 29 | for (let i = 0; i < minDatasetLength; i += 1) { 30 | const validParamSet = {} 31 | const invalidParamSet = {} 32 | 33 | Object.keys(validData).forEach((key) => { 34 | const v = _sample(validData[key]) 35 | 36 | validParamSet[key] = v 37 | invalidParamSet[key] = `__not_valid_${v}` 38 | }) 39 | 40 | valid.push(validParamSet) 41 | invalid.push(invalidParamSet) 42 | } 43 | 44 | it('validate: false for invalid instance(s)', () => { 45 | if (_isArray(invalid)) { 46 | assert(_isError(model.validate(invalid))) // test all 47 | 48 | invalid.forEach(i => { // test single & array of one 49 | assert(_isError(model.validate(i))) 50 | assert(_isError(model.validate([i]))) 51 | }) 52 | } else { // test single & array of one 53 | assert(_isError(model.validate(invalid))) 54 | assert(_isError(model.validate([invalid]))) 55 | } 56 | }) 57 | 58 | it('validate: true for valid instance(s)', () => { 59 | if (_isArray(valid)) { 60 | assert.strictEqual(model.validate(valid), null) // test all 61 | 62 | valid.forEach(i => { // test single & array of one 63 | assert.strictEqual(model.validate(i), null) 64 | assert.strictEqual(model.validate([i]), null) 65 | }) 66 | } else { // test single & array of one 67 | assert.strictEqual(model.validate(valid), null) 68 | assert.strictEqual(model.validate([valid]), null) 69 | } 70 | }) 71 | 72 | it('validate: false if one instance out of a set is invalid', () => { 73 | assert(_isError(model.validate(_flattenDeep([valid, invalid])))) 74 | }) 75 | } 76 | -------------------------------------------------------------------------------- /test/lib/models/account_summary.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { AccountSummary } = require('../../../lib') 6 | const testModelValidation = require('../../helpers/test_model_validation') 7 | const tradingVol30d = [ 8 | { 9 | curr: 'BTC', 10 | vol: 0.01917394 11 | }, 12 | { 13 | curr: 'ETH', 14 | vol: 0.67504702 15 | }, 16 | { 17 | curr: 'XRP', 18 | vol: 11243.7965533 19 | }, 20 | { 21 | curr: 'Total (USD)', 22 | vol: 7621.42803742, 23 | vol_safe: 7621.42803742, 24 | vol_maker: 6673.18852682, 25 | vol_BFX: 7621.42803742, 26 | vol_BFX_safe: 7621.42803742, 27 | vol_BFX_maker: 6673.18852682 28 | } 29 | ] 30 | const OBJ = { USD: 3.14966754, ETH: 0.10302856 } 31 | const DATA = [ 32 | null, 33 | null, 34 | null, 35 | null, 36 | [ 37 | [0.001, 0.001, 0.001, null, null, -0.0002], 38 | [0.002, 0.0021, 0.0022, null, null, 0.00075] 39 | ], 40 | [ 41 | tradingVol30d, 42 | { USD: 8.56966754, BTC: 1.00006754 }, 43 | 30008.56966754 44 | ], 45 | [ 46 | null, 47 | { USD: 3.14966754, ETH: 0.10302856 }, 48 | 283.14966754 49 | ], 50 | null, 51 | null, 52 | { leo_lev: 0, leo_amount_avg: 0.002 } 53 | ] 54 | 55 | describe('Account Summary model', () => { 56 | testModelValidation({ 57 | model: AccountSummary, 58 | validData: { 59 | trade_vol_30d: [...(new Array(5))].map(() => tradingVol30d), 60 | fees_trading_30d: [...(new Array(5))].map(() => OBJ), 61 | fees_trading_total_30d: [...(new Array(5))].map(() => Math.random()), 62 | fees_funding_30d: [...(new Array(5))].map(() => OBJ), 63 | fees_funding_total_30d: [...(new Array(5))].map(() => Math.random()), 64 | makerFee: [...(new Array(5))].map(() => Math.random()), 65 | derivMakerRebate: [...(new Array(5))].map(() => Math.random()), 66 | takerFeeToCrypto: [...(new Array(5))].map(() => Math.random()), 67 | takerFeeToStable: [...(new Array(5))].map(() => Math.random()), 68 | takerFeeToFiat: [...(new Array(5))].map(() => Math.random()), 69 | derivTakerFee: [...(new Array(5))].map(() => Math.random()), 70 | leoLev: [...(new Array(5))].map(() => Math.random()), 71 | leoAmountAvg: [...(new Array(5))].map(() => Math.random()) 72 | } 73 | }) 74 | 75 | it('initializes correctly', () => { 76 | const summary = new AccountSummary(DATA) 77 | assert.deepStrictEqual(summary.trade_vol_30d, tradingVol30d) 78 | assert.deepStrictEqual( 79 | summary.fees_trading_30d, 80 | { USD: 8.56966754, BTC: 1.00006754 } 81 | ) 82 | assert.strictEqual(summary.fees_trading_total_30d, 30008.56966754) 83 | assert.deepStrictEqual( 84 | summary.fees_funding_30d, 85 | { USD: 3.14966754, ETH: 0.10302856 } 86 | ) 87 | assert.strictEqual(summary.fees_funding_total_30d, 283.14966754) 88 | assert.strictEqual(summary.makerFee, 0.001) 89 | assert.strictEqual(summary.derivMakerRebate, -0.0002) 90 | assert.strictEqual(summary.takerFeeToCrypto, 0.002) 91 | assert.strictEqual(summary.takerFeeToStable, 0.0021) 92 | assert.strictEqual(summary.takerFeeToFiat, 0.0022) 93 | assert.strictEqual(summary.derivTakerFee, 0.00075) 94 | assert.strictEqual(summary.leoLev, 0) 95 | assert.strictEqual(summary.leoAmountAvg, 0.002) 96 | }) 97 | 98 | it('serializes correctly', () => { 99 | const summary = new AccountSummary(DATA) 100 | const arr = summary.serialize() 101 | 102 | assert.deepStrictEqual(arr, DATA) 103 | }) 104 | 105 | it('unserializes correctly', () => { 106 | const summary = AccountSummary.unserialize(DATA) 107 | assert.deepStrictEqual(summary.trade_vol_30d, tradingVol30d) 108 | assert.deepStrictEqual( 109 | summary.fees_trading_30d, 110 | { USD: 8.56966754, BTC: 1.00006754 } 111 | ) 112 | assert.strictEqual(summary.fees_trading_total_30d, 30008.56966754) 113 | assert.deepStrictEqual( 114 | summary.fees_funding_30d, 115 | { USD: 3.14966754, ETH: 0.10302856 } 116 | ) 117 | assert.strictEqual(summary.fees_funding_total_30d, 283.14966754) 118 | assert.strictEqual(summary.makerFee, 0.001) 119 | assert.strictEqual(summary.derivMakerRebate, -0.0002) 120 | assert.strictEqual(summary.takerFeeToCrypto, 0.002) 121 | assert.strictEqual(summary.takerFeeToStable, 0.0021) 122 | assert.strictEqual(summary.takerFeeToFiat, 0.0022) 123 | assert.strictEqual(summary.derivTakerFee, 0.00075) 124 | assert.strictEqual(summary.leoLev, 0) 125 | assert.strictEqual(summary.leoAmountAvg, 0.002) 126 | }) 127 | }) 128 | -------------------------------------------------------------------------------- /test/lib/models/alert.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { SYMBOLS } = require('bfx-hf-util') 5 | const { Alert } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | describe('Alert model', () => { 10 | testModel({ 11 | model: Alert, 12 | orderedFields: ['key', 'type', 'symbol', 'price'] 13 | }) 14 | 15 | testModelValidation({ 16 | model: Alert, 17 | validData: { 18 | symbol: Object.values(SYMBOLS), 19 | price: [...(new Array(5))].map(() => Math.random()) 20 | } 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /test/lib/models/auth_permission.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { AuthPermission } = require('../../../lib') 6 | const testModelValidation = require('../../helpers/test_model_validation') 7 | 8 | const DATA = ['orders', 1, 0] 9 | 10 | describe('Auth Permission model', () => { 11 | testModelValidation({ 12 | model: AuthPermission, 13 | validData: { 14 | key: ['account', 'orders', 'funding', 'settings', 'wallets', 'withdraw'], 15 | read: [true, false], 16 | write: [true, false] 17 | } 18 | }) 19 | 20 | it('initializes correctly', () => { 21 | const perm = new AuthPermission(DATA) 22 | assert.strictEqual(perm.key, 'orders') 23 | assert.strictEqual(perm.read, true) 24 | assert.strictEqual(perm.write, false) 25 | }) 26 | 27 | it('serializes correctly', () => { 28 | const details = new AuthPermission(DATA) 29 | const arr = details.serialize() 30 | 31 | assert.deepStrictEqual(arr, DATA) 32 | }) 33 | 34 | it('unserializes correctly', () => { 35 | const perm = AuthPermission.unserialize(DATA) 36 | assert.strictEqual(perm.key, 'orders') 37 | assert.strictEqual(perm.read, true) 38 | assert.strictEqual(perm.write, false) 39 | }) 40 | }) 41 | -------------------------------------------------------------------------------- /test/lib/models/balance_info.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { BalanceInfo } = require('../../../lib') 5 | const testModel = require('../../helpers/test_model') 6 | const testModelValidation = require('../../helpers/test_model_validation') 7 | 8 | describe('BalanceInfo model', () => { 9 | testModel({ 10 | model: BalanceInfo, 11 | orderedFields: ['amount', 'amountNet'] 12 | }) 13 | 14 | testModelValidation({ 15 | model: BalanceInfo, 16 | validData: { 17 | amount: [...(new Array(5))].map(() => Math.random()), 18 | amountNet: [...(new Array(5))].map(() => Math.random()) 19 | } 20 | }) 21 | }) 22 | -------------------------------------------------------------------------------- /test/lib/models/candle.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { RESTv2 } = require('bfx-api-node-rest') 6 | const { Candle } = require('../../../lib') 7 | const testModel = require('../../helpers/test_model') 8 | const testModelValidation = require('../../helpers/test_model_validation') 9 | 10 | describe('Candle model', () => { 11 | testModel({ 12 | model: Candle, 13 | orderedFields: ['mts', 'open', 'close', 'high', 'low', 'volume'] 14 | }) 15 | 16 | testModelValidation({ 17 | model: Candle, 18 | validData: { 19 | mts: [...(new Array(5))].map(() => Math.random()), 20 | open: [...(new Array(5))].map(() => Math.random()), 21 | high: [...(new Array(5))].map(() => Math.random()), 22 | low: [...(new Array(5))].map(() => Math.random()), 23 | close: [...(new Array(5))].map(() => Math.random()), 24 | volume: [...(new Array(5))].map(() => Math.random()) 25 | } 26 | }) 27 | 28 | it('unserializes live data correctly', async () => { 29 | const rest = new RESTv2() 30 | 31 | const arr = await rest.candles({ 32 | timeframe: '1D', 33 | symbol: 'tBTCUSD', 34 | section: 'hist' 35 | }) 36 | 37 | arr.forEach(candle => { 38 | const obj = Candle.unserialize(candle) 39 | 40 | assert.strictEqual(obj.mts, candle[0]) 41 | assert.strictEqual(obj.open, candle[1]) 42 | assert.strictEqual(obj.close, candle[2]) 43 | assert.strictEqual(obj.high, candle[3]) 44 | assert.strictEqual(obj.low, candle[4]) 45 | assert.strictEqual(obj.volume, candle[5]) 46 | }) 47 | }).timeout(4000) 48 | }) 49 | -------------------------------------------------------------------------------- /test/lib/models/change_logs.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | 6 | const { ChangeLog } = require('../../../lib') 7 | const testModel = require('../../helpers/test_model') 8 | const testModelValidation = require('../../helpers/test_model_validation') 9 | 10 | describe('ChangeLog model', () => { 11 | testModel({ 12 | model: ChangeLog, 13 | orderedFields: [ 14 | 'mtsCreate', null, 'log', null, null, 'ip', 'userAgent' 15 | ] 16 | }) 17 | 18 | testModelValidation({ 19 | model: ChangeLog, 20 | validData: { 21 | mtsCreate: [...(new Array(5))].map(() => Math.random()), 22 | log: ['not', 'today', 'man', 'but', 'maybe', 'tomorrow'], 23 | ip: ['not', 'today', 'man', 'but', 'maybe', 'tomorrow'], 24 | userAgent: ['not', 'today', 'man', 'but', 'maybe', 'tomorrow'] 25 | } 26 | }) 27 | 28 | describe('toString', () => { 29 | it('includes pertinent information', () => { 30 | const t = new ChangeLog({ 31 | mtsCreate: 123456789, 32 | log: 'someLog', 33 | ip: '1.2.3.4', 34 | userAgent: 'firefox' 35 | }) 36 | 37 | assert.strictEqual(t.mtsCreate, 123456789, 'mts create missing') 38 | assert.strictEqual(t.log, 'someLog', 'log missing') 39 | assert.strictEqual(t.ip, '1.2.3.4', 'ip missing') 40 | assert.strictEqual(t.userAgent, 'firefox', 'user agent missing') 41 | }) 42 | }) 43 | }) 44 | -------------------------------------------------------------------------------- /test/lib/models/core_settings.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { CoreSettings } = require('../../../lib') 6 | 7 | const DATA = [ 8 | 'te_limit_order_*', 9 | [ 10 | ['te_limit_order_cnt', '3000'], 11 | ['te_limit_order_symbol_cnt', '300'] 12 | ] 13 | ] 14 | 15 | describe('Core Settings model', () => { 16 | it('initializes correctly', () => { 17 | const coreSettings = new CoreSettings(DATA) 18 | assert.strictEqual(coreSettings.key, 'te_limit_order_*') 19 | assert.strictEqual(coreSettings.value, DATA[1]) 20 | }) 21 | 22 | it('serializes correctly', () => { 23 | const details = new CoreSettings(DATA) 24 | const arr = details.serialize() 25 | 26 | assert.deepStrictEqual(arr, DATA) 27 | }) 28 | 29 | it('unserializes correctly', () => { 30 | const coreSettings = CoreSettings.unserialize(DATA) 31 | assert.strictEqual(coreSettings.key, 'te_limit_order_*') 32 | assert.strictEqual(coreSettings.value, DATA[1]) 33 | }) 34 | }) 35 | -------------------------------------------------------------------------------- /test/lib/models/currency.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { WALLET_TYPES, CURRENCIES } = require('bfx-hf-util') 5 | const { Currency } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | // get data from somewhere 10 | const VALID_STRINGS = Object.values(WALLET_TYPES) 11 | 12 | describe('Currency model', () => { 13 | testModel({ 14 | model: Currency, 15 | orderedFields: ['id', 'name', 'pool', 'explorer', 'symbol', 'walletFx'] 16 | }) 17 | 18 | testModelValidation({ 19 | model: Currency, 20 | validData: { 21 | currency: Object.values(CURRENCIES), 22 | id: [...(new Array(5))].map(() => Math.random()), 23 | name: VALID_STRINGS, 24 | pool: VALID_STRINGS, 25 | explorer: new Array(5).fill([]), 26 | walletFx: new Array(5).fill([]) 27 | } 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /test/lib/models/funding_credit.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { SYMBOLS } = require('bfx-hf-util') 5 | const { FundingCredit } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | const VALID_SYMBOLS = Object.values(SYMBOLS) 10 | 11 | describe('FundingCredit model', () => { 12 | testModel({ 13 | model: FundingCredit, 14 | boolFields: ['notify', 'hidden', 'renew', 'noClose'], 15 | orderedFields: [ 16 | 'id', 'symbol', 'side', 'mtsCreate', 'mtsUpdate', 'amount', 'flags', 17 | 'status', null, null, null, 'rate', 'period', 'mtsOpening', 18 | 'mtsLastPayout', 'notify', 'hidden', null, 'renew', 'rateReal', 'noClose', 19 | 'positionPair' 20 | ] 21 | }) 22 | 23 | testModelValidation({ 24 | model: FundingCredit, 25 | validData: { 26 | symbol: VALID_SYMBOLS, 27 | status: VALID_SYMBOLS, // need data from somewhere 28 | id: [...(new Array(5))].map(() => Math.random()), 29 | mtsCreate: [...(new Array(5))].map(() => Math.random()), 30 | mtsUpdate: [...(new Array(5))].map(() => Math.random()), 31 | mtsOpening: [...(new Array(5))].map(() => Math.random()), 32 | mtsLastPayout: [...(new Array(5))].map(() => Math.random()), 33 | amount: [...(new Array(5))].map(() => Math.random()), 34 | flags: [...(new Array(5))].map(() => Math.random()), 35 | rate: [...(new Array(5))].map(() => Math.random()), 36 | period: [...(new Array(5))].map(() => Math.random()), 37 | rateReal: [...(new Array(5))].map(() => Math.random()), 38 | notify: [...(new Array(5))].map(() => Math.random() > 0.5), 39 | hidden: [...(new Array(5))].map(() => Math.random() > 0.5), 40 | renew: [...(new Array(5))].map(() => Math.random() > 0.5), 41 | noClose: [...(new Array(5))].map(() => Math.random() > 0.5) 42 | } 43 | }) 44 | }) 45 | -------------------------------------------------------------------------------- /test/lib/models/funding_info.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { FundingInfo } = require('../../../lib') 6 | 7 | describe('FundingInfo model', () => { 8 | // TODO: test validation 9 | 10 | it('initializes correctly', () => { 11 | const fi = new FundingInfo([ 12 | 'sym', 13 | 'ftEOSUSD', 14 | [ 15 | 12, 16 | 24, 17 | 48, 18 | 96 19 | ] 20 | ]) 21 | 22 | assert.strictEqual(fi.symbol, 'ftEOSUSD') 23 | assert.strictEqual(fi.yieldLoan, 12) 24 | assert.strictEqual(fi.yieldLend, 24) 25 | assert.strictEqual(fi.durationLoan, 48) 26 | assert.strictEqual(fi.durationLend, 96) 27 | }) 28 | 29 | it('serializes correctly', () => { 30 | const fi = new FundingInfo([ 31 | 'sym', 32 | 'ftEOSUSD', 33 | [ 34 | 12, 35 | 24, 36 | 48, 37 | 96 38 | ] 39 | ]) 40 | 41 | const arr = fi.serialize() 42 | assert.deepStrictEqual(arr, [ 43 | 'sym', 44 | 'ftEOSUSD', 45 | [ 46 | 12, 47 | 24, 48 | 48, 49 | 96 50 | ] 51 | ]) 52 | }) 53 | 54 | it('unserializes correctly', () => { 55 | const obj = FundingInfo.unserialize([ 56 | 'sym', 57 | 'ftEOSUSD', 58 | [ 59 | 12, 60 | 24, 61 | 48, 62 | 96 63 | ] 64 | ]) 65 | 66 | assert.strictEqual(obj.symbol, 'ftEOSUSD') 67 | assert.strictEqual(obj.yieldLoan, 12) 68 | assert.strictEqual(obj.yieldLend, 24) 69 | assert.strictEqual(obj.durationLoan, 48) 70 | assert.strictEqual(obj.durationLend, 96) 71 | }) 72 | }) 73 | -------------------------------------------------------------------------------- /test/lib/models/funding_loan.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { SYMBOLS } = require('bfx-hf-util') 5 | const { FundingLoan } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | const VALID_SYMBOLS = Object.values(SYMBOLS) 10 | 11 | describe('FundingLoan model', () => { 12 | testModel({ 13 | model: FundingLoan, 14 | boolFields: ['notify', 'hidden', 'renew', 'noClose'], 15 | orderedFields: [ 16 | 'id', 'symbol', 'side', 'mtsCreate', 'mtsUpdate', 'amount', 'flags', 17 | 'status', null, null, null, 'rate', 'period', 'mtsOpening', 18 | 'mtsLastPayout', 'notify', 'hidden', null, 'renew', 'rateReal', 'noClose' 19 | ] 20 | }) 21 | 22 | testModelValidation({ 23 | model: FundingLoan, 24 | validData: { 25 | symbol: VALID_SYMBOLS, 26 | status: VALID_SYMBOLS, // need data from somewhere 27 | id: [...(new Array(5))].map(() => Math.random()), 28 | mtsCreate: [...(new Array(5))].map(() => Math.random()), 29 | mtsUpdate: [...(new Array(5))].map(() => Math.random()), 30 | mtsOpening: [...(new Array(5))].map(() => Math.random()), 31 | mtsLastPayout: [...(new Array(5))].map(() => Math.random()), 32 | amount: [...(new Array(5))].map(() => Math.random()), 33 | flags: [...(new Array(5))].map(() => Math.random()), 34 | rate: [...(new Array(5))].map(() => Math.random()), 35 | period: [...(new Array(5))].map(() => Math.random()), 36 | rateReal: [...(new Array(5))].map(() => Math.random()), 37 | notify: [...(new Array(5))].map(() => Math.random() > 0.5), 38 | hidden: [...(new Array(5))].map(() => Math.random() > 0.5), 39 | renew: [...(new Array(5))].map(() => Math.random() > 0.5), 40 | noClose: [...(new Array(5))].map(() => Math.random() > 0.5) 41 | } 42 | }) 43 | }) 44 | -------------------------------------------------------------------------------- /test/lib/models/funding_ticker.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { SYMBOLS } = require('bfx-hf-util') 6 | const { RESTv2 } = require('bfx-api-node-rest') 7 | const { FundingTicker } = require('../../../lib') 8 | const testModel = require('../../helpers/test_model') 9 | const testModelValidation = require('../../helpers/test_model_validation') 10 | 11 | const VALID_SYMBOLS = Object.values(SYMBOLS) 12 | const DATA = [ 13 | 'fUSD', 14 | 0.00009351, 15 | 0.00009526, 16 | 1365265.8039803, 17 | 30, 18 | 0.00009042, 19 | 1920909.19369824, 20 | 2, 21 | -0.00001159, 22 | -0.1136, 23 | 0.00009041, 24 | 255643282.81674618, 25 | 0.000163, 26 | 2.7e-7 27 | ] 28 | 29 | describe('FundingTicker model', () => { 30 | testModel({ 31 | model: FundingTicker, 32 | orderedFields: [ 33 | 'symbol', 'frr', 'bid', 'bidSize', 'bidPeriod', 'ask', 'askSize', 34 | 'askPeriod', 'dailyChange', 'dailyChangePerc', 'lastPrice', 'volume', 35 | 'high', 'low' 36 | ] 37 | }) 38 | 39 | testModelValidation({ 40 | model: FundingTicker, 41 | validData: { 42 | symbol: VALID_SYMBOLS, 43 | bid: [...(new Array(5))].map(() => Math.random()), 44 | bidSize: [...(new Array(5))].map(() => Math.random()), 45 | bidPeriod: [...(new Array(5))].map(() => Math.random()), 46 | ask: [...(new Array(5))].map(() => Math.random()), 47 | askSize: [...(new Array(5))].map(() => Math.random()), 48 | askPeriod: [...(new Array(5))].map(() => Math.random()), 49 | dailyChange: [...(new Array(5))].map(() => Math.random()), 50 | dailyChangePerc: [...(new Array(5))].map(() => Math.random()), 51 | lastPrice: [...(new Array(5))].map(() => Math.random()), 52 | volume: [...(new Array(5))].map(() => Math.random()), 53 | high: [...(new Array(5))].map(() => Math.random()), 54 | low: [...(new Array(5))].map(() => Math.random()), 55 | frr: [...(new Array(5))].map(() => Math.random() > 0.5) 56 | } 57 | }) 58 | 59 | it('initializes correctly', () => { 60 | const ticker = new FundingTicker(DATA) 61 | assert.strictEqual(ticker.symbol, 'fUSD') 62 | assert.strictEqual(ticker.frr, 0.00009351) 63 | assert.strictEqual(ticker.bid, 0.00009526) 64 | assert.strictEqual(ticker.bidPeriod, 30) 65 | assert.strictEqual(ticker.bidSize, 1365265.8039803) 66 | assert.strictEqual(ticker.ask, 0.00009042) 67 | assert.strictEqual(ticker.askPeriod, 2) 68 | assert.strictEqual(ticker.askSize, 1920909.19369824) 69 | assert.strictEqual(ticker.dailyChange, -0.00001159) 70 | assert.strictEqual(ticker.dailyChangePerc, -0.1136) 71 | assert.strictEqual(ticker.lastPrice, 0.00009041) 72 | assert.strictEqual(ticker.volume, 255643282.81674618) 73 | assert.strictEqual(ticker.high, 0.000163) 74 | assert.strictEqual(ticker.low, 2.7e-7) 75 | }) 76 | 77 | it('serializes correctly', () => { 78 | const ticker = new FundingTicker(DATA) 79 | const arr = ticker.serialize() 80 | 81 | assert.deepStrictEqual(arr, DATA) 82 | }) 83 | 84 | it('unserializes correctly', () => { 85 | const obj = FundingTicker.unserialize(DATA) 86 | assert.strictEqual(obj.symbol, 'fUSD') 87 | assert.strictEqual(obj.frr, 0.00009351) 88 | assert.strictEqual(obj.bid, 0.00009526) 89 | assert.strictEqual(obj.bidPeriod, 30) 90 | assert.strictEqual(obj.bidSize, 1365265.8039803) 91 | assert.strictEqual(obj.ask, 0.00009042) 92 | assert.strictEqual(obj.askPeriod, 2) 93 | assert.strictEqual(obj.askSize, 1920909.19369824) 94 | assert.strictEqual(obj.dailyChange, -0.00001159) 95 | assert.strictEqual(obj.dailyChangePerc, -0.1136) 96 | assert.strictEqual(obj.lastPrice, 0.00009041) 97 | assert.strictEqual(obj.volume, 255643282.81674618) 98 | assert.strictEqual(obj.high, 0.000163) 99 | assert.strictEqual(obj.low, 2.7e-7) 100 | }) 101 | 102 | it('unserializes live data correctly', async () => { 103 | const rest = new RESTv2() 104 | const arr = await rest.ticker({ symbol: 'fUSD' }) 105 | const obj = FundingTicker.unserialize(arr) 106 | 107 | assert.strictEqual(obj.symbol, arr[0]) 108 | assert.strictEqual(obj.frr, arr[1]) 109 | assert.strictEqual(obj.bid, arr[2]) 110 | assert.strictEqual(obj.bidSize, arr[3]) 111 | assert.strictEqual(obj.bidPeriod, arr[4]) 112 | assert.strictEqual(obj.ask, arr[5]) 113 | assert.strictEqual(obj.askSize, arr[6]) 114 | assert.strictEqual(obj.askPeriod, arr[7]) 115 | assert.strictEqual(obj.dailyChange, arr[8]) 116 | assert.strictEqual(obj.dailyChangePerc, arr[9]) 117 | assert.strictEqual(obj.lastPrice, arr[10]) 118 | assert.strictEqual(obj.volume, arr[11]) 119 | assert.strictEqual(obj.high, arr[12]) 120 | assert.strictEqual(obj.low, arr[13]) 121 | }).timeout(60000) 122 | 123 | describe('quote', () => { 124 | it('returns quote currency', () => { 125 | const t = new FundingTicker({ symbol: 'tBTCUSD' }) 126 | assert.strictEqual(t.quote(), 'USD') 127 | }) 128 | }) 129 | 130 | describe('base', () => { 131 | it('returns base currency', () => { 132 | const t = new FundingTicker({ symbol: 'tBTCUSD' }) 133 | assert.strictEqual(t.base(), 'BTC') 134 | }) 135 | }) 136 | }) 137 | -------------------------------------------------------------------------------- /test/lib/models/funding_ticker_hist.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { SYMBOLS } = require('bfx-hf-util') 6 | const { RESTv2 } = require('bfx-api-node-rest') 7 | const { FundingTickerHist } = require('../../../lib') 8 | const testModel = require('../../helpers/test_model') 9 | const testModelValidation = require('../../helpers/test_model_validation') 10 | 11 | const VALID_SYMBOLS = Object.values(SYMBOLS) 12 | const DATA = [ 13 | 'fUSD', 14 | null, 15 | 0.00009526, 16 | null, 17 | 30, 18 | 0.00009042, 19 | null, 20 | null, 21 | null, 22 | null, 23 | null, 24 | null, 25 | null, 26 | null, 27 | null, 28 | 1544097835000 29 | ] 30 | 31 | describe('FundingTicker history model', () => { 32 | testModel({ 33 | model: FundingTickerHist, 34 | orderedFields: [ 35 | 'symbol', null, 'bid', null, 'bidPeriod', 'ask', null, null, null, null, 36 | null, null, null, null, null, 'mtsUpdate' 37 | ] 38 | }) 39 | 40 | testModelValidation({ 41 | model: FundingTickerHist, 42 | validData: { 43 | symbol: VALID_SYMBOLS, 44 | bid: [...(new Array(5))].map(() => Math.random()), 45 | bidPeriod: [...(new Array(5))].map(() => Math.random()), 46 | ask: [...(new Array(5))].map(() => Math.random()), 47 | mtsUpdate: [...(new Array(5))].map(() => Math.random()) 48 | } 49 | }) 50 | 51 | it('initializes correctly', () => { 52 | const ticker = new FundingTickerHist(DATA) 53 | assert.strictEqual(ticker.symbol, 'fUSD') 54 | assert.strictEqual(ticker.bid, 0.00009526) 55 | assert.strictEqual(ticker.bidPeriod, 30) 56 | assert.strictEqual(ticker.ask, 0.00009042) 57 | assert.strictEqual(ticker.mtsUpdate, 1544097835000) 58 | }) 59 | 60 | it('serializes correctly', () => { 61 | const ticker = new FundingTickerHist(DATA) 62 | const arr = ticker.serialize() 63 | assert.strictEqual(JSON.stringify(arr), JSON.stringify(DATA)) 64 | }) 65 | 66 | it('unserializes correctly', () => { 67 | const obj = FundingTickerHist.unserialize(DATA) 68 | assert.strictEqual(obj.symbol, 'fUSD') 69 | assert.strictEqual(obj.bid, 0.00009526) 70 | assert.strictEqual(obj.bidPeriod, 30) 71 | assert.strictEqual(obj.ask, 0.00009042) 72 | assert.strictEqual(obj.mtsUpdate, 1544097835000) 73 | }) 74 | 75 | it('unserializes live data correctly', async () => { 76 | const rest = new RESTv2() 77 | const arr = await rest.ticker({ symbol: 'fUSD' }) 78 | const obj = FundingTickerHist.unserialize(arr) 79 | 80 | assert.strictEqual(obj.symbol, arr[0]) 81 | assert.strictEqual(obj.bid, arr[2]) 82 | assert.strictEqual(obj.bidPeriod, arr[4]) 83 | assert.strictEqual(obj.ask, arr[5]) 84 | assert.strictEqual(obj.mtsUpdate, arr[15]) 85 | }).timeout(60000) 86 | 87 | describe('quote', () => { 88 | it('returns quote currency', () => { 89 | const t = new FundingTickerHist({ symbol: 'tBTCUSD' }) 90 | assert.strictEqual(t.quote(), 'USD') 91 | }) 92 | }) 93 | 94 | describe('base', () => { 95 | it('returns base currency', () => { 96 | const t = new FundingTickerHist({ symbol: 'tBTCUSD' }) 97 | assert.strictEqual(t.base(), 'BTC') 98 | }) 99 | }) 100 | }) 101 | -------------------------------------------------------------------------------- /test/lib/models/funding_trade.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _includes = require('lodash/includes') 6 | const { SYMBOLS } = require('bfx-hf-util') 7 | const { FundingTrade } = require('../../../lib') 8 | const testModel = require('../../helpers/test_model') 9 | const testModelValidation = require('../../helpers/test_model_validation') 10 | 11 | const VALID_SYMBOLS = Object.values(SYMBOLS) 12 | 13 | describe('FundingTrade model', () => { 14 | testModel({ 15 | model: FundingTrade, 16 | orderedFields: [ 17 | 'id', 'symbol', 'mtsCreate', 'offerID', 'amount', 'rate', 'period', 18 | 'maker' 19 | ] 20 | }) 21 | 22 | testModelValidation({ 23 | model: FundingTrade, 24 | validData: { 25 | symbol: VALID_SYMBOLS, 26 | id: [...(new Array(5))].map(() => Math.random()), 27 | mtsCreate: [...(new Array(5))].map(() => Math.random()), 28 | offerID: [...(new Array(5))].map(() => Math.random()), 29 | amount: [...(new Array(5))].map(() => Math.random()), 30 | rate: [...(new Array(5))].map(() => Math.random()), 31 | period: [...(new Array(5))].map(() => Math.random()), 32 | maker: [...(new Array(5))].map(() => Math.random() > 0.5) 33 | } 34 | }) 35 | 36 | describe('toString', () => { 37 | it('includes pertinent information', () => { 38 | const ft = new FundingTrade({ 39 | symbol: 'tBTCUSD', 40 | amount: 42, 41 | rate: 0.1, 42 | period: 30 43 | }) 44 | 45 | const str = ft.toString() 46 | assert.ok(/BTCUSD/.test(str), 'symbol missing') 47 | assert.ok(_includes(str, '42'), 'amount missing') 48 | assert.ok(_includes(str, '0.1'), 'rate missing') 49 | assert.ok(_includes(str, '30'), 'period missing') 50 | }) 51 | }) 52 | }) 53 | -------------------------------------------------------------------------------- /test/lib/models/invoice.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _compact = require('lodash/compact') 6 | const _includes = require('lodash/includes') 7 | const { Invoice } = require('../../../lib') 8 | const testModel = require('../../helpers/test_model') 9 | 10 | describe('Invoice model', () => { 11 | testModel({ 12 | model: Invoice, 13 | orderedFields: [ 14 | 'invoiceHash', 15 | 'invoice', 16 | null, 17 | null, 18 | 'amount' 19 | ] 20 | }) 21 | 22 | it('initializes correctly', () => { 23 | const invc = new Invoice([ 24 | 'invoiceHash', 25 | 'invoice', 26 | null, 27 | null, 28 | 'amount' 29 | ]) 30 | 31 | assert.strictEqual(invc.invoiceHash, 'invoiceHash') 32 | assert.strictEqual(invc.invoice, 'invoice') 33 | assert.strictEqual(invc.amount, 'amount') 34 | }) 35 | 36 | it('serializes correctly', () => { 37 | const invc = new Invoice([ 38 | 'invoiceHash', 39 | 'invoice', 40 | null, 41 | null, 42 | 'amount' 43 | ]) 44 | 45 | const arr = _compact(invc.serialize()) 46 | assert.deepStrictEqual(arr, [ 47 | 'invoiceHash', 48 | 'invoice', 49 | 'amount' 50 | ]) 51 | }) 52 | 53 | it('unserializes correctly', () => { 54 | const obj = Invoice.unserialize([ 55 | 'invoiceHash', 56 | 'invoice', 57 | null, 58 | null, 59 | 'amount' 60 | ]) 61 | 62 | assert.strictEqual(obj.invoiceHash, 'invoiceHash') 63 | assert.strictEqual(obj.invoice, 'invoice') 64 | assert.strictEqual(obj.amount, 'amount') 65 | }) 66 | 67 | describe('toString', () => { 68 | it('includes pertinent information', () => { 69 | const invc = new Invoice({ 70 | invoiceHash: 'invoiceHash', 71 | invoice: 'invoice', 72 | amount: '0.0001' 73 | }) 74 | 75 | const str = invc.toString() 76 | assert.ok(_includes(str, 'invoiceHash: invoiceHash'), 'invoiceHash missing') 77 | assert.ok(_includes(str, 'invoice: invoice'), 'invoice missing') 78 | assert.ok(_includes(str, 'amount: 0.0001'), 'amount missing') 79 | }) 80 | }) 81 | }) 82 | -------------------------------------------------------------------------------- /test/lib/models/ledger_entry.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { CURRENCIES } = require('bfx-hf-util') 5 | const { LedgerEntry } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | const VALID_CURRENCIES = Object.values(CURRENCIES) 10 | 11 | describe('Ledger entry model', () => { 12 | testModel({ 13 | model: LedgerEntry, 14 | orderedFields: [ 15 | 'id', 'currency', null, 'mts', null, 'amount', 'balance', null, 16 | 'description' 17 | ] 18 | }) 19 | 20 | testModelValidation({ 21 | model: LedgerEntry, 22 | validData: { 23 | currency: VALID_CURRENCIES, 24 | description: VALID_CURRENCIES, // pull data from somewhere 25 | id: [...(new Array(5))].map(() => Math.random()), 26 | mts: [...(new Array(5))].map(() => Math.random()), 27 | amount: [...(new Array(5))].map(() => Math.random()), 28 | balance: [...(new Array(5))].map(() => Math.random()) 29 | } 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /test/lib/models/liquidations.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _includes = require('lodash/includes') 6 | const { SYMBOLS } = require('bfx-hf-util') 7 | const { Liquidations } = require('../../../lib') 8 | const testModel = require('../../helpers/test_model') 9 | const testModelValidation = require('../../helpers/test_model_validation') 10 | 11 | const VALID_SYMBOLS = Object.values(SYMBOLS) 12 | 13 | describe('Liquidations entry model', () => { 14 | testModel({ 15 | model: Liquidations, 16 | orderedFields: [ 17 | null, 'posId', 'mtsUpdated', null, 'symbol', 'amount', 'basePrice', null, 'isMatch', 'isMarketSold' 18 | ] 19 | }) 20 | 21 | testModelValidation({ 22 | model: Liquidations, 23 | validData: { 24 | symbol: VALID_SYMBOLS, 25 | posId: [...(new Array(5))].map(() => Math.random()), 26 | mtsUpdated: [...(new Array(5))].map(() => Math.random()), 27 | amount: [...(new Array(5))].map(() => Math.random()), 28 | basePrice: [...(new Array(5))].map(() => Math.random()), 29 | isMatch: [...(new Array(5))].map(() => Math.random() > 0.5), 30 | isMarketSold: [...(new Array(5))].map(() => Math.random() > 0.5) 31 | } 32 | }) 33 | 34 | describe('toString', () => { 35 | it('includes pertinent information', () => { 36 | const l = new Liquidations({ 37 | symbol: 'tBTCUSD', 38 | amount: 42, 39 | basePrice: 0.1 40 | }) 41 | 42 | const str = l.toString() 43 | assert.ok(/BTCUSD/.test(str), 'symbol missing') 44 | assert.ok(_includes(str, '42'), 'amount missing') 45 | assert.ok(_includes(str, '0.1'), 'rate missing') 46 | }) 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /test/lib/models/login.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { SYMBOLS } = require('bfx-hf-util') 5 | const { Login } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | const VALID_SYMBOLS = Object.values(SYMBOLS) 10 | 11 | describe('Login entry model', () => { 12 | testModel({ 13 | model: Login, 14 | orderedFields: [ 15 | 'id', null, 'time', null, 'ip', null, null, 'extraData' 16 | ] 17 | }) 18 | 19 | testModelValidation({ 20 | model: Login, 21 | validData: { 22 | id: [...(new Array(5))].map(() => Math.random()), 23 | time: [...(new Array(5))].map(() => Math.random()), 24 | ip: VALID_SYMBOLS // grab data from somewhere 25 | } 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /test/lib/models/margin_info.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { MarginInfo } = require('../../../lib') 6 | 7 | describe('MarginInfo model', () => { 8 | // TODO: test validation 9 | 10 | it('initializes correctly w/ sym', () => { 11 | const miSym = new MarginInfo([ 12 | 'sym', 13 | 'tEOSUSD', 14 | [ 15 | 26912, 16 | 51443, 17 | 23397, 18 | 26912 19 | ] 20 | ]) 21 | 22 | assert.strictEqual(miSym.type, 'sym') 23 | assert.strictEqual(miSym.symbol, 'tEOSUSD') 24 | assert.strictEqual(miSym.tradableBalance, 26912) 25 | assert.strictEqual(miSym.grossBalance, 51443) 26 | assert.strictEqual(miSym.buy, 23397) 27 | assert.strictEqual(miSym.sell, 26912) 28 | }) 29 | 30 | it('initializes correctly for base', () => { 31 | const miBase = new MarginInfo([ 32 | 'base', 33 | [ 34 | -4784, 35 | -251, 36 | 16392, 37 | 11355 38 | ] 39 | ]) 40 | 41 | assert.strictEqual(miBase.type, 'base') 42 | assert.strictEqual(miBase.userPL, -4784) 43 | assert.strictEqual(miBase.userSwaps, -251) 44 | assert.strictEqual(miBase.marginBalance, 16392) 45 | assert.strictEqual(miBase.marginNet, 11355) 46 | }) 47 | 48 | it('serializes correctly w/ sym', () => { 49 | const miSym = new MarginInfo([ 50 | 'sym', 51 | 'tEOSUSD', 52 | [ 53 | 26912, 54 | 51443, 55 | 23397, 56 | 26912 57 | ] 58 | ]) 59 | 60 | const arr = miSym.serialize() 61 | 62 | assert.deepStrictEqual(arr, [ 63 | 'sym', 64 | 'tEOSUSD', 65 | [ 66 | 26912, 67 | 51443, 68 | 23397, 69 | 26912 70 | ] 71 | ]) 72 | }) 73 | 74 | it('serializes correctly for base', () => { 75 | const miBase = new MarginInfo([ 76 | 'base', 77 | [ 78 | -4784, 79 | -251, 80 | 16392, 81 | 11355 82 | ] 83 | ]) 84 | 85 | const arr = miBase.serialize() 86 | assert.deepStrictEqual(arr, [ 87 | 'base', 88 | [ 89 | -4784, 90 | -251, 91 | 16392, 92 | 11355 93 | ] 94 | ]) 95 | }) 96 | 97 | it('unserializes correctly w/ sym', () => { 98 | const obj = MarginInfo.unserialize([ 99 | 'sym', 100 | 'tEOSUSD', 101 | [ 102 | 26912, 103 | 51443, 104 | 23397, 105 | 26912 106 | ] 107 | ]) 108 | 109 | assert.strictEqual(obj.type, 'sym') 110 | assert.strictEqual(obj.symbol, 'tEOSUSD') 111 | assert.strictEqual(obj.tradableBalance, 26912) 112 | assert.strictEqual(obj.grossBalance, 51443) 113 | assert.strictEqual(obj.buy, 23397) 114 | assert.strictEqual(obj.sell, 26912) 115 | }) 116 | 117 | it('unserializes correctly for base', () => { 118 | const obj = MarginInfo.unserialize([ 119 | 'base', 120 | [ 121 | -4784, 122 | -251, 123 | 16392, 124 | 11355 125 | ] 126 | ]) 127 | 128 | assert.strictEqual(obj.type, 'base') 129 | assert.strictEqual(obj.userPL, -4784) 130 | assert.strictEqual(obj.userSwaps, -251) 131 | assert.strictEqual(obj.marginBalance, 16392) 132 | assert.strictEqual(obj.marginNet, 11355) 133 | }) 134 | }) 135 | -------------------------------------------------------------------------------- /test/lib/models/model.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | /* eslint-env mocha */ 3 | 4 | const assert = require('assert') 5 | const _isError = require('lodash/isError') 6 | const _isFinite = require('lodash/isFinite') 7 | const _isString = require('lodash/isString') 8 | const _isEmpty = require('lodash/isEmpty') 9 | const Model = require('../../../lib/model') 10 | 11 | describe('base model class', () => { 12 | describe('toJS', () => { 13 | it('returns a pojo version of the model', function () { 14 | const fields = { a: 0 } 15 | 16 | class SomeModel extends Model { 17 | constructor (data) { 18 | super({ data, fields }) 19 | } 20 | 21 | static unserialize (data) { 22 | return super.unserialize({ data, fields }) 23 | } 24 | } 25 | 26 | const m = new SomeModel({ a: 42 }) 27 | const js = m.toJS() 28 | 29 | assert.deepStrictEqual(js, { a: 42 }) 30 | }) 31 | }) 32 | 33 | describe('validate', () => { 34 | const fields = { num: 0, str: 1 } 35 | const validators = { 36 | num: v => _isFinite(v) ? null : 'must be a number', 37 | str: v => (_isString(v) && !_isEmpty(v)) ? null : 'must be a non-empty string' 38 | } 39 | 40 | const validateArgs = { fields, validators } 41 | const validInstance = { num: 42, str: 'some_data' } 42 | const invalidInstance = { num: null, str: null } 43 | 44 | it('returns null if an item passes the provided validators', () => { 45 | assert(Model.validate({ 46 | data: validInstance, 47 | ...validateArgs 48 | }) === null) 49 | }) 50 | 51 | it('returns error if an item fails the provided validators', () => { 52 | assert(_isError(Model.validate({ 53 | data: invalidInstance, 54 | ...validateArgs 55 | }))) 56 | }) 57 | 58 | it('returns error if a single item in a collection fails the validators', () => { 59 | assert(_isError(Model.validate({ 60 | data: [validInstance, validInstance, invalidInstance, validInstance], 61 | ...validateArgs 62 | }))) 63 | }) 64 | 65 | it('returns null if all items in a collection pass the validators', () => { 66 | assert(Model.validate({ 67 | data: [validInstance, validInstance, validInstance, validInstance], 68 | ...validateArgs 69 | }) === null) 70 | }) 71 | }) 72 | }) 73 | -------------------------------------------------------------------------------- /test/lib/models/movement.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { CURRENCIES } = require('bfx-hf-util') 5 | const { Movement } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | const VALID_CURRENCIES = Object.values(CURRENCIES) 10 | 11 | describe('Movement model', () => { 12 | testModel({ 13 | model: Movement, 14 | orderedFields: [ 15 | 'id', 'currency', 'currencyName', null, null, 'mtsStarted', 'mtsUpdated', 16 | null, null, 'status', null, null, 'amount', 'fees', null, null, 17 | 'destinationAddress', null, null, null, 'transactionId', 'note' 18 | ] 19 | }) 20 | 21 | testModelValidation({ 22 | model: Movement, 23 | validData: { 24 | currency: VALID_CURRENCIES, 25 | currencyName: VALID_CURRENCIES, // pull data from somewhere 26 | destinationAddress: VALID_CURRENCIES, // pull data from somewhere 27 | transactionId: VALID_CURRENCIES, // pull data from somewhere 28 | status: VALID_CURRENCIES, // pull data from somewhere 29 | id: [...(new Array(5))].map(() => Math.random()), 30 | mtsStarted: [...(new Array(5))].map(() => Math.random()), 31 | mtsUpdated: [...(new Array(5))].map(() => Math.random()), 32 | amount: [...(new Array(5))].map(() => Math.random()), 33 | fees: [...(new Array(5))].map(() => Math.random()), 34 | note: VALID_CURRENCIES // pull data from somewhere 35 | } 36 | }) 37 | }) 38 | -------------------------------------------------------------------------------- /test/lib/models/movement_info.js: -------------------------------------------------------------------------------- 1 | //* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { CURRENCIES } = require('bfx-hf-util') 5 | const { MovementInfo } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | const VALID_CURRENCIES = Object.values(CURRENCIES) 10 | 11 | describe('MovementInfo model', () => { 12 | testModel({ 13 | model: MovementInfo, 14 | orderedFields: [ 15 | 'id', 'currency', 'currencyName', null, 'remark', 'mtsStarted', 'mtsUpdated', 16 | null, null, 'status', null, null, 'amount', 'fees', null, null, 17 | 'destinationAddress', 'memo', null, null, 'transactionId', 'note', 18 | null, null, 'bankFees', 'bankRouterId', null, null, 'externalBankMovId', 19 | 'externalBankMovStatus', 'externalBankMovDescription', 'externalBankAccInfo' 20 | ] 21 | }) 22 | 23 | testModelValidation({ 24 | model: MovementInfo, 25 | validData: { 26 | id: [...(new Array(5))].map(() => Math.random()), 27 | currency: VALID_CURRENCIES, 28 | currencyName: VALID_CURRENCIES, // pull data from somewhere 29 | remark: VALID_CURRENCIES, 30 | mtsStarted: [...(new Array(5))].map(() => Math.random()), 31 | mtsUpdated: [...(new Array(5))].map(() => Math.random()), 32 | status: VALID_CURRENCIES, 33 | amount: [...(new Array(5))].map(() => Math.random()), 34 | fees: [...(new Array(5))].map(() => Math.random()), 35 | destinationAddress: VALID_CURRENCIES, 36 | memo: VALID_CURRENCIES, 37 | transactionId: VALID_CURRENCIES, 38 | note: VALID_CURRENCIES, 39 | bankFees: [...(new Array(5))].map(() => Math.random()), 40 | bankRouterId: [...(new Array(5))].map(() => Math.random()), 41 | externalBankMovId: VALID_CURRENCIES, 42 | externalBankMovStatus: VALID_CURRENCIES, 43 | externalBankMovDescription: VALID_CURRENCIES, 44 | externalBankAccInfo: [...(new Array(5))].map(() => ({ 45 | router: `my-router-${Math.random()}`, 46 | meta: { [`foo-${Math.random()}`]: `bar-${Math.random()}` } 47 | })) 48 | } 49 | }) 50 | }) 51 | -------------------------------------------------------------------------------- /test/lib/models/notification.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { SYMBOLS } = require('bfx-hf-util') 5 | const { Notification } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | const VALID_STRINGS = Object.values(SYMBOLS) 10 | 11 | describe('Notification model', () => { 12 | testModel({ 13 | model: Notification, 14 | orderedFields: [ 15 | 'mts', 'type', 'messageID', null, 'notifyInfo', 'code', 'status', 'text' 16 | ] 17 | }) 18 | 19 | testModelValidation({ 20 | model: Notification, 21 | validData: { 22 | status: VALID_STRINGS, // pull data from somewhere 23 | text: VALID_STRINGS, // pull data from somewhere 24 | type: ['success', 'error', 'info'], 25 | mts: [...(new Array(5))].map(() => Math.random()), 26 | messageID: [...(new Array(5))].map(() => Math.random()), 27 | code: [...(new Array(5))].map(() => Math.random()) 28 | } 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /test/lib/models/position.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _includes = require('lodash/includes') 6 | const { SYMBOLS } = require('bfx-hf-util') 7 | const { Position, Order } = require('../../../lib') 8 | const testModel = require('../../helpers/test_model') 9 | const testModelValidation = require('../../helpers/test_model_validation') 10 | 11 | const VALID_SYMBOLS = Object.values(SYMBOLS) 12 | 13 | const getTestPosition = (opts = {}) => new Position({ 14 | symbol: 'tLEOUDS', 15 | amount: 100, 16 | price: 2, 17 | ...opts 18 | }) 19 | 20 | describe('Position model', () => { 21 | testModel({ 22 | model: Position, 23 | orderedFields: [ 24 | 'symbol', 'status', 'amount', 'basePrice', 'marginFunding', 25 | 'marginFundingType', 'pl', 'plPerc', 'liquidationPrice', 'leverage', 26 | null, 'id', 'mtsCreate', 'mtsUpdate', null, 'type', null, 27 | 'collateral', 'collateralMin', 'meta' 28 | ] 29 | }) 30 | 31 | testModelValidation({ 32 | model: Position, 33 | validData: { 34 | symbol: VALID_SYMBOLS, 35 | status: VALID_SYMBOLS, // grab data from somewhere 36 | amount: [...(new Array(5))].map(() => Math.random()), 37 | basePrice: [...(new Array(5))].map(() => Math.random()), 38 | marginFunding: [...(new Array(5))].map(() => Math.random()), 39 | marginFundingType: VALID_SYMBOLS, // grab data from somewhere 40 | pl: [...(new Array(5))].map(() => Math.random()), 41 | plPerc: [...(new Array(5))].map(() => Math.random()), 42 | liquidationPrice: [...(new Array(5))].map(() => Math.random()), 43 | leverage: [...(new Array(5))].map(() => Math.random()), 44 | id: [...(new Array(5))].map(() => Math.random()), 45 | mtsCreate: [...(new Array(5))].map(() => Math.random()), 46 | mtsUpdate: [...(new Array(5))].map(() => Math.random()), 47 | type: VALID_SYMBOLS, // grab data from somewhere 48 | collateral: [...(new Array(5))].map(() => Math.random()), 49 | collateralMin: [...(new Array(5))].map(() => Math.random()) 50 | } 51 | }) 52 | 53 | describe('orderToClose', () => { 54 | it('generates a MARKET order', () => { 55 | const p = getTestPosition() 56 | const o = p.orderToClose() 57 | 58 | assert.strictEqual(o.type, Order.type.MARKET, 'position close order is not a market order') 59 | }) 60 | 61 | it('generates an order that would close the position', () => { 62 | const p = getTestPosition({ amount: 20 }) 63 | const o = p.orderToClose() 64 | 65 | assert.strictEqual(+o.amount, -20, 'position close order would not close the position') 66 | }) 67 | 68 | it('sets the reduce-only and pos-close flags', () => { 69 | const p = getTestPosition({ amount: 20 }) 70 | const o = p.orderToClose() 71 | 72 | assert.ok(o.flags & Order.flags.REDUCE_ONLY, 'position close order does not have reduce-only flag set') 73 | assert.ok(o.flags & Order.flags.REDUCE_ONLY, 'position close order does not have pos-close flag set') 74 | }) 75 | }) 76 | 77 | describe('claim', () => { 78 | it('throws an error if no interface provided', (done) => { 79 | const p = new Position() 80 | p.claim().catch(() => done()) 81 | }) 82 | 83 | it('calls claimPosition on the interface', (done) => { 84 | const p = new Position({ id: 42 }) 85 | p.claim({ 86 | claimPosition: async ({ id }) => { 87 | assert.strictEqual(id, 42) 88 | done() 89 | return [] 90 | } 91 | }) 92 | }) 93 | 94 | it('saves received data on itself', async () => { 95 | const p = new Position({ symbol: 'tBTCUSD' }) 96 | const remoteP = new Position({ symbol: 'just-testing' }) 97 | 98 | await p.claim({ 99 | claimPosition: async () => remoteP.serialize() 100 | }) 101 | 102 | assert.strictEqual(p.symbol, 'just-testing') 103 | }) 104 | }) 105 | 106 | describe('close', () => { 107 | it('throws an error if no interface provided', (done) => { 108 | const p = new Position() 109 | p.close().catch(() => done()) 110 | }) 111 | 112 | it('calls closePosition on the interface', (done) => { 113 | const p = new Position({ id: 42 }) 114 | p.close({ 115 | closePosition: async ({ position_id }) => { // eslint-disable-line 116 | assert.strictEqual(position_id, 42) // eslint-disable-line 117 | done() 118 | } 119 | }) 120 | }) 121 | }) 122 | 123 | describe('toString', () => { 124 | it('includes pertinent information', () => { 125 | const p = new Position({ 126 | symbol: 'tBTCUSD', 127 | amount: 42, 128 | price: 1, 129 | type: 'STOP', 130 | hidden: true, 131 | postonly: true, 132 | reduceonly: true, 133 | pl: 9001, 134 | liquidationPrice: 33 135 | }) 136 | 137 | const str = p.toString() 138 | assert.ok(/BTC\/USD/.test(str), 'symbol missing') 139 | assert.ok(_includes(str, '1'), 'price missing') 140 | assert.ok(_includes(str, '42'), 'amount missing') 141 | assert.ok(_includes(str, '9001'), 'pl missing') 142 | assert.ok(_includes(str, '33'), 'liq price missing') 143 | }) 144 | }) 145 | }) 146 | -------------------------------------------------------------------------------- /test/lib/models/public_trade.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _includes = require('lodash/includes') 6 | const { RESTv2 } = require('bfx-api-node-rest') 7 | const { PublicTrade } = require('../../../lib') 8 | const testModel = require('../../helpers/test_model') 9 | const testModelValidation = require('../../helpers/test_model_validation') 10 | 11 | const snapshot = [ 12 | [267951933, 1645117845846, -5862.1, 0.002, 2], 13 | [267947377, 1645115432454, -83763.1, 0.003, 3] 14 | ] 15 | 16 | describe('Public Trade model', () => { 17 | testModel({ 18 | model: PublicTrade, 19 | orderedFields: ['id', 'mts', 'amount', 'price'] 20 | }) 21 | 22 | // TODO: Fix this 23 | /* 24 | testModelValidation({ // funding 25 | model: PublicTrade, 26 | validData: { 27 | id: [...(new Array(5))].map(() => Math.random()), 28 | mts: [...(new Array(5))].map(() => Math.random()), 29 | amount: [...(new Array(5))].map(() => Math.random()), 30 | rate: [...(new Array(5))].map(() => Math.random()), 31 | period: [...(new Array(5))].map(() => Math.random()) 32 | } 33 | }) 34 | */ 35 | 36 | testModelValidation({ // trading 37 | model: PublicTrade, 38 | validData: { 39 | id: [...(new Array(5))].map(() => Math.random()), 40 | mts: [...(new Array(5))].map(() => Math.random()), 41 | amount: [...(new Array(5))].map(() => Math.random()), 42 | price: [...(new Array(5))].map(() => Math.random()) 43 | } 44 | }) 45 | 46 | it('unserializes live trading data correctly', async () => { 47 | const rest = new RESTv2() 48 | const arr = await rest.trades('tBTCUSD') 49 | 50 | arr.forEach(trade => { 51 | const obj = PublicTrade.unserialize(trade) 52 | 53 | Object.keys(PublicTrade.TRADING_FIELDS).forEach(field => { 54 | assert.strictEqual(obj[field], trade[PublicTrade.TRADING_FIELDS[field]]) 55 | }) 56 | }) 57 | }).timeout(60000) 58 | 59 | it('unserializes live funding data correctly', async () => { 60 | const rest = new RESTv2() 61 | const arr = await rest.trades('fUSD') 62 | 63 | arr.forEach(trade => { 64 | const obj = PublicTrade.unserialize(trade) 65 | 66 | Object.keys(PublicTrade.FUNDING_FIELDS).forEach(field => { 67 | assert.strictEqual(obj[field], trade[PublicTrade.FUNDING_FIELDS[field]]) 68 | }) 69 | }) 70 | }).timeout(60000) 71 | 72 | it('unserializes snapshot', async () => { 73 | const serialized = PublicTrade.unserialize(snapshot) 74 | 75 | serialized.forEach((item, i) => { 76 | Object.keys(PublicTrade.FUNDING_FIELDS).forEach(field => { 77 | assert.strictEqual(item[field], snapshot[i][PublicTrade.FUNDING_FIELDS[field]]) 78 | }) 79 | }) 80 | }).timeout(60000) 81 | 82 | it('creates instance from unserialized snapshot ', async () => { 83 | const trades = new PublicTrade(PublicTrade.unserialize(snapshot)) 84 | 85 | for (let i = 0; i < trades.length; i++) { 86 | const item = trades[i] 87 | 88 | Object.keys(PublicTrade.FUNDING_FIELDS).forEach(field => { 89 | assert.strictEqual(item[field], snapshot[i][PublicTrade.FUNDING_FIELDS[field]]) 90 | }) 91 | } 92 | }).timeout(60000) 93 | 94 | it('creates instance from snapshot', async () => { 95 | const trades = new PublicTrade(snapshot) 96 | 97 | for (let i = 0; i < trades.length; i++) { 98 | const item = trades[i] 99 | 100 | Object.keys(PublicTrade.FUNDING_FIELDS).forEach(field => { 101 | assert.strictEqual(item[field], snapshot[i][PublicTrade.FUNDING_FIELDS[field]]) 102 | }) 103 | } 104 | }).timeout(60000) 105 | 106 | describe('toString', () => { 107 | it('includes pertinent information', () => { 108 | const t = new PublicTrade({ 109 | id: 42, 110 | amount: 3, 111 | price: 7 112 | }) 113 | 114 | const str = t.toString() 115 | assert.ok(_includes(str, '42'), 'id missing') 116 | assert.ok(_includes(str, '3'), 'amount missing') 117 | assert.ok(_includes(str, '7'), 'price missing') 118 | }) 119 | }) 120 | }) 121 | -------------------------------------------------------------------------------- /test/lib/models/status_messages_deriv.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { SYMBOLS } = require('bfx-hf-util') 5 | const { StatusMessagesDeriv } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | const VALID_STRINGS = Object.values(SYMBOLS) 10 | 11 | describe('Derivatives Status Message model', () => { 12 | testModel({ 13 | model: StatusMessagesDeriv, 14 | orderedFields: [ 15 | 'key', 'timestamp', null, 'price', 'priceSpot', null, 'fundBal', null, 16 | null, 'fundingAccrued', 'fundingStep', null, null, null, null, null, 17 | null, null, null, null, null, null, 'clampMin', 'clampMax' 18 | ] 19 | }) 20 | 21 | testModelValidation({ 22 | model: StatusMessagesDeriv, 23 | validData: { 24 | key: VALID_STRINGS, // pull data from somewhere 25 | timestamp: VALID_STRINGS, // pull data from somewhere 26 | price: new Array(5).fill().map(Math.random), 27 | priceSpot: new Array(5).fill().map(Math.random), 28 | fundBal: new Array(5).fill().map(Math.random), 29 | fundingAccrued: new Array(5).fill().map(Math.random), 30 | fundingStep: new Array(5).fill().map(Math.random), 31 | clampMin: new Array(5).fill().map(Math.random), 32 | clampMax: new Array(5).fill().map(Math.random) 33 | } 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /test/lib/models/symbol_details.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { SYMBOLS } = require('bfx-hf-util') 6 | const { SymbolDetails } = require('../../../lib') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | const VALID_SYMBOLS = Object.values(SYMBOLS) 10 | const DATA = ['BTCEUR', [null, null, null, '0.0002', '2000.0', null, null, null, 0.2, 0.1]] 11 | 12 | describe('Symbol Details model', () => { 13 | testModelValidation({ 14 | model: SymbolDetails, 15 | validData: { 16 | pair: VALID_SYMBOLS, 17 | initialMargin: [...(new Array(5))].map(() => Math.random()), 18 | minimumMargin: [...(new Array(5))].map(() => Math.random()), 19 | maximumOrderSize: [...(new Array(5))].map(() => Math.random().toString()), 20 | minimumOrderSize: [...(new Array(5))].map(() => Math.random().toString()), 21 | margin: [true, false] 22 | } 23 | }) 24 | 25 | it('initializes correctly', () => { 26 | const details = new SymbolDetails(DATA) 27 | assert.strictEqual(details.pair, 'BTCEUR') 28 | assert.strictEqual(details.initialMargin, 0.2) 29 | assert.strictEqual(details.minimumMargin, 0.1) 30 | assert.strictEqual(details.maximumOrderSize, '2000.0') 31 | assert.strictEqual(details.minimumOrderSize, '0.0002') 32 | assert.strictEqual(details.margin, true) 33 | }) 34 | 35 | it('serializes correctly', () => { 36 | const details = new SymbolDetails(DATA) 37 | const arr = details.serialize() 38 | 39 | assert.deepStrictEqual(arr, DATA) 40 | }) 41 | 42 | it('unserializes correctly', () => { 43 | const details = SymbolDetails.unserialize(DATA) 44 | assert.strictEqual(details.pair, 'BTCEUR') 45 | assert.strictEqual(details.initialMargin, 0.2) 46 | assert.strictEqual(details.minimumMargin, 0.1) 47 | assert.strictEqual(details.maximumOrderSize, '2000.0') 48 | assert.strictEqual(details.minimumOrderSize, '0.0002') 49 | assert.strictEqual(details.margin, true) 50 | }) 51 | }) 52 | -------------------------------------------------------------------------------- /test/lib/models/trade.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _includes = require('lodash/includes') 6 | const { SYMBOLS, CURRENCIES } = require('bfx-hf-util') 7 | const { Trade, Order } = require('../../../lib') 8 | const testModel = require('../../helpers/test_model') 9 | const testModelValidation = require('../../helpers/test_model_validation') 10 | 11 | const VALID_CURRENCIES = Object.values(CURRENCIES) 12 | const VALID_SYMBOLS = Object.values(SYMBOLS) 13 | 14 | describe('Trade model', () => { 15 | testModel({ 16 | model: Trade, 17 | boolFields: ['maker'], 18 | orderedFields: [ 19 | 'id', 'symbol', 'mtsCreate', 'orderID', 'execAmount', 'execPrice', 20 | 'orderType', 'orderPrice', 'maker', 'fee', 'feeCurrency' 21 | ] 22 | }) 23 | 24 | testModelValidation({ 25 | model: Trade, 26 | validData: { 27 | symbol: VALID_SYMBOLS, 28 | orderID: VALID_SYMBOLS, // get some data 29 | orderType: Object.values(Order.type), 30 | id: [...(new Array(5))].map(() => Math.random()), 31 | mtsCreate: [...(new Array(5))].map(() => Math.random()), 32 | execAmount: [...(new Array(5))].map(() => Math.random()), 33 | execPrice: [...(new Array(5))].map(() => Math.random()), 34 | orderPrice: [...(new Array(5))].map(() => Math.random()), 35 | maker: [...(new Array(5))].map(() => Math.random() > 0.5), 36 | fee: [...(new Array(5))].map(() => Math.random()), 37 | feeCurrency: VALID_CURRENCIES 38 | } 39 | }) 40 | 41 | describe('toString', () => { 42 | it('includes pertinent information', () => { 43 | const t = new Trade({ 44 | symbol: 'tBTCUSD', 45 | id: 1, 46 | execAmount: 24, 47 | execPrice: 32, 48 | maker: true, 49 | fee: 7, 50 | feeCurrency: 'ETH' 51 | }) 52 | 53 | const str = t.toString() 54 | assert.ok(/tBTCUSD/.test(str), 'symbol missing') 55 | assert.ok(_includes(str, '1'), 'id missing') 56 | assert.ok(_includes(str, '32'), 'exec price missing') 57 | assert.ok(_includes(str, '24'), 'exec amount missing') 58 | assert.ok(/maker/.test(str), 'maker flag missing') 59 | assert.ok(_includes(str, '7'), 'fee missing') 60 | assert.ok(/ETH/.test(str), 'fee currency missing') 61 | }) 62 | }) 63 | }) 64 | -------------------------------------------------------------------------------- /test/lib/models/trading_ticker.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { SYMBOLS } = require('bfx-hf-util') 6 | const { RESTv2 } = require('bfx-api-node-rest') 7 | const { TradingTicker } = require('../../../lib') 8 | const testModel = require('../../helpers/test_model') 9 | const testModelValidation = require('../../helpers/test_model_validation') 10 | 11 | const VALID_SYMBOLS = Object.values(SYMBOLS) 12 | const DATA = [ 13 | 'tBTCUSD', 14 | 228.56, 15 | 430.1902224, 16 | 228.58, 17 | 496.39268958, 18 | -55.08222913, 19 | -0.1942, 20 | 228.56777087, 21 | 881908.12214509, 22 | 284.62, 23 | 211.19 24 | ] 25 | 26 | describe('TradingTicker model', () => { 27 | testModel({ 28 | model: TradingTicker, 29 | orderedFields: [ 30 | 'symbol', 'bid', 'bidSize', 'ask', 'askSize', 'dailyChange', 31 | 'dailyChangePerc', 'lastPrice', 'volume', 'high', 'low' 32 | ] 33 | }) 34 | 35 | testModelValidation({ 36 | model: TradingTicker, 37 | validData: { 38 | symbol: VALID_SYMBOLS, 39 | bid: [...(new Array(5))].map(() => Math.random()), 40 | bidSize: [...(new Array(5))].map(() => Math.random()), 41 | ask: [...(new Array(5))].map(() => Math.random()), 42 | askSize: [...(new Array(5))].map(() => Math.random()), 43 | dailyChange: [...(new Array(5))].map(() => Math.random()), 44 | dailyChangePerc: [...(new Array(5))].map(() => Math.random()), 45 | lastPrice: [...(new Array(5))].map(() => Math.random()), 46 | volume: [...(new Array(5))].map(() => Math.random()), 47 | high: [...(new Array(5))].map(() => Math.random()), 48 | low: [...(new Array(5))].map(() => Math.random()) 49 | } 50 | }) 51 | 52 | it('initializes correctly', () => { 53 | const ticker = new TradingTicker(DATA) 54 | 55 | assert.strictEqual(ticker.symbol, 'tBTCUSD') 56 | assert.strictEqual(ticker.bid, 228.56) 57 | assert.strictEqual(ticker.bidSize, 430.1902224) 58 | assert.strictEqual(ticker.ask, 228.58) 59 | assert.strictEqual(ticker.askSize, 496.39268958) 60 | assert.strictEqual(ticker.dailyChange, -55.08222913) 61 | assert.strictEqual(ticker.dailyChangePerc, -0.1942) 62 | assert.strictEqual(ticker.lastPrice, 228.56777087) 63 | assert.strictEqual(ticker.volume, 881908.12214509) 64 | assert.strictEqual(ticker.high, 284.62) 65 | assert.strictEqual(ticker.low, 211.19) 66 | }) 67 | 68 | it('serializes correctly', () => { 69 | const ticker = new TradingTicker(DATA) 70 | const arr = ticker.serialize() 71 | 72 | assert.deepStrictEqual(arr, DATA) 73 | }) 74 | 75 | it('unserializes correctly', () => { 76 | const obj = TradingTicker.unserialize(DATA) 77 | 78 | assert.strictEqual(obj.symbol, 'tBTCUSD') 79 | assert.strictEqual(obj.bid, 228.56) 80 | assert.strictEqual(obj.bidSize, 430.1902224) 81 | assert.strictEqual(obj.ask, 228.58) 82 | assert.strictEqual(obj.askSize, 496.39268958) 83 | assert.strictEqual(obj.dailyChange, -55.08222913) 84 | assert.strictEqual(obj.dailyChangePerc, -0.1942) 85 | assert.strictEqual(obj.lastPrice, 228.56777087) 86 | assert.strictEqual(obj.volume, 881908.12214509) 87 | assert.strictEqual(obj.high, 284.62) 88 | assert.strictEqual(obj.low, 211.19) 89 | }) 90 | 91 | it('unserializes live data correctly', async () => { 92 | const rest = new RESTv2() 93 | const arr = await rest.ticker({ symbol: 'tBTCUSD' }) 94 | const obj = TradingTicker.unserialize(arr) 95 | 96 | assert.strictEqual(obj.symbol, arr[0]) 97 | assert.strictEqual(obj.bid, arr[1]) 98 | assert.strictEqual(obj.bidSize, arr[2]) 99 | assert.strictEqual(obj.ask, arr[3]) 100 | assert.strictEqual(obj.askSize, arr[4]) 101 | assert.strictEqual(obj.dailyChange, arr[5]) 102 | assert.strictEqual(obj.dailyChangePerc, arr[6]) 103 | assert.strictEqual(obj.lastPrice, arr[7]) 104 | assert.strictEqual(obj.volume, arr[8]) 105 | assert.strictEqual(obj.high, arr[9]) 106 | assert.strictEqual(obj.low, arr[10]) 107 | }) 108 | 109 | describe('base', () => { 110 | it('returns the base currency for the ticker', () => { 111 | const t = new TradingTicker({ symbol: 'tBTCUSD' }) 112 | assert.strictEqual(t.base(), 'BTC') 113 | }) 114 | }) 115 | 116 | describe('quote', () => { 117 | it('returns the quote currency for the ticker', () => { 118 | const t = new TradingTicker({ symbol: 'tBTCUSD' }) 119 | assert.strictEqual(t.quote(), 'USD') 120 | }) 121 | }) 122 | }) 123 | -------------------------------------------------------------------------------- /test/lib/models/trading_ticker_hist.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { RESTv2 } = require('bfx-api-node-rest') 6 | const { SYMBOLS } = require('bfx-hf-util') 7 | const { TradingTickerHist } = require('../../../lib') 8 | const testModel = require('../../helpers/test_model') 9 | const testModelValidation = require('../../helpers/test_model_validation') 10 | 11 | const VALID_SYMBOLS = Object.values(SYMBOLS) 12 | const DATA = [ 13 | 'tBTCUSD', 14 | 228.56, 15 | null, 16 | 228.58, 17 | null, 18 | null, 19 | null, 20 | null, 21 | null, 22 | null, 23 | null, 24 | null, 25 | 1544097835000 26 | ] 27 | 28 | describe('TradingTickerHistory model', () => { 29 | testModel({ 30 | model: TradingTickerHist, 31 | orderedFields: [ 32 | 'symbol', 'bid', null, 'ask', null, null, null, null, null, null, null, 33 | null, 'mtsUpdate' 34 | ] 35 | }) 36 | 37 | testModelValidation({ 38 | model: TradingTickerHist, 39 | validData: { 40 | symbol: VALID_SYMBOLS, 41 | bid: [...(new Array(5))].map(() => Math.random()), 42 | ask: [...(new Array(5))].map(() => Math.random()), 43 | mtsUpdated: [...(new Array(5))].map(() => Math.random()) 44 | } 45 | }) 46 | 47 | it('initializes correctly', () => { 48 | const ticker = new TradingTickerHist(DATA) 49 | 50 | assert.strictEqual(ticker.symbol, 'tBTCUSD') 51 | assert.strictEqual(ticker.bid, 228.56) 52 | assert.strictEqual(ticker.ask, 228.58) 53 | assert.strictEqual(ticker.mtsUpdate, 1544097835000) 54 | }) 55 | 56 | it('serializes correctly', () => { 57 | const ticker = new TradingTickerHist(DATA) 58 | const arr = ticker.serialize() 59 | 60 | assert.strictEqual(JSON.stringify(arr), JSON.stringify(DATA)) 61 | }) 62 | 63 | it('unserializes correctly', () => { 64 | const obj = TradingTickerHist.unserialize(DATA) 65 | 66 | assert.strictEqual(obj.symbol, 'tBTCUSD') 67 | assert.strictEqual(obj.bid, 228.56) 68 | assert.strictEqual(obj.ask, 228.58) 69 | assert.strictEqual(obj.mtsUpdate, 1544097835000) 70 | }) 71 | 72 | it('unserializes live data correctly', async () => { 73 | const rest = new RESTv2() 74 | const arr = await rest.ticker({ symbol: 'tBTCUSD' }) 75 | const obj = TradingTickerHist.unserialize(arr) 76 | 77 | assert.strictEqual(obj.symbol, arr[0]) 78 | assert.strictEqual(obj.bid, arr[1]) 79 | assert.strictEqual(obj.ask, arr[3]) 80 | assert.strictEqual(obj.mtsUpdate, arr[12]) 81 | }) 82 | 83 | describe('base', () => { 84 | it('returns the base currency for the ticker', () => { 85 | const t = new TradingTickerHist({ symbol: 'tBTCUSD' }) 86 | assert.strictEqual(t.base(), 'BTC') 87 | }) 88 | }) 89 | 90 | describe('quote', () => { 91 | it('returns the quote currency for the ticker', () => { 92 | const t = new TradingTickerHist({ symbol: 'tBTCUSD' }) 93 | assert.strictEqual(t.quote(), 'USD') 94 | }) 95 | }) 96 | }) 97 | -------------------------------------------------------------------------------- /test/lib/models/transaction_fee.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const { SYMBOLS } = require('bfx-hf-util') 6 | const { TransactionFee } = require('../../../lib') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | const VALID_SYMBOLS = Object.values(SYMBOLS) 10 | const DATA = ['BTC', [0, 0.0004]] 11 | 12 | describe('Transaction Fee model', () => { 13 | testModelValidation({ 14 | model: TransactionFee, 15 | validData: { 16 | symbol: VALID_SYMBOLS, 17 | fee: [...(new Array(5))].map(() => Math.random()) 18 | } 19 | }) 20 | 21 | it('initializes correctly', () => { 22 | const txFee = new TransactionFee(DATA) 23 | assert.strictEqual(txFee.symbol, 'BTC') 24 | assert.strictEqual(txFee.fee, 0.0004) 25 | }) 26 | 27 | it('serializes correctly', () => { 28 | const txFee = new TransactionFee(DATA) 29 | const arr = txFee.serialize() 30 | 31 | assert.deepStrictEqual(arr, DATA) 32 | }) 33 | 34 | it('unserializes correctly', () => { 35 | const txFee = TransactionFee.unserialize(DATA) 36 | assert.strictEqual(txFee.symbol, 'BTC') 37 | assert.strictEqual(txFee.fee, 0.0004) 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /test/lib/models/user_info.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { UserInfo } = require('../../../lib') 5 | const testModel = require('../../helpers/test_model') 6 | const testModelValidation = require('../../helpers/test_model_validation') 7 | 8 | describe('User info model', () => { 9 | testModel({ 10 | model: UserInfo, 11 | orderedFields: [ 12 | 'id', 'email', 'username', null, null, null, null, 'timezone', 13 | null, null, null, null, null, null, null, null, null, null, null, 14 | null, null, 'isPaperTradeEnabled', 'isUserMerchant' 15 | ] 16 | }) 17 | 18 | testModelValidation({ 19 | model: UserInfo, 20 | validData: { 21 | id: [...(new Array(5))].map(() => Math.random()), 22 | email: ['test@test.com', 'what@testing.com', 'really@nope.com'], 23 | username: ['not', 'today', 'man', 'but', 'maybe', 'tomorrow'], 24 | timezone: ['all', 'over', 'the', 'world', 'vim', 'and', 'all'], 25 | isPaperTradeEnabled: [true, false], 26 | isUserMerchant: [true, false] 27 | } 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /test/lib/models/wallet.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { CURRENCIES, WALLET_TYPES } = require('bfx-hf-util') 5 | const { Wallet } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | describe('Wallet', () => { 10 | testModel({ 11 | model: Wallet, 12 | orderedFields: [ 13 | 'type', 'currency', 'balance', 'unsettledInterest', 'balanceAvailable' 14 | ] 15 | }) 16 | 17 | testModelValidation({ 18 | model: Wallet, 19 | validData: { 20 | type: Object.values(WALLET_TYPES), 21 | currency: Object.values(CURRENCIES), 22 | description: [null, ...Object.values(CURRENCIES)], 23 | meta: [null, ...Object.values(CURRENCIES).map(reason => ({ reason: 'TRADE' }))], // need a data source 24 | balance: [...(new Array(5))].map(() => Math.random()), 25 | balanceAvailable: [...(new Array(5))].map(() => Math.random()), 26 | unsettledInterest: [...(new Array(5))].map(() => Math.random()) 27 | } 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /test/lib/models/wallet_hist.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { CURRENCIES, WALLET_TYPES } = require('bfx-hf-util') 5 | const { WalletHist } = require('../../../lib') 6 | const testModel = require('../../helpers/test_model') 7 | const testModelValidation = require('../../helpers/test_model_validation') 8 | 9 | describe('Historical wallet model', () => { 10 | testModel({ 11 | model: WalletHist, 12 | orderedFields: [ 13 | 'type', 'currency', 'balance', 'unsettledInterest', 'balanceAvailable', null, 'mtsUpdate' 14 | ] 15 | }) 16 | 17 | testModelValidation({ 18 | model: WalletHist, 19 | validData: { 20 | type: Object.values(WALLET_TYPES), 21 | currency: Object.values(CURRENCIES), 22 | balance: [...(new Array(5))].map(() => Math.random()), 23 | balanceAvailable: [...(new Array(5))].map(() => Math.random()), 24 | unsettledInterest: [...(new Array(5))].map(() => Math.random()), 25 | mtsUpdate: [...(new Array(5))].map(() => Math.random()) 26 | } 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /test/lib/models/weighted_averages.js: -------------------------------------------------------------------------------- 1 | //* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const { WeightedAverages } = require('../../../lib') 5 | const testModel = require('../../helpers/test_model') 6 | const testModelValidation = require('../../helpers/test_model_validation') 7 | 8 | describe('WeightedAverages model', () => { 9 | testModel({ 10 | model: WeightedAverages, 11 | orderedFields: [ 12 | 'tradeCount', 'sumBuyingSpent', 'sumBuyingAmount', null, 13 | 'sumSellingSpent', 'sumSellingAmount', null, 14 | 'buyingWeightedPrice', 'sellingWeightedPrice', null, 15 | 'firstTradeMts', 'lastTradeMts' 16 | ] 17 | }) 18 | 19 | testModelValidation({ 20 | model: WeightedAverages, 21 | validData: { 22 | tradeCount: [...(new Array(5))].map(() => Math.random()), 23 | sumBuyingSpent: [...(new Array(5))].map(() => Math.random()), 24 | sumBuyingAmount: [...(new Array(5))].map(() => Math.random()), 25 | sumSellingSpent: [...(new Array(5))].map(() => Math.random()), 26 | sumSellingAmount: [...(new Array(5))].map(() => Math.random()), 27 | buyingWeightedPrice: [...(new Array(5))].map(() => Math.random()), 28 | sellingWeightedPrice: [...(new Array(5))].map(() => Math.random()), 29 | firstTradeMts: [...(new Array(5))].map(() => Math.random()), 30 | lastTradeMts: [...(new Array(5))].map(() => Math.random()) 31 | } 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /test/lib/util/arr_fill_empty.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | /* eslint-env mocha */ 3 | 4 | const assert = require('assert') 5 | const arrFillEmpty = require('../../../lib/util/arr_fill_empty') 6 | 7 | describe('arrFillEmpty', () => { 8 | it('it should fill empty spots with null', () => { 9 | const arr = new Array(5) 10 | arr[3] = new Array(3) 11 | arr[3][1] = true 12 | arr[1] = 'test' 13 | 14 | arrFillEmpty(arr) 15 | const expected = [null, 'test', null, [null, true, null], null] 16 | 17 | assert.deepStrictEqual(arr, expected) 18 | }) 19 | 20 | it('it should fill empty spots with value when specified', () => { 21 | const arr = new Array(5) 22 | arr[3] = new Array(3) 23 | arr[3][1] = true 24 | arr[1] = 'test' 25 | 26 | arrFillEmpty(arr, false) 27 | const expected = [false, 'test', false, [false, true, false], false] 28 | 29 | assert.deepStrictEqual(arr, expected) 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /test/lib/util/assign_from_collection_or_instance.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | /* eslint-env mocha */ 3 | 4 | const assert = require('assert') 5 | const _isArray = require('lodash/isArray') 6 | const _isObject = require('lodash/isObject') 7 | const _isFinite = require('lodash/isFinite') 8 | const isCollection = require('../../../lib/util/is_collection') 9 | const assignFromCollectionOrInstance = require('../../../lib/util/assign_from_collection_or_instance') 10 | 11 | describe('static assignFromCollectionOrInstance', () => { 12 | it('correctly assigns object values', () => { 13 | class TestModel { 14 | static unserialize (data) { 15 | assert(_isObject(data)) 16 | assert.deepStrictEqual(Object.keys(data), { a: 5, b: 42 }) 17 | 18 | return data // already object 19 | } 20 | } 21 | 22 | const data = { a: 5, b: 42 } 23 | const target = new TestModel() 24 | 25 | assignFromCollectionOrInstance({ data, target }) 26 | 27 | assert.strictEqual(target.a, 5) 28 | assert.strictEqual(target.b, 42) 29 | }) 30 | 31 | it('correctly assigns an array of objects via iterator', () => { 32 | class TestModel { 33 | static unserialize (data) { 34 | if (isCollection(data)) { 35 | return data.map(TestModel.unserialize) 36 | } 37 | 38 | assert(_isObject(data)) 39 | assert.deepStrictEqual(Object.keys(data), ['a']) 40 | 41 | return data // already object 42 | } 43 | } 44 | 45 | const data = [{ a: 0 }, { a: 1 }, { a: 2 }, { a: 3 }] 46 | const target = new TestModel() 47 | 48 | assignFromCollectionOrInstance({ data, target }) 49 | 50 | assert.strictEqual(target.length, 4) 51 | assert.deepStrictEqual(target[0], { a: 0 }) 52 | assert.deepStrictEqual(target[1], { a: 1 }) 53 | assert.deepStrictEqual(target[2], { a: 2 }) 54 | assert.deepStrictEqual(target[3], { a: 3 }) 55 | }) 56 | 57 | it('correctly assigns an array of arrays via iterator', () => { 58 | class TestModel { 59 | static unserialize (data) { 60 | if (isCollection(data)) { 61 | return data.map(TestModel.unserialize) 62 | } 63 | 64 | assert(_isArray(data)) 65 | assert.strictEqual(data.length, 1) 66 | assert(_isFinite(data[0])) 67 | 68 | return { a: data[0] } 69 | } 70 | } 71 | 72 | const data = [[0], [1], [2], [3]] 73 | const target = new TestModel() 74 | 75 | assignFromCollectionOrInstance({ data, target }) 76 | 77 | assert.strictEqual(target.length, 4) 78 | assert.deepStrictEqual(target[0], { a: 0 }) 79 | assert.deepStrictEqual(target[1], { a: 1 }) 80 | assert.deepStrictEqual(target[2], { a: 2 }) 81 | assert.deepStrictEqual(target[3], { a: 3 }) 82 | }) 83 | 84 | it('correctly assigns an array model via unserialize', (done) => { 85 | class TestModel { 86 | static unserialize (data) { 87 | assert.strictEqual(data.length, 4) 88 | assert.deepStrictEqual(data, [0, 1, 2, 3]) 89 | done() 90 | } 91 | } 92 | 93 | const data = [0, 1, 2, 3] 94 | const target = new TestModel() 95 | 96 | assignFromCollectionOrInstance({ data, target }) 97 | }) 98 | }) 99 | -------------------------------------------------------------------------------- /test/lib/util/is_collection.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | /* eslint-env mocha */ 3 | 4 | const assert = require('assert') 5 | const isCollection = require('../../../lib/util/is_collection') 6 | 7 | describe('isCollection', () => { 8 | it('false for a single array', () => assert(!isCollection([]))) 9 | it('false for a single object', () => assert(!isCollection({}))) 10 | it('true for an array of arrays', () => assert(isCollection([[], []]))) 11 | it('true for an array of objects', () => assert(isCollection([{}, {}]))) 12 | it('true for an array of mixed arrays and objects', () => assert(isCollection([[], {}]))) 13 | }) 14 | -------------------------------------------------------------------------------- /test/lib/validators/amount.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _isEmpty = require('lodash/isEmpty') 6 | const validator = require('../../../lib/validators/amount') 7 | 8 | describe('amount validator', () => { 9 | it('returns no error if given a number', () => { 10 | assert.strictEqual(validator(42), null, 'failed validation for a number') 11 | }) 12 | 13 | it('returns an error for any other value', () => { 14 | assert.ok(!_isEmpty(validator('42')), 'passed validation for number') 15 | assert.ok(!_isEmpty(validator({})), 'passed validation for object') 16 | assert.ok(!_isEmpty(validator([])), 'passed validation for array') 17 | assert.ok(!_isEmpty(validator(true)), 'passed validation for bool') 18 | assert.ok(!_isEmpty(validator(() => {})), 'passed validation for func') 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /test/lib/validators/bool.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _isEmpty = require('lodash/isEmpty') 6 | const validator = require('../../../lib/validators/bool') 7 | 8 | describe('bool validator', () => { 9 | it('returns no error if given a bool', () => { 10 | assert.strictEqual(validator(true), null, 'failed validation for true') 11 | assert.strictEqual(validator(false), null, 'failed validation for false') 12 | }) 13 | 14 | it('returns an error for any other value', () => { 15 | assert.ok(!_isEmpty(validator(3)), 'passed validation for number') 16 | assert.ok(!_isEmpty(validator('42')), 'passed validation for number') 17 | assert.ok(!_isEmpty(validator({})), 'passed validation for object') 18 | assert.ok(!_isEmpty(validator([])), 'passed validation for array') 19 | assert.ok(!_isEmpty(validator(() => {})), 'passed validation for func') 20 | }) 21 | }) 22 | -------------------------------------------------------------------------------- /test/lib/validators/currency.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _isEmpty = require('lodash/isEmpty') 6 | const { CURRENCIES } = require('bfx-hf-util') 7 | const validator = require('../../../lib/validators/currency') 8 | 9 | const VALID_CURRENCIES = Object.values(CURRENCIES) 10 | 11 | describe('currency validator', () => { 12 | it('returns no error for known currencies', () => { 13 | VALID_CURRENCIES.forEach((ccy) => { 14 | assert.strictEqual(validator(ccy), null, 'failed validation for known currency') 15 | }) 16 | }) 17 | 18 | it('returns an error for any other value', () => { 19 | VALID_CURRENCIES.forEach((ccy) => { 20 | assert.ok(!_isEmpty(validator(`__${ccy}`)), 'passed validation for unknown currency') 21 | }) 22 | 23 | assert.ok(!_isEmpty(validator(42)), 'passed validation for number') 24 | assert.ok(!_isEmpty(validator({})), 'passed validation for object') 25 | assert.ok(!_isEmpty(validator([])), 'passed validation for array') 26 | assert.ok(!_isEmpty(validator(true)), 'passed validation for bool') 27 | assert.ok(!_isEmpty(validator(() => {})), 'passed validation for func') 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /test/lib/validators/date.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _isEmpty = require('lodash/isEmpty') 6 | const validator = require('../../../lib/validators/date') 7 | 8 | describe('date validator', () => { 9 | it('returns no error if given a number gte zero', () => { 10 | assert.strictEqual(validator(0), null, 'failed validation for a number gte zero') 11 | assert.strictEqual(validator(1), null, 'failed validation for a number gte zero') 12 | }) 13 | 14 | it('returns no error if given a date', () => { 15 | assert.strictEqual(validator(new Date()), null, 'failed validation for a number gte zero') 16 | }) 17 | 18 | it('returns an error for any other value', () => { 19 | assert.ok(!_isEmpty(validator(-1)), 'passed validation for negative number') 20 | assert.ok(!_isEmpty(validator('test')), 'passed validation for object') 21 | assert.ok(!_isEmpty(validator({ test: 42 })), 'passed validation for object') 22 | assert.ok(!_isEmpty(validator(['test'])), 'passed validation for array') 23 | assert.ok(!_isEmpty(validator(() => {})), 'passed validation for func') 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /test/lib/validators/number.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _isEmpty = require('lodash/isEmpty') 6 | const validator = require('../../../lib/validators/number') 7 | 8 | describe('number validator', () => { 9 | it('returns no error if given a number', () => { 10 | assert.strictEqual(validator(42), null, 'failed validation for a number') 11 | }) 12 | 13 | it('returns an error for any other value', () => { 14 | assert.ok(!_isEmpty(validator('42')), 'passed validation for number') 15 | assert.ok(!_isEmpty(validator({})), 'passed validation for object') 16 | assert.ok(!_isEmpty(validator([])), 'passed validation for array') 17 | assert.ok(!_isEmpty(validator(true)), 'passed validation for bool') 18 | assert.ok(!_isEmpty(validator(() => {})), 'passed validation for func') 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /test/lib/validators/price.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _isEmpty = require('lodash/isEmpty') 6 | const validator = require('../../../lib/validators/price') 7 | 8 | describe('price validator', () => { 9 | it('returns no error if given a number gte zero', () => { 10 | assert.strictEqual(validator(0), null, 'failed validation for a number gte zero') 11 | assert.strictEqual(validator(1), null, 'failed validation for a number gte zero') 12 | }) 13 | 14 | it('returns an error for any other value', () => { 15 | assert.ok(!_isEmpty(validator(-1)), 'passed validation for negative number') 16 | assert.ok(!_isEmpty(validator('42')), 'passed validation for number') 17 | assert.ok(!_isEmpty(validator({})), 'passed validation for object') 18 | assert.ok(!_isEmpty(validator([])), 'passed validation for array') 19 | assert.ok(!_isEmpty(validator(true)), 'passed validation for bool') 20 | assert.ok(!_isEmpty(validator(() => {})), 'passed validation for func') 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /test/lib/validators/string.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _isEmpty = require('lodash/isEmpty') 6 | const validator = require('../../../lib/validators/string') 7 | 8 | describe('string validator', () => { 9 | it('returns no error if given a string', () => { 10 | assert.strictEqual(validator(''), null, 'failed validation for a string') 11 | }) 12 | 13 | it('returns an error if given a filter list and a value not in the list', () => { 14 | assert.ok(!_isEmpty(validator('not-test', ['test'])), 'passed validation for an unknown string') 15 | }) 16 | 17 | it('returns no error if given a filter list and a value in the list', () => { 18 | assert.strictEqual(validator('test', ['test']), null, 'failed validation for a known string') 19 | }) 20 | 21 | it('returns an error for any other value', () => { 22 | assert.ok(!_isEmpty(validator(42)), 'passed validation for number') 23 | assert.ok(!_isEmpty(validator({})), 'passed validation for object') 24 | assert.ok(!_isEmpty(validator([])), 'passed validation for array') 25 | assert.ok(!_isEmpty(validator(true)), 'passed validation for bool') 26 | assert.ok(!_isEmpty(validator(() => {})), 'passed validation for func') 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /test/lib/validators/symbol.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | 'use strict' 3 | 4 | const assert = require('assert') 5 | const _isEmpty = require('lodash/isEmpty') 6 | const { SYMBOLS } = require('bfx-hf-util') 7 | const validator = require('../../../lib/validators/symbol') 8 | 9 | const VALID_SYMBOLS = Object.values(SYMBOLS) 10 | 11 | describe('symbol validator', () => { 12 | it('returns no error for known symbols', () => { 13 | VALID_SYMBOLS.forEach((sym) => { 14 | assert.strictEqual(validator(sym), null, 'failed validation for known symbol') 15 | }) 16 | }) 17 | 18 | it('returns an error for any other value', () => { 19 | VALID_SYMBOLS.forEach((sym) => { 20 | assert.ok(!_isEmpty(validator(`__${sym}`)), 'passed validation for unknown symbol') 21 | }) 22 | 23 | assert.ok(!_isEmpty(validator(42)), 'passed validation for number') 24 | assert.ok(!_isEmpty(validator({})), 'passed validation for object') 25 | assert.ok(!_isEmpty(validator([])), 'passed validation for array') 26 | assert.ok(!_isEmpty(validator(true)), 'passed validation for bool') 27 | assert.ok(!_isEmpty(validator(() => {})), 'passed validation for func') 28 | }) 29 | }) 30 | --------------------------------------------------------------------------------