Overview:
Digital asset exchange already offers a great set of benefits including secure transactions, private asset management and great added value to your wealth when done accordingly. However, there is still much undiscovered potential and, for the power users of us, there is just way further where we can reach. starting from notifications system when certain conditions are met, to automatic prediction of exchange rates and automatic exchanges based on that. This can all be achieved through the introduction of code to build an automated bot. This article will introduce a code sample to achieve that, put in simple words, a class that consumes the SmartValor's API/endpoints, written in Javascript, and using node JS.
Obtaining your Credentials:
The first step is, as always, to obtain your credentials: API Key, Secret key and identification number, from the Smartvalor platform. This is as easy as heading to your settings, and generating these credentials, or simply through this link for production environment: SMART VALOR API Keys
We recommend of course not to use the production environment just to test your code. you should only used when everything is tested, and instead use the uat environment for that: UAT SMART VALOR API Keys
The following lines of code are used as a declaration of these variables, and to generate a nonce:
const crypto = require('crypto');
const ExchangeIntegration = require('../exchange-integrations');
const apiUrl = 'https://api.uat-valor.com';
const apiKey = 'put_your_api_key_here';
const secret = 'put_your_secret_key_here';
const identification = 999999; // user_id provided by smart valor
const nonce = parseInt(crypto.randomBytes(4).toString('hex'), 16);;
const axios = require('axios');
Then, you should generate a signature, as follows:
this.signature = crypto
.createHmac('sha256', secret)
.update(`${nonce}${identification}${apiKey}`)
.digest('hex');
The signature is used for to call an endpoint, which can be done for example with curl as follows:
curl -X GET "https://api.uat-valor.com/account/balance" \
-H "accept: application/json" \
-H "api-key: api-key-provided-by-smart-valor" \
-H "nonce: 123456" \
-H "signature: generate-signature-for-the-secret-nonce-and-user-id" \
-H "user-id: 99999"
For Javascript code, the signature should be generated in the constructor of the calls, that will be provided in the Client class later.
How do I access API
The extensive list of API endpoints, can be found here, as swagger documentation:
- For Production environment: SMART VALOR API
- For UAT Environment: UAT SMART VALOR API
Full sample Code:
The following sample can be split into 3 main parts: credential variables declaration, and the Client class which contains a constructor that generates the signature and a set of asynchronous methods.
The Client class is based on ExchangeIntegration class, which you can find here:
Leverage our public API to speed your asset transaction
const crypto = require('crypto');
const ExchangeIntegration = require('../exchange-integrations');
const apiUrl = 'https://api.uat-valor.com';
const apiKey = 'put_your_api_key_here';
const secret = 'put_your_secret_key_here';
const identification = 999999; // user_id provided by smart valor
const nonce = parseInt(crypto.randomBytes(4).toString('hex'), 16);;
const axios = require('axios');
class Client extends ExchangeIntegration {
constructor() {
super();
this.signature = crypto
.createHmac('sha256', secret)
.update(`${nonce}${identification}${apiKey}`)
.digest('hex');
}
getHeaders() {
return {
"Content-Type": "application/json",
"nonce": nonce,
"signature": this.signature,
"user-id": identification,
"api-key": apiKey
};
}
getName() {
return 'SVP Exchange';
}
async getBalance(currency) {
const request = {
url: `${apiUrl}/account/balance`,
method: 'GET',
headers: this.getHeaders()
};
const data = (await this.executeRequest(request)).data;
if (!currency) {
return data;
}
return data.find(c => c.product.isoCode === currency);
}
async getLastPrice(market) {
const instrument = await this.getInstrument(market);
const request = {
url: `${apiUrl}/instruments/${instrument.id}/price`,
method: 'GET',
headers: this.getHeaders()
};
return (await this.executeRequest(request)).data.amount;
}
async getInstrument(market) {
const instruments = await this.getInstruments();
const instrument = instruments.find(i => i.symbol === market);
if (!instrument) {
throw new Error(`No such market found: ${market}`);
}
return instrument;
}
async getInstruments() {
const request = {
url: `${apiUrl}/instruments`,
method: 'GET',
headers: this.getHeaders()
};
return (await this.executeRequest(request)).data;
}
// { id: number, status: string }
async createOrder(market, sellOrBuy, marketOrLimit, price, quantity) {
const request = {
url: `${apiUrl}/orders`,
method: 'POST',
headers: this.getHeaders(),
data: {
side: sellOrBuy,
quantity: quantity,
type: marketOrLimit,
instrumentId: (await this.getInstrument(market)).id,
price: price
}
};
try {
return (await this.executeRequest(request)).data;
} catch (e) {
throw e;
}
}
async getLevel1(market) {
const instrument = await this.getInstrument(market);
const request = {
url: `${apiUrl}/instruments/${instrument.id}/level1`,
method: 'GET',
headers: this.getHeaders()
};
return (await this.executeRequest(request)).data;
}
async getLevel2(market) {
const instrument = await this.getInstrument(market);
const request = {
url: `${apiUrl}/instruments/${instrument.id}/level2`,
method: 'GET',
headers: this.getHeaders()
};
return (await this.executeRequest(request)).data;
}
async getAskPrice(market) {
return (await this.getLevel1(market)).bestOffer;
}
async getBidPrice(market) {
return (await this.getLevel1(market)).bestBid;
}
async isOrderExecuted(orderId) {
const request = {
url: `${apiUrl}/orders/history`,
method: 'GET',
headers: this.getHeaders()
};
const orders = (await this.executeRequest(request)).data;
const order = orders.find(o => o.id === orderId);
if (!order) {
throw new Error(`Order was not found ${orderId}`);
}
return order.status === 'FULLYEXECUTED';
}
async cancelAllOrders() {
const request = {
url: `${apiUrl}/orders`,
method: 'DELETE',
headers: this.getHeaders()
};
return (await this.executeRequest(request)).data;
}
async executeRequest(request) {
const start = new Date();
const response = await axios.request(request);
const end = new Date() - start;
console.info('Execution time [%s] %dms', request.url, end);
return response;
}
}
module.exports = Client;