@tangany/waas
Version:
node.js SDK for Tangany Wallet as a Service API
442 lines • 20.2 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
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());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Waas = exports.ethereumRecipientTypeSendAsync = exports.ethereumRecipientType = exports.btcRecipientType = exports.recipientType = exports.ApiVersion = exports.BitcoinTxSpeed = exports.BlockchainTxConfirmations = exports.TezosNetwork = exports.BitcoinNetwork = exports.EthereumTxSpeed = exports.EthereumPublicNetwork = exports.WalletSecurity = exports.WalletVersion = void 0;
var axios_1 = require("axios");
var Debug = require("debug");
var qs = require("qs");
var t = require("typeforce");
var btc_1 = require("./btc");
var errors_1 = require("./errors");
var eth_1 = require("./eth");
var limiter_1 = require("./utils/limiter");
var request_1 = require("./request");
var wallet_1 = require("./wallet");
var polling_helper_1 = require("./utils/polling-helper");
var xtz_1 = require("./xtz");
var debug = Debug("waas-js-sdk:main");
var WalletVersion;
(function (WalletVersion) {
WalletVersion["LATEST"] = "latest";
})(WalletVersion = exports.WalletVersion || (exports.WalletVersion = {}));
var WalletSecurity;
(function (WalletSecurity) {
WalletSecurity["SOFTWARE"] = "software";
WalletSecurity["HSM"] = "hsm";
})(WalletSecurity = exports.WalletSecurity || (exports.WalletSecurity = {}));
var EthereumPublicNetwork;
(function (EthereumPublicNetwork) {
EthereumPublicNetwork["MAINNET"] = "mainnet";
EthereumPublicNetwork["ROPSTEN"] = "ropsten";
EthereumPublicNetwork["POLYGON"] = "polygon";
EthereumPublicNetwork["BINANCE"] = "bsc";
EthereumPublicNetwork["GOERLI"] = "goerli";
})(EthereumPublicNetwork = exports.EthereumPublicNetwork || (exports.EthereumPublicNetwork = {}));
var EthereumTxSpeed;
(function (EthereumTxSpeed) {
EthereumTxSpeed["DEFAULT"] = "default";
EthereumTxSpeed["FAST"] = "fast";
EthereumTxSpeed["SLOW"] = "slow";
EthereumTxSpeed["NONE"] = "none";
})(EthereumTxSpeed = exports.EthereumTxSpeed || (exports.EthereumTxSpeed = {}));
var BitcoinNetwork;
(function (BitcoinNetwork) {
BitcoinNetwork["BITCOIN"] = "bitcoin";
BitcoinNetwork["TESTNET"] = "testnet";
})(BitcoinNetwork = exports.BitcoinNetwork || (exports.BitcoinNetwork = {}));
var TezosNetwork;
(function (TezosNetwork) {
TezosNetwork["MAINNET"] = "mainnet";
})(TezosNetwork = exports.TezosNetwork || (exports.TezosNetwork = {}));
var BlockchainTxConfirmations;
(function (BlockchainTxConfirmations) {
BlockchainTxConfirmations["NONE"] = "none";
BlockchainTxConfirmations["DEFAULT"] = "default";
BlockchainTxConfirmations["SECURE"] = "secure";
})(BlockchainTxConfirmations = exports.BlockchainTxConfirmations || (exports.BlockchainTxConfirmations = {}));
var BitcoinTxSpeed;
(function (BitcoinTxSpeed) {
BitcoinTxSpeed["SLOW"] = "slow";
BitcoinTxSpeed["DEFAULT"] = "default";
BitcoinTxSpeed["FAST"] = "fast";
})(BitcoinTxSpeed = exports.BitcoinTxSpeed || (exports.BitcoinTxSpeed = {}));
var ApiVersion;
(function (ApiVersion) {
ApiVersion["V1"] = "v1";
ApiVersion["V2_ALPHA"] = "v2-alpha";
})(ApiVersion = exports.ApiVersion || (exports.ApiVersion = {}));
exports.recipientType = t.compile({
to: "?String",
wallet: "?String",
amount: "String",
});
// Amount is optional for btc recipients
exports.btcRecipientType = t.compile({
to: "?String",
wallet: "?String",
amount: "?String",
});
exports.ethereumRecipientType = t.compile({
to: "?String",
wallet: "?String",
amount: "?String",
data: "?String",
});
exports.ethereumRecipientTypeSendAsync = t.compile({
to: "?String",
wallet: "?String",
amount: "?String",
});
/**
* Instantiates a new API interface. Multiple instances with different settings can run in parallel
* @param options - api options
* @param options.clientId - Subscription client id
* @param options.clientSecret - Subscription client secret
* @param options.subscription - Subscription code
* @param options.vaultUrl - Tangany vault url
* @param options.ethereumNetwork - Public Ethereum network name or private Ethereum network url
* @param options.ethereumTxConfirmations - Amount of block confirmations required to consider an Ethereum transaction as valid
* @param options.ethereumTxSpeed - Amount of additional gas fee that is added to the base gas fee for the given Ethereum network to speed up the mining process of the transaction
* @param options.bitcoinNetwork - Public Bitcoin network name
* @param options.bitcoinTxConfirmations - Amount of block confirmations required for Bitcoin balance outputs to be included in the total wallet balance calculation
* @param options.bitcoinTxSpeed - Target amount of block confirmations for the transaction to be included to the Bitcoin network
* @param options.bitcoinMaxFeeRate - Maximum allowed fee rate in sat/vbyte for a Bitcoin transaction
* @param options.bitcoinFeeRate - User-defined transaction fee rate in sat/vbyte for a Bitcoin transaction
* @param version - WaaS API version
* @param limiterEnabled - Enable API throttling limiter
*/
var Waas = /** @class */ (function () {
function Waas(options, version, limiterEnabled) {
var _this = this;
if (version === void 0) { version = ApiVersion.V1; }
if (limiterEnabled === void 0) { limiterEnabled = true; }
var _options = __assign({ clientId: process.env.TANGANY_CLIENT_ID, clientSecret: process.env.TANGANY_CLIENT_SECRET, subscription: process.env.TANGANY_SUBSCRIPTION, vaultUrl: process.env.TANGANY_VAULT_URL }, options);
if (!_options.clientId) {
throw new errors_1.AuthenticationError("Missing variable 'clientId'");
}
if (!_options.clientSecret) {
throw new errors_1.AuthenticationError("Missing variable 'clientSecret'");
}
if (!_options.subscription) {
throw new errors_1.AuthenticationError("Missing variable 'subscription'");
}
t({
clientId: "String",
clientSecret: "String",
subscription: "String",
vaultUrl: "?String",
ethereumNetwork: "?String",
ethereumTxSpeed: "?String",
ethereumTxConfirmations: t.anyOf("?String", "?Number"),
ethereumGasPrice: "?String",
ethereumGas: "?Number",
ethereumNonce: "?Number",
ethereumChainId: "?Number",
useGasTank: "?Boolean",
bitcoinNetwork: "?String",
bitcoinTxSpeed: "?String",
bitcoinTxConfirmations: t.anyOf("?String", "?Number"),
bitcoinMaxFeeRate: "?Number",
bitcoinFeeRate: "?Number",
version: "?Number",
tezosNetwork: "?String",
tezosGasLimit: "?Number",
tezosStorageLimit: "?Number",
tezosOperationConfirmation: t.anyOf("?String", "?Number"),
requestId: "?String",
}, _options, true);
axios_1.default.defaults.withCredentials = true;
var api = {
baseURL: (function () {
switch (version) {
case ApiVersion.V1:
return "https://api.tangany.com/v1";
default:
return version;
}
})(),
headers: {
"tangany-client-id": _options.clientId,
"tangany-client-secret": _options.clientSecret,
"tangany-subscription": _options.subscription,
"common": {
Accept: "application/json",
},
},
responseType: "json",
paramsSerializer: function (params) {
if (params instanceof URLSearchParams) {
return params.toString();
}
return qs.stringify(params, { arrayFormat: 'repeat' });
},
};
if (_options.vaultUrl) {
api.headers["tangany-vault-url"] = _options.vaultUrl;
}
if (_options.ethereumNetwork) {
api.headers["tangany-ethereum-network"] = _options.ethereumNetwork;
}
if (_options.ethereumTxConfirmations) {
api.headers["tangany-ethereum-tx-confirmations"] = _options.ethereumTxConfirmations;
}
if (_options.ethereumTxSpeed) {
api.headers["tangany-ethereum-tx-speed"] = _options.ethereumTxSpeed;
}
if (_options.ethereumGasPrice) {
api.headers["tangany-ethereum-gas-price"] = _options.ethereumGasPrice;
}
if (_options.ethereumGas) {
api.headers["tangany-ethereum-gas"] = _options.ethereumGas;
}
if (_options.ethereumNonce) {
api.headers["tangany-ethereum-nonce"] = _options.ethereumNonce;
}
if (_options.useGasTank) {
api.headers["tangany-use-gas-tank"] = _options.useGasTank;
}
if (_options.bitcoinNetwork) {
api.headers["tangany-bitcoin-network"] = _options.bitcoinNetwork;
}
if (_options.bitcoinTxSpeed) {
api.headers["tangany-bitcoin-tx-speed"] = _options.bitcoinTxSpeed;
}
if (_options.bitcoinTxConfirmations) {
api.headers["tangany-bitcoin-tx-confirmations"] = _options.bitcoinTxConfirmations;
}
if (_options.bitcoinMaxFeeRate) {
api.headers["tangany-bitcoin-max-fee-rate"] = _options.bitcoinMaxFeeRate;
}
if (_options.bitcoinFeeRate) {
api.headers["tangany-bitcoin-fee-rate"] = _options.bitcoinFeeRate;
}
if (_options.tezosNetwork) {
api.headers["tangany-tezos-network"] = _options.tezosNetwork;
}
if (_options.tezosGasLimit) {
api.headers["tangany-tezos-gas-limit"] = _options.tezosGasLimit;
}
if (_options.tezosStorageLimit) {
api.headers["tangany-tezos-storage-limit"] = _options.tezosStorageLimit;
}
if (_options.tezosOperationConfirmation) {
api.headers["tangany-tezos-operation-confirmations"] = _options.tezosOperationConfirmation;
}
if (_options.requestId) {
api.headers["tangany-request-id"] = _options.requestId;
}
var instance = axios_1.default.create(api);
// removes axios' proprietary "delete", "get", "head" etc. functions from its headers object
var filterHeaders = function (headers) { return headers && Object.entries(headers)
.filter(function (v) {
switch (true) {
case v[0] === "common":
case typeof v[1] === "string":
case v[1].constructor === Array:
return true;
default:
return false;
}
})
.reduce(function (o, e) {
var _a;
return (__assign(__assign({}, o), (_a = {}, _a[e[0]] = e[1], _a)));
}, {}); };
instance.interceptors.request.use(function (req) {
var method = req.method, url = req.url, baseURL = req.baseURL, data = req.data, headers = req.headers;
debug("interceptors.request", { method: method, url: "".concat(baseURL, "/").concat(url), data: data, headers: filterHeaders(headers) });
return req;
});
instance.interceptors.response.use(function (response) {
var headers = response.headers, data = response.data, status = response.status, statusText = response.statusText;
debug("interceptors.response", {
headers: filterHeaders(headers),
data: data,
status: status,
statusText: statusText,
});
if (headers && headers.hasOwnProperty("set-cookie")) {
var cookie = headers["set-cookie"].map(function (h) { return h.split(";")[0]; }).join("; "); // make cookie available for consequent axios instance calls in current session
instance.defaults.headers.cookie = cookie;
}
return data;
}, function (e) { return __awaiter(_this, void 0, void 0, function () {
var response, message, noErrorDetails, waasError, activityId, waasMessage;
return __generator(this, function (_a) {
response = e.response, message = e.message;
if (!response) {
throw e;
}
debug("interceptors.response.error", {
response: response.data,
headers: filterHeaders(response.headers),
message: message,
});
noErrorDetails = { message: "An error has occurred for which no error details could be retrieved", statusCode: 0, activityId: "" };
waasError = (typeof response.data === "object" && "output" in response.data ? response.data.output : response.data) || noErrorDetails;
activityId = waasError.activityId, waasMessage = waasError.message;
switch (response.status) {
case 401:
throw new errors_1.AuthenticationError(waasMessage, activityId);
case 409:
throw new errors_1.ConflictError(waasMessage, activityId);
case 404:
throw new errors_1.NotFoundError(waasMessage);
default:
throw new errors_1.GeneralError(waasMessage, response.status, activityId);
}
return [2 /*return*/];
});
}); });
this.instance = instance;
if (limiterEnabled) {
this.limiter = limiter_1.limiter;
}
}
Object.defineProperty(Waas.prototype, "axios", {
/**
* Exposes the preconfigured AxiosInstance for arbitrary api calls
*/
get: function () {
return this.instance;
},
enumerable: false,
configurable: true
});
/**
* Execute the statusGetterCall periodically until timeout and resolves the status
* @param statusGetterCall - function to fetch the transaction status from a blockchain
* @param [hash} - transaction hash
* @param [timeout] - if the statusGetterCall did not resolved during the timeout period (in ms) the function will reject
* @param [ms] - milliseconds delay between api polling attempts
*/
Waas.waitForTxStatus = function (statusGetterCall, hash, timeout, ms) {
if (timeout === void 0) { timeout = 20e3; }
if (ms === void 0) { ms = 400; }
return __awaiter(this, void 0, void 0, function () {
var validate;
return __generator(this, function (_a) {
validate = function (s) {
switch (s.status) {
case "confirmed":
return true;
case "error":
throw new errors_1.MiningError(s);
case "pending":
default:
return false;
}
};
return [2 /*return*/, (0, polling_helper_1.poll)(statusGetterCall, validate, "transaction status ".concat(hash), timeout, ms)];
});
});
};
/**
* read wallet based api calls
* @param [name] - wallet name
*/
Waas.prototype.wallet = function (name) {
var w = new wallet_1.Wallet(this, name);
return w;
};
/**
* read eth based api calls
* @param [txHash] - Ethereum transaction hash
*/
Waas.prototype.eth = function (txHash) {
var e = new eth_1.Ethereum(this, txHash);
return e;
};
/**
* read btc based api calls
* @param [txHash] - Bitcoin transaction hash
*/
Waas.prototype.btc = function (txHash) {
var b = new btc_1.Bitcoin(this, txHash);
return b;
};
/**
* read xtz based api calls
* @param [txHash] - Tezos transaction hash
*/
Waas.prototype.xtz = function (txHash) {
var xtz = new xtz_1.Tezos(this, txHash);
return xtz;
};
/**
* read api calls for asynchronous requests
* @param id - Unique identifier for an asynchronous request
*/
Waas.prototype.request = function (id) {
return new request_1.Request(this, id);
};
/**
* wrap async call to the bottleneck limiter
* @param fn - function that returns a promise function. Pass the promise function's arguments via the functions argument
* @param args - promise function arguments
*/
Waas.prototype.wrap = function (fn) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (!this.limiter) {
// throw new Error("Cannot wrap function without limiter instance");
return [2 /*return*/, fn(args)];
}
return [2 /*return*/, this.limiter.schedule(fn, args)];
});
});
};
return Waas;
}());
exports.Waas = Waas;
//# sourceMappingURL=waas.js.map