Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/wagerfield/ig-api
Axios wrapper around IG's API
https://github.com/wagerfield/ig-api
Last synced: about 2 months ago
JSON representation
Axios wrapper around IG's API
- Host: GitHub
- URL: https://github.com/wagerfield/ig-api
- Owner: wagerfield
- License: mit
- Created: 2017-08-24T17:49:19.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2020-03-31T01:46:59.000Z (over 4 years ago)
- Last Synced: 2024-09-21T13:50:10.274Z (3 months ago)
- Language: JavaScript
- Homepage:
- Size: 90.8 KB
- Stars: 25
- Watchers: 4
- Forks: 18
- Open Issues: 6
-
Metadata Files:
- Readme: readme.md
- License: license
Awesome Lists containing this project
README
**Minimalistic wrapper around [IG's API][ig-rest-api]**
- [Installation](#install)
- [Usage](#usage)
- [Instance API](#instance-api)
- [constructor](#api-constructor)
- [login](#api-login)
- [logout](#api-logout)
- [request](#api-request)
- [get](#api-get)
- [post](#api-post)
- [put](#api-put)
- [delete](#api-delete)
- [Static API](#static-api)
- [IG.transformResponse](#api-transform-response)
- [IG.transformError](#api-transform-error)
- [IG.uniqueId](#api-unique-id)
- [Options](#options)
- [Errors](#errors)
- [Promises](#promises)
- [Testing](#testing)## Install
```bash
yarn add ig-api
```## Usage
```js
import IG from 'ig-api'const ig = new IG(apiKey, isDemo)
// Using promises
ig.login(username, password)
// Response data is automatically
// passed to the resolve callback
.then((summary) => {
console.log('summary:', summary)
// Once logged in, use the shorthand
// get(), post(), put() and delete()
// methods to interact with IG's API
ig.get('positions')
.then((positions) => {
console.log('positions:', positions)
})
})
// Errors are automatically transformed
// into a more user friendly format with
// the response status and IG error code
.catch(console.error)// Using async await
try {
await ig.login(username, password)
const positions = await ig.get('positions')
console.log('positions:', positions)
} catch (error) {
console.error(error)
}
```## Instance API
```js
// ES6 Module
import IG from 'ig-api'// Common JS
const IG = require('ig-api')
```The `IG` class is a minimalistic wrapper around [`axios`][axios]—a Promise based HTTP client that works in browsers and node. `IG` class instances take care of setting the request URL, headers and authentication tokens when logging into an account.
Responses and errors are automatically transformed into a more user friendly format, though this can be customised or disabled if desired. See [options](#options) for more information.
### `constructor(apiKey, isDemo, options)`parameter | type | required | description
----------|---------|----------|------------
apiKey | string | true | Application API key
isDemo | boolean | false | Is the API key associated with a demo account? Defaults to false
options | object | false | See [options](#options) for more information
### `login(username, password, encryptPassword, options)`parameter | type | required | description
----------------|---------|----------|------------
username | string | true | Account user name
password | string | true | Account password
encryptPassword | boolean | false | Encrypt password before posting to API. Defaults to false
options | object | false | See [options](#options) for more informationparameter | type | required | description
----------|---------|----------|------------
options | object | false | See [options](#options) for more information
### `request(method, path, version, config, options)`parameter | type | required | description
----------|---------|----------|------------
method | string | true | Request method to use ('get', 'post', 'put' or 'delete')
path | string | true | Endpoint path eg. 'history/transactions'
version | number | false | Endpoint version (1, 2 or 3). Defaults to 1
config | object | false | Request config to pass to axios. See [documentation][axios-request-config]
options | object | false | See [options](#options) for more information
### `get(path, version, params, options)`Shorthand to `request`, passing `'get'` as the `method` and `params` as the key value to `config`.
```js
// Get detailed account activity since 25th December 2016
ig.get('history/activity', 3, {
from: '2016-12-25',
detailed: true
})
// ...is the same as
ig.request('get', 'history/activity', 3, {
params: {
from: '2016-12-25',
detailed: true
}
})
```
### `post(path, version, data, options)`Shorthand to `request`, passing `'post'` as the `method` and `data` as the key value to `config`.
```js
// Create a new watchlist
ig.post('watchlist', 1, {
name: 'Forex Majors',
epics: [
'CS.D.AUDUSD.TODAY.IP', // AUD/USD
'CS.D.EURGBP.TODAY.IP', // EUR/GBP
'CS.D.EURUSD.TODAY.IP', // EUR/USD
]
})
// ...is the same as
ig.request('post', 'watchlist', 1, {
data: {
name: 'Forex Majors',
epics: [
'CS.D.AUDUSD.TODAY.IP', // AUD/USD
'CS.D.EURGBP.TODAY.IP', // EUR/GBP
'CS.D.EURUSD.TODAY.IP', // EUR/USD
]
}
})
```
### `put(path, version, data, options)`Shorthand to `request`, passing `'put'` as the `method` and `data` as the key value to `config`.
```js
// Switch active account
ig.put('session', 1, {
accountId: 'XXXXX'
})
// ...is the same as
ig.request('put', 'session', 1, {
data: {
accountId: 'XXXXX'
}
})
```
### `delete(path, version, data, options)`Shorthand to `request`, passing `'delete'` as the `method` and `data` as the key value to `config`.
```js
// Close a position
ig.delete('positions/otc', 1, {
epic: 'UA.D.AAPL.DAILY.IP', // AAPL DFB
orderType: 'MARKET',
direction: 'SELL',
expiry: 'DFB',
size: 0.5
})
// ...is the same as
ig.request('delete', 'positions/otc', 1, {
data: {
epic: 'UA.D.AAPL.DAILY.IP', // AAPL DFB
orderType: 'MARKET',
direction: 'SELL',
expiry: 'DFB',
size: 0.5
}
})
```## Static API
### `IG.transformResponse(response)`parameter | type | required | description
----------|---------|----------|------------
response | object | true | Response objectSimply returns `response.data`.
### `IG.transformError(error)`parameter | type | required | description
----------|---------|----------|------------
error | object | true | Error objectThrows a new `Error` from `error` with additional key values. See [errors](#errors) for more detail.
### `IG.uniqueId(length, chars)`parameter | type | required | description
----------|---------|----------|------------
length | number | false | Length of the unique id. Defaults to 15
chars | string | false | Chars to use. Defaults to [A-Z0-9]Creates a unique id that matches IG's format of 15 uppercase alphanumeric characters eg. `ABCDE12345WVXYZ`.
This can be useful when opening a new position and providing a unique `dealReference`.
## Options
The `IG` constructor and all instance methods take an `options` argument as the final parameter.
The `options` object has the following shape:
```js
{
transformResponse: false || function(response) {
// Transform and return a custom response
return response
},
transformError: false || function(error) {
// Transform and throw a custom error
throw error
}
}
```Both `transformResponse` and `transformError` can be specified as functions or disabled by passing `false`.
By default, the built-in transform functions are used. See [IG.transformResponse](#api-transform-response) and [IG.transformError](#api-transform-error).
When setting `transformResponse` to `false`, the original `response` object is _returned_ from the request's `resolve` method. This is useful if you want to access the response `headers` or `status` code for example.
When setting `transformError` to `false`, the original `error` object is _thrown_ from the request's `reject` method. This is useful if you want to access the error `request` or `response` objects and throw your own custom error.
You can also specify your own custom transform functions that map the `response` and `error` objects to whatever you so choose.
For example if you wanted to return the response `data` and `status` code for _all_ requests on an instance and customise the error:
```js
import IG from 'ig-api'const ig = new IG(apiKey, isDemo, {
transformResponse(response) {
return {
code: response.status,
data: response.data
}
},
transformError(error) {
throw new Error(`Uh oh! ${error.message}`)
}
})const customResponse = await ig.login(username, password)
console.log(customResponse) // { code: 200, data: { ... } }
```If you want to use the built-in transform functions in your own code, they are available as static properties on the `IG` class:
```js
import IG from 'ig-api'const ig = new IG(apiKey, isDemo, {
transformResponse(response) {
// Do something with the response...
return IG.transformResponse(response)
},
transformError(error) {
// Do something with the error...
IG.transformError(error) // throw is called within IG.transformError
}
})
```Passing an `options` object to the `IG` constructor (as shown above) serves as a way for setting the default transform functions for _all_ requests on that instance.
If you want to override these transformation functions on a call-by-call basis, you can do so by passing an `options` object when calling an instance method:
```js
import IG from 'ig-api'const ig = new IG(apiKey, isDemo)
// Default configuration
const summary = await ig.login(username, password)
console.log(summary) // response.data object by default// Disable response transform on single call
const response = await ig.login(username, password, {
transformResponse: false
})
console.log(response) // original response object// Customise response transform on single call
const status = await ig.login(username, password, {
transformResponse: (response) => response.status
})
console.log(status) // 200
```## Errors
Unless the `transformError` function is disabled or overridden via [options](#options), _all_ request errors are handled by the built-in transform function.
When an `error` is thrown from a `request`, a new `Error` is created that has the following shape:
key | description
-----------|------------
type | Either 'request', 'response' or 'internal'
message | Error message
url | Request url
data | Request data
params | Request params
method | Request method
headers | Request headers
statusCode | Response status code (type: 'response' only)
statusText | Response status text (type: 'response' only)
errorCode | Response IG error code (type: 'response' only)Using `type` and `errorCode` can be very useful for handling IG error codes within your application:
```js
ig.login(username, password)
.catch((error) => {
if (error.type === 'response') {
switch (error.errorCode) {
case 'error.security.invalid-details':
alert('Incorrect username or password')
break;
default:
console.error(error.errorCode)
break;
}
} else {
console.error(error.message)
}
})
```## Promises
This library depends on a native ES6 [Promise][promise-docs] implementation to be supported.
If your environment doesn't [support][promise-support] ES6 Promises, you can [polyfill][promise-polyfill].
## Testing
To run the tests locally, you will need to create a `.env` file at the root of the repository that contains the following:
```bash
DEMO_API_KEY=yourDemoApiKey
DEMO_USERNAME=yourDemoUsername
DEMO_PASSWORD=yourDemoPassword
```### Creating API Keys
Since tests mutate your account by creating and deleting watchlists, **you must use a demo account and API key**.
_I will not take any resposibility for running tests using your live account credentials!_
To create an API key, login to IG and go to:
```bash
My IG > Settings > API keys
```Here you will be able to create API keys for both your _live_ and _demo_ accounts.
If you don't have a demo account, you will need to create one.
**NOTE:** After creating a _demo_ account for the first time, it is important that you login to your account, go to the **Dashboard** and make one of your _demo_ accounts a `default` by clicking the radio button next to it. If you don't do this, you will get a "[Transformation failure](https://labs.ig.com/node/562)" error when attempting to login using your demo credentials.
### Running Tests
Tests are written using [jest][jest]. To run the tests:
```bash
yarn test
```To run the tests continuously during development:
```bash
yarn test:watch
```## Author
[Matthew Wagerfield][twitter]
## License
[MIT][mit]
[ig-rest-api]: https://labs.ig.com/rest-trading-api-reference
[promise-docs]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
[promise-polyfill]: https://www.npmjs.com/package/es6-promise
[promise-support]: http://caniuse.com/#feat=promises
[axios]: https://www.npmjs.com/package/axios
[axios-request-config]: https://www.npmjs.com/package/axios#request-config
[jest]: https://facebook.github.io/jest
[mit]: https://opensource.org/licenses/MIT
[twitter]: https://twitter.com/wagerfield