UNPKG

scrypt-ts

Version:

A toolset for building sCrypt smart contract applications on Bitcoin SV network written in typescript.

193 lines 7.67 kB
"use strict"; 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 __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WhatsonchainProvider = void 0; const scryptlib_1 = require("scryptlib"); const abstract_provider_1 = require("../bsv/abstract-provider"); const superagent_1 = __importDefault(require("superagent")); const utils_1 = require("../bsv/utils"); /** * The WhatsonchainProvider is backed by [whatsonchain]{@link https://whatsonchain.com}, * which is the popular blockchain exxplorer for Bitcoin. */ class WhatsonchainProvider extends abstract_provider_1.Provider { constructor(network) { super(); this._isConnected = false; this._network = network; this._initializeConnection(); } get apiPrefix() { // TODO: check all avaiable networks const networkStr = this._network.name === scryptlib_1.bsv.Networks.mainnet.name ? 'main' : 'test'; return `https://api.whatsonchain.com/v1/bsv/${networkStr}`; } isConnected() { return this._isConnected; } connect() { var _a; return __awaiter(this, void 0, void 0, function* () { try { const res = yield superagent_1.default.get(`${this.apiPrefix}/woc`) .timeout(3000); if (res.ok && res.text === "Whats On Chain") { this._isConnected = true; this.emit("connected" /* ProviderEvent.Connected */, true); } else { throw new Error(`${res.body.msg ? res.body.msg : res.text}`); } } catch (error) { this._isConnected = false; this.emit("connected" /* ProviderEvent.Connected */, false); throw new Error(`connect failed: ${(_a = error.message) !== null && _a !== void 0 ? _a : "unknown error"}`); } return Promise.resolve(this); }); } updateNetwork(network) { this._network = network; this.emit("networkChange" /* ProviderEvent.NetworkChange */, network); } getNetwork() { return this._network; } sendRawTransaction(rawTxHex) { return __awaiter(this, void 0, void 0, function* () { yield this._ready(); // 1 second per KB const size = Math.max(1, rawTxHex.length / 2 / 1024); //KB const timeout = Math.max(10000, 1000 * size); try { const res = yield superagent_1.default.post(`${this.apiPrefix}/tx/raw`) .timeout({ response: timeout, // Wait 5 seconds for the server to start sending, deadline: 60000, // but allow 1 minute for the file to finish loading. }) .set('Content-Type', 'application/json') .send({ txhex: rawTxHex }); return res.body; } catch (error) { if (error.response && error.response.text) { if (needIgnoreError(error.response.text)) { return new scryptlib_1.bsv.Transaction(rawTxHex).id; } throw new Error(`WhatsonchainProvider ERROR: ${friendlyBIP22RejectionMsg(error.response.text)}`); } throw new Error(`WhatsonchainProvider ERROR: ${error.message}`); } }); } listUnspent(address, options) { return __awaiter(this, void 0, void 0, function* () { yield this._ready(); const res = yield superagent_1.default.get(`${this.apiPrefix}/address/${address}/unspent`); let utxos = res.body.map(item => ({ txId: item.tx_hash, outputIndex: item.tx_pos, satoshis: item.value, script: scryptlib_1.bsv.Script.buildPublicKeyHashOut(address).toHex(), })); if (options) { return (0, utils_1.filterUTXO)(utxos, options); } return utxos; }); } getBalance(address) { return this.listUnspent(address).then(utxos => { return { confirmed: utxos.reduce((acc, utxo) => { acc += utxo.satoshis; return acc; }, 0), unconfirmed: 0 }; }); } getTransaction(txHash) { return __awaiter(this, void 0, void 0, function* () { yield this._ready(); return superagent_1.default.get(`${this.apiPrefix}/tx/${txHash}/hex`).then(res => { if (res.ok) { return new scryptlib_1.bsv.Transaction(res.text); } else if (res.error) { throw res.error; } else { throw `getTransaction error ${txHash}`; } }); }); } getFeePerKb() { return Promise.resolve(1); } } exports.WhatsonchainProvider = WhatsonchainProvider; function needIgnoreError(inMsg) { if (inMsg.includes('Transaction already in the mempool')) { return true; } else if (inMsg.includes('txn-already-known')) { return true; } return false; } function friendlyBIP22RejectionMsg(inMsg) { if (inMsg.includes('bad-txns-vin-empty')) { return 'Transaction is missing inputs.'; } else if (inMsg.includes('bad-txns-vout-empty')) { return 'Transaction is missing outputs.'; } else if (inMsg.includes('bad-txns-oversize')) { return 'Transaction is too large.'; } else if (inMsg.includes('bad-txns-vout-negative')) { return 'Transaction output value is negative.'; } else if (inMsg.includes('bad-txns-vout-toolarge')) { return 'Transaction outputut value is too large.'; } else if (inMsg.includes('bad-txns-txouttotal-toolarge')) { return 'Transaction total outputut value is too large.'; } else if (inMsg.includes('bad-txns-prevout-null')) { return 'Transaction inputs previous TX reference is null.'; } else if (inMsg.includes('bad-txns-inputs-duplicate')) { return 'Transaction contains duplicate inputs.'; } else if (inMsg.includes('bad-txns-inputs-too-large')) { return 'Transaction inputs too large.'; } else if (inMsg.includes('bad-txns-fee-negative')) { return 'Transaction network fee is negative.'; } else if (inMsg.includes('bad-txns-fee-outofrange')) { return 'Transaction network fee is out of range.'; } else if (inMsg.includes('mandatory-script-verify-flag-failed')) { return 'Script evaluation failed.'; } else { return inMsg; } } //# sourceMappingURL=whatsonchain-provider.js.map