11import { BaseKey , BaseTransaction , InvalidTransactionError , TransactionType } from '@bitgo/sdk-core' ;
22import { BaseCoin as CoinConfig } from '@bitgo/statics' ;
3- import { CantonPrepareCommandResponse , PreparedTxnParsedInfo , TxData } from '../iface' ;
3+ import {
4+ CantonPrepareCommandResponse ,
5+ MultiHashSignature ,
6+ PartySignature ,
7+ PreparedTxnParsedInfo ,
8+ TransactionBroadcastData ,
9+ TxData ,
10+ } from '../iface' ;
411import utils from '../utils' ;
12+ import { DUMMY_HASH , HASHING_SCHEME_VERSION , SIGNATURE_ALGORITHM_SPEC , SIGNATURE_FORMAT } from '../constant' ;
513
614export class Transaction extends BaseTransaction {
715 private _prepareCommand : CantonPrepareCommandResponse ;
16+ private _signerFingerprint : string ;
817
918 constructor ( coinConfig : Readonly < CoinConfig > ) {
1019 super ( coinConfig ) ;
@@ -37,23 +46,84 @@ export class Transaction extends BaseTransaction {
3746 return false ;
3847 }
3948
49+ set signatures ( signature : string ) {
50+ this . _signatures . push ( signature ) ;
51+ }
52+
53+ set signerFingerprint ( fingerprint : string ) {
54+ this . _signerFingerprint = fingerprint ;
55+ }
56+
4057 toBroadcastFormat ( ) : string {
58+ if ( ! this . _type ) {
59+ throw new InvalidTransactionError ( 'Transaction type is not set' ) ;
60+ }
61+ if ( this . _type === TransactionType . TransferAcknowledge ) {
62+ const minData : TransactionBroadcastData = {
63+ txType : TransactionType [ this . _type ] ,
64+ submissionId : this . id ,
65+ } ;
66+ return Buffer . from ( JSON . stringify ( minData ) ) . toString ( 'base64' ) ;
67+ }
4168 if ( ! this . _prepareCommand ) {
4269 throw new InvalidTransactionError ( 'Empty transaction data' ) ;
4370 }
44- return Buffer . from ( JSON . stringify ( this . _prepareCommand ) ) . toString ( 'base64' ) ;
71+ const partySignatures : PartySignature [ ] = [ ] ;
72+ const data : TransactionBroadcastData = {
73+ prepareCommandResponse : this . _prepareCommand ,
74+ txType : this . _type ? TransactionType [ this . _type ] : '' ,
75+ preparedTransaction : '' ,
76+ partySignatures : {
77+ signatures : partySignatures ,
78+ } ,
79+ deduplicationPeriod : {
80+ Empty : { } ,
81+ } ,
82+ submissionId : this . id ,
83+ hashingSchemeVersion : HASHING_SCHEME_VERSION ,
84+ minLedgerTime : {
85+ time : {
86+ Empty : { } ,
87+ } ,
88+ } ,
89+ } ;
90+ const signatures : MultiHashSignature [ ] = [ ] ;
91+ if ( this . _signatures . length > 0 && this . _signerFingerprint ) {
92+ const signerPartyId = `${ this . _signerFingerprint . slice ( 0 , 5 ) } ::${ this . _signerFingerprint } ` ;
93+ this . signature . map ( ( signature ) => {
94+ const signatureObj : MultiHashSignature = {
95+ format : SIGNATURE_FORMAT ,
96+ signature : signature ,
97+ signedBy : this . _signerFingerprint ,
98+ signingAlgorithmSpec : SIGNATURE_ALGORITHM_SPEC ,
99+ } ;
100+ signatures . push ( signatureObj ) ;
101+ } ) ;
102+ const partySignature = {
103+ party : signerPartyId ,
104+ signatures : signatures ,
105+ } ;
106+ data . partySignatures ?. signatures . push ( partySignature ) ;
107+ data . preparedTransaction = this . _prepareCommand . preparedTransaction
108+ ? this . _prepareCommand . preparedTransaction
109+ : '' ;
110+ }
111+ return Buffer . from ( JSON . stringify ( data ) ) . toString ( 'base64' ) ;
45112 }
46113
47114 toJson ( ) : TxData {
48- if ( ! this . _prepareCommand || ! this . _prepareCommand . preparedTransaction ) {
49- throw new InvalidTransactionError ( 'Empty transaction data' ) ;
50- }
51115 const result : TxData = {
52116 id : this . id ,
53117 type : this . _type as TransactionType ,
54118 sender : '' ,
55119 receiver : '' ,
56120 } ;
121+ if ( this . _type === TransactionType . TransferAcknowledge ) {
122+ return result ;
123+ }
124+ if ( ! this . _prepareCommand || ! this . _prepareCommand . preparedTransaction ) {
125+ throw new InvalidTransactionError ( 'Empty transaction data' ) ;
126+ }
57127 // TODO: extract other required data (utxo used, request time, execute before etc)
58128 let parsedInfo : PreparedTxnParsedInfo ;
59129 try {
@@ -67,6 +137,9 @@ export class Transaction extends BaseTransaction {
67137 }
68138
69139 get signablePayload ( ) : Buffer {
140+ if ( this . _type === TransactionType . TransferAcknowledge ) {
141+ return Buffer . from ( DUMMY_HASH , 'base64' ) ;
142+ }
70143 if ( ! this . _prepareCommand ) {
71144 throw new InvalidTransactionError ( 'Empty transaction data' ) ;
72145 }
@@ -75,8 +148,18 @@ export class Transaction extends BaseTransaction {
75148
76149 fromRawTransaction ( rawTx : string ) : void {
77150 try {
78- const decoded : CantonPrepareCommandResponse = JSON . parse ( Buffer . from ( rawTx , 'base64' ) . toString ( 'utf8' ) ) ;
79- this . prepareCommand = decoded ;
151+ const decoded : TransactionBroadcastData = JSON . parse ( Buffer . from ( rawTx , 'base64' ) . toString ( 'utf8' ) ) ;
152+ this . id = decoded . submissionId ;
153+ this . transactionType = TransactionType [ decoded . txType ] ;
154+ if ( this . transactionType !== TransactionType . TransferAcknowledge ) {
155+ if ( decoded . prepareCommandResponse ) {
156+ this . prepareCommand = decoded . prepareCommandResponse ;
157+ }
158+ if ( decoded . partySignatures && decoded . partySignatures . signatures . length > 0 ) {
159+ this . signerFingerprint = decoded . partySignatures . signatures [ 0 ] . party . split ( '::' ) [ 1 ] ;
160+ this . signatures = decoded . partySignatures . signatures [ 0 ] . signatures [ 0 ] . signature ;
161+ }
162+ }
80163 } catch ( e ) {
81164 throw new InvalidTransactionError ( 'Unable to parse raw transaction data' ) ;
82165 }
0 commit comments