import { generatePseudoRandomSalt , orderHashUtils , SignatureType , signatureUtils , SignerType , } from '0x-v2-order-utils' ; import * as ethUtils from 'ethereumjs-util' ; import { utils , Wallet } from 'ethers' ; import { BigNumber , orderBNToString } from '../utils' ; import { ecSignOrderHash } from './ecsign' ; export const generateSaltWithFeeFactor = ( feeFactor ) => { const feeHex = utils . hexZeroPad ( '0x' + feeFactor . toString ( 16 ) , 2 ) ; return new BigNumber ( generatePseudoRandomSalt ( ) . toString ( 16 ) . slice ( 0 , - 4 ) + feeHex . slice ( 2 ) , 16 ) ; } ; export function signWithUserAndFee ( signer , orderHash , userAddr , feeFactor ) { const hash = ethUtils . bufferToHex ( Buffer . concat ( [ ethUtils . toBuffer ( orderHash ) , ethUtils . toBuffer ( userAddr . toLowerCase ( ) ) , ethUtils . toBuffer ( feeFactor > 255 ? feeFactor : [ 0 , feeFactor ] ) , ] ) ) ; const signature = ecSignOrderHash ( signer . privateKey . slice ( 2 ) , hash , signer . address , SignerType . Default ) ; const walletSign = ethUtils . bufferToHex ( Buffer . concat ( [ ethUtils . toBuffer ( signature ) . slice ( 0 , 65 ) , ethUtils . toBuffer ( userAddr . toLowerCase ( ) ) , ethUtils . toBuffer ( feeFactor > 255 ? feeFactor : [ 0 , feeFactor ] ) , ] ) ) ; return walletSign ; } async function signByEOA ( orderHash , wallet ) { const hashArray = utils . arrayify ( orderHash ) ; let signature = await wallet . signMessage ( hashArray ) ; signature = signature . slice ( 2 ) ; const v = signature . slice ( signature . length - 2 , signature . length ) ; const rs = signature . slice ( 0 , signature . length - 2 ) ; signature = '0x' + v + rs ; return signatureUtils . convertToSignatureWithType ( signature , SignatureType . EthSign ) ; } function signByMMPSigner ( orderHash , userAddr , feeFactor , wallet ) { const walletSign = signWithUserAndFee ( wallet , orderHash , userAddr , feeFactor ) ; return signatureUtils . convertToSignatureWithType ( walletSign , SignatureType . Wallet ) ; } export const buildSignedOrder = async ( signer , order , userAddr , pmm ) : Promise < any > => { const feeFactor = order . feeFactor ; order . takerAddress = pmm . toLowerCase ( ) ; order . senderAddress = pmm . toLowerCase ( ) ; order . feeRecipientAddress = userAddr ; const o = { ... order , salt : generateSaltWithFeeFactor ( feeFactor ) , } ; const orderHash = orderHashUtils . getOrderHashHex ( o ) ; const makerWalletSignature = signer . address . toLowerCase ( ) == o . makerAddress . toLowerCase ( ) ? await signByEOA ( orderHash , signer ) : signByMMPSigner ( orderHash , userAddr , feeFactor , signer ) ; const signedOrder = { ... o , makerWalletSignature , } ; return orderBNToString ( signedOrder ) ; } ;