liquid-qex
v0.6.1
Published
Liquid QuickExchange API Client
Downloads
26
Readme
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