cardano-wallet-core-2022.7.1: The Wallet Backend for a Cardano node.
Copyright © 2021 IOHK
License Apache-2.0
Safe Haskell None
Language Haskell2010

Cardano.Wallet.CoinSelection.Internal.Balance

Description

Provides an algorithm for producing a balanced coin selection with change, where the fee is paid for.

This module uses the Random-Round-Robin coin selection algorithm for multi-asset UTxO sets.

See documentation for the performSelection function for more details on how to perform a selection.

Synopsis

Performing a selection

performSelection :: forall m ctx. ( HasCallStack , MonadRandom m, SelectionContext ctx) => PerformSelection m [] ctx Source #

Performs a coin selection and generates change bundles in one step.

Provided that isUTxOBalanceSufficient returns True for the given selection criteria, this function guarantees to return a SelectionResult for which selectionHasValidSurplus returns True .

performSelectionEmpty :: forall m ctx. Functor m => PerformSelection m NonEmpty ctx -> PerformSelection m [] ctx Source #

Transforms a coin selection function that requires a non-empty list of outputs into a function that accepts an empty list of outputs.

If the original list is already non-empty, this function does not alter the parameters or the result in any way, such that:

params == transformParams params result == transformResult result

If the original list is empty, this function:

  1. applies a balance-preserving transformation to the parameters, adding a single minimal ada-only output to act as a change generation target, such that:

    computeUTxOBalanceSufficiencyInfo params == computeUTxOBalanceSufficiencyInfo (transformParams params)

  2. applies an inverse transformation to the result, removing the output, such that:

    selectionSurplus result == selectionSurplus (transformResult result)

    selectionHasValidSurplus constraints result ==> selectionHasValidSurplus constraints (transformResult result)

data SelectionConstraints ctx Source #

Specifies all constraints required for coin selection.

Selection constraints:

  • place limits on the coin selection algorithm, enabling it to produce selections that are acceptable to the ledger.
  • are dependent on the current set of protocol parameters.
  • are not specific to a given selection.

Constructors

SelectionConstraints

Fields

Instances

Instances details
Generic ( SelectionConstraints ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep ( SelectionConstraints ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

data SelectionParamsOf f ctx Source #

Specifies all parameters that are specific to a given selection.

Constructors

SelectionParams

Fields

Instances

Instances details
( Eq (f ( Address ctx, TokenBundle )), Eq ( UTxO ctx)) => Eq ( SelectionParamsOf f ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

( Show (f ( Address ctx, TokenBundle )), Show ( UTxO ctx)) => Show ( SelectionParamsOf f ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Generic ( SelectionParamsOf f ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Associated Types

type Rep ( SelectionParamsOf f ctx) :: Type -> Type Source #

type Rep ( SelectionParamsOf f ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

data SelectionSkeleton ctx Source #

A skeleton selection that can be used to estimate the cost of a final selection.

Change outputs are deliberately stripped of their asset quantities, as the fee estimation function must be agnostic to the magnitudes of these quantities.

Increasing or decreasing the quantity of a particular asset in a change output must not change the estimated cost of a selection.

Instances

Instances details
SelectionContext ctx => Eq ( SelectionSkeleton ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

SelectionContext ctx => Show ( SelectionSkeleton ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Generic ( SelectionSkeleton ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep ( SelectionSkeleton ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep ( SelectionSkeleton ctx) = D1 (' MetaData "SelectionSkeleton" "Cardano.Wallet.CoinSelection.Internal.Balance" "cardano-wallet-core-2022.7.1-AGKhlyz9liLKN3QqZD1gj" ' False ) ( C1 (' MetaCons "SelectionSkeleton" ' PrefixI ' True ) ( S1 (' MetaSel (' Just "skeletonInputCount") ' NoSourceUnpackedness ' SourceStrict ' DecidedStrict ) ( Rec0 Int ) :*: ( S1 (' MetaSel (' Just "skeletonOutputs") ' NoSourceUnpackedness ' SourceStrict ' DecidedStrict ) ( Rec0 [( Address ctx, TokenBundle )]) :*: S1 (' MetaSel (' Just "skeletonChange") ' NoSourceUnpackedness ' SourceStrict ' DecidedStrict ) ( Rec0 [ Set AssetId ]))))

data SelectionResultOf f ctx Source #

The result of performing a successful selection.

Constructors

SelectionResult

Fields

Instances

Instances details
( Eq (f ( Address ctx, TokenBundle )), Eq ( UTxO ctx)) => Eq ( SelectionResultOf f ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

( Show (f ( Address ctx, TokenBundle )), Show ( UTxO ctx)) => Show ( SelectionResultOf f ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Generic ( SelectionResultOf f ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Associated Types

type Rep ( SelectionResultOf f ctx) :: Type -> Type Source #

type Rep ( SelectionResultOf f ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

data SelectionStrategy Source #

Indicates a choice of selection strategy.

A SelectionStrategy determines how much of each asset the selection algorithm will attempt to select from the available UTxO set, relative to the minimum amount necessary to make the selection balance.

The default SelectionStrategy is SelectionStrategyOptimal , which when specified will cause the selection algorithm to attempt to select around twice the minimum possible amount of each asset from the available UTxO set, making it possible to generate change outputs that are roughly the same sizes and shapes as the user-specified outputs.

Specifying SelectionStrategyMinimal will cause the selection algorithm to only select just enough of each asset from the available UTxO set to meet the minimum amount. The selection process will terminate as soon as the minimum amount of each asset is covered.

The "optimal" strategy is recommended for most situations, as using this strategy will help to ensure that a wallet's UTxO distribution can evolve over time to resemble the typical distribution of payments made by the wallet owner. This increases the likelihood that future selections will succeed, and lowers the amortized cost of future transactions.

The "minimal" strategy is recommended only for situations where it is not possible to create a selection with the "optimal" strategy. It is advised to use this strategy only when necessary, as it increases the likelihood of generating change outputs that are much smaller than user-specified outputs. If this strategy is used regularly, the UTxO set can evolve to a state where the distribution no longer resembles the typical distribution of payments made by the user. This increases the likelihood that future selections will not succeed, and increases the amortized cost of future transactions.

data SelectionBalanceError ctx Source #

Represents the set of errors that may occur while performing a selection.

Instances

Instances details
SelectionContext ctx => Eq ( SelectionBalanceError ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

SelectionContext ctx => Show ( SelectionBalanceError ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Generic ( SelectionBalanceError ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

IsServerError ( SelectionBalanceError WalletSelectionContext ) Source #
Instance details

Defined in Cardano.Wallet.Api.Server

type Rep ( SelectionBalanceError ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

data BalanceInsufficientError Source #

Indicates that the balance of available UTxO entries is insufficient to cover the balance required.

See computeUTxOBalanceSufficiency .

Instances

Instances details
Eq BalanceInsufficientError Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Show BalanceInsufficientError Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Generic BalanceInsufficientError Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep BalanceInsufficientError Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep BalanceInsufficientError = D1 (' MetaData "BalanceInsufficientError" "Cardano.Wallet.CoinSelection.Internal.Balance" "cardano-wallet-core-2022.7.1-AGKhlyz9liLKN3QqZD1gj" ' False ) ( C1 (' MetaCons "BalanceInsufficientError" ' PrefixI ' True ) ( S1 (' MetaSel (' Just "utxoBalanceAvailable") ' NoSourceUnpackedness ' SourceStrict ' DecidedStrict ) ( Rec0 TokenBundle ) :*: S1 (' MetaSel (' Just "utxoBalanceRequired") ' NoSourceUnpackedness ' SourceStrict ' DecidedStrict ) ( Rec0 TokenBundle )))

data UnableToConstructChangeError Source #

Constructors

UnableToConstructChangeError

Fields

  • requiredCost :: ! Coin

    The minimal required cost needed for the transaction to be considered valid. This does not include min Ada values.

  • shortfall :: ! Coin

    The additional coin quantity that would be required to cover the selection cost and minimum coin quantity of each change output.

Instances

Instances details
Eq UnableToConstructChangeError Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Show UnableToConstructChangeError Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Generic UnableToConstructChangeError Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep UnableToConstructChangeError Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep UnableToConstructChangeError = D1 (' MetaData "UnableToConstructChangeError" "Cardano.Wallet.CoinSelection.Internal.Balance" "cardano-wallet-core-2022.7.1-AGKhlyz9liLKN3QqZD1gj" ' False ) ( C1 (' MetaCons "UnableToConstructChangeError" ' PrefixI ' True ) ( S1 (' MetaSel (' Just "requiredCost") ' NoSourceUnpackedness ' SourceStrict ' DecidedStrict ) ( Rec0 Coin ) :*: S1 (' MetaSel (' Just "shortfall") ' NoSourceUnpackedness ' SourceStrict ' DecidedStrict ) ( Rec0 Coin )))

Selection limits

type SelectionLimit = SelectionLimitOf Int Source #

Specifies a limit to adhere to when performing a selection.

data SelectionLimitOf a Source #

Constructors

NoLimit

Indicates that there is no limit.

MaximumInputLimit a

Indicates a maximum limit on the number of inputs to select.

selectionLimitExceeded :: IsUTxOSelection s u => s u -> SelectionLimit -> Bool Source #

Indicates whether or not the given selection limit has been exceeded.

data SelectionLimitReachedError ctx Source #

Indicates that the balance of selected UTxO entries was insufficient to cover the balance required while remaining within the selection limit.

Constructors

SelectionLimitReachedError

Fields

Instances

Instances details
SelectionContext ctx => Eq ( SelectionLimitReachedError ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

SelectionContext ctx => Show ( SelectionLimitReachedError ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Generic ( SelectionLimitReachedError ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep ( SelectionLimitReachedError ctx) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep ( SelectionLimitReachedError ctx) = D1 (' MetaData "SelectionLimitReachedError" "Cardano.Wallet.CoinSelection.Internal.Balance" "cardano-wallet-core-2022.7.1-AGKhlyz9liLKN3QqZD1gj" ' False ) ( C1 (' MetaCons "SelectionLimitReachedError" ' PrefixI ' True ) ( S1 (' MetaSel (' Just "utxoBalanceRequired") ' NoSourceUnpackedness ' SourceStrict ' DecidedStrict ) ( Rec0 TokenBundle ) :*: ( S1 (' MetaSel (' Just "inputsSelected") ' NoSourceUnpackedness ' SourceStrict ' DecidedStrict ) ( Rec0 [( UTxO ctx, TokenBundle )]) :*: S1 (' MetaSel (' Just "outputsToCover") ' NoSourceUnpackedness ' SourceStrict ' DecidedStrict ) ( Rec0 ( NonEmpty ( Address ctx, TokenBundle ))))))

reduceSelectionLimitBy :: SelectionLimit -> Int -> SelectionLimit Source #

Reduces a selection limit by a given reduction amount.

If the given reduction amount is positive, then this function will reduce the selection limit by that amount.

If the given reduction amount is zero or negative, then this function will return the original limit unchanged.

Querying selections

data SelectionDelta a Source #

Indicates the difference between total input value and total output value of a SelectionResult .

There are two possibilities:

Indicates a surplus, when the total input value is greater than or equal to the total output value.

Indicates a deficit, when the total input value is NOT greater than or equal to the total output value.

selectionHasValidSurplus :: Foldable f => SelectionConstraints ctx -> SelectionResultOf f ctx -> Bool Source #

Indicates whether or not a selection result has a valid surplus.

selectionSurplusCoin :: Foldable f => SelectionResultOf f ctx -> Coin Source #

Calculates the ada selection surplus, assuming there is a surplus.

If there is a surplus, then this function returns that surplus. If there is a deficit, then this function returns zero.

Use selectionDeltaCoin if you wish to handle the case where there is a deficit.

selectionMinimumCost :: Foldable f => SelectionConstraints ctx -> SelectionResultOf f ctx -> Coin Source #

Computes the minimum required cost of a selection.

selectionMaximumCost :: Foldable f => SelectionConstraints ctx -> SelectionResultOf f ctx -> Coin Source #

Computes the maximum acceptable cost of a selection.

This function acts as a safety limit to ensure that fees of selections produced by performSelection are not excessively high.

Ideally, we'd always be able to generate selections with fees that are precisely equal to selectionMinimumCost . However, in some situations it may be necessary to exceed this cost very slightly.

This function provides a conservative upper bound to a selection cost that we can reference from within property tests.

See selectionHasValidSurplus .

selectionSkeleton :: Foldable f => SelectionResultOf f ctx -> SelectionSkeleton ctx Source #

Converts a selection into a skeleton.

Querying parameters

data UTxOBalanceSufficiencyInfo Source #

Gives more information about UTxO balance sufficiency.

See computeUTxOBalanceSufficiencyInfo .

Instances

Instances details
Eq UTxOBalanceSufficiencyInfo Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Show UTxOBalanceSufficiencyInfo Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Generic UTxOBalanceSufficiencyInfo Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep UTxOBalanceSufficiencyInfo Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

computeUTxOBalanceAvailable :: SelectionParamsOf f ctx -> TokenBundle Source #

Computes the balance of UTxO entries available for selection.

computeUTxOBalanceRequired :: Foldable f => SelectionParamsOf f ctx -> TokenBundle Source #

Computes the balance of UTxO entries required to be selected.

isUTxOBalanceSufficient :: Foldable f => SelectionParamsOf f ctx -> Bool Source #

Indicates whether or not the UTxO balance is sufficient.

The balance of available UTxO entries is sufficient if (and only if) it is greater than or equal to the required balance.

Running a selection (without making change)

data RunSelectionParams u Source #

Parameters for runSelection .

Constructors

RunSelectionParams

Fields

Instances

Instances details
Eq u => Eq ( RunSelectionParams u) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Show u => Show ( RunSelectionParams u) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Generic ( RunSelectionParams u) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep ( RunSelectionParams u) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Running a selection step

runSelectionStep :: forall m state state'. Monad m => SelectionLens m state state' -> state -> m ( Maybe state') Source #

Runs just a single step of a coin selection.

It returns an updated state if (and only if) the updated selection represents an improvement over the selection in the previous state.

An improvement, for a given token quantity, is defined in the following way:

  • If the total selected token quantity of the previous selection had not yet reached 100% of the output token quantity, any additional selection is considered to be an improvement.
  • If the total selected token quantity of the previous selection had already reached or surpassed 100% of the output token quantity, any additional selection is considered to be an improvement if and only if it takens the total selected token quantity closer to the target token quantity, but not further away.

data SelectionLens m state state' Source #

Provides a lens on the current selection state.

A SelectionLens gives runSelectionStep just the information it needs to make a decision, and no more.

Making change

data MakeChangeCriteria minCoinFor bundleSizeAssessor Source #

Criteria for the makeChange function.

Constructors

MakeChangeCriteria

Fields

Instances

Instances details
( Eq minCoinFor, Eq bundleSizeAssessor) => Eq ( MakeChangeCriteria minCoinFor bundleSizeAssessor) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Methods

(==) :: MakeChangeCriteria minCoinFor bundleSizeAssessor -> MakeChangeCriteria minCoinFor bundleSizeAssessor -> Bool Source #

(/=) :: MakeChangeCriteria minCoinFor bundleSizeAssessor -> MakeChangeCriteria minCoinFor bundleSizeAssessor -> Bool Source #

( Show minCoinFor, Show bundleSizeAssessor) => Show ( MakeChangeCriteria minCoinFor bundleSizeAssessor) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Methods

showsPrec :: Int -> MakeChangeCriteria minCoinFor bundleSizeAssessor -> ShowS Source #

show :: MakeChangeCriteria minCoinFor bundleSizeAssessor -> String Source #

showList :: [ MakeChangeCriteria minCoinFor bundleSizeAssessor] -> ShowS Source #

Generic ( MakeChangeCriteria minCoinFor bundleSizeAssessor) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

Associated Types

type Rep ( MakeChangeCriteria minCoinFor bundleSizeAssessor) :: Type -> Type Source #

Methods

from :: MakeChangeCriteria minCoinFor bundleSizeAssessor -> Rep ( MakeChangeCriteria minCoinFor bundleSizeAssessor) x Source #

to :: Rep ( MakeChangeCriteria minCoinFor bundleSizeAssessor) x -> MakeChangeCriteria minCoinFor bundleSizeAssessor Source #

type Rep ( MakeChangeCriteria minCoinFor bundleSizeAssessor) Source #
Instance details

Defined in Cardano.Wallet.CoinSelection.Internal.Balance

type Rep ( MakeChangeCriteria minCoinFor bundleSizeAssessor) = D1 (' MetaData "MakeChangeCriteria" "Cardano.Wallet.CoinSelection.Internal.Balance" "cardano-wallet-core-2022.7.1-AGKhlyz9liLKN3QqZD1gj" ' False ) ( C1 (' MetaCons "MakeChangeCriteria" ' PrefixI ' True ) ((( S1 (' MetaSel (' Just "minCoinFor") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 minCoinFor) :*: S1 (' MetaSel (' Just "bundleSizeAssessor") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 bundleSizeAssessor)) :*: ( S1 (' MetaSel (' Just "requiredCost") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 Coin ) :*: ( S1 (' MetaSel (' Just "extraCoinSource") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 Coin ) :*: S1 (' MetaSel (' Just "extraCoinSink") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 Coin )))) :*: (( S1 (' MetaSel (' Just "inputBundles") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 ( NonEmpty TokenBundle )) :*: ( S1 (' MetaSel (' Just "outputBundles") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 ( NonEmpty TokenBundle )) :*: S1 (' MetaSel (' Just "assetsToMint") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 TokenMap ))) :*: ( S1 (' MetaSel (' Just "assetsToBurn") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 TokenMap ) :*: ( S1 (' MetaSel (' Just "maximumOutputAdaQuantity") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 Coin ) :*: S1 (' MetaSel (' Just "maximumOutputTokenQuantity") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 TokenQuantity ))))))

makeChange Source #

Arguments

:: MakeChangeCriteria ( TokenMap -> Coin ) TokenBundleSizeAssessor

Criteria for making change.

-> Either UnableToConstructChangeError [ TokenBundle ]

Generated change bundles.

Constructs change bundles for a set of selected inputs and outputs.

Returns Nothing if the specified inputs do not provide enough ada to satisfy the minimum delta and minimum ada quantities of the change bundles generated.

This function will generate runtime errors if:

  1. The total balance of all outputs is not less than or equal to the total balance of all inputs.
  2. The total ada balance of all outputs is zero.

Pre-condition (1) should be satisfied by any result produced by the runSelection function.

Pre-condition (2) should be satisfied by assigning a minimum ada quantity to every output token bundle.

makeChangeForCoin Source #

Arguments

:: HasCallStack
=> NonEmpty Coin

A list of weights for the distribution. Conveniently captures both the weights, and the number of elements amongst which the surplus ada quantity should be distributed.

-> Coin

A surplus ada quantity to be distributed.

-> NonEmpty Coin

Constructs a list of ada change outputs based on the given distribution.

If the sum of weights in given distribution is equal to zero, this function throws a runtime error.

The length of the output list is always the same as the length of the input list, and the sum of its quantities is always exactly equal to the Coin value given as the second argument.

makeChangeForUserSpecifiedAsset Source #

Arguments

:: NonEmpty TokenMap

A list of weights for the distribution. Conveniently captures both the weights, and the number of elements amongst which the quantity should be distributed.

-> ( AssetId , TokenQuantity )

A surplus token quantity to distribute.

-> NonEmpty TokenMap

Constructs change outputs for a user-specified asset: an asset that was present in the original set of outputs.

If the given asset does not appear in the given distribution, this function returns a list of empty token maps. Otherwise, the given token quantity is partitioned into a list of quantities that are proportional to the weights within the given input distribution, modulo rounding.

The length of the output list is always the same as the the length of the input list, and the sum of its quantities is either zero, or exactly equal to the token quantity in the second argument.

makeChangeForNonUserSpecifiedAsset Source #

Arguments

:: NonEmpty a

Determines the number of change maps to create.

-> ( AssetId , NonEmpty TokenQuantity )

An asset quantity to distribute.

-> NonEmpty TokenMap

The resultant change maps.

Constructs change outputs for a non-user-specified asset: an asset that was not present in the original set of outputs.

This function constructs a list of change outputs by preserving the input distribution as much as possible. Note that only the length of the first argument is used.

The length of the output list is always the same as the length of the input list, and the sum of its quantities is always exactly equal to the sum of all token quantities given in the second argument.

The resultant list is sorted into ascending order when maps are compared with the leq function.

makeChangeForNonUserSpecifiedAssets Source #

Arguments

:: NonEmpty a

Determines the number of change maps to create.

-> Map AssetId ( NonEmpty TokenQuantity )

A map of asset quantities to distribute.

-> NonEmpty TokenMap

The resultant change maps.

Constructs change outputs for all non-user-specified assets: assets that were not present in the original set of outputs.

The resultant list is sorted into ascending order when maps are compared with the leq function.

assignCoinsToChangeMaps Source #

Arguments

:: HasCallStack
=> Coin

The total quantity of ada available, including any extra source of ada.

-> ( TokenMap -> Coin )

A function to calculate the minimum required ada quantity for any token map.

-> NonEmpty ( TokenMap , Coin )

A list of pre-computed asset change maps paired with original output coins, sorted into an order that ensures all empty token maps are at the start of the list.

-> Either Coin [ TokenBundle ]

Resulting change bundles, or the shortfall quantity if there was not enough ada available to assign a minimum ada quantity to all non-empty token maps.

Assigns coin quantities to a list of pre-computed asset change maps.

Each pre-computed asset change map must be paired with the original coin value of its corresponding output.

This function:

  • expects the list of pre-computed asset change maps to be sorted in an order that ensures all empty token maps are at the start of the list.
  • attempts to assign a minimum ada quantity to every change map, but iteratively drops empty change maps from the start of the list if the amount of ada is insufficient to cover them all.
  • continues dropping empty change maps from the start of the list until it is possible to assign a minimum ada value to all remaining entries.
  • returns a list that is identical in length to the input list if (and only if) it was possible to assign a minimum ada quantity to all change maps.
  • returns a list that is shorter than the input list if it was only possible to assign a minimum ada quantity to a suffix of the given list.
  • fails if (and only if) there was not enough ada available to assign the minimum ada quantity to all non-empty change maps.

collateNonUserSpecifiedAssetQuantities Source #

Arguments

:: NonEmpty TokenMap

Token maps of all selected inputs.

-> Set AssetId

Set of all assets in user-specified outputs.

-> Map AssetId ( NonEmpty TokenQuantity )

Generates a map of all non-user-specified assets and their quantities.

Each key in the resulting map corresponds to an asset that was NOT included in the original set of user-specified outputs, but that was nevertheless selected during the selection process.

The value associated with each key corresponds to the complete list of all discrete non-zero quantities of that asset present in the selected inputs.

addMintValueToChangeMaps :: ( AssetId , TokenQuantity ) -> NonEmpty TokenMap -> NonEmpty TokenMap Source #

Adds a minted asset quantity to a list of change maps.

This function always adds the given quantity to the final change map in the given list.

Example:

Suppose we have the following list of change maps:

[ ( B , 7)
[( A , 1), ( B , 8)
[( A , 2), ( B , 9)
[( A , 3), ( B , 9)
[( A , 4), ( B , 12)

If we add 4 tokens of asset A , we obtain the following result:

[ ( B , 7)
[( A , 1), ( B , 8)
[( A , 2), ( B , 9)
[( A , 3), ( B , 9)
[( A , 8), ( B , 12)
-- Increased by 4

Provided that the specified change maps are in ascending partial order, this function guarantees that the resulting change maps will also be in ascending partial order.

The length of the given list is preserved in the output list.

addMintValuesToChangeMaps Source #

Arguments

:: TokenMap

Map of minted values

-> NonEmpty TokenMap

Change maps

-> NonEmpty TokenMap

Change maps with minted values

Adds minted values for multiple assets to a list of change maps.

Plural of addMintValueToChangeMaps .

removeBurnValueFromChangeMaps Source #

Arguments

:: ( AssetId , TokenQuantity )

Asset quantity reduction target

-> NonEmpty TokenMap

Change maps with quantities of the given asset to be reduced

-> NonEmpty TokenMap

Change maps with reduced quantities of the given asset

Removes a burned asset quantity from a list of change maps.

For a given asset a and reduction target t , this function traverses the given list from left to right, reducing the quantity of asset a in each change map until the reduction target t has been met, or until the list is exhausted.

For each change map m under consideration:

  • if the quantity q of asset a in map m is less than or equal to the remaining required reduction r , it will be replaced with a zero (effectively eliminating asset a from the map).
  • if the quantity q of asset a in map m is greater than the remaining required reduction r , it will be replaced with the absolute difference between q and r .

If the total quantity of the given asset in the given change maps is greater than the specified reduction target, the total reduction will be equal to the specified reduction target. Otherwise, the given asset will be completely eliminated from all change maps.

Example:

Suppose we have the following list of change maps:

[ ( B , 7)
[( A , 1), ( B , 8)
[( A , 2), ( B , 9)
[( A , 3), ( B , 9)
[( A , 4), ( B , 12)

If our target is to reduce the quantity of asset A by 4, then we should obtain the following result:

[ ( B , 7)
-- Unable to reduce (already 0)
[ ( B , 8)
-- Reduced by 1 (and eliminated from map)
[ ( B , 9)
-- Reduced by 2 (and eliminated from map)
[( A , 2), ( B , 9)
-- Reduced by 1
[( A , 4), ( B , 12)

Provided that the specified change maps are in ascending partial order, this function guarantees that the resulting change maps will also be in ascending partial order.

The length of the given list is preserved in the output list.

removeBurnValuesFromChangeMaps Source #

Arguments

:: TokenMap

Map of burned values

-> NonEmpty TokenMap

Change maps

-> NonEmpty TokenMap

Change maps with burned values removed

Removes burned values for multiple assets from a list of change maps.

Plural of removeBurnValueFromChangeMaps .

reduceTokenQuantities Source #

Arguments

:: TokenQuantity

Reduction target

-> NonEmpty TokenQuantity

List of quantities to reduce

-> NonEmpty TokenQuantity

The list of reduced quantities

Reduces the total value of the given list of token quantities by the given reduction target.

This function traverses the given list of quantities from left to right, reducing each quantity in turn until the total reduction is equal to the given reduction target, or until the list is exhausted.

For each quantity q under consideration:

  • if q is less than or equal to the remaining required reduction r , it will be replaced with a zero.
  • if q is greater than the remaining required reduction r , it will be replaced with the absolute difference between q and r .

If the total value in the list is less than the reduction target, the result will be a list of zeros.

Provided the given list is in ascending order, the resulting list is also guaranteed to be in ascending order.

The length of the given list is preserved in the output.

Splitting bundles

splitBundleIfAssetCountExcessive Source #

Arguments

:: TokenBundle

The token bundle suspected to have an excessive number of assets.

-> ( TokenBundle -> Bool )

A function that returns True if (and only if) the asset count of the given bundle is excessive.

-> NonEmpty TokenBundle

Splits a bundle into smaller bundles if its asset count is excessive when measured with the given isExcessive indicator function.

Returns a list of smaller bundles for which isExcessive returns False .

splitBundlesWithExcessiveAssetCounts Source #

Arguments

:: NonEmpty TokenBundle

Token bundles.

-> ( TokenBundle -> Bool )

A function that returns True if (and only if) the asset count of the given bundle is excessive.

-> NonEmpty TokenBundle

Splits bundles with excessive asset counts into smaller bundles.

Only token bundles where the isExcessive indicator function returns True will be split.

Returns a list of smaller bundles for which isExcessive returns False .

If none of the bundles in the given list has an excessive asset count, this function will return the original list.

splitBundlesWithExcessiveTokenQuantities Source #

Arguments

:: NonEmpty TokenBundle

Token bundles.

-> TokenQuantity

Maximum allowable token quantity.

-> NonEmpty TokenBundle

The partitioned bundles.

Splits bundles with excessive token quantities into smaller bundles.

Only token bundles containing quantities that exceed the maximum token quantity will be split.

If none of the bundles in the given list contain a quantity that exceeds the maximum token quantity, this function will return the original list.

Grouping and ungrouping

groupByKey :: forall k v. Ord k => [(k, v)] -> Map k ( NonEmpty v) Source #

ungroupByKey :: forall k v. Map k ( NonEmpty v) -> [(k, v)] Source #

Round-robin processing

runRoundRobin :: s -> (s' -> s) -> [s -> Maybe s'] -> s Source #

runRoundRobinM :: Monad m => s -> (s' -> s) -> [s -> m ( Maybe s')] -> m s Source #

Utility classes

Utility functions

balanceMissing :: BalanceInsufficientError -> TokenBundle Source #

Calculate the missing balance from a BalanceInsufficientError .