import { Fixed8 } from "../u" ; import AssetBalance from "../wallet/components/AssetBalance" ; import Coin from "../wallet/components/Coin" ; export type calculationStrategyFunction = ( assetBalance : AssetBalance , requiredAmt : Fixed8 ) => Coin [ ] ; param { Fixed8 } requiredAmt param { Coin [ ] } availableInputs return { Coin [ ] } function fillFromLeft ( requiredAmt , availableInputs ) { let selectPointer = 0 ; let selectedAmt = new Fixed8 ( 0 ) ; while ( selectedAmt . lt ( requiredAmt ) ) { selectPointer += 1 ; if ( selectPointer > availableInputs . length ) { throw new Error ( `Insufficient assets! Reached end of unspent coins! ${ availableInputs . length }` ) ; } selectedAmt = selectedAmt . add ( availableInputs [ selectPointer - 1 ] . value ) ; } return availableInputs . slice ( 0 , selectPointer ) ; } param { AssetBalance } assetBalance param { Fixed8 } requiredAmt return { Coin [ ] } export function smallestFirst ( assetBalance , requiredAmt ) { assetBalance . unspent . sort ( ( a , b ) => a . value . sub ( b . value ) . toNumber ( ) ) ; return fillFromLeft ( requiredAmt , assetBalance . unspent ) ; } param { AssetBalance } assetBalance param { Fixed8 } requiredAmt return { Coin [ ] } export function biggestFirst ( assetBalance , requiredAmt ) { assetBalance . unspent . sort ( ( a , b ) => b . value . sub ( a . value ) . toNumber ( ) ) ; return fillFromLeft ( requiredAmt , assetBalance . unspent ) ; } param { AssetBalance } assetBalance param { Fixed8 } requiredAmt return { Coin [ ] } export function balancedApproach ( assetBalance , requiredAmt ) { assetBalance . unspent . sort ( ( a , b ) => a . value . sub ( b . value ) . toNumber ( ) ) ; const smallCoins = assetBalance . unspent . filter ( ( c ) => c . value . lte ( requiredAmt ) ) ; if ( smallCoins . length === 0 ) { return [ assetBalance . unspent [ 0 ] ] ; } const i = smallCoins . findIndex ( ( c ) => requiredAmt . eq ( c . value ) ) ; if ( i >= 0 ) { return [ smallCoins [ i ] ] ; } const bigCoins = assetBalance . unspent . slice ( smallCoins . length ) ; const selectedInputs = [ ] ; const lastCoin = smallCoins . pop ( ) ; if ( lastCoin !== undefined ) { selectedInputs . push ( lastCoin ) ; } const firstCoinValue = selectedInputs [ 0 ] ? selectedInputs [ 0 ] . value : 0 ; const remainderAmt = requiredAmt . minus ( firstCoinValue ) ; const remainderInputs = fillFromLeft ( remainderAmt , smallCoins . concat ( bigCoins ) ) ; return selectedInputs . concat ( remainderInputs ) ; }