postchain-client
Version:
Client library for accessing a Postchain node through REST.
277 lines • 11.4 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { Buffer } from "buffer";
import { logger } from "../..";
import { SerializedTransactionFormatException, InvalidTxRidException, } from "../restclient/errors";
import { handlePostResponse } from "../restclient/restclient";
import * as gtxTool from "../gtx/gtx";
import { BlockchainUrlUndefinedException, DirectoryNodeUrlPoolException, InvalidTransactionFormatException, MissingBlockchainIdentifierError, } from "./errors";
import { getBlockchainRidFromIid } from "../restclient/restclientutil";
import { toBuffer } from "../formatter";
import { createClient } from "./blockchainClient";
import { FailoverStrategy } from "./enums";
import { createNodeManager } from "../restclient/nodeManager";
export function getClientConfigFromSettings(settings) {
var _a, _b, _c, _d, _e, _f, _g, _h;
return __awaiter(this, void 0, void 0, function* () {
const nodeUrlPoolToUse = yield getNodeUrlsFromSettings(settings);
if (nodeUrlPoolToUse.length === 0) {
const id = (_b = (_a = settings.blockchainRid) !== null && _a !== void 0 ? _a : settings.blockchainIid) !== null && _b !== void 0 ? _b : "Unknown";
throw new BlockchainUrlUndefinedException(id);
}
const endpointPool = createEndpointObjects(nodeUrlPoolToUse);
const nodeManager = createNodeManager({
nodeUrls: nodeUrlPoolToUse,
useStickyNode: (_c = settings.useStickyNode) !== null && _c !== void 0 ? _c : false,
unavailableDuration: (_d = settings.failOverConfig) === null || _d === void 0 ? void 0 : _d.unreachableDuration,
});
const blockchainRidToUse = yield (() => __awaiter(this, void 0, void 0, function* () {
if (settings.blockchainRid) {
return settings.blockchainRid;
}
if (settings.blockchainIid !== undefined) {
return yield getBlockchainRidFromIid({
nodeManager,
endpointPool,
chainId: settings.blockchainIid,
});
}
throw new MissingBlockchainIdentifierError();
}))();
return {
endpointPool,
nodeManager: nodeManager,
blockchainRid: blockchainRidToUse,
statusPollInterval: settings.statusPollInterval || 500,
statusPollCount: settings.statusPollCount || 20,
failoverStrategy: ((_e = settings.failOverConfig) === null || _e === void 0 ? void 0 : _e.strategy) || defaultFailoverConfig.strategy,
attemptsPerEndpoint: ((_f = settings.failOverConfig) === null || _f === void 0 ? void 0 : _f.attemptsPerEndpoint) ||
defaultFailoverConfig.attemptsPerEndpoint,
attemptInterval: ((_g = settings.failOverConfig) === null || _g === void 0 ? void 0 : _g.attemptInterval) ||
defaultFailoverConfig.attemptInterval,
unreachableDuration: ((_h = settings.failOverConfig) === null || _h === void 0 ? void 0 : _h.unreachableDuration) ||
defaultFailoverConfig.unreachableDuration,
};
});
}
export function validTxRid(txRID) {
if (txRID.length != 32) {
const error = new InvalidTxRidException(txRID);
logger.error(error.toString());
return false;
}
return true;
}
export function nodeDiscovery({ nodeManager, directoryEndpointPool, failOverConfig, blockchainRid, blockchainIid, }) {
return __awaiter(this, void 0, void 0, function* () {
if (directoryEndpointPool.length === 0) {
throw new DirectoryNodeUrlPoolException();
}
if (!blockchainRid && blockchainIid === undefined) {
throw new MissingBlockchainIdentifierError();
}
const directoryIid = 0;
const directoryBRID = yield getBlockchainRidFromIid({
nodeManager,
endpointPool: directoryEndpointPool,
chainId: directoryIid,
failOverConfig,
});
const blockchainRidToUse = yield (() => __awaiter(this, void 0, void 0, function* () {
if (blockchainRid) {
return blockchainRid;
}
if (blockchainIid !== undefined) {
return yield getBlockchainRidFromIid({
nodeManager,
endpointPool: directoryEndpointPool,
chainId: blockchainIid,
failOverConfig,
});
}
throw new MissingBlockchainIdentifierError();
}))();
const queryObject = {
name: "cm_get_blockchain_api_urls",
args: { blockchain_rid: toBuffer(blockchainRidToUse) },
};
const D1Client = yield createClient({
nodeUrlPool: getUrlsFromEndpoints(directoryEndpointPool),
blockchainRid: directoryBRID,
});
const baseUrls = yield D1Client.query(queryObject);
return baseUrls;
});
}
export function convertToRellOperation(operations) {
return operations.map((operation) => {
var _a;
return {
opName: operation.name,
args: (_a = operation.args) !== null && _a !== void 0 ? _a : [],
};
});
}
export function getSerializedGTX(gtx) {
const gtxBytes = gtxTool.serialize(gtx);
if (!Buffer.isBuffer(gtxBytes)) {
throw new SerializedTransactionFormatException();
}
return gtxBytes;
}
export function getGTXFromBufferOrTransactionOrOperation(transaction, blockchainRid) {
if (Buffer.isBuffer(transaction)) {
return gtxTool.deserialize(transaction);
}
else if ("operations" in transaction) {
return {
blockchainRid: toBuffer(blockchainRid),
operations: convertToRellOperation(transaction.operations),
signers: transaction.signers,
signatures: [],
};
}
else if ("name" in transaction) {
return {
blockchainRid: toBuffer(blockchainRid),
operations: convertToRellOperation([transaction]),
signers: [],
signatures: [],
};
}
else {
throw new InvalidTransactionFormatException();
}
}
export const callbackPromiseBuilder = (reject, resolve, callback) => {
return (error, result) => {
if (error) {
if (typeof callback === "function") {
callback(error, null);
}
reject(error);
}
else {
if (typeof callback === "function") {
callback(null, result);
}
resolve(result);
}
};
};
export const handlePostResponsePromisified = (error, statusCode, rspBody) => {
return new Promise((resolve, reject) => {
handlePostResponse(error, statusCode, rspBody, (_error) => {
if (_error) {
reject(_error);
}
else {
resolve();
}
});
});
};
function ensureArray(input) {
if (typeof input === "string") {
return [input];
}
return input;
}
export const formatTransactionInfoResponse = (transactionInfoResponse) => {
return {
blockRid: toBuffer(transactionInfoResponse.blockRID),
blockHeight: transactionInfoResponse.blockHeight,
blockHeader: toBuffer(transactionInfoResponse.blockHeader),
witness: toBuffer(transactionInfoResponse.witness),
timestamp: transactionInfoResponse.timestamp,
txRid: toBuffer(transactionInfoResponse.txRID),
txHash: toBuffer(transactionInfoResponse.txHash),
txData: toBuffer(transactionInfoResponse.txData),
};
};
export const formatBlockInfoResponse = (blockInfoResponse) => {
return {
rid: toBuffer(blockInfoResponse.rid),
prevBlockRid: toBuffer(blockInfoResponse.prevBlockRID),
header: toBuffer(blockInfoResponse.header),
transactions: blockInfoResponse.transactions.map(formatTransaction),
height: blockInfoResponse.height,
witness: toBuffer(blockInfoResponse.witness),
witnesses: blockInfoResponse.witnesses.map((witness) => {
return toBuffer(witness);
}),
timestamp: blockInfoResponse.timestamp,
};
};
const formatTransaction = (transaction) => {
const formattedTransaction = {
rid: toBuffer(transaction.rid),
hash: toBuffer(transaction.hash),
};
if (transaction.data !== undefined) {
formattedTransaction.data = toBuffer(transaction.data);
}
return formattedTransaction;
};
export const isKeyPair = (keypair) => {
return (typeof keypair === "object" &&
keypair !== null &&
"privKey" in keypair &&
"pubKey" in keypair &&
keypair.privKey instanceof Buffer &&
keypair.pubKey instanceof Buffer);
};
function getNodeUrlsFromSettings(settings) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (settings.directoryNodeUrlPool) {
// If directoryNodeUrlPool is provided, use nodeDiscovery
const nodeManager = createNodeManager({
nodeUrls: ensureArray(settings.directoryNodeUrlPool),
unavailableDuration: (_a = settings.failOverConfig) === null || _a === void 0 ? void 0 : _a.unreachableDuration,
});
return yield nodeDiscovery({
nodeManager,
directoryEndpointPool: createEndpointObjects(ensureArray(settings.directoryNodeUrlPool)),
failOverConfig: settings.failOverConfig,
blockchainRid: settings.blockchainRid,
blockchainIid: settings.blockchainIid,
});
}
else if (typeof settings.nodeUrlPool === "string") {
// If nodeUrlPool is a string, convert it to an array
return [settings.nodeUrlPool];
}
else if (Array.isArray(settings.nodeUrlPool)) {
// If nodeUrlPool is already an array, use it as-is
return settings.nodeUrlPool;
}
else {
// Default to an empty array if no valid configuration is provided
return [];
}
});
}
export const defaultFailoverConfig = {
strategy: FailoverStrategy.AbortOnError,
attemptsPerEndpoint: 3,
attemptInterval: 500,
unreachableDuration: 30000,
};
export const createEndpointObjects = (endpointPoolUrls) => {
const endpoints = endpointPoolUrls.map((endpointUrl) => {
return { url: endpointUrl, whenAvailable: 0 };
});
return endpoints;
};
export const getUrlsFromEndpoints = (endpointPool) => {
return endpointPool.map((endpoint) => endpoint.url);
};
//# sourceMappingURL=utils.js.map