import {NotFoundError, NetworkError, BadRequestError, BadResponseError} from "./errors";
import {AccountCallBuilder} from "./account_call_builder";
import {AccountResponse} from "./account_response";
import {Config} from "./config";
import {LedgerCallBuilder} from "./ledger_call_builder";
import {TransactionCallBuilder} from "./transaction_call_builder";
import {OperationCallBuilder} from "./operation_call_builder";
import {OfferCallBuilder} from "./offer_call_builder";
import {OrderbookCallBuilder} from "./orderbook_call_builder";
import {TradesCallBuilder} from "./trades_call_builder";
import {PathCallBuilder} from "./path_call_builder";
import {PaymentCallBuilder} from "./payment_call_builder";
import {EffectCallBuilder} from "./effect_call_builder";
import {FriendbotBuilder} from "./friendbot_builder";
import {AssetsCallBuilder} from "./assets_call_builder";
import { TradeAggregationCallBuilder } from "./trade_aggregation_call_builder";
import {xdr} from "digitalbits-base";
import isString from "lodash/isString";
let axios = require("axios");
let toBluebird = require("bluebird").resolve;
let URI = require("urijs");
let URITemplate = require("urijs").URITemplate;
export const SUBMIT_TRANSACTION_TIMEOUT = 60*1000;
/**
* Server handles the network connection to a [Frontier](https://developer.digitalbits.io/frontier/learn/index.html)
* instance and exposes an interface for requests to that instance.
* @constructor
* @param {string} serverURL Frontier Server URL (ex. `https://frontier.testnet.digitalbits.io`).
* @param {object} [opts]
* @param {boolean} [opts.allowHttp] - Allow connecting to http servers, default: `false`. This must be set to false in production deployments! You can also use {@link Config} class to set this globally.
*/
export class Server {
constructor(serverURL, opts = {}) {
this.serverURL = URI(serverURL);
let allowHttp = Config.isAllowHttp();
if (typeof opts.allowHttp !== 'undefined') {
allowHttp = opts.allowHttp;
}
if (this.serverURL.protocol() != 'https' && !allowHttp) {
throw new Error('Cannot connect to insecure frontier server');
}
}
/**
* Submits a transaction to the network.
* @see [Post Transaction](https://developer.digitalbits.io/frontier/reference/transactions-create.html)
* @param {Transaction} transaction - The transaction to submit.
* @returns {Promise} Promise that resolves or rejects with response from frontier.
*/
submitTransaction(transaction) {
let tx = encodeURIComponent(transaction.toEnvelope().toXDR().toString("base64"));
var promise = axios.post(
URI(this.serverURL).segment('transactions').toString(),
`tx=${tx}`,
{timeout: SUBMIT_TRANSACTION_TIMEOUT}
)
.then(function(response) {
return response.data;
})
.catch(function (response) {
if (response instanceof Error) {
return Promise.reject(response);
} else {
return Promise.reject(new BadResponseError(`Transaction submission failed. Server responded: ${response.status} ${response.statusText}`, response.data));
}
});
return toBluebird(promise);
}
/**
* Returns new {@link AccountCallBuilder} object configured by a current Frontier server configuration.
* @returns {AccountCallBuilder}
*/
accounts() {
return new AccountCallBuilder(URI(this.serverURL));
}
/**
* Returns new {@link LedgerCallBuilder} object configured by a current Frontier server configuration.
* @returns {LedgerCallBuilder}
*/
ledgers() {
return new LedgerCallBuilder(URI(this.serverURL));
}
/**
* Returns new {@link TransactionCallBuilder} object configured by a current Frontier server configuration.
* @returns {TransactionCallBuilder}
*/
transactions() {
return new TransactionCallBuilder(URI(this.serverURL));
}
/**
* People on the DigitalBits network can make offers to buy or sell assets. This endpoint represents all the offers a particular account makes.
* Currently this method only supports querying offers for account and should be used like this:
* ```
* server.offers('accounts', accountId).call()
* .then(function(offers) {
* console.log(offers);
* });
* ```
* @param {string} resource Resource to query offers
* @param {...string} resourceParams Parameters for selected resource
* @returns OfferCallBuilder
*/
offers(resource, ...resourceParams) {
return new OfferCallBuilder(URI(this.serverURL), resource, ...resourceParams);
}
/**
* Returns new {@link OrderbookCallBuilder} object configured by a current Frontier server configuration.
* @param {Asset} selling Asset being sold
* @param {Asset} buying Asset being bought
* @returns {OrderbookCallBuilder}
*/
orderbook(selling, buying) {
return new OrderbookCallBuilder(URI(this.serverURL), selling, buying);
}
/**
* Returns new {@link TradesCallBuilder} object configured by a current Frontier server configuration.
* @returns {TradesCallBuilder}
*/
trades() {
return new TradesCallBuilder(URI(this.serverURL));
}
/**
* Returns new {@link OperationCallBuilder} object configured by a current Frontier server configuration.
* @returns {OperationCallBuilder}
*/
operations() {
return new OperationCallBuilder(URI(this.serverURL));
}
/**
* The DigitalBits Network allows payments to be made between assets through path payments. A path payment specifies a
* series of assets to route a payment through, from source asset (the asset debited from the payer) to destination
* asset (the asset credited to the payee).
*
* A path search is specified using:
*
* * The destination address
* * The source address
* * The asset and amount that the destination account should receive
*
* As part of the search, frontier will load a list of assets available to the source address and will find any
* payment paths from those source assets to the desired destination asset. The search's amount parameter will be
* used to determine if there a given path can satisfy a payment of the desired amount.
*
* Returns new {@link PathCallBuilder} object configured with the current Frontier server configuration.
*
* @param {string} source The sender's account ID. Any returned path will use a source that the sender can hold.
* @param {string} destination The destination account ID that any returned path should use.
* @param {Asset} destinationAsset The destination asset.
* @param {string} destinationAmount The amount, denominated in the destination asset, that any returned path should be able to satisfy.
* @returns {@link PathCallBuilder}
*/
paths(source, destination, destinationAsset, destinationAmount) {
return new PathCallBuilder(URI(this.serverURL), source, destination, destinationAsset, destinationAmount);
}
/**
* Returns new {@link PaymentCallBuilder} object configured with the current Frontier server configuration.
* @returns {PaymentCallBuilder}
*/
payments() {
return new PaymentCallBuilder(URI(this.serverURL));
}
/**
* Returns new {@link EffectCallBuilder} object configured with the current Frontier server configuration.
* @returns {EffectCallBuilder}
*/
effects() {
return new EffectCallBuilder(URI(this.serverURL));
}
/**
* Returns new {@link FriendbotBuilder} object configured with the current Frontier server configuration.
* @returns {FriendbotBuilder}
* @private
*/
friendbot(address) {
return new FriendbotBuilder(URI(this.serverURL), address);
}
/**
* Returns new {@link AssetsCallBuilder} object configured with the current Frontier server configuration.
* @returns {AssetsCallBuilder}
*/
assets() {
return new AssetsCallBuilder(URI(this.serverURL));
}
/**
* Fetches an account's most current state in the ledger and then creates and returns an {@link Account} object.
* @param {string} accountId - The account to load.
* @returns {Promise} Returns a promise to the {@link AccountResponse} object with populated sequence number.
*/
loadAccount(accountId) {
return this.accounts()
.accountId(accountId)
.call()
.then(function (res) {
return new AccountResponse(res);
});
}
/**
*
* @param {Asset} base base aseet
* @param {Asset} counter counter asset
* @param {long} start_time lower time boundary represented as millis since epoch
* @param {long} end_time upper time boundary represented as millis since epoch
* @param {long} resolution segment duration as millis since epoch. *Supported values are 5 minutes (300000), 15 minutes (900000), 1 hour (3600000), 1 day (86400000) and 1 week (604800000).
* Returns new {@link TradeAggregationCallBuilder} object configured with the current Frontier server configuration.
* @returns {TradeAggregationCallBuilder}
*/
tradeAggregation(base, counter, start_time, end_time, resolution){
return new TradeAggregationCallBuilder(URI(this.serverURL), base, counter, start_time, end_time, resolution);
}
}