import { curve } from "elliptic" ; import { convertObjectToSignBytes , UVarInt , marshalBinary , encodeBinaryByteArray , } from "../amino" ; import * as crypto from "../crypto" ; import { BaseMsg , SignMsg , StdSignMsg , StdSignature , StdTx , AminoPrefix , } from "../types" ; example property param { Number } data . account_number param { String } data . chain_id param { String } data . memo param { String } type param { Msg } data . msg param { Number } data . sequence param { Number } data . source export default class Transaction { private sequence : NonNullable < StdSignMsg [ "sequence" ] > ; private accountNumber : NonNullable < StdSignMsg [ "accountNumber" ] > ; private chainId : StdSignMsg [ "chainId" ] ; private msg ? : any ; private baseMsg ? : NonNullable < BaseMsg > ; private memo : StdSignMsg [ "memo" ] ; private source : NonNullable < StdSignMsg [ "source" ] > ; private signatures : Array < StdSignature > ; constructor ( data ) { data = data || { } ; if ( ! data . chainId ) { throw new Error ( "chain id should not be null" ) ; } this . sequence = data . sequence || 0 ; this . accountNumber = data . accountNumber || 0 ; this . chainId = data . chainId ; this . msg = data . msg ; this . baseMsg = data . baseMsg ; this . memo = data . memo ; this . source = data . source || 0 ; this . signatures = [ ] ; } param { SignMsg } concrete return { Buffer } getSignBytes ( msg ? ) { msg = msg || ( this . baseMsg && this . baseMsg . getSignMsg ( ) ) ; const signMsg = { account_number : this . accountNumber . toString ( ) , chain_id : this . chainId , data : null , memo : this . memo , msgs : [ msg ] , sequence : this . sequence . toString ( ) , source : this . source . toString ( ) , } ; return convertObjectToSignBytes ( signMsg ) ; } param { Elliptic . PublicKey } pubKey param { Buffer } signature return { Transaction } addSignature ( pubKey , signature ) { const pubKeyBuf = this . _serializePubKey ( pubKey ) ; this . signatures = [ { pub_key : pubKeyBuf , signature : signature , account_number : this . accountNumber , sequence : this . sequence , } , ] ; return this ; } param { string } privateKey param { SignMsg } concrete return { Transaction } sign ( privateKey , msg ? ) { if ( ! privateKey ) { throw new Error ( "private key should not be null" ) ; } const signBytes = this . getSignBytes ( msg ) ; const privKeyBuf = Buffer . from ( privateKey , "hex" ) ; const signature = crypto . generateSignature ( signBytes . toString ( "hex" ) , privKeyBuf ) ; this . addSignature ( crypto . generatePubKey ( privKeyBuf ) , signature ) ; return this ; } /**
     * encode signed transaction to hex which is compatible with amino
     */ serialize ( ) { if ( ! this . signatures ) { throw new Error ( "need signature" ) ; } const msg = this . msg || ( this . baseMsg && this . baseMsg . getMsg ( ) ) ; const stdTx = { msg : [ msg ] , signatures : this . signatures , memo : this . memo , source : this . source , data : "" , aminoPrefix : AminoPrefix . StdTx , } ; const bytes = marshalBinary ( stdTx ) ; return bytes . toString ( "hex" ) ; } param { Elliptic . PublicKey } unencodedPubKey return { Buffer } private _serializePubKey ( unencodedPubKey ) { let format = 0x2 ; const y = unencodedPubKey . getY ( ) ; const x = unencodedPubKey . getX ( ) ; if ( y && y . isOdd ( ) ) { format |= 0x1 ; } let pubBz = Buffer . concat ( [ UVarInt . encode ( format ) , x . toArrayLike ( Buffer , "be" , 32 ) , ] ) ; pubBz = encodeBinaryByteArray ( pubBz ) ; pubBz = Buffer . concat ( [ Buffer . from ( "EB5AE987" , "hex" ) , pubBz ] ) ; return pubBz ; } }