diff --git a/src/model/transaction/CosignatureTransaction.ts b/src/model/transaction/CosignatureTransaction.ts index 3c1dcbf31a..a89c77a956 100644 --- a/src/model/transaction/CosignatureTransaction.ts +++ b/src/model/transaction/CosignatureTransaction.ts @@ -26,7 +26,7 @@ import { Transaction } from './Transaction'; */ export class CosignatureTransaction { /** - * @param transactionToCosign + * @param transactionToCosign Aggregate transaction */ constructor( /** @@ -66,13 +66,14 @@ export class CosignatureTransaction { /** * Serialize and sign transaction creating a new SignedTransaction * @param account + * @param transactionHash Transaction hash (optional) * @returns {CosignatureSignedTransaction} */ - public signWith(account: Account): CosignatureSignedTransaction { - if (!this.transactionToCosign.transactionInfo!.hash) { + public signWith(account: Account, transactionHash?: string): CosignatureSignedTransaction { + if ((!this.transactionToCosign.transactionInfo || !this.transactionToCosign.transactionInfo!.hash) && !transactionHash) { throw new Error('Transaction to cosign should be announced first'); } - const hash = this.transactionToCosign.transactionInfo!.hash; + const hash = !transactionHash ? this.transactionToCosign.transactionInfo!.hash : transactionHash; const hashBytes = Convert.hexToUint8(hash ? hash : ''); const keyPairEncoded = KeyPair.createKeyPairFromPrivateKeyString(account.privateKey); const signature = KeyPair.sign(keyPairEncoded, new Uint8Array(hashBytes)); diff --git a/test/model/transaction/CosignatureTransaction.spec.ts b/test/model/transaction/CosignatureTransaction.spec.ts index 187a996456..116dd6be93 100644 --- a/test/model/transaction/CosignatureTransaction.spec.ts +++ b/test/model/transaction/CosignatureTransaction.spec.ts @@ -32,63 +32,63 @@ describe('CosignatureTransaction', () => { account = TestingAccount; }); - it('should createComplete an TransferTransaction object and sign it', () => { - const aggregateTransferTransactionDTO = { - meta: { - hash: '671653C94E2254F2A23EFEDB15D67C38332AED1FBD24B063C0A8E675582B6A96', - height: '18160', - id: '5A0069D83F17CF0001777E55', - index: 0, - merkleComponentHash: '81E5E7AE49998802DABC816EC10158D3A7879702FF29084C2C992CD1289877A7', - }, - transaction: { - cosignatures: [ - { - version: '0', - signature: - '5780C8DF9D46BA2BCF029DCC5D3BF55FE1CB5BE7ABCF30387C4637DD' + - 'EDFC2152703CA0AD95F21BB9B942F3CC52FCFC2064C7B84CF60D1A9E69195F1943156C07', - signerPublicKey: 'A5F82EC8EBB341427B6785C8111906CD0DF18838FB11B51CE0E18B5E79DFF630', + const aggregateTransferTransactionDTO = { + meta: { + hash: '671653C94E2254F2A23EFEDB15D67C38332AED1FBD24B063C0A8E675582B6A96', + height: '18160', + id: '5A0069D83F17CF0001777E55', + index: 0, + merkleComponentHash: '81E5E7AE49998802DABC816EC10158D3A7879702FF29084C2C992CD1289877A7', + }, + transaction: { + cosignatures: [ + { + version: '0', + signature: + '5780C8DF9D46BA2BCF029DCC5D3BF55FE1CB5BE7ABCF30387C4637DD' + + 'EDFC2152703CA0AD95F21BB9B942F3CC52FCFC2064C7B84CF60D1A9E69195F1943156C07', + signerPublicKey: 'A5F82EC8EBB341427B6785C8111906CD0DF18838FB11B51CE0E18B5E79DFF630', + }, + ], + deadline: '1000', + maxFee: '0', + signature: + '939673209A13FF82397578D22CC96EB8516A6760C894D9B7535E3A1E0680' + + '07B9255CFA9A914C97142A7AE18533E381C846B69D2AE0D60D1DC8A55AD120E2B606', + signerPublicKey: '7681ED5023141D9CDCF184E5A7B60B7D466739918ED5DA30F7E71EA7B86EFF2D', + transactions: [ + { + meta: { + aggregateHash: '3D28C804EDD07D5A728E5C5FFEC01AB07AFA5766AE6997B38526D36015A4D006', + aggregateId: '5A0069D83F17CF0001777E55', + height: '18160', + id: '5A0069D83F17CF0001777E56', + index: 0, }, - ], - deadline: '1000', - maxFee: '0', - signature: - '939673209A13FF82397578D22CC96EB8516A6760C894D9B7535E3A1E0680' + - '07B9255CFA9A914C97142A7AE18533E381C846B69D2AE0D60D1DC8A55AD120E2B606', - signerPublicKey: '7681ED5023141D9CDCF184E5A7B60B7D466739918ED5DA30F7E71EA7B86EFF2D', - transactions: [ - { - meta: { - aggregateHash: '3D28C804EDD07D5A728E5C5FFEC01AB07AFA5766AE6997B38526D36015A4D006', - aggregateId: '5A0069D83F17CF0001777E55', - height: '18160', - id: '5A0069D83F17CF0001777E56', - index: 0, + transaction: { + message: { + payload: '746573742D6D657373616765', + type: 0, }, - transaction: { - message: { - payload: '746573742D6D657373616765', - type: 0, + mosaics: [ + { + amount: '100', + id: '85BBEA6CC462B244', }, - mosaics: [ - { - amount: '100', - id: '85BBEA6CC462B244', - }, - ], - recipientAddress: '6823BB7C3C089D996585466380EDBDC19D4959184893E38C', - signerPublicKey: 'B4F12E7C9F6946091E2CB8B6D3A12B50D17CCBBF646386EA27CE2946A7423DCF', - type: 16724, - version: 36865, - }, + ], + recipientAddress: '6823BB7C3C089D996585466380EDBDC19D4959184893E38C', + signerPublicKey: 'B4F12E7C9F6946091E2CB8B6D3A12B50D17CCBBF646386EA27CE2946A7423DCF', + type: 16724, + version: 36865, }, - ], - type: 16705, - version: 36865, - }, - }; + }, + ], + type: 16705, + version: 36865, + }, + }; + it('should createComplete an TransferTransaction object and sign it', () => { const aggregateTransferTransaction = CreateTransactionFromDTO(aggregateTransferTransactionDTO); const cosignatureTransaction = CosignatureTransaction.create(aggregateTransferTransaction as AggregateTransaction); @@ -119,4 +119,69 @@ describe('CosignatureTransaction', () => { expect(signedTx.signerPublicKey).to.be.equal(account.publicKey); expect(signedTx.version.toString()).to.be.equal('0'); }); + + it('should sign a transaction with provided transactionHash', () => { + const tx = TransferTransaction.create( + Deadline.create(), + account.address, + [], + PlainMessage.create('a to b'), + NetworkType.MIJIN_TEST, + ); + + const aggregate = AggregateTransaction.createComplete( + Deadline.create(), + [tx.toAggregate(account.publicAccount)], + NetworkType.MIJIN_TEST, + [], + ); + const txHash = '9801508C58666C746F471538E43002B85B1CD542F9874B2861183919BA8787B6'; + + const cosignTx = new CosignatureTransaction(aggregate); + + const signedTx = cosignTx.signWith(account, txHash); + + expect(signedTx.parentHash).to.be.equal('9801508C58666C746F471538E43002B85B1CD542F9874B2861183919BA8787B6'); + expect(signedTx.signerPublicKey).to.be.equal('9801508C58666C746F471538E43002B85B1CD542F9874B2861183919BA8787B6'); + expect(signedTx.signerPublicKey).to.be.equal(account.publicKey); + expect(signedTx.version.toString()).to.be.equal('0'); + }); + + it('should sign a transaction to throw', () => { + const tx = TransferTransaction.create( + Deadline.create(), + account.address, + [], + PlainMessage.create('a to b'), + NetworkType.MIJIN_TEST, + ); + + const aggregate = AggregateTransaction.createComplete( + Deadline.create(), + [tx.toAggregate(account.publicAccount)], + NetworkType.MIJIN_TEST, + [], + ); + const cosignTx = new CosignatureTransaction(aggregate); + expect(() => { + cosignTx.signWith(account); + }).to.throw(Error, 'Transaction to cosign should be announced first'); + }); + + it('should sign a transaction to throw no hash in transaction info', () => { + Object.assign(aggregateTransferTransactionDTO, { + meta: { + hash: undefined, + height: '18160', + id: '5A0069D83F17CF0001777E55', + index: 0, + merkleComponentHash: '81E5E7AE49998802DABC816EC10158D3A7879702FF29084C2C992CD1289877A7', + }, + }); + const aggregate = CreateTransactionFromDTO(aggregateTransferTransactionDTO) as AggregateTransaction; + const cosignTx = new CosignatureTransaction(aggregate); + expect(() => { + cosignTx.signWith(account); + }).to.throw(Error, 'Transaction to cosign should be announced first'); + }); });