UNPKG

scrypt-ts

Version:

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

182 lines 8.95 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Signer = exports.DEFAULT_SIGHASH_TYPE = void 0; const scryptlib_1 = require("scryptlib"); exports.DEFAULT_SIGHASH_TYPE = scryptlib_1.bsv.crypto.Signature.ALL; /** * A `Signer` is a class which in some way directly or indirectly has access to a private key, which can sign messages and transactions to authorize the network to perform operations. */ class Signer { constructor(provider) { this._isSigner = true; this.provider = provider; } // Signing /** * Sign a raw transaction hex string. * * @param rawTxHex The raw transaction hex to sign. * @param options The options for signing, see the details of `SignTransactionOptions`. * @returns A promise which resolves to the signed transaction hex string. * @throws If any input of the transaction can not be signed properly. */ signRawTransaction(rawTxHex, options) { return __awaiter(this, void 0, void 0, function* () { const signedTx = yield this.signTransaction(new scryptlib_1.bsv.Transaction(rawTxHex), options); return signedTx.toString(); }); } /** * Sign a transaction object. By default only signs inputs, which are unlocking P2PKH UTXO's. * @param tx The transaction object to sign. * @param options The options for signing, see the details of `SignTransactionOptions`. * @returns A promise which resolves to the signed transaction object. */ signTransaction(tx, options) { return __awaiter(this, void 0, void 0, function* () { const network = yield this.getNetwork(); const sigReqsByInputIndex = ((options === null || options === void 0 ? void 0 : options.sigRequests) || []).reduce((m, sigReq) => { m.set(sigReq.inputIndex, sigReq); return m; }, new Map()); tx.inputs.forEach((input, inputIndex) => { if (input.output) { const sigReq = sigReqsByInputIndex.get(inputIndex); if (!sigReq) { return; } const scriptFromOptions = sigReq.scriptHex ? sigReq.scriptHex : scryptlib_1.bsv.Script.buildPublicKeyHashOut(sigReq.address.toString()).toHex(); if (scriptFromOptions !== input.output.script.toHex()) { throw new Error(`\`SignatureRequest\` script is not match the script of input: ${inputIndex}`); } if (sigReq.satoshis !== input.output.satoshis) { throw new Error(`\`SignatureRequest\` satoshis is not match the satoshis of input: ${inputIndex}`); } } else { const sigReq = sigReqsByInputIndex.get(inputIndex); if (!sigReq) { throw new Error(`\`SignatureRequest\` info should be provided for the input ${inputIndex} to call #signTransaction`); } const script = sigReq.scriptHex ? new scryptlib_1.bsv.Script(sigReq.scriptHex) : scryptlib_1.bsv.Script.buildPublicKeyHashOut(sigReq.address.toString()); // set ref output of the input input.output = new scryptlib_1.bsv.Transaction.Output({ script, satoshis: sigReq.satoshis }); } }); // Generate default `sigRequests` if not passed by user const sigRequests = tx.inputs.map((input, inputIndex) => { var _a, _b, _c, _d, _e; if ((_b = (_a = input.output) === null || _a === void 0 ? void 0 : _a.script) === null || _b === void 0 ? void 0 : _b.isPublicKeyHashOut()) { const useAddressToSign = input.output.script.toAddress(network); return { prevTxId: (0, scryptlib_1.toHex)(input.prevTxId), outputIndex: input.outputIndex, inputIndex, satoshis: (_c = input.output) === null || _c === void 0 ? void 0 : _c.satoshis, address: useAddressToSign, scriptHex: (_e = (_d = input.output) === null || _d === void 0 ? void 0 : _d.script) === null || _e === void 0 ? void 0 : _e.toHex(), sigHashType: exports.DEFAULT_SIGHASH_TYPE, }; } else { return undefined; } }).filter(inputInfo => typeof inputInfo === 'object'); const sigResponses = yield this.getSignatures(tx.toString(), sigRequests); // Set the acquired signature as an unlocking script for the transaction tx.inputs.forEach((input, inputIndex) => { var _a; const sigResp = sigResponses.find(sigResp => sigResp.inputIndex === inputIndex); if (sigResp && ((_a = input.output) === null || _a === void 0 ? void 0 : _a.script.isPublicKeyHashOut())) { const unlockingScript = new scryptlib_1.bsv.Script("") .add(Buffer.from(sigResp.sig, 'hex')) .add(Buffer.from(sigResp.publicKey, 'hex')); input.setScript(unlockingScript); } }); return tx; }); } /** * Get the connected provider. * @returns the connected provider. * @throws if no provider is connected to `this`. */ get connectedProvider() { if (!this.provider) { throw new Error(`the provider of signer ${this.constructor.name} is not set yet!`); } return this.provider; } /** * Sign transaction and broadcast it * @param tx A transaction is signed and broadcast * @param options The options for signing, see the details of `SignTransactionOptions`. * @returns A promise which resolves to the transaction id. */ signAndsendTransaction(tx, options) { return __awaiter(this, void 0, void 0, function* () { yield tx.sealAsync(); const signedTx = yield this.signTransaction(tx, options); yield this.connectedProvider.sendTransaction(signedTx); return signedTx; }); } ; /** * Get a list of the P2PKH UTXOs. * @param address The address of the returned UTXOs belongs to. * @param options The optional query conditions, see details in `UtxoQueryOptions`. * @returns A promise which resolves to a list of UTXO for the query options. */ listUnspent(address, options) { // Default implementation using provider. Can be overriden. return this.connectedProvider.listUnspent(address, options); } /** * Get the balance of BSVs in satoshis for an address. * @param address The query address. * @returns A promise which resolves to the address balance status. */ getBalance(address) { return __awaiter(this, void 0, void 0, function* () { // Default implementation using provider. Can be overriden. address = address ? address : yield this.getDefaultAddress(); return this.connectedProvider.getBalance(address); }); } // Inspection /** * Check if an object is a `Signer` * @param value The target object * @returns Returns `true` if and only if `object` is a Provider. */ static isSigner(value) { return !!(value && value._isSigner); } /** * Align provider's network after the signer is authenticated */ alignProviderNetwork() { var _a; return __awaiter(this, void 0, void 0, function* () { const isAuthenticated = yield this.isAuthenticated(); if (isAuthenticated) { yield ((_a = this.provider) === null || _a === void 0 ? void 0 : _a.connect()); const network = yield this.getNetwork(); this.connectedProvider.updateNetwork(network); } }); } } exports.Signer = Signer; //# sourceMappingURL=abstract-signer.js.map