@meshsdk/transaction 1.6.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/package.json +35 -0
- package/src/index.ts +4 -0
- package/src/mesh-tx-builder/index.ts +259 -0
- package/src/mesh-tx-builder/tx-builder-core.ts +1180 -0
- package/src/scripts/forge.script.ts +63 -0
- package/src/scripts/index.ts +1 -0
- package/src/transaction/index.ts +609 -0
- package/src/transaction/transaction-v2.ts +81 -0
- package/src/utxo-selection/common.ts +113 -0
- package/src/utxo-selection/experimental.ts +137 -0
- package/src/utxo-selection/index.ts +69 -0
- package/src/utxo-selection/keepRelevant.ts +35 -0
- package/src/utxo-selection/largestFirst.ts +31 -0
- package/src/utxo-selection/largestFirstMultiAsset.ts +37 -0
- package/tsconfig.json +5 -0
- package/types/index.ts +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Asset, Data, UTxO } from "@meshsdk/common";
|
|
2
|
+
|
|
3
|
+
export interface TransactionV2 {
|
|
4
|
+
sendAssets(
|
|
5
|
+
receiver: string,
|
|
6
|
+
assets: Asset[],
|
|
7
|
+
datum?: Data,
|
|
8
|
+
inlineScript?: string,
|
|
9
|
+
isInline?: boolean,
|
|
10
|
+
): this;
|
|
11
|
+
spendUtxo(utxo: UTxO, redeemer?: Data): this;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// export type TxBuilder = {
|
|
15
|
+
// readFrom: (utxos: UTxO[]) => TxBuilder;
|
|
16
|
+
// collectFrom: (utxos: UTxO[], redeemer?: string | undefined) => TxBuilder;
|
|
17
|
+
// pay: {
|
|
18
|
+
// ToAddress: (address: string, assets: Assets) => TxBuilder;
|
|
19
|
+
// ToAddressWithData: (
|
|
20
|
+
// address: string,
|
|
21
|
+
// outputDatum: OutputDatum,
|
|
22
|
+
// assets?: Assets | undefined,
|
|
23
|
+
// scriptRef?: Script | undefined
|
|
24
|
+
// ) => TxBuilder;
|
|
25
|
+
// ToContract: (
|
|
26
|
+
// address: string,
|
|
27
|
+
// outputDatum: OutputDatum,
|
|
28
|
+
// assets?: Assets | undefined,
|
|
29
|
+
// scriptRef?: Script | undefined
|
|
30
|
+
// ) => TxBuilder;
|
|
31
|
+
// };
|
|
32
|
+
// addSigner: (address: Address) => TxBuilder;
|
|
33
|
+
// registerStake: (rewardAddress: RewardAddress) => TxBuilder;
|
|
34
|
+
// deRegisterStake: (
|
|
35
|
+
// rewardAddress: RewardAddress,
|
|
36
|
+
// redeemer?: string
|
|
37
|
+
// ) => TxBuilder;
|
|
38
|
+
// withdraw: (
|
|
39
|
+
// rewardAddress: RewardAddress,
|
|
40
|
+
// amount: Lovelace,
|
|
41
|
+
// redeemer?: string
|
|
42
|
+
// ) => TxBuilder;
|
|
43
|
+
// mintAssets: (assets: Assets, redeemer?: string | undefined) => TxBuilder;
|
|
44
|
+
// validFrom: (unixTime: number) => TxBuilder;
|
|
45
|
+
// validTo: (unixTime: number) => TxBuilder;
|
|
46
|
+
// delegateTo: (
|
|
47
|
+
// rewardAddress: RewardAddress,
|
|
48
|
+
// poolId: PoolId,
|
|
49
|
+
// redeemer?: Redeemer
|
|
50
|
+
// ) => TxBuilder;
|
|
51
|
+
// attachMetadata: (
|
|
52
|
+
// label: Label,
|
|
53
|
+
// metadata: Metadata.TransactionMetadata
|
|
54
|
+
// ) => TxBuilder;
|
|
55
|
+
// attach: {
|
|
56
|
+
// Script: (script: Script) => TxBuilder;
|
|
57
|
+
// SpendingValidator: (spendingValidator: Script) => TxBuilder;
|
|
58
|
+
// MintingPolicy: (mintingPolicy: Script) => TxBuilder;
|
|
59
|
+
// CertificateValidator: (certValidator: Script) => TxBuilder;
|
|
60
|
+
// WithdrawalValidator: (withdrawalValidator: Script) => TxBuilder;
|
|
61
|
+
// };
|
|
62
|
+
// complete: (
|
|
63
|
+
// options?: CompleteTxBuilder.CompleteOptions
|
|
64
|
+
// ) => Promise<TxSignBuilder.TxSignBuilder>;
|
|
65
|
+
// completeProgram: (
|
|
66
|
+
// options?: CompleteTxBuilder.CompleteOptions
|
|
67
|
+
// ) => Effect.Effect<TxSignBuilder.TxSignBuilder, TransactionError>;
|
|
68
|
+
// completeSafe: (
|
|
69
|
+
// options?: CompleteTxBuilder.CompleteOptions
|
|
70
|
+
// ) => Promise<Either<TxSignBuilder.TxSignBuilder, TransactionError>>;
|
|
71
|
+
// chainProgram: () => Effect.Effect<
|
|
72
|
+
// [UTxO[], UTxO[], TxSignBuilder.TxSignBuilder],
|
|
73
|
+
// TransactionError,
|
|
74
|
+
// never
|
|
75
|
+
// >;
|
|
76
|
+
// chain: () => Promise<[UTxO[], UTxO[], TxSignBuilder.TxSignBuilder]>;
|
|
77
|
+
// chainSafe: () => Promise<
|
|
78
|
+
// Either<[UTxO[], UTxO[], TxSignBuilder.TxSignBuilder], TransactionError>
|
|
79
|
+
// >;
|
|
80
|
+
// config: () => TxBuilderConfig;
|
|
81
|
+
// };
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { BigNum } from "@meshsdk/common";
|
|
2
|
+
import { resolveTxFees } from "@meshsdk/common";
|
|
3
|
+
import type { Protocol, Quantity, Unit, UTxO } from "@meshsdk/common";
|
|
4
|
+
|
|
5
|
+
export const enoughValueHasBeenSelected = (
|
|
6
|
+
selection: UTxO[],
|
|
7
|
+
assets: Map<Unit, Quantity>
|
|
8
|
+
): boolean => {
|
|
9
|
+
return Array.from(assets, (asset) => ({
|
|
10
|
+
unit: asset[0],
|
|
11
|
+
quantity: BigNum.new(asset[1]),
|
|
12
|
+
})).every((asset) => {
|
|
13
|
+
return (
|
|
14
|
+
selection
|
|
15
|
+
.filter((utxo) => {
|
|
16
|
+
return (
|
|
17
|
+
utxo.output.amount.find((a) => a.unit === asset.unit) !== undefined
|
|
18
|
+
);
|
|
19
|
+
})
|
|
20
|
+
.reduce((selectedQuantity, utxo) => {
|
|
21
|
+
const utxoQuantity = utxo.output.amount.reduce(
|
|
22
|
+
(quantity, a) =>
|
|
23
|
+
quantity.checkedAdd(
|
|
24
|
+
BigNum.new(asset.unit === a.unit ? a.quantity : "0")
|
|
25
|
+
),
|
|
26
|
+
BigNum.new("0")
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
return selectedQuantity.checkedAdd(utxoQuantity);
|
|
30
|
+
}, BigNum.new("0"))
|
|
31
|
+
.lessThan(asset.quantity) === false
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const largestLovelaceQuantity = (utxoA: UTxO, utxoB: UTxO): number => {
|
|
37
|
+
const aLovelaceQuantity = BigNum.new(
|
|
38
|
+
utxoA.output.amount.find((asset) => asset.unit === "lovelace")?.quantity ??
|
|
39
|
+
"0"
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const bLovelaceQuantity = BigNum.new(
|
|
43
|
+
utxoB.output.amount.find((asset) => asset.unit === "lovelace")?.quantity ??
|
|
44
|
+
"0"
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return bLovelaceQuantity.compare(aLovelaceQuantity);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const maxTxFees = (parameters: Protocol) => {
|
|
51
|
+
const { maxTxSize, minFeeA, minFeeB } = parameters;
|
|
52
|
+
|
|
53
|
+
return BigNum.new(resolveTxFees(maxTxSize, minFeeA, minFeeB));
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const multiAssetUTxO = (utxo: UTxO): boolean =>
|
|
57
|
+
utxo.output.amount.length > 1;
|
|
58
|
+
|
|
59
|
+
export const selectedLovelaceQuantity = (multiAsset: UTxO[]) => {
|
|
60
|
+
return multiAsset.reduce((sum, utxo) => {
|
|
61
|
+
const lovelace =
|
|
62
|
+
utxo.output.amount.find((asset) => asset.unit === "lovelace")?.quantity ??
|
|
63
|
+
"0";
|
|
64
|
+
|
|
65
|
+
return sum.checkedAdd(BigNum.new(lovelace));
|
|
66
|
+
}, BigNum.new("0"));
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const remainingLovelace = (
|
|
70
|
+
quantity: Quantity,
|
|
71
|
+
initialUTxOSet: UTxO[]
|
|
72
|
+
) => {
|
|
73
|
+
const sortedUTxOs = initialUTxOSet.sort(largestLovelaceQuantity);
|
|
74
|
+
|
|
75
|
+
const requestedOutputSet = new Map<Unit, Quantity>([["lovelace", quantity]]);
|
|
76
|
+
|
|
77
|
+
const selection = selectValue(sortedUTxOs, requestedOutputSet);
|
|
78
|
+
|
|
79
|
+
return selection;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const selectValue = (
|
|
83
|
+
inputUTxO: UTxO[],
|
|
84
|
+
outputSet: Map<Unit, Quantity>,
|
|
85
|
+
selection: UTxO[] = []
|
|
86
|
+
): UTxO[] => {
|
|
87
|
+
if (
|
|
88
|
+
inputUTxO.length === 0 ||
|
|
89
|
+
enoughValueHasBeenSelected(selection, outputSet)
|
|
90
|
+
) {
|
|
91
|
+
return selection;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (valueCanBeSelected(inputUTxO[0]!, outputSet)) {
|
|
95
|
+
return selectValue(inputUTxO.slice(1), outputSet, [
|
|
96
|
+
...selection,
|
|
97
|
+
inputUTxO[0]!,
|
|
98
|
+
]);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return selectValue(inputUTxO.slice(1), outputSet, selection);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const valueCanBeSelected = (
|
|
105
|
+
utxo: UTxO,
|
|
106
|
+
assets: Map<Unit, Quantity>
|
|
107
|
+
): boolean => {
|
|
108
|
+
return Array.from(assets.keys()).some((unit) => {
|
|
109
|
+
return (
|
|
110
|
+
utxo.output.amount.find((asset) => asset.unit === unit) !== undefined
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { Quantity, UTxO, Unit } from "@meshsdk/common";
|
|
2
|
+
|
|
3
|
+
export const experimentalSelectUtxos = (
|
|
4
|
+
requiredAssets: Map<Unit, Quantity>,
|
|
5
|
+
inputs: UTxO[],
|
|
6
|
+
threshold: Quantity
|
|
7
|
+
): UTxO[] => {
|
|
8
|
+
const totalRequiredAssets = new Map<Unit, Quantity>(requiredAssets);
|
|
9
|
+
totalRequiredAssets.set(
|
|
10
|
+
"lovelace",
|
|
11
|
+
String(Number(totalRequiredAssets.get("lovelace") || 0) + Number(threshold))
|
|
12
|
+
);
|
|
13
|
+
const utxoMap = new Map<number, UTxO>();
|
|
14
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
15
|
+
utxoMap.set(i, inputs[i]!);
|
|
16
|
+
}
|
|
17
|
+
const selectedInputs = new Set<number>();
|
|
18
|
+
const onlyLovelace = new Set<number>();
|
|
19
|
+
const singletons = new Set<number>();
|
|
20
|
+
const pairs = new Set<number>();
|
|
21
|
+
const rest = new Set<number>();
|
|
22
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
23
|
+
switch (inputs[i]!.output.amount.length) {
|
|
24
|
+
case 1: {
|
|
25
|
+
onlyLovelace.add(i);
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case 2: {
|
|
29
|
+
singletons.add(i);
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
case 3: {
|
|
33
|
+
pairs.add(i);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
default: {
|
|
37
|
+
rest.add(i);
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const addUtxoWithAssetAmount = (
|
|
44
|
+
inputIndex: number,
|
|
45
|
+
assetUnit: string,
|
|
46
|
+
set: Set<number>
|
|
47
|
+
) => {
|
|
48
|
+
const utxo = utxoMap.get(inputIndex);
|
|
49
|
+
if (!utxo) return;
|
|
50
|
+
|
|
51
|
+
const amount = getAssetAmount(utxo, assetUnit);
|
|
52
|
+
if (Number(amount) > 0) {
|
|
53
|
+
selectedInputs.add(inputIndex);
|
|
54
|
+
set.delete(inputIndex);
|
|
55
|
+
for (const asset of utxo.output.amount) {
|
|
56
|
+
totalRequiredAssets.set(
|
|
57
|
+
asset.unit,
|
|
58
|
+
String(
|
|
59
|
+
Number(totalRequiredAssets.get(asset.unit)) - Number(asset.quantity)
|
|
60
|
+
)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
for (const assetUnit of totalRequiredAssets.keys()) {
|
|
67
|
+
if (assetUnit == "lovelace") continue;
|
|
68
|
+
for (const inputIndex of singletons) {
|
|
69
|
+
const assetRequired = totalRequiredAssets.get(assetUnit);
|
|
70
|
+
if (!assetRequired || Number(assetRequired) <= 0) break;
|
|
71
|
+
addUtxoWithAssetAmount(inputIndex, assetUnit, singletons);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (const inputIndex of pairs) {
|
|
75
|
+
const assetRequired = totalRequiredAssets.get(assetUnit);
|
|
76
|
+
if (!assetRequired || Number(assetRequired) <= 0) break;
|
|
77
|
+
addUtxoWithAssetAmount(inputIndex, assetUnit, pairs);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
for (const inputIndex of rest) {
|
|
81
|
+
const assetRequired = totalRequiredAssets.get(assetUnit);
|
|
82
|
+
if (!assetRequired || Number(assetRequired) <= 0) break;
|
|
83
|
+
addUtxoWithAssetAmount(inputIndex, assetUnit, rest);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
for (const inputIndex of onlyLovelace) {
|
|
88
|
+
const assetRequired = totalRequiredAssets.get("lovelace");
|
|
89
|
+
if (!assetRequired || Number(assetRequired) <= 0) break;
|
|
90
|
+
addUtxoWithAssetAmount(inputIndex, "lovelace", onlyLovelace);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
for (const inputIndex of singletons) {
|
|
94
|
+
const assetRequired = totalRequiredAssets.get("lovelace");
|
|
95
|
+
if (!assetRequired || Number(assetRequired) <= 0) break;
|
|
96
|
+
addUtxoWithAssetAmount(inputIndex, "lovelace", singletons);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for (const inputIndex of pairs) {
|
|
100
|
+
const assetRequired = totalRequiredAssets.get("lovelace");
|
|
101
|
+
if (!assetRequired || Number(assetRequired) <= 0) break;
|
|
102
|
+
addUtxoWithAssetAmount(inputIndex, "lovelace", pairs);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
for (const inputIndex of rest) {
|
|
106
|
+
const assetRequired = totalRequiredAssets.get("lovelace");
|
|
107
|
+
if (!assetRequired || Number(assetRequired) <= 0) break;
|
|
108
|
+
addUtxoWithAssetAmount(inputIndex, "lovelace", rest);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
for (const assetUnit of totalRequiredAssets.keys()) {
|
|
112
|
+
if (Number(totalRequiredAssets.get(assetUnit)) > 0) {
|
|
113
|
+
console.log("Insufficient funds for", assetUnit);
|
|
114
|
+
console.log(
|
|
115
|
+
"Remaining quantity",
|
|
116
|
+
Number(totalRequiredAssets.get(assetUnit))
|
|
117
|
+
);
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const selectedUtxos: UTxO[] = [];
|
|
123
|
+
for (const inputIndex of selectedInputs) {
|
|
124
|
+
const utxo = utxoMap.get(inputIndex);
|
|
125
|
+
if (utxo) {
|
|
126
|
+
selectedUtxos.push(utxo);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return selectedUtxos;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const getAssetAmount = (utxo: UTxO, assetUnit: string): string => {
|
|
133
|
+
for (const utxoAsset of utxo.output.amount) {
|
|
134
|
+
if (utxoAsset.unit == assetUnit) return utxoAsset.quantity;
|
|
135
|
+
}
|
|
136
|
+
return "0";
|
|
137
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Unit, Quantity, UTxO } from "@meshsdk/common";
|
|
2
|
+
import { keepRelevant } from "./keepRelevant";
|
|
3
|
+
import { largestFirst } from "./largestFirst";
|
|
4
|
+
import { largestFirstMultiAsset } from "./largestFirstMultiAsset";
|
|
5
|
+
import { experimentalSelectUtxos } from "./experimental";
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
keepRelevant,
|
|
9
|
+
largestFirst,
|
|
10
|
+
largestFirstMultiAsset,
|
|
11
|
+
experimentalSelectUtxos,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* All UTxO selection algorithms follows below's interface
|
|
16
|
+
*
|
|
17
|
+
* Supported algorithms:
|
|
18
|
+
* - largestFirst - CIP2 suggested algorithm
|
|
19
|
+
* - largestFirstMultiAsset - CIP2 suggested algorithm
|
|
20
|
+
* - keepRelevant - CIP2 suggested algorithm
|
|
21
|
+
* - experimental - The always evolving algorithm according to the latest research
|
|
22
|
+
*
|
|
23
|
+
* @param requestedOutputSet
|
|
24
|
+
* @param initialUTxOSet
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
export class UtxoSelection {
|
|
28
|
+
constructor() {}
|
|
29
|
+
|
|
30
|
+
largestFirst(
|
|
31
|
+
requiredAssets: Map<Unit, Quantity>,
|
|
32
|
+
inputs: UTxO[],
|
|
33
|
+
threshold = "5000000"
|
|
34
|
+
) {
|
|
35
|
+
const lovelaceAmount = requiredAssets.get("lovelace") ?? "0";
|
|
36
|
+
const requiredAssetWithThreshold =
|
|
37
|
+
BigInt(lovelaceAmount) + BigInt(threshold);
|
|
38
|
+
return largestFirst(requiredAssetWithThreshold.toString(), inputs, false);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
keepRelevant(
|
|
42
|
+
requiredAssets: Map<Unit, Quantity>,
|
|
43
|
+
inputs: UTxO[],
|
|
44
|
+
threshold = "5000000"
|
|
45
|
+
) {
|
|
46
|
+
return keepRelevant(requiredAssets, inputs, threshold);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
largestFirstMultiAsset(
|
|
50
|
+
requiredAssets: Map<Unit, Quantity>,
|
|
51
|
+
inputs: UTxO[],
|
|
52
|
+
threshold: Quantity
|
|
53
|
+
) {
|
|
54
|
+
const lovelaceAmount = requiredAssets.get("lovelace") ?? "0";
|
|
55
|
+
requiredAssets.set(
|
|
56
|
+
"lovelace",
|
|
57
|
+
(BigInt(lovelaceAmount) + BigInt(threshold)).toString()
|
|
58
|
+
);
|
|
59
|
+
return largestFirstMultiAsset(requiredAssets, inputs, false);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
experimental(
|
|
63
|
+
requiredAssets: Map<Unit, Quantity>,
|
|
64
|
+
inputs: UTxO[],
|
|
65
|
+
threshold: Quantity
|
|
66
|
+
) {
|
|
67
|
+
return experimentalSelectUtxos(requiredAssets, inputs, threshold);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { BigNum, Quantity, UTxO, Unit } from "@meshsdk/common";
|
|
2
|
+
import { remainingLovelace, selectedLovelaceQuantity } from "./common";
|
|
3
|
+
|
|
4
|
+
export const keepRelevant = (
|
|
5
|
+
requiredAssets: Map<Unit, Quantity>,
|
|
6
|
+
inputs: UTxO[],
|
|
7
|
+
threshold = "5000000"
|
|
8
|
+
) => {
|
|
9
|
+
const requestedLovelace = BigNum.new(
|
|
10
|
+
requiredAssets.get("lovelace") ?? "0"
|
|
11
|
+
).checkedAdd(BigNum.new(threshold));
|
|
12
|
+
|
|
13
|
+
const multiAsset = inputs.filter((utxo) =>
|
|
14
|
+
utxo.output.amount
|
|
15
|
+
.filter((asset) => asset.unit !== "lovelace")
|
|
16
|
+
.some((asset) => requiredAssets.has(asset.unit))
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const selectedLovelace = selectedLovelaceQuantity(multiAsset);
|
|
20
|
+
|
|
21
|
+
const lovelace = selectedLovelace.lessThan(requestedLovelace)
|
|
22
|
+
? remainingLovelace(
|
|
23
|
+
requestedLovelace.clampedSub(selectedLovelace).toString(),
|
|
24
|
+
inputs.filter((input) => {
|
|
25
|
+
return !multiAsset.some(
|
|
26
|
+
(selectedUtxo) =>
|
|
27
|
+
selectedUtxo.input.txHash === input.input.txHash &&
|
|
28
|
+
selectedUtxo.input.outputIndex === input.input.outputIndex
|
|
29
|
+
);
|
|
30
|
+
})
|
|
31
|
+
)
|
|
32
|
+
: [];
|
|
33
|
+
|
|
34
|
+
return [...lovelace, ...multiAsset];
|
|
35
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Quantity,
|
|
3
|
+
UTxO,
|
|
4
|
+
DEFAULT_PROTOCOL_PARAMETERS,
|
|
5
|
+
BigNum,
|
|
6
|
+
resolveTxFees,
|
|
7
|
+
Unit,
|
|
8
|
+
} from "@meshsdk/common";
|
|
9
|
+
import { multiAssetUTxO, largestLovelaceQuantity, selectValue } from "./common";
|
|
10
|
+
|
|
11
|
+
export const largestFirst = (
|
|
12
|
+
lovelace: Quantity,
|
|
13
|
+
initialUTxOSet: UTxO[],
|
|
14
|
+
includeTxFees = false,
|
|
15
|
+
{ maxTxSize, minFeeA, minFeeB } = DEFAULT_PROTOCOL_PARAMETERS
|
|
16
|
+
): UTxO[] => {
|
|
17
|
+
const sortedUTxOs = initialUTxOSet
|
|
18
|
+
.filter((utxo) => multiAssetUTxO(utxo) === false)
|
|
19
|
+
.sort(largestLovelaceQuantity);
|
|
20
|
+
|
|
21
|
+
const maxTxFees = BigNum.new(resolveTxFees(maxTxSize, minFeeA, minFeeB));
|
|
22
|
+
|
|
23
|
+
const quantity = includeTxFees
|
|
24
|
+
? BigNum.new(lovelace).checkedAdd(maxTxFees).toString()
|
|
25
|
+
: lovelace;
|
|
26
|
+
|
|
27
|
+
const requestedOutputSet = new Map<Unit, Quantity>([["lovelace", quantity]]);
|
|
28
|
+
|
|
29
|
+
const selection = selectValue(sortedUTxOs, requestedOutputSet);
|
|
30
|
+
return selection;
|
|
31
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BigNum,
|
|
3
|
+
DEFAULT_PROTOCOL_PARAMETERS,
|
|
4
|
+
Quantity,
|
|
5
|
+
UTxO,
|
|
6
|
+
Unit,
|
|
7
|
+
} from "@meshsdk/common";
|
|
8
|
+
import {
|
|
9
|
+
multiAssetUTxO,
|
|
10
|
+
largestLovelaceQuantity,
|
|
11
|
+
maxTxFees,
|
|
12
|
+
selectValue,
|
|
13
|
+
} from "./common";
|
|
14
|
+
|
|
15
|
+
export const largestFirstMultiAsset = (
|
|
16
|
+
requestedOutputSet: Map<Unit, Quantity>,
|
|
17
|
+
initialUTxOSet: UTxO[],
|
|
18
|
+
includeTxFees = false,
|
|
19
|
+
parameters = DEFAULT_PROTOCOL_PARAMETERS
|
|
20
|
+
): UTxO[] => {
|
|
21
|
+
const sortedMultiAssetUTxOs = initialUTxOSet
|
|
22
|
+
.filter(multiAssetUTxO)
|
|
23
|
+
.sort(largestLovelaceQuantity);
|
|
24
|
+
|
|
25
|
+
const txFees = maxTxFees(parameters);
|
|
26
|
+
const lovelace = requestedOutputSet.get("lovelace") ?? "0";
|
|
27
|
+
|
|
28
|
+
const quantity = includeTxFees
|
|
29
|
+
? BigNum.new(lovelace).checkedAdd(txFees).toString()
|
|
30
|
+
: lovelace;
|
|
31
|
+
|
|
32
|
+
requestedOutputSet.set("lovelace", quantity);
|
|
33
|
+
|
|
34
|
+
const selection = selectValue(sortedMultiAssetUTxOs, requestedOutputSet);
|
|
35
|
+
|
|
36
|
+
return selection;
|
|
37
|
+
};
|
package/tsconfig.json
ADDED
package/types/index.ts
ADDED
|
File without changes
|