UNPKG

airgap-coin-lib

Version:

The airgap-coin-lib is a protocol agnostic library to prepare, sign and broadcast cryptocurrency transactions.

346 lines 16.5 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); 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 }); var RPCBody_1 = require("../../../../data/RPCBody"); var index_1 = require("../../../../dependencies/src/axios-0.19.0/index"); var bignumber_1 = require("../../../../dependencies/src/bignumber.js-9.0.0/bignumber"); var IAirGapTransaction_1 = require("../../../../interfaces/IAirGapTransaction"); var EthereumProtocolOptions_1 = require("../../EthereumProtocolOptions"); var utils_1 = require("../../utils/utils"); var NodeClient_1 = require("./NodeClient"); var EthereumRPCBody = /** @class */ (function (_super) { __extends(EthereumRPCBody, _super); function EthereumRPCBody() { return _super !== null && _super.apply(this, arguments) || this; } EthereumRPCBody.prototype.toRPCBody = function () { return JSON.stringify(this.toJSON()); }; EthereumRPCBody.prototype.toJSON = function () { return { jsonrpc: this.jsonrpc, method: this.method, params: this.params, id: this.id }; }; EthereumRPCBody.blockEarliest = 'earliest'; EthereumRPCBody.blockLatest = 'latest'; EthereumRPCBody.blockPending = 'pending'; return EthereumRPCBody; }(RPCBody_1.RPCBody)); var EthereumRPCData = /** @class */ (function () { function EthereumRPCData(methodSignature) { this.methodSignature = methodSignature; } EthereumRPCData.prototype.abiEncoded = function () { var hash = utils_1.EthereumUtils.sha3(this.methodSignature); if (hash === null) { return ''; } return "0x" + hash.slice(2, 10); }; EthereumRPCData.addLeadingZeroPadding = function (value, targetLength) { if (targetLength === void 0) { targetLength = EthereumRPCData.parametersLength; } var result = value; while (result.length < targetLength) { result = '0' + result; } return result; }; EthereumRPCData.removeLeadingZeroPadding = function (value) { var result = value; while (result.startsWith('0')) { result = result.slice(1); // this can probably be done much more efficiently with a regex } return result; }; // 2 chars = 1 byte hence to get to 32 bytes we need 64 chars EthereumRPCData.parametersLength = 64; return EthereumRPCData; }()); exports.EthereumRPCData = EthereumRPCData; var EthereumRPCDataBalanceOf = /** @class */ (function (_super) { __extends(EthereumRPCDataBalanceOf, _super); function EthereumRPCDataBalanceOf(address) { var _this = _super.call(this, EthereumRPCDataBalanceOf.methodName + "(address)") || this; _this.address = address; return _this; } EthereumRPCDataBalanceOf.prototype.abiEncoded = function () { var srcAddress = this.address; if (srcAddress.startsWith('0x')) { srcAddress = srcAddress.slice(2); } return _super.prototype.abiEncoded.call(this) + EthereumRPCData.addLeadingZeroPadding(srcAddress); }; EthereumRPCDataBalanceOf.methodName = 'balanceOf'; return EthereumRPCDataBalanceOf; }(EthereumRPCData)); exports.EthereumRPCDataBalanceOf = EthereumRPCDataBalanceOf; var EthereumRPCDataTransfer = /** @class */ (function (_super) { __extends(EthereumRPCDataTransfer, _super); function EthereumRPCDataTransfer(toAddressOrData, amount) { var _this = _super.call(this, EthereumRPCDataTransfer.methodName + "(address,uint256)") || this; if (amount) { var toAddress = toAddressOrData; _this.recipient = toAddress; _this.amount = amount; } else { var data = toAddressOrData; var methodID = _super.prototype.abiEncoded.call(_this); if (!data.startsWith(methodID)) { throw new Error('unexpected method ID'); } var params = data.slice(methodID.length); var recipient = EthereumRPCData.removeLeadingZeroPadding(params.slice(0, EthereumRPCData.parametersLength)); var parsedAmount = EthereumRPCData.removeLeadingZeroPadding(params.slice(EthereumRPCData.parametersLength)); _this.recipient = "0x" + recipient; _this.amount = "0x" + parsedAmount; } return _this; } EthereumRPCDataTransfer.prototype.abiEncoded = function () { var dstAddress = this.recipient; if (dstAddress.startsWith('0x')) { dstAddress = dstAddress.slice(2); } var transferAmount = this.amount; if (transferAmount.startsWith('0x')) { transferAmount = transferAmount.slice(2); } return (_super.prototype.abiEncoded.call(this) + EthereumRPCData.addLeadingZeroPadding(dstAddress.toLowerCase()) + EthereumRPCData.addLeadingZeroPadding(transferAmount.toLowerCase())); }; EthereumRPCDataTransfer.methodName = 'transfer'; return EthereumRPCDataTransfer; }(EthereumRPCData)); exports.EthereumRPCDataTransfer = EthereumRPCDataTransfer; var AirGapNodeClient = /** @class */ (function (_super) { __extends(AirGapNodeClient, _super); function AirGapNodeClient(baseURL) { if (baseURL === void 0) { baseURL = EthereumProtocolOptions_1.NODE_URL; } return _super.call(this, baseURL) || this; } AirGapNodeClient.prototype.fetchBalance = function (address) { return __awaiter(this, void 0, void 0, function () { var body, response; return __generator(this, function (_a) { switch (_a.label) { case 0: body = new EthereumRPCBody('eth_getBalance', [address, EthereumRPCBody.blockLatest]); return [4 /*yield*/, this.send(body)]; case 1: response = _a.sent(); return [2 /*return*/, new bignumber_1.BigNumber(response.result)]; } }); }); }; AirGapNodeClient.prototype.fetchTransactionCount = function (address) { return __awaiter(this, void 0, void 0, function () { var body, response; return __generator(this, function (_a) { switch (_a.label) { case 0: body = new EthereumRPCBody('eth_getTransactionCount', [address, EthereumRPCBody.blockLatest]); return [4 /*yield*/, this.send(body)]; case 1: response = _a.sent(); return [2 /*return*/, new bignumber_1.BigNumber(response.result).toNumber()]; } }); }); }; AirGapNodeClient.prototype.sendSignedTransaction = function (transaction) { return __awaiter(this, void 0, void 0, function () { var body; return __generator(this, function (_a) { switch (_a.label) { case 0: body = new EthereumRPCBody('eth_sendRawTransaction', [transaction]); return [4 /*yield*/, this.send(body)]; case 1: return [2 /*return*/, (_a.sent()).result]; } }); }); }; AirGapNodeClient.prototype.getTransactionStatus = function (transactionHash) { return __awaiter(this, void 0, void 0, function () { var body, response; return __generator(this, function (_a) { switch (_a.label) { case 0: body = new EthereumRPCBody('eth_getTransactionReceipt', [transactionHash]); return [4 /*yield*/, this.send(body)]; case 1: response = _a.sent(); return [2 /*return*/, response.result.status === '0x1' ? IAirGapTransaction_1.AirGapTransactionStatus.APPLIED : IAirGapTransaction_1.AirGapTransactionStatus.FAILED]; } }); }); }; AirGapNodeClient.prototype.callBalanceOf = function (contractAddress, address) { return __awaiter(this, void 0, void 0, function () { var body, response; return __generator(this, function (_a) { switch (_a.label) { case 0: body = this.balanceOfBody(contractAddress, address); return [4 /*yield*/, this.send(body)]; case 1: response = _a.sent(); return [2 /*return*/, new bignumber_1.BigNumber(response.result)]; } }); }); }; AirGapNodeClient.prototype.callBalanceOfOnContracts = function (contractAddresses, address) { return __awaiter(this, void 0, void 0, function () { var bodies, responses, result; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: bodies = contractAddresses.map(function (contractAddress, index) { return _this.balanceOfBody(contractAddress, address, index); }); return [4 /*yield*/, this.batchSend(bodies)]; case 1: responses = _a.sent(); result = {}; responses.forEach(function (response) { var _a; result[contractAddresses[response.id]] = new bignumber_1.BigNumber((_a = response.result, (_a !== null && _a !== void 0 ? _a : 0))); }); return [2 /*return*/, result]; } }); }); }; AirGapNodeClient.prototype.balanceOfBody = function (contractAddress, address, id) { if (id === void 0) { id = 0; } var data = new EthereumRPCDataBalanceOf(address); return new EthereumRPCBody('eth_call', [{ to: contractAddress, data: data.abiEncoded() }, EthereumRPCBody.blockLatest], id); }; AirGapNodeClient.prototype.estimateTransactionGas = function (fromAddress, toAddress, amount, data, gas) { return __awaiter(this, void 0, void 0, function () { var body, response; return __generator(this, function (_a) { switch (_a.label) { case 0: body = new EthereumRPCBody('eth_estimateGas', [{ from: fromAddress, to: toAddress, gas: gas, value: amount, data: data }]); return [4 /*yield*/, this.send(body)]; case 1: response = _a.sent(); return [2 /*return*/, new bignumber_1.BigNumber(response.result)]; } }); }); }; AirGapNodeClient.prototype.estimateTransferGas = function (contractAddress, fromAddress, toAddress, hexAmount) { return __awaiter(this, void 0, void 0, function () { var data, result; return __generator(this, function (_a) { data = new EthereumRPCDataTransfer(toAddress, hexAmount); result = this.estimateTransactionGas(fromAddress, contractAddress, undefined, data.abiEncoded()); return [2 /*return*/, result]; }); }); }; AirGapNodeClient.prototype.getGasPrice = function () { return __awaiter(this, void 0, void 0, function () { var body, response; return __generator(this, function (_a) { switch (_a.label) { case 0: body = new EthereumRPCBody('eth_gasPrice', []); return [4 /*yield*/, this.send(body)]; case 1: response = _a.sent(); return [2 /*return*/, new bignumber_1.BigNumber(response.result)]; } }); }); }; AirGapNodeClient.prototype.send = function (body) { return __awaiter(this, void 0, void 0, function () { var data; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, index_1.default.post(this.baseURL, body.toRPCBody())]; case 1: data = (_a.sent()).data; if (data.error !== undefined) { throw new Error(data.error.message); } return [2 /*return*/, data]; } }); }); }; AirGapNodeClient.prototype.batchSend = function (bodies) { return __awaiter(this, void 0, void 0, function () { var data; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, index_1.default.post(this.baseURL, JSON.stringify(bodies.map(function (body) { return body.toJSON(); })))]; case 1: data = (_a.sent()).data; return [2 /*return*/, data]; } }); }); }; return AirGapNodeClient; }(NodeClient_1.EthereumNodeClient)); exports.AirGapNodeClient = AirGapNodeClient; //# sourceMappingURL=AirGapNodeClient.js.map