Skip to content

Commit

Permalink
feat(cip2): add functions to create selection constraints (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
mkazlauskas committed Sep 28, 2021
1 parent 2832a26 commit f41d37c
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 1 deletion.
51 changes: 51 additions & 0 deletions packages/cip2/src/selectionConstraints.ts
@@ -0,0 +1,51 @@
import { CardanoSerializationLib, CSL, ProtocolParametersRequiredByWallet } from '@cardano-sdk/core';
import { ComputeMinimumCoinQuantity, EstimateTxFee, SelectionSkeleton } from './types';

export type BuildTx = (selection: SelectionSkeleton) => Promise<CSL.Transaction>;

export const computeMinimumCost =
(
csl: CardanoSerializationLib,
{ minFeeCoefficient, minFeeConstant }: ProtocolParametersRequiredByWallet,
buildTx: BuildTx
): EstimateTxFee =>
async (selection) => {
const tx = await buildTx(selection);
return BigInt(
csl
.min_fee(
tx,
csl.LinearFee.new(
csl.BigNum.from_str(minFeeCoefficient.toString()),
csl.BigNum.from_str(minFeeConstant.toString())
)
)
.to_str()
);
};

//
export const computeMinimumCoinQuantity =
(
csl: CardanoSerializationLib,
{ coinsPerUtxoWord }: ProtocolParametersRequiredByWallet
): ComputeMinimumCoinQuantity =>
(multiasset) => {
const minUTxOValue = CSL.BigNum.from_str((BigInt(coinsPerUtxoWord) * 29n).toString());
const value = csl.Value.new(csl.BigNum.from_str('0'));
if (multiasset) {
value.set_multiasset(multiasset);
}
return BigInt(csl.min_ada_required(value, minUTxOValue).to_str());
};

// tokenBundleSizeExceedsLimit: (tokenBundle) => {
// logger.debug('SelectionConstraint: tokenBundleSizeExceedsLimit', tokenBundle);
// // Todo: Replace with real implementation
// return false;
// },
// computeSelectionLimit: async (selectionSkeleton) => {
// logger.debug('SelectionConstraint: computeSelectionLimit', selectionSkeleton);
// // Todo: Replace with real implementation
// return 5;
// }
3 changes: 2 additions & 1 deletion packages/cip2/src/types.ts
Expand Up @@ -22,6 +22,7 @@ export interface SelectionResult {
/**
* Estimated fee for the transaction.
* This value is included in 'change', so the actual change returned by the transaction is change-fee.
* TODO: refactor this to return CSL.BigNum?
*/
fee: bigint;
};
Expand Down Expand Up @@ -53,7 +54,7 @@ export type TokenBundleSizeExceedsLimit = (tokenBundle: CSL.MultiAsset) => boole
/**
* @returns minimum lovelace amount in a UTxO
*/
export type ComputeMinimumCoinQuantity = (assetQuantities: CSL.MultiAsset) => bigint;
export type ComputeMinimumCoinQuantity = (assetQuantities?: CSL.MultiAsset) => bigint;

/**
* @returns an upper bound for the number of ordinary inputs to
Expand Down
56 changes: 56 additions & 0 deletions packages/cip2/test/selectionConstraints.test.ts
@@ -0,0 +1,56 @@
import {
CardanoSerializationLib,
loadCardanoSerializationLib,
ProtocolParametersRequiredByWallet
} from '@cardano-sdk/core';
import { PXL_Asset, TSLA_Asset } from './util';
import { computeMinimumCoinQuantity, computeMinimumCost } from '../src/selectionConstraints';
import { SelectionSkeleton } from '../src/types';
import { valueQuantitiesToValue } from '../src/util';

describe('selectionConstraints', () => {
let csl: CardanoSerializationLib;
beforeAll(async () => {
csl = await loadCardanoSerializationLib();
});

it('computeMinimumCost', async () => {
const fee = 200_000n;
// Need this to not have to build Tx
const stubCsl = {
min_fee: jest.fn().mockReturnValueOnce(csl.BigNum.from_str(fee.toString())),
LinearFee: csl.LinearFee,
BigNum: csl.BigNum
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any as CardanoSerializationLib;
const buildTx = jest.fn();
const selectionSkeleton = {} as SelectionSkeleton;
const result = await computeMinimumCost(
stubCsl,
{ minFeeCoefficient: 44, minFeeConstant: 155_381 } as ProtocolParametersRequiredByWallet,
buildTx
)(selectionSkeleton);
expect(result).toEqual(fee);
expect(buildTx).toBeCalledTimes(1);
expect(buildTx).toBeCalledWith(selectionSkeleton);
});

it('computeMinimumCoinQuantity', () => {
const withAssets = valueQuantitiesToValue(
{
coins: 10_000n,
assets: {
[TSLA_Asset]: 5000n,
[PXL_Asset]: 3000n
}
},
csl
).multiasset();
const protocolParams = { coinsPerUtxoWord: 34_482 } as ProtocolParametersRequiredByWallet;
const minCoinWithAssets = computeMinimumCoinQuantity(csl, protocolParams)(withAssets);
const minCoinWithoutAssets = computeMinimumCoinQuantity(csl, protocolParams)();
expect(typeof minCoinWithAssets).toBe('bigint');
expect(typeof minCoinWithoutAssets).toBe('bigint');
expect(minCoinWithAssets).toBeGreaterThan(minCoinWithoutAssets);
});
});

0 comments on commit f41d37c

Please sign in to comment.