LiquidQex Javascript Client
A javascript client for interacting with the Quick Exchange server through Tap.
This is dependent on the LiquidTap
client library.
Quick Start
npm install --save liquid-tap
npm install --save liquid-qex
import { TapClient } from "liquid-tap";
import { QexClient, ProductType, SIDE } from "liquid-qex";
const tap = new TapClient();
const qex = new QexClient(tap);
const channel = qex.quoteStream(
"BTC/JPY",
"JPY",
SIDE.BUY,
500
);
channel.bind("updated", data => console.log(JSON.stringify(data, null, 2)));
Authentication
For informaiton on how to authenticate, see LiquidTap
In the example below, the QEX server will tick back indicative quotes only (not tradable).
import LiquidTap from 'liquid-tap';
import { QexClient }, { SIDE } from 'liquid-qex';
const tap = new LiquidTap();
const qex = new LiquidQex(tap)
const channel = qex.quoteStream('BTC/JPY', 'JPY', SIDE.BUY, 500);
channel.bind('updated', quote => {
console.log(quote.client_ask.state);
// INDICATIVE
});
Once a user in authenticated, the quotes (can) be dealable
import LiquidTap from 'liquid-tap';
import { QexClient }, { SIDE } from 'liquid-qex';
const tap = new LiquidTap();
const qex = new LiquidQex(tap)
tap.authenticate(signedJwt);
const channel = qex.quoteStream('BTC/JPY', 'JPY', SIDE.BUY, 500);
channel.bind('updated', quote => {
console.log(quote.client_ask.state);
qex.tradeOnQuote(quote, side, vendorId, allowPriceImprovement, account, openingUserId)
});
Buy Sell Helper Class
A helper class exists to simplify the construction and side selection of the quote stream request.
Initialization
let request = new BuySellHelperImmutable({ sellCcy: 'USD', buyCcy: 'BTC', fixSide: SIDE.SELL });
Argument | Type | Description |
---|---|---|
ccy1 | string | (Optional) Short uppercase currency |
ccy2 | string | (Optional) Short uppercase currency |
ccy | string | (Optional) Short uppercase currency |
side | string | (Optional) Derived from the SIDE enum |
Input Methods
Purpose | Sell side | Buy side | Convenience Wrapper |
---|---|---|---|
Specify Currencies | r.setSellCcy(ccy) |
r.setBuyCcy(ccy) |
r.setCcy(SIDE.BUY / SIDE.SELL, ccy) |
Fix a currency value | r.fixSellQty() |
r.fixBuyQty() |
r.fixQty(SIDE.BUY / SIDE.SELL, qty) |
Output Methods
Method | Purpose |
---|---|
r.symbol() |
Returns the symbol to use. |
r.currency() |
Returns the currency to use. |
r.side() |
Returns the side to use. |
r.rateField() |
Returns the rate field from the quote to use. (either client_bid or client_ask ) |
Quote Parser
const quoteParser = new QuoteParser(request, quote);
Output Methods
Method | Returns | Purpose |
---|---|---|
.hasQuote() |
boolean | Returns whether a quote has been provided |
.client_x() |
Rate object. | Return either the client_bid or client_ask , which ever is present. |
.price() |
string (containing number) |
The effective price of the quote. |
.sellRate() |
string (containing number) |
The rate for (sellQty - fee) * rate = buyQty
|
.buyRate() |
string (containing number) |
The rate for buyQty * rate = (sellQty - fee) , excluding any fees. |
.state() |
QUOTE_STATE (enum) |
Returns the rate field from the quote to use. (either client_bid or client_ask ) |
.dealable() |
boolean | True if the quote state is dealable. |
.error() |
boolean | True if there is some error |
.quantityAccepted() |
boolean | True if the requested quantaty matches the dealable quantity |
.dealableQuantity() |
boolean | Quantity available for dealing (should match the quantity in the quote request |
.quantityTooSmall() |
boolean | True if the requested quantity is too small |
.quantityTooLarge() |
boolean | True if the requested quantity is too large |
.sellQuantityValid() |
boolean | True if the sell quantity is a valid float |
.buyQuantityValid() |
boolean | True if the buy quantity is a valid float |
.baseCcy() |
string (Curency) |
Left side currency of the symbol |
.termsCcy() |
string (Currency) |
Right side currency of the symbol |
.sellIsBase() |
boolean | True if the sell currency is on the left sid eof the symbol |
.buyIdBase() |
boolean | True if the buy currency is on the left side of the symbol |
.fee() |
QuoteFeeRaw | null | Returns the fee object from the quote if present |
Useage
import { QexClient, BuySellHelperImmutable } from '../src/index';
const defaultQuantity = 50;
const helper = new BuySellHelperImmutable({sellCcy: 'USD', buyCcy: 'BTC', fixSide: SIDE.SELL, quantity: defaultQuantity});
...
const channel = qex.quoteStream(helper.symbol(), helper.currency(), helper.side(), 500);
channel.bind('updated', (quote) => {
console.log("Rate: " + quote[helper.rateField()].value);
});
There also can be used with ReactJS.
import { QexClient, RequestHelperImmutable } from '../src/index';
const tapClient = new TapClient();
const qexClient = new QexClient(tapClient);
class MyComponent extends React.Component {
constructor() {
this.state = {
request: new RequestHelperImmutable('USD', 'BTC');
quoteRaw: new QuoteParser();
}
}
openStreamingQuote(request) {
this.setState({ request })
const channel = qexClient.quoteStreamFromHelper(helper);
channel.bind('updated', (quoteStr) => {
this.setState({quoteRaw: JSON.parse(quoteStr)})
});
}
handleUserInputOnTextBox1 = (event) => {
// user changes quantity in funding side textbox
openStreamingQuote(request.fixCcy1(event.target.value));
}
handleUserInputOnTextBox2 = (event) => {
// user changes quantity in payout side textbox
openStreamingQuote(helper.fixCcy2(event.target.value));
}
handleChangeCurrency1 = (event) => {
// user changes funding currency
openStreamingQuote(helper.setCcy1(event.target.value));
}
handleChangeCurrency2 = (event) => {
// user changes payout currency
openStreamingQuote(helper.setCcy2(event.target.value));
}
render(){
const {request, quoteRaw} = this.state;
const quoteParser = new QuoteParser(request, quoteRaw);
return (
<div>
<input type="number" value={quoteParser.sellQty()} onChange={this.handleUserInputOnTextBox1}/>
<input type="number" value={quoteParser.buyQty()} onChange={this.handleUserInputOnTextBox1}/>
</div>
)
}
}
References
Function Requirements https://quoine.atlassian.net/wiki/spaces/PRODM/pages/865739240/Quick+Exchange+Functional+Requirements