2021-09-14 08:27:45 -04:00
|
|
|
import * as grpcWeb from 'grpc-web';
|
2021-10-22 13:51:57 -04:00
|
|
|
import {GetVersionClient, PriceClient, WalletsClient, OffersClient, PaymentAccountsClient, TradesClient} from './protobuf/GrpcServiceClientPb';
|
|
|
|
import {GetVersionRequest, GetVersionReply, MarketPriceRequest, MarketPriceReply, GetBalancesRequest, GetBalancesReply, XmrBalanceInfo, GetOffersRequest, GetOffersReply, OfferInfo, GetPaymentAccountsRequest, GetPaymentAccountsReply, CreateCryptoCurrencyPaymentAccountRequest, CreateCryptoCurrencyPaymentAccountReply, CreateOfferRequest, CreateOfferReply, CancelOfferRequest, TakeOfferRequest, TakeOfferReply, TradeInfo, GetTradeRequest, GetTradeReply, GetNewDepositSubaddressRequest, GetNewDepositSubaddressReply, ConfirmPaymentStartedRequest, ConfirmPaymentReceivedRequest} from './protobuf/grpc_pb';
|
2021-09-19 14:00:22 -04:00
|
|
|
import {PaymentAccount, AvailabilityResult} from './protobuf/pb_pb';
|
2021-09-12 09:39:21 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Haveno daemon client using gRPC.
|
|
|
|
*/
|
|
|
|
class HavenoDaemon {
|
|
|
|
|
|
|
|
// instance variables
|
|
|
|
_url: string;
|
2021-09-14 08:27:45 -04:00
|
|
|
_password: string;
|
|
|
|
_getVersionClient: GetVersionClient;
|
2021-10-22 13:51:57 -04:00
|
|
|
_priceClient: PriceClient;
|
2021-09-14 08:27:45 -04:00
|
|
|
_walletsClient: WalletsClient;
|
|
|
|
_paymentAccountsClient: PaymentAccountsClient;
|
2021-09-19 14:00:22 -04:00
|
|
|
_offersClient: OffersClient;
|
|
|
|
_tradesClient: TradesClient;
|
2021-09-12 09:39:21 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct a client connected to a Haveno daemon.
|
|
|
|
*
|
|
|
|
* @param {string} url - Haveno daemon url
|
|
|
|
* @param {string} password - Haveno daemon password if applicable
|
|
|
|
*/
|
2021-09-14 08:27:45 -04:00
|
|
|
constructor(url: string, password: string) {
|
2021-09-12 09:39:21 -04:00
|
|
|
this._url = url;
|
|
|
|
this._password = password;
|
2021-09-14 08:27:45 -04:00
|
|
|
this._getVersionClient = new GetVersionClient(this._url);
|
2021-10-22 13:51:57 -04:00
|
|
|
this._priceClient = new PriceClient(this._url);
|
2021-09-14 08:27:45 -04:00
|
|
|
this._walletsClient = new WalletsClient(this._url);
|
|
|
|
this._paymentAccountsClient = new PaymentAccountsClient(this._url);
|
2021-09-19 14:00:22 -04:00
|
|
|
this._offersClient = new OffersClient(this._url);
|
|
|
|
this._tradesClient = new TradesClient(this._url);
|
2021-09-12 09:39:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the Haveno version.
|
|
|
|
*
|
|
|
|
* @return {string} the Haveno daemon version
|
|
|
|
*/
|
|
|
|
async getVersion(): Promise<string> {
|
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
2021-09-19 14:00:22 -04:00
|
|
|
that._getVersionClient.getVersion(new GetVersionRequest(), {password: that._password}, function(err: grpcWeb.Error, response: GetVersionReply) {
|
2021-09-12 09:39:21 -04:00
|
|
|
if (err) reject(err);
|
|
|
|
else resolve(response.getVersion());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-10-22 13:51:57 -04:00
|
|
|
/**
|
|
|
|
* Get the current market price of the given currency code as a ratio, e.g. ETH/XMR.
|
|
|
|
*
|
|
|
|
* @param {string} currencyCode - currency code to get the price of
|
|
|
|
* @return {number} the current market price of the given currency code as a ratio, e.g. XMR/ETH
|
|
|
|
*/
|
2021-10-27 14:18:07 -04:00
|
|
|
async getPrice(currencyCode: string): Promise<number> {
|
2021-10-22 13:51:57 -04:00
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
that._priceClient.getMarketPrice(new MarketPriceRequest().setCurrencyCode(currencyCode), {password: that._password}, function(err: grpcWeb.Error, response: MarketPriceReply) {
|
|
|
|
if (err) reject(err);
|
|
|
|
else resolve(response.getPrice());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-09-12 09:39:21 -04:00
|
|
|
/**
|
|
|
|
* Get the user's balances.
|
|
|
|
*
|
2021-09-14 08:27:45 -04:00
|
|
|
* @return {XmrBalanceInfo} the user's balances
|
2021-09-12 09:39:21 -04:00
|
|
|
*/
|
2021-09-14 08:27:45 -04:00
|
|
|
async getBalances(): Promise<XmrBalanceInfo> {
|
2021-09-12 09:39:21 -04:00
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
2021-09-19 14:00:22 -04:00
|
|
|
that._walletsClient.getBalances(new GetBalancesRequest(), {password: that._password}, function(err: grpcWeb.Error, response: GetBalancesReply) {
|
2021-09-12 09:39:21 -04:00
|
|
|
if (err) reject(err);
|
2021-09-15 08:06:50 -04:00
|
|
|
else resolve(response.getBalances()!.getXmr()!);
|
2021-09-12 09:39:21 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-09-19 14:00:22 -04:00
|
|
|
* Get a new subaddress in the Haveno wallet to receive deposits.
|
2021-09-12 09:39:21 -04:00
|
|
|
*
|
2021-09-19 14:00:22 -04:00
|
|
|
* @return {string} the deposit address (a subaddress in the Haveno wallet)
|
2021-09-12 09:39:21 -04:00
|
|
|
*/
|
2021-09-19 14:00:22 -04:00
|
|
|
async getNewDepositSubaddress(): Promise<string> {
|
2021-09-12 09:39:21 -04:00
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
2021-09-19 14:00:22 -04:00
|
|
|
that._walletsClient.getNewDepositSubaddress(new GetNewDepositSubaddressRequest(), {password: that._password}, function(err: grpcWeb.Error, response: GetNewDepositSubaddressReply) {
|
2021-09-12 09:39:21 -04:00
|
|
|
if (err) reject(err);
|
2021-09-19 14:00:22 -04:00
|
|
|
else resolve(response.getSubaddress());
|
2021-09-14 08:27:45 -04:00
|
|
|
});
|
|
|
|
});
|
2021-09-12 09:39:21 -04:00
|
|
|
}
|
2021-09-14 08:27:45 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get payment accounts.
|
|
|
|
*
|
|
|
|
* @return {PaymentAccount[]} the payment accounts
|
|
|
|
*/
|
|
|
|
async getPaymentAccounts(): Promise<PaymentAccount[]> {
|
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
that._paymentAccountsClient.getPaymentAccounts(new GetPaymentAccountsRequest(), {password: that._password}, function(err: grpcWeb.Error, response: GetPaymentAccountsReply) {
|
|
|
|
if (err) reject(err);
|
2021-09-15 08:06:50 -04:00
|
|
|
else resolve(response.getPaymentAccountsList());
|
2021-09-14 08:27:45 -04:00
|
|
|
});
|
|
|
|
});
|
2021-09-12 09:39:21 -04:00
|
|
|
}
|
2021-09-14 08:30:22 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a crypto payment account.
|
|
|
|
*
|
|
|
|
* @param {string} accountName - description of the account
|
|
|
|
* @param {string} currencyCode - currency code of the account
|
|
|
|
* @param {string} address - payment address of the account
|
|
|
|
* @return {PaymentAccount} the created payment account
|
|
|
|
*/
|
|
|
|
async createCryptoPaymentAccount(accountName: string,
|
|
|
|
currencyCode: string,
|
2021-10-22 13:51:57 -04:00
|
|
|
address: string): Promise<PaymentAccount> {
|
2021-09-14 08:30:22 -04:00
|
|
|
let that = this;
|
|
|
|
let request = new CreateCryptoCurrencyPaymentAccountRequest()
|
2021-09-15 08:06:50 -04:00
|
|
|
.setAccountName(accountName)
|
|
|
|
.setCurrencyCode(currencyCode)
|
2021-09-14 08:30:22 -04:00
|
|
|
.setAddress(address)
|
2021-11-10 17:47:30 -05:00
|
|
|
.setTradeInstant(false); // not using instant trades
|
2021-09-14 08:30:22 -04:00
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
that._paymentAccountsClient.createCryptoCurrencyPaymentAccount(request, {password: that._password}, function(err: grpcWeb.Error, response: CreateCryptoCurrencyPaymentAccountReply) {
|
|
|
|
if (err) reject(err);
|
2021-09-15 08:06:50 -04:00
|
|
|
else resolve(response.getPaymentAccount()!);
|
2021-09-14 08:30:22 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-09-19 14:00:22 -04:00
|
|
|
/**
|
|
|
|
* Get available offers to buy or sell XMR.
|
|
|
|
*
|
|
|
|
* @param {string} direction - one of "BUY" or "SELL"
|
|
|
|
*
|
|
|
|
* @return {OfferInfo[]} available offers
|
|
|
|
*/
|
|
|
|
async getOffers(direction: string): Promise<OfferInfo[]> {
|
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
that._offersClient.getOffers(new GetOffersRequest().setDirection(direction).setCurrencyCode("XMR"), {password: that._password}, function(err: grpcWeb.Error, response: GetOffersReply) {
|
|
|
|
if (err) reject(err);
|
|
|
|
else resolve(response.getOffersList());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get user's created offers to buy or sell XMR.
|
|
|
|
*
|
|
|
|
* @param {string} direction - one of "BUY" or "SELL"
|
|
|
|
*
|
|
|
|
* @return {OfferInfo[]} the user's created offers
|
|
|
|
*/
|
|
|
|
async getMyOffers(direction: string): Promise<OfferInfo[]> {
|
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
that._offersClient.getMyOffers(new GetOffersRequest().setDirection(direction).setCurrencyCode("XMR"), {password: that._password}, function(err: grpcWeb.Error, response: GetOffersReply) {
|
|
|
|
if (err) reject(err);
|
|
|
|
else resolve(response.getOffersList());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-09-14 08:30:22 -04:00
|
|
|
/**
|
|
|
|
* Post an offer.
|
|
|
|
*
|
|
|
|
* @param {string} currencyCode - currency code of traded pair
|
|
|
|
* @param {string} direction - one of "BUY" or "SELL"
|
|
|
|
* @param {number} price - trade price
|
|
|
|
* @param {bool} useMarketBasedPrice - base trade on market price
|
|
|
|
* @param {number} marketPriceMargin - % from market price to tolerate
|
|
|
|
* @param {bigint} amount - amount to trade
|
|
|
|
* @param {bigint} minAmount - minimum amount to trade
|
|
|
|
* @param {number} buyerSecurityDeposit - buyer security deposit as % of trade amount
|
|
|
|
* @param {string} paymentAccountId - payment account id
|
|
|
|
* @param {number} triggerPrice - price to remove offer
|
2021-09-19 14:00:22 -04:00
|
|
|
* @return {OfferInfo} the created offer
|
2021-09-14 08:30:22 -04:00
|
|
|
*/
|
|
|
|
async postOffer(currencyCode: string,
|
|
|
|
direction: string,
|
|
|
|
price: number,
|
|
|
|
useMarketBasedPrice: boolean,
|
|
|
|
marketPriceMargin: number,
|
|
|
|
amount: bigint,
|
|
|
|
minAmount: bigint,
|
|
|
|
buyerSecurityDeposit: number,
|
|
|
|
paymentAccountId: string,
|
|
|
|
triggerPrice?: number): Promise<OfferInfo> {
|
|
|
|
let that = this;
|
|
|
|
let request = new CreateOfferRequest()
|
2021-09-15 08:06:50 -04:00
|
|
|
.setCurrencyCode(currencyCode)
|
2021-09-14 08:30:22 -04:00
|
|
|
.setDirection(direction)
|
|
|
|
.setPrice(price.toString())
|
2021-09-15 08:06:50 -04:00
|
|
|
.setUseMarketBasedPrice(useMarketBasedPrice)
|
|
|
|
.setMarketPriceMargin(marketPriceMargin)
|
2021-09-14 08:30:22 -04:00
|
|
|
.setAmount(amount.toString())
|
2021-09-15 08:06:50 -04:00
|
|
|
.setMinAmount(minAmount.toString())
|
|
|
|
.setBuyerSecurityDeposit(buyerSecurityDeposit)
|
2021-10-15 13:17:52 -04:00
|
|
|
.setPaymentAccountId(paymentAccountId);
|
2021-09-15 08:06:50 -04:00
|
|
|
if (triggerPrice) request.setTriggerPrice(BigInt(triggerPrice.toString()).toString());
|
2021-09-14 08:30:22 -04:00
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
that._offersClient.createOffer(request, {password: that._password}, function(err: grpcWeb.Error, response: CreateOfferReply) {
|
|
|
|
if (err) reject(err);
|
2021-09-15 08:06:50 -04:00
|
|
|
else resolve(response.getOffer()!);
|
2021-09-14 08:30:22 -04:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-09-17 09:33:58 -04:00
|
|
|
* Remove a posted offer, releasing its reserved funds.
|
2021-09-14 08:30:22 -04:00
|
|
|
*
|
2021-09-19 14:00:22 -04:00
|
|
|
* @param {string} offerId - the offer id to cancel
|
|
|
|
*/
|
|
|
|
async removeOffer(offerId: string): Promise<void> {
|
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
that._offersClient.cancelOffer(new CancelOfferRequest().setId(offerId), {password: that._password}, function(err: grpcWeb.Error) {
|
|
|
|
if (err) reject(err);
|
|
|
|
else resolve();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Take an offer.
|
|
|
|
*
|
|
|
|
* @param {string} offerId - id of the offer to take
|
|
|
|
* @param {string} paymentAccountId - id of the payment account
|
|
|
|
* @return {TradeInfo} the initialized trade
|
|
|
|
*/
|
|
|
|
async takeOffer(offerId: string, paymentAccountId: string): Promise<TradeInfo> {
|
|
|
|
let that = this;
|
|
|
|
let request = new TakeOfferRequest()
|
|
|
|
.setOfferId(offerId)
|
2021-10-15 13:17:52 -04:00
|
|
|
.setPaymentAccountId(paymentAccountId);
|
2021-09-19 14:00:22 -04:00
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
that._tradesClient.takeOffer(request, {password: that._password}, function(err: grpcWeb.Error, response: TakeOfferReply) {
|
|
|
|
if (err) reject(err);
|
|
|
|
else if (response.getFailureReason() && response.getFailureReason()!.getAvailabilityResult() !== AvailabilityResult.AVAILABLE) reject(response.getFailureReason()!.getDescription());
|
|
|
|
else resolve(response.getTrade());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a trade by id.
|
|
|
|
*
|
|
|
|
* @param {string} tradeId - the id of the trade and its offer
|
|
|
|
* @return {TradeInfo} the trade with the given id
|
|
|
|
*/
|
|
|
|
async getTrade(tradeId: string): Promise<TradeInfo> {
|
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
that._tradesClient.getTrade(new GetTradeRequest().setTradeId(tradeId), {password: that._password}, function(err: grpcWeb.Error, response: GetTradeReply) {
|
|
|
|
if (err) reject(err);
|
|
|
|
else resolve(response.getTrade());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Confirm a payment is started.
|
|
|
|
*
|
|
|
|
* @param {string} tradeId - the id of the trade
|
|
|
|
*/
|
|
|
|
async confirmPaymentStarted(tradeId: string): Promise<void> {
|
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
|
|
that._tradesClient.confirmPaymentStarted(new ConfirmPaymentStartedRequest().setTradeId(tradeId), {password: that._password}, function(err: grpcWeb.Error) {
|
|
|
|
if (err) reject(err);
|
|
|
|
else resolve();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Confirm a payment is received.
|
|
|
|
*
|
|
|
|
* @param {string} tradeId - the id of the trade
|
2021-09-14 08:30:22 -04:00
|
|
|
*/
|
2021-09-19 14:00:22 -04:00
|
|
|
async confirmPaymentReceived(tradeId: string): Promise<void> {
|
2021-09-14 08:30:22 -04:00
|
|
|
let that = this;
|
|
|
|
return new Promise(function(resolve, reject) {
|
2021-09-19 14:00:22 -04:00
|
|
|
that._tradesClient.confirmPaymentReceived(new ConfirmPaymentReceivedRequest().setTradeId(tradeId), {password: that._password}, function(err: grpcWeb.Error) {
|
2021-09-14 08:30:22 -04:00
|
|
|
if (err) reject(err);
|
|
|
|
else resolve();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2021-09-12 09:39:21 -04:00
|
|
|
}
|
|
|
|
|
2021-09-14 08:27:45 -04:00
|
|
|
export {HavenoDaemon};
|