├── .gitignore ├── README.md ├── lib ├── enums.js └── exchange.js ├── package-lock.json ├── package.json └── test └── testEndpoints.js /.gitignore: -------------------------------------------------------------------------------- 1 | credentials.json 2 | node_modules/**/* 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Namebase Exchange Api 2 | == 3 | 4 | An easy-to-use Node.js package that lets you programmatically interact with the Namebase exchange. 5 | 6 | ## Usage 7 | 8 | Here is some sample code demonstrating how to use this package. First, go to https://www.namebase.io/pro and generate an API key. 9 | 10 | Note: this is not a comprehensive enumeration of the supported features. Read the source code for a full list. The raw API documentation can be found here: https://github.com/namebasehq/exchange-api-documentation/ 11 | 12 | ```javascript 13 | const namebase = require('@namebasehq/exchange-api'); 14 | const exchange = new namebase.Exchange( 15 | /* ACCESS KEY */, 16 | /* SECRET KEY */ 17 | ); 18 | 19 | // get the last trade price 20 | const result1 = await exchange.priceTicker(namebase.HNSBTC); 21 | 22 | // place a limit sell order 23 | const quantity = '112.010000'; // units are HNS for the HNSBTC market 24 | const orderPrice = '0.00004321'; // units are BTC for the HNSBTC market 25 | const result2 = await exchange.limitSell( 26 | namebase.HNSBTC, 27 | quantity, 28 | orderPrice 29 | ); 30 | 31 | // find all open orders 32 | const result3 = await exchange.openOrders(namebase.HNSBTC); 33 | 34 | if (result3.length > 0) { 35 | // pick a random order 36 | const orderIds = result3.map(order => order.orderId); 37 | const orderIndex = Math.floor(Math.random() * orderIds.length); 38 | 39 | // cancel the order 40 | const result4 = await exchange.cancelOrder( 41 | namebase.HNSBTC, 42 | orderIds[orderIndex] 43 | ); 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /lib/enums.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Misc: { DEFAULT_API_ROOT: 'https://www.namebase.io/api/v0' }, 3 | Assets: { HNS: 'HNS', BTC: 'BTC' }, 4 | Symbols: { HNSBTC: 'HNSBTC' }, 5 | OrderTypes: { LMT: 'LMT', MKT: 'MKT' }, 6 | OrderSides: { BUY: 'BUY', SELL: 'SELL' }, 7 | Intervals: { 8 | ONE_MINUTE: '1m', 9 | FIVE_MINUTES: '5m', 10 | FIFTEEN_MINUTES: '15m', 11 | ONE_HOUR: '1h', 12 | FOUR_HOURS: '4h', 13 | TWELVE_HOURS: '12h', 14 | ONE_DAY: '1d', 15 | ONE_WEEK: '1w', 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /lib/exchange.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { encode } = require('querystring'); 3 | const enums = require('./enums'); 4 | 5 | // flatten the enums for convenience 6 | const flattenedEnums = {}; 7 | Object.keys(enums).forEach(key => { 8 | Object.keys(enums[key]).forEach(keyKey => { 9 | flattenedEnums[keyKey] = enums[key][keyKey]; 10 | }); 11 | }); 12 | 13 | // main export 14 | class Exchange { 15 | constructor(accessKey, secretKey, apiRoot = enums.Misc.DEFAULT_API_ROOT) { 16 | this.accessKey = accessKey; 17 | this.secretKey = secretKey; 18 | this.apiRoot = apiRoot; 19 | 20 | if (this.accessKey && this.secretKey) { 21 | const credentials = Buffer.from(this.accessKey + ':' + this.secretKey); 22 | this.authorization = 'Basic ' + credentials.toString('base64'); 23 | } else { 24 | this.authorization = null; 25 | } 26 | } 27 | 28 | info() { 29 | const endpoint = '/info'; 30 | return this._request('GET', endpoint, {}); 31 | } 32 | 33 | depth(symbol, limit) { 34 | const endpoint = '/depth'; 35 | return this._request('GET', endpoint, { symbol, limit }); 36 | } 37 | 38 | priceTicker(symbol) { 39 | const endpoint = '/ticker/price'; 40 | return this._request('GET', endpoint, { symbol }); 41 | } 42 | 43 | bookTicker(symbol) { 44 | const endpoint = '/ticker/book'; 45 | return this._request('GET', endpoint, { symbol }); 46 | } 47 | 48 | supplyTicker(asset) { 49 | const endpoint = '/ticker/supply'; 50 | return this._request('GET', endpoint, { asset }); 51 | } 52 | 53 | klinesTicker(symbol, interval, startTime, endTime, limit) { 54 | const endpoint = '/ticker/klines'; 55 | return this._request('GET', endpoint, { 56 | symbol, 57 | interval, 58 | startTime, 59 | endTime, 60 | limit, 61 | }); 62 | } 63 | 64 | dayTicker(symbol) { 65 | const endpoint = '/ticker/day'; 66 | return this._request('GET', endpoint, { symbol }); 67 | } 68 | 69 | trades(symbol, tradeId, limit, receiveWindow) { 70 | const endpoint = '/trade'; 71 | return this._timedRequest('GET', endpoint, { 72 | symbol, 73 | tradeId, 74 | limit, 75 | receiveWindow, 76 | }); 77 | } 78 | 79 | limitSell(symbol, quantity, price, receiveWindow) { 80 | return this._createOrder( 81 | symbol, 82 | enums.OrderSides.SELL, 83 | enums.OrderTypes.LMT, 84 | quantity, 85 | price, 86 | receiveWindow 87 | ); 88 | } 89 | 90 | limitBuy(symbol, quantity, price, receiveWindow) { 91 | return this._createOrder( 92 | symbol, 93 | enums.OrderSides.BUY, 94 | enums.OrderTypes.LMT, 95 | quantity, 96 | price, 97 | receiveWindow 98 | ); 99 | } 100 | 101 | marketSell(symbol, quantity, receiveWindow) { 102 | return this._createOrder( 103 | symbol, 104 | enums.OrderSides.SELL, 105 | enums.OrderTypes.MKT, 106 | quantity, 107 | null, 108 | receiveWindow 109 | ); 110 | } 111 | 112 | marketBuy(symbol, quantity, receiveWindow) { 113 | return this._createOrder( 114 | symbol, 115 | enums.OrderSides.BUY, 116 | enums.OrderTypes.MKT, 117 | quantity, 118 | null, 119 | receiveWindow 120 | ); 121 | } 122 | 123 | cancelOrder(symbol, orderId, receiveWindow) { 124 | const endpoint = '/order'; 125 | return this._timedRequest('DELETE', endpoint, { symbol, orderId, receiveWindow }); 126 | } 127 | 128 | order(symbol, orderId, receiveWindow) { 129 | const endpoint = '/order'; 130 | return this._timedRequest('GET', endpoint, { symbol, orderId, receiveWindow }); 131 | } 132 | 133 | openOrders(symbol, receiveWindow) { 134 | const endpoint = '/order/open'; 135 | return this._timedRequest('GET', endpoint, { symbol, receiveWindow }); 136 | } 137 | 138 | allOrders(symbol, orderId, limit, receiveWindow) { 139 | const endpoint = '/order/all'; 140 | return this._timedRequest('GET', endpoint, { symbol, orderId, limit, receiveWindow }); 141 | } 142 | 143 | accountInfo(receiveWindow) { 144 | const endpoint = '/account'; 145 | return this._timedRequest('GET', endpoint, { receiveWindow }); 146 | } 147 | 148 | userTrades(symbol, tradeId, limit, receiveWindow) { 149 | const endpoint = '/trade/account'; 150 | return this._timedRequest('GET', endpoint, { symbol, tradeId, limit, receiveWindow }); 151 | } 152 | 153 | orderTrades(symbol, orderId, receiveWindow) { 154 | const endpoint = '/trade/order'; 155 | return this._timedRequest('GET', endpoint, { symbol, orderId, receiveWindow }); 156 | } 157 | 158 | depositAddress(asset, receiveWindow) { 159 | const endpoint = '/deposit/address'; 160 | return this._timedRequest('POST', endpoint, { asset, receiveWindow }); 161 | } 162 | 163 | withdraw(asset, address, amount, receiveWindow) { 164 | const endpoint = '/withdraw'; 165 | return this._timedRequest('POST', endpoint, { asset, address, amount, receiveWindow }); 166 | } 167 | 168 | depositHistory(asset, startTime, endTime, receiveWindow) { 169 | const endpoint = '/deposit/history'; 170 | return this._timedRequest('GET', endpoint, { asset, startTime, endTime, receiveWindow }); 171 | } 172 | 173 | withdrawalHistory(asset, startTime, endTime, receiveWindow) { 174 | const endpoint = '/withdraw/history'; 175 | return this._timedRequest('GET', endpoint, { asset, startTime, endTime, receiveWindow }); 176 | } 177 | 178 | _createOrder(symbol, side, type, quantity, price, receiveWindow) { 179 | const endpoint = '/order'; 180 | return this._timedRequest('POST', endpoint, { 181 | symbol, 182 | side, 183 | type, 184 | quantity, 185 | price, 186 | receiveWindow, 187 | }); 188 | } 189 | 190 | _timedRequest(method, endpoint, payload) { 191 | return this._request(method, endpoint, { 192 | ...payload, 193 | timestamp: Date.now(), 194 | }); 195 | } 196 | 197 | _request(method, endpoint, payload) { 198 | // clear out null keys 199 | const keys = Object.keys(payload); 200 | keys.forEach(key => { 201 | if (!payload[key] && key !== false && key !== 0) { 202 | delete payload[key]; 203 | } 204 | }); 205 | 206 | // put the payload in the right spot 207 | let url = `${this.apiRoot}${endpoint}`; 208 | let options = {}; 209 | if (method === 'GET') { 210 | url += `?${encode(payload)}`; 211 | } else { 212 | options.body = JSON.stringify(payload); 213 | } 214 | 215 | // actually make the request 216 | return fetch(url, { 217 | method, 218 | headers: { 219 | Authorization: this.authorization, 220 | Accept: 'application/json', 221 | 'Content-Type': 'application/json', 222 | }, 223 | ...options, 224 | }).then(res => res.json()); 225 | } 226 | } 227 | 228 | module.exports = { 229 | Exchange, 230 | ...flattenedEnums, 231 | }; 232 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@namebasehq/exchange-api", 3 | "version": "0.0.10", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@namebasehq/exchange-api", 9 | "version": "0.0.10", 10 | "license": "MIT", 11 | "dependencies": { 12 | "node-fetch": "~2.6.13" 13 | } 14 | }, 15 | "node_modules/node-fetch": { 16 | "version": "2.6.13", 17 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", 18 | "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", 19 | "license": "MIT", 20 | "dependencies": { 21 | "whatwg-url": "^5.0.0" 22 | }, 23 | "engines": { 24 | "node": "4.x || >=6.0.0" 25 | }, 26 | "peerDependencies": { 27 | "encoding": "^0.1.0" 28 | }, 29 | "peerDependenciesMeta": { 30 | "encoding": { 31 | "optional": true 32 | } 33 | } 34 | }, 35 | "node_modules/tr46": { 36 | "version": "0.0.3", 37 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 38 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", 39 | "license": "MIT" 40 | }, 41 | "node_modules/webidl-conversions": { 42 | "version": "3.0.1", 43 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 44 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", 45 | "license": "BSD-2-Clause" 46 | }, 47 | "node_modules/whatwg-url": { 48 | "version": "5.0.0", 49 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 50 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 51 | "license": "MIT", 52 | "dependencies": { 53 | "tr46": "~0.0.3", 54 | "webidl-conversions": "^3.0.0" 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@namebasehq/exchange-api", 3 | "version": "0.0.10", 4 | "description": "An easy-to-use Node.js interface for the Namebase exchange.", 5 | "main": "./lib/exchange.js", 6 | "scripts": { 7 | "test": "node ./test/testEndpoints.js" 8 | }, 9 | "homepage": "https://github.com/namebasehq/exchange-api/", 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/namebasehq/exchange-api.git" 13 | }, 14 | "author": "Anthony Liu", 15 | "license": "MIT", 16 | "dependencies": { 17 | "node-fetch": "~2.6.13" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/testEndpoints.js: -------------------------------------------------------------------------------- 1 | const namebase = require('../lib/exchange'); 2 | const credentials = require('../credentials.json'); 3 | 4 | const x = new namebase.Exchange( 5 | credentials.ACCESS_KEY, 6 | credentials.SECRET_KEY, 7 | credentials.API_ROOT 8 | ); 9 | 10 | async function log(name, ...parameters) { 11 | const result = await x[name].apply(x, parameters); 12 | console.log(`--- Executing ${name}() ---\n`); 13 | console.log(result); 14 | console.log('\n\n'); 15 | return result; 16 | } 17 | 18 | (async () => { 19 | await log('info'); 20 | await log('depth', namebase.HNSBTC); 21 | await log('priceTicker', namebase.HNSBTC); 22 | await log('bookTicker', namebase.HNSBTC); 23 | await log('supplyTicker', namebase.HNS); 24 | await log('klinesTicker', namebase.HNSBTC, namebase.ONE_HOUR, null, null, 2); 25 | await log('dayTicker', namebase.HNSBTC); 26 | await log('trades', namebase.HNSBTC, null, 2); 27 | await log('openOrders', namebase.HNSBTC); 28 | await log('allOrders', namebase.HNSBTC, null, 2); 29 | await log('accountInfo'); 30 | await log('userTrades', namebase.HNSBTC, null, 2); 31 | await log('depositAddress', namebase.HNS); 32 | await log('depositHistory', namebase.HNS); 33 | await log('withdrawalHistory', namebase.BTC); 34 | })(); 35 | --------------------------------------------------------------------------------