import { MassetMachine , MassetDetails } from "@utils/machines" ; import { assert , expect } from "chai" ; import { BN , simpleToExactAmount } from "./math" ; import { fullScale } from "./constants" ; param actual param expected export const assertBNClose = ( actual , expected , variance = BN . from ( 10 ) , reason = null ) : void => { const actualBN = BN . from ( actual ) ; const actualDelta = actualBN . gt ( expected ) ? actualBN . sub ( expected ) : expected . sub ( actualBN ) ; const str = reason ? `\n\tReason: ${ reason }\n\t${ actualBN . toString ( ) } vs ${ expected . toString ( ) }` : "" ; assert . ok ( actualBN . gte ( expected . sub ( variance ) ) , `Number is too small to be close (Delta between actual and expected is ${ actualDelta . toString ( ) }, but variance was only ${ variance . toString ( ) }${ str }` ) ; assert . ok ( actualBN . lte ( expected . add ( variance ) ) , `Number is too large to be close (Delta between actual and expected is ${ actualDelta . toString ( ) }, but variance was only ${ variance . toString ( ) })${ str }` ) ; } ; param actual param expected export const assertBNClosePercent = ( a , b , variance = "0.02" , reason = null ) : void => { if ( a . eq ( b ) ) return ; const varianceBN = simpleToExactAmount ( variance . toString ( ) . substr ( 0 , 6 ) , 16 ) ; const diff = a . sub ( b ) . abs ( ) . mul ( 2 ) . mul ( fullScale ) . div ( a . add ( b ) ) ; const str = reason ? `\n\tReason: ${ reason }\n\t${ a . toString ( ) } vs ${ b . toString ( ) }` : "" ; assert . ok ( diff . lte ( varianceBN ) , `Numbers exceed ${ variance }% diff (Delta between a and b is ${ diff . toString ( ) }%, but variance was only ${ varianceBN . toString ( ) })${ str }` ) ; } ; param actual param expected export const assertBnGte = ( actual , comparison ) : void => { assert . ok ( actual . gte ( comparison ) , `Number must be GTE comparitor, got: ${ actual . toString ( ) }; comparitor: ${ comparison . toString ( ) }` ) ; } ; param actual param equator param maxActualShouldExceedExpected param mustBeGreater export const assertBNSlightlyGT = ( actual , equator , maxActualShouldExceedExpected = BN . from ( 100 ) , mustBeGreater = false , reason = null ) : void => { const actualDelta = actual . gt ( equator ) ? actual . sub ( equator ) : equator . sub ( actual ) ; const str = reason ? `\n\t${ reason }\n\t${ actual . toString ( ) } vs ${ equator . toString ( ) }` : "" ; assert . ok ( mustBeGreater ? actual . gt ( equator ) : actual . gte ( equator ) , `Actual value should be greater than the expected value ${ str }` ) ; assert . ok ( actual . lte ( equator . add ( maxActualShouldExceedExpected ) ) , `Actual value should not exceed ${ maxActualShouldExceedExpected . toString ( ) } units greater than expected. Variance was ${ actualDelta . toString ( ) } ${ str }` ) ; } ; param actual param equator param maxActualShouldExceedExpected param mustBeGreater export const assertBNSlightlyGTPercent = ( actual , equator , maxPercentIncrease = "0.1" , mustBeGreater = false ) : void => { const maxIncreaseBN = simpleToExactAmount ( maxPercentIncrease , 16 ) ; const maxIncreaseUnits = equator . mul ( maxIncreaseBN ) . div ( fullScale ) ; assert . ok ( mustBeGreater ? actual . gt ( equator ) : actual . gte ( equator ) , `Actual value should be greater than the expected value` ) ; assert . ok ( actual . lte ( equator . add ( maxIncreaseUnits ) ) , `Actual value should not exceed ${ maxPercentIncrease }% greater than expected` ) ; } ; export const assertBasketIsHealthy = async ( machine , md ) : Promise < void > => { const composition = await machine . getBasketComposition ( md ) ; assertBnGte ( composition . sumOfBassets , composition . totalSupply . add ( composition . surplus ) ) ; composition . bAssets . forEach ( ( b , i ) => { expect ( b . actualBalance , `assertBasketIsHealthy: Actual balance of ${ i } < vaultBalance` ) . gte ( b . vaultBalance ) ; } ) ; expect ( composition . undergoingRecol , "not undergoing recol" ) . to . eq ( false ) ; expect ( composition . failed , "mAsset not failed" ) . to . eq ( false ) ; await md . mAsset [ "getBasset(address)" ] ( md . bAssets [ 0 ] . address ) ; } ;