UNPKG

apostille-library

Version:

A novel & holistic blockchain notarization and timestamping with transferable, updatable, branded, and conjointly owned notarizations.

280 lines 14 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const lodash_1 = require("lodash"); const nem2_sdk_1 = require("nem2-sdk"); const rxjs_1 = require("rxjs"); const operators_1 = require("rxjs/operators"); const Errors_1 = require("../types/Errors"); const Initiator_1 = require("./Initiator"); const incompleteTransactionsFunc = (readyTransaction) => { if (readyTransaction.initiator) { return !readyTransaction.initiator.complete; } return true; }; class ApostilleHttp { constructor(url) { this.announceList = []; this.unannouncedTransactions = []; this.transactionHttp = new nem2_sdk_1.TransactionHttp(url); this.accountHttp = new nem2_sdk_1.AccountHttp(url); this.blockHttp = new nem2_sdk_1.BlockHttp(url); this.listener = new nem2_sdk_1.Listener(url); } static createLockFundsTransaction(signedAggregateBondedTransaction) { const lockFundsTransaction = nem2_sdk_1.LockFundsTransaction.create(nem2_sdk_1.Deadline.create(), new nem2_sdk_1.Mosaic(new nem2_sdk_1.NamespaceId('nem.xem'), nem2_sdk_1.UInt64.fromUint(10)), nem2_sdk_1.UInt64.fromUint(480), signedAggregateBondedTransaction, signedAggregateBondedTransaction.networkType); return lockFundsTransaction; } announce(signedTransaction) { return new Promise((resolve, reject) => { this.transactionHttp.announce(signedTransaction) .subscribe((x) => resolve(x), (err) => reject(err)); }); } announceAggregateBonded(cosignatoryAccount, signedAggregateBondedTransaction, signedLockFundsTransaction) { return new Promise((resolve, reject) => { this.listener.open().then(() => { this.transactionHttp .announce(signedLockFundsTransaction) .subscribe((x) => console.log(x), (err) => reject(err)); this.listener .confirmed(cosignatoryAccount.address) .pipe(operators_1.filter((transaction) => { return transaction.transactionInfo !== undefined && transaction.transactionInfo.hash === signedLockFundsTransaction.hash; }), operators_1.mergeMap(() => this.transactionHttp.announceAggregateBonded(signedAggregateBondedTransaction))) .subscribe((announcedAggregateBonded) => { resolve(announcedAggregateBonded); }, (err) => { reject(err); }); }); }); } isCreated(publicAccount) { return __awaiter(this, void 0, void 0, function* () { try { const unconfirmedTransactions = yield this._unconfirmedTransactions(publicAccount).toPromise(); if (unconfirmedTransactions.length > 0) { return true; } else { const transactions = yield this._transactions(publicAccount).toPromise(); return (transactions.length > 0); } } catch (err) { throw new Error(err); } }); } getCosignatories(address) { return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { this.accountHttp.getMultisigAccountInfo(address).subscribe((multisigAccountInfo) => { resolve(multisigAccountInfo.cosignatories); }, (err) => reject(err)); })); } isOwned(address) { return new Promise((resolve, reject) => { this.getCosignatories(address).then((cosignatories) => { resolve(cosignatories.length > 0); }).catch((error) => { const errorText = JSON.parse(error.response.text); if (errorText.code === 'ResourceNotFound') { resolve(false); } else { reject(error); } }); }); } getCreationTransactionInfo(publicAccount) { return __awaiter(this, void 0, void 0, function* () { try { const transaction = yield this.getCreationTransaction(publicAccount); if (transaction.transactionInfo instanceof nem2_sdk_1.TransactionInfo) { return transaction.transactionInfo; } else { throw new Error(Errors_1.Errors[Errors_1.Errors.TRANSACTION_INFO_NOT_FOUND]); } } catch (error) { throw new Error(error); } }); } getCreationTransaction(publicAccount) { return new Promise((resolve, reject) => { this.fetchAllTransactions(publicAccount).pipe(operators_1.reduce((acc, txs) => { return acc.concat(txs); })).subscribe((transactions) => { if (transactions.length > 0) { const firstTransaction = transactions[transactions.length - 1]; if (firstTransaction instanceof nem2_sdk_1.TransferTransaction) { resolve(firstTransaction); } else if (firstTransaction instanceof nem2_sdk_1.AggregateTransaction) { const innerTransactions = firstTransaction.innerTransactions; const sortedInnerTransactions = lodash_1.sortBy(innerTransactions, ['transactionInfo.index']); for (let i = 0; i < sortedInnerTransactions.length; i++) { const innerTransaction = sortedInnerTransactions[i]; if (innerTransaction.type === nem2_sdk_1.TransactionType.TRANSFER) { resolve(innerTransaction); } } } } reject(Errors_1.Errors[Errors_1.Errors.CREATION_TRANSACTIONS_NOT_FOUND]); }); }); } fetchAllTransactions(publicAccount) { let nextId = ''; const pageSize = 100; let lastPageSize = 100; let queryParams = new nem2_sdk_1.QueryParams(pageSize); return this._transactions(publicAccount, queryParams).pipe(operators_1.expand((transactions) => { lastPageSize = transactions.length; if (lastPageSize < pageSize) { return rxjs_1.EMPTY; } nextId = transactions[transactions.length - 1].transactionInfo.id; queryParams = new nem2_sdk_1.QueryParams(pageSize, nextId !== '' ? nextId : undefined); return this._transactions(publicAccount, queryParams); }), operators_1.shareReplay()); } fetchAllTransactionsSync(publicAccount) { return this.fetchAllTransactions(publicAccount).pipe(operators_1.reduce((acc, txs) => { return acc.concat(txs); })).toPromise(); } _transactions(publicAccount, queryParams) { return this.accountHttp.transactions(publicAccount, queryParams); } _unconfirmedTransactions(publicAccount, queryParams) { return this.accountHttp.unconfirmedTransactions(publicAccount, queryParams); } addTransaction(readyTransaction) { const { initiator } = readyTransaction; if (initiator.canSign()) { return this.unannouncedTransactions.push(readyTransaction); } else { throw Error(Errors_1.Errors[Errors_1.Errors.INITIATOR_UNABLE_TO_SIGN]); } } getIncompleteTransactions() { return this.unannouncedTransactions.filter(incompleteTransactionsFunc); } hasIncompleteTransactions() { return this.unannouncedTransactions.some(incompleteTransactionsFunc); } reduceInitiatorList(initiators) { let allInitiators = []; for (const i of initiators) { if (i.account instanceof nem2_sdk_1.Account) { allInitiators.push(i.account); } if (i.accountType === Initiator_1.initiatorAccountType.MULTISIG_ACCOUNT) { allInitiators = allInitiators.concat(i.multiSigAccount.cosignatories); } } return lodash_1.uniq(allInitiators); } aggregateAndSign(innerTransactions, generationHash) { return lodash_1.chain(innerTransactions) .chunk(1000) .map((innerT) => { const initiatorsArray = innerT.map((innerTransaction) => innerTransaction.initiator); const innerTransactionsArray = innerT.map((innerTransaction) => innerTransaction.innerTransaction); const allInitiators = this.reduceInitiatorList(initiatorsArray); const [firstCosigner, ...cosigners] = allInitiators; const aggregateTransaction = nem2_sdk_1.AggregateTransaction.createComplete(nem2_sdk_1.Deadline.create(), innerTransactionsArray, firstCosigner.address.networkType, []); return firstCosigner.signTransactionWithCosignatories(aggregateTransaction, cosigners, generationHash); }).value(); } announceAll() { return this.fetchGenerationHash().pipe(operators_1.first(), operators_1.concatMap((generationHash) => { if (generationHash === '') { throw new Error('generationHash cannot be empty!'); } let innerTransactionsList = []; let readyTx; while (this.unannouncedTransactions.length > 0) { readyTx = this.unannouncedTransactions.pop(); if (readyTx === undefined) { break; } const { initiator, transaction } = readyTx; if (transaction.type === nem2_sdk_1.TransactionType.TRANSFER || transaction.type === nem2_sdk_1.TransactionType.MODIFY_MULTISIG_ACCOUNT) { if (initiator.complete) { const refreshedTransaction = transaction.reapplyGiven(nem2_sdk_1.Deadline.create()); const innerTransaction = refreshedTransaction.toAggregate(initiator.publicAccount); innerTransactionsList.push({ initiator, innerTransaction }); } else { this.announceList = this.announceList.concat(this.aggregateAndSign(innerTransactionsList, generationHash)); innerTransactionsList = []; const aggregateBondedTransaction = initiator.sign(transaction, generationHash); const lockFundsTransaction = ApostilleHttp.createLockFundsTransaction(aggregateBondedTransaction); const signedLockFunds = initiator.sign(lockFundsTransaction, generationHash); this.announceList.push(signedLockFunds); this.announceList.push(aggregateBondedTransaction); } } else if (transaction.type === nem2_sdk_1.TransactionType.AGGREGATE_BONDED || transaction.type === nem2_sdk_1.TransactionType.AGGREGATE_COMPLETE) { this.announceList.concat(this.aggregateAndSign(innerTransactionsList, generationHash)); innerTransactionsList = []; const signedTransaction = initiator.sign(transaction, generationHash); this.announceList.push(signedTransaction); } } this.announceList = this.announceList.concat(this.aggregateAndSign(innerTransactionsList, generationHash)); innerTransactionsList = []; return rxjs_1.concat(rxjs_1.of(this.announceList), rxjs_1.from(this.announceList).pipe(operators_1.switchMap((signedTx) => { return this.transactionHttp.announce(signedTx); })), this.confirmedListener()); })); } fetchGenerationHash() { return this.blockHttp.getBlockByHeight(1).pipe(operators_1.pluck('generationHash')); } confirmedListener() { return rxjs_1.from(this.listener.open()).pipe(operators_1.switchMap(() => { return this.listener.newBlock() .pipe(operators_1.finalize(() => this.listener.close()), operators_1.takeWhile(() => this.announceList.length > 0), operators_1.switchMap(() => { const transactionHashes = this.announceList.map((signedTx) => signedTx.hash); return this.transactionHttp.getTransactionsStatuses(transactionHashes); }), operators_1.map((txs) => { for (const tx of txs) { if (tx.group === 'confirmed') { lodash_1.remove(this.announceList, (signedTx) => { return signedTx.hash === tx.hash; }); } if (tx.group === 'failed') { lodash_1.remove(this.announceList, (signedTx) => { return signedTx.hash === tx.hash; }); } } return txs; })); })); } } exports.ApostilleHttp = ApostilleHttp; //# sourceMappingURL=ApostilleHttp.js.map