UNPKG

postchain-client

Version:

Client library for accessing a Postchain node through REST.

236 lines 8.25 kB
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 * as gtv from "../gtv"; import { checkDigestSignature, createPublicKey, makeKeyPair, signDigest, } from "../encryption/encryption"; import { AlreadySignedTransactionException, MissingGtxException, MissingSignerException, } from "./errors"; import { encode as gtxEncode, decode as gtxDecode } from "./index"; import { ensureBuffer } from "../formatter"; export function emptyGtx(blockchainRid) { return { blockchainRid, operations: [], signers: [] }; } /** * Adds a function call to a GTX. Creates a new GTX if none specified. * This function will throw Error if gtx is already signed * @param opName the name of the function to call * @param args the array of arguments of the function call. If no args, this must be an empty array * @param gtx the function call will be added to this gtx * @returns the gtx * @throws if gtx is null or if gtx is already signed */ export function addTransactionToGtx(opName, args, gtx) { if (gtx == null) { throw new MissingGtxException(); } if (gtx.signatures) { throw new AlreadySignedTransactionException("function"); } gtx.operations.push({ opName: opName, args: args }); return gtx; } export function addSignerToGtx(signer, gtx) { if (gtx.signatures) { throw new AlreadySignedTransactionException("signer"); } gtx.signers.push(signer); } /** * Serializes the gtx to get tx hash * @param gtx the gtx to serialize */ export function getDigest(gtx) { return gtv.gtvHash(gtxToRawGtx(gtx)); } /** * Serializes the gtx for signing * @param gtx the gtx to serialize */ export function getDigestToSign(gtx) { return gtv.gtvHash(gtxToRawGtxBody(gtx)); } export function getDigestToSignFromRawGtxBody(gtxBody) { return gtv.gtvHash(gtxBody); } export function gtxToRawGtxBody(gtx) { return [ gtx.blockchainRid, gtx.operations.map((op) => [op.opName, op.args]), gtx.signers, ]; } export function gtxToRawGtx(gtx) { var _a; return [ [ gtx.blockchainRid, gtx.operations.map((op) => [op.opName, op.args]), gtx.signers, ], (_a = gtx.signatures) !== null && _a !== void 0 ? _a : [], ]; } export function sign(gtx, privOrSigProv, pubKey) { return __awaiter(this, void 0, void 0, function* () { if (privOrSigProv instanceof Buffer) { const digestToSign = getDigestToSign(gtx); const signature = signDigest(digestToSign, privOrSigProv); return addSignature(pubKey || makeKeyPair(privOrSigProv).pubKey, signature, gtx); } else { // Removes signatures and extract the rawgtxBody const rawGtxBody = gtxToRawGtxBody(gtx); const signature = yield privOrSigProv.sign(rawGtxBody); return addSignature(privOrSigProv.pubKey, signature, gtx); } }); } export function signRawTransaction(_keyPair, _rawTransaction) { throw Error("TODO"); //TODO //const gtx = module.exports.deserialize(rawTransaction); //module.exports.sign(keyPair.privKey, keyPair.pubKey, gtx); // return module.exports.serialize(gtx) } /** * Adds a signature to the gtx */ export function addSignature(pubKeyBuffer, signatureBuffer, gtx) { if (!gtx.signatures) { gtx.signatures = Array(gtx.signers.length); } const signerIndex = gtx.signers.findIndex((signer) => pubKeyBuffer.equals(signer)); if (signerIndex === -1) { throw new MissingSignerException(); } gtx.signatures[signerIndex] = signatureBuffer; return gtx; } export function serialize(gtx) { if (!gtx.signatures) { // TODO // The gtx is not signed, but we must include // the signatures attribute, so let's add that. gtx.signatures = []; } return gtxEncode([gtxToRawGtxBody(gtx), gtx.signatures]); } export function deserialize(gtxBytes) { const deserializedTx = gtxDecode(gtxBytes); const body = deserializedTx[0]; const gtvTxBody = { blockchainRid: body[0], operations: body[1].map((operation) => ({ opName: operation[0], args: operation[1], })), signers: body[2], }; const signatures = deserializedTx[1]; return { blockchainRid: gtvTxBody.blockchainRid, operations: gtvTxBody.operations, signers: gtvTxBody.signers, signatures, }; } export function checkGTXSignatures(txHash, gtx) { var _a; for (const i in gtx.signers) { const signValid = checkDigestSignature(txHash, gtx.signers[i], (_a = gtx.signatures) === null || _a === void 0 ? void 0 : _a[i]); if (!signValid) return signValid; } return true; } export function checkExistingGTXSignatures(txHash, gtx) { var _a; for (const i in gtx.signers) { if ((_a = gtx.signatures) === null || _a === void 0 ? void 0 : _a[i]) { const signValid = checkDigestSignature(txHash, gtx.signers[i], gtx.signatures[i]); if (!signValid) return signValid; } } return true; } export function newSignatureProvider(keyPair) { let pub, priv; if (keyPair) { priv = ensureBuffer(keyPair.privKey); pub = keyPair.pubKey ? ensureBuffer(keyPair.pubKey) : createPublicKey(priv); } else { ({ privKey: priv, pubKey: pub } = makeKeyPair()); } return { pubKey: pub, sign: (gtx) => __awaiter(this, void 0, void 0, function* () { const signature = getDigestToSignFromRawGtxBody(gtx); return signDigest(signature, priv); }), }; } export function rawGtvToGtx(gtv) { if (Array.isArray(gtv) && gtv.length !== 2) { throw new Error("Gtv must be an array of size 2"); } const gtvArray = gtv; if (!Array.isArray(gtvArray[0])) { throw new Error("First element must be an array"); } if (!Array.isArray(gtvArray[1])) { throw new Error("Second element must be an array"); } gtvArray[1].forEach((element) => { if (!Buffer.isBuffer(element)) { throw new Error("Element must be a buffer"); } }); const gtxBody = rawGtvToGtxBody(gtvArray[0]); return Object.assign(Object.assign({}, gtxBody), { signatures: gtvArray[1] }); } function rawGtvToGtxBody(gtv) { if (Array.isArray(gtv) && gtv.length !== 3) { throw new Error("Gtv must be an array of size 3"); } const array = gtv; if (!Buffer.isBuffer(array[0])) { throw new Error("First element must be a byte array"); } if (!Array.isArray(array[1])) { throw new Error("Second element must be an array"); } if (!Array.isArray(array[2])) { throw new Error("Third element must be an array"); } array[2].forEach((element) => { if (!Buffer.isBuffer(element)) { throw new Error("Element must be a buffer"); } }); return { blockchainRid: array[0], operations: array[1].map((element) => rawGtvToRellOp(element)), signers: array[2], }; } function rawGtvToRellOp(gtv) { if (Array.isArray(gtv) && gtv.length !== 2) { throw new Error("Gtv must be an array of size 2"); } const array = gtv; if (typeof array[0] !== "string") { throw new Error("First element must be a string"); } if (!Array.isArray(array[1])) { throw new Error("Second element must be an array"); } return { opName: array[0], args: array[1] }; } //# sourceMappingURL=gtx.js.map