blockcypher-client
Version:
A TypeScript client for interacting with BlockCypher's API that provides strong typing and safety when interacting with BlockCypher services.
118 lines (117 loc) • 4.31 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createBlockCypherClient = createBlockCypherClient;
const constants_1 = require("./constants");
const api_1 = require("./errors/api");
function createBlockCypherClient(options) {
return new BlockCypherClient(options);
}
class BlockCypherClient {
constructor(options) {
this.baseUrl = "https://api.blockcypher.com/v1";
if (options != null) {
this.options = options;
}
else {
this.options = {};
}
}
async request(path, options) {
const coin = this.options.coin || options.coin;
const network = this.options.network || options.network;
// ###################################################
if (!coin) {
throw new Error("Coin is required");
}
if (!network) {
throw new Error("Network is required");
}
if (this.options.coin && options.coin) {
throw new Error("Coin is already set in the constructor");
}
if (this.options.network && options.network) {
throw new Error("Network is already set in the constructor");
}
if (!constants_1.SUPPORTED_COIN_NETWORKS[coin].includes(network)) {
throw new Error(`Network ${network} is not supported for coin ${coin}`);
}
// ###################################################
if (this.options.token)
options.query = { token: this.options.token, ...options.query };
const query = new URLSearchParams(options.query);
const url = `${this.baseUrl}/${coin}/${network}/${path}${query ? `?${query}` : ""}`;
const headers = {
"Content-Type": "application/json",
"User-Agent": this.options?.userAgent || "blockcypher-client-lixqa",
...options.headers
};
const response = await fetch(url, {
method: options.method,
headers,
body: JSON.stringify(options.body)
});
if (!response.ok) {
if (response.status === 429) {
if (options._currentRateLimitRetryAttempt === undefined) {
options._currentRateLimitRetryAttempt = 1;
}
else {
options._currentRateLimitRetryAttempt++;
}
if (options._currentRateLimitRetryAttempt <= (this.options.rateLimitRetries || 3)) {
await new Promise(resolve => setTimeout(resolve, response.headers.get("retry-after") ? Number(response.headers.get("retry-after")) * 1000 : options._currentRateLimitRetryAttempt * 1000));
return this.request(path, options);
}
}
throw new api_1.ApiError({
status: response.status,
statusText: response.statusText,
url: response.url,
body: await response.json()
});
}
return response.json();
}
async getAddressBalance(...args) {
const [address, maybeChain] = args;
return this.request(`addrs/${address}/balance`, {
method: "GET",
...(maybeChain || {}),
});
}
async getBlockChainInfo(...args) {
const [maybeChain] = args;
return this.request("", {
method: "GET",
...maybeChain
});
}
async getBlock(...args) {
const [blockHashOrHeight, maybeChain] = args;
return this.request(`blocks/${blockHashOrHeight}`, {
method: "GET",
...maybeChain
});
}
async getAddress(...args) {
const [address, maybeChain] = args;
return this.request(`addrs/${address}`, {
method: "GET",
...(maybeChain || {})
});
}
async getTransaction(...args) {
const [hash, maybeChain] = args;
return this.request(`txs/${hash}`, {
method: "GET",
...(maybeChain || {})
});
}
async getTransactionConfidence(...args) {
const [hash, maybeChain] = args;
return this.request(`txs/${hash}/confidence`, {
method: "GET",
...(maybeChain || {})
});
}
}