@fleet-sdk/common 0.1.0-alpha.29 → 0.1.0-alpha.31
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/CHANGELOG.md +7 -0
- package/dist/cjs/types/boxes.d.ts +7 -6
- package/dist/cjs/types/common.js +2 -2
- package/dist/cjs/types/common.js.map +1 -1
- package/dist/cjs/utils/arrayUtils.d.ts +6 -2
- package/dist/cjs/utils/arrayUtils.js +23 -1
- package/dist/cjs/utils/arrayUtils.js.map +1 -1
- package/dist/cjs/utils/boxUtils.d.ts +12 -9
- package/dist/cjs/utils/boxUtils.js +61 -16
- package/dist/cjs/utils/boxUtils.js.map +1 -1
- package/dist/esm/types/boxes.d.ts +7 -6
- package/dist/esm/utils/arrayUtils.d.ts +6 -2
- package/dist/esm/utils/arrayUtils.js +20 -0
- package/dist/esm/utils/arrayUtils.js.map +1 -1
- package/dist/esm/utils/boxUtils.d.ts +12 -9
- package/dist/esm/utils/boxUtils.js +58 -14
- package/dist/esm/utils/boxUtils.js.map +1 -1
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -3
- package/src/types/boxes.ts +13 -6
- package/src/utils/arrayUtils.ts +36 -2
- package/src/utils/boxUtils.ts +90 -22
package/src/utils/arrayUtils.ts
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
import { SortingDirection, SortingSelector } from "../types";
|
2
2
|
|
3
|
+
type ObjectSelector<T> = (item: T) => T[keyof T];
|
4
|
+
|
3
5
|
export function isEmpty<T extends object>(obj?: T): obj is undefined;
|
4
6
|
export function isEmpty<T>(array?: T[]): array is undefined;
|
5
7
|
export function isEmpty<T>(obj?: T[] | object): obj is undefined {
|
@@ -43,7 +45,7 @@ export function hasDuplicates<T>(array: T[]): boolean {
|
|
43
45
|
/**
|
44
46
|
* Check for duplicate keys in complex elements
|
45
47
|
*/
|
46
|
-
export function hasDuplicatesBy<T>(array: T[], selector:
|
48
|
+
export function hasDuplicatesBy<T>(array: T[], selector: ObjectSelector<T>): boolean {
|
47
49
|
return array.some((item, index) => {
|
48
50
|
return array.findIndex((x) => selector(x) === selector(item)) !== index;
|
49
51
|
});
|
@@ -99,7 +101,7 @@ export function areEqual<T>(array1: ArrayLike<T>, array2: ArrayLike<T>): boolean
|
|
99
101
|
export function areEqualBy<T>(
|
100
102
|
array1: ArrayLike<T>,
|
101
103
|
array2: ArrayLike<T>,
|
102
|
-
selector:
|
104
|
+
selector: ObjectSelector<T>
|
103
105
|
): boolean {
|
104
106
|
if (array1 === array2) {
|
105
107
|
return true;
|
@@ -155,3 +157,35 @@ export function endsWith<T>(array: ArrayLike<T>, target: ArrayLike<T>): boolean
|
|
155
157
|
|
156
158
|
return true;
|
157
159
|
}
|
160
|
+
|
161
|
+
export function uniq<T>(array: Array<T>): Array<T> {
|
162
|
+
if (isEmpty(array)) {
|
163
|
+
return array;
|
164
|
+
}
|
165
|
+
|
166
|
+
return Array.from(new Set(array));
|
167
|
+
}
|
168
|
+
|
169
|
+
export function uniqBy<T>(
|
170
|
+
array: Array<T>,
|
171
|
+
selector: ObjectSelector<T>,
|
172
|
+
selection: "keep-first" | "keep-last" = "keep-first"
|
173
|
+
): Array<T> {
|
174
|
+
if (isEmpty(array)) {
|
175
|
+
return array;
|
176
|
+
}
|
177
|
+
|
178
|
+
return Array.from(
|
179
|
+
array
|
180
|
+
.reduce((map, e) => {
|
181
|
+
const key = selector(e);
|
182
|
+
|
183
|
+
if (selection === "keep-first" && map.has(key)) {
|
184
|
+
return map;
|
185
|
+
}
|
186
|
+
|
187
|
+
return map.set(key, e);
|
188
|
+
}, new Map())
|
189
|
+
.values()
|
190
|
+
);
|
191
|
+
}
|
package/src/utils/boxUtils.ts
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
-
import { Amount, NonMandatoryRegisters, TokenId } from "../types";
|
1
|
+
import { Amount, AmountType, Box, NonMandatoryRegisters, TokenAmount, TokenId } from "../types";
|
2
|
+
import { isEmpty } from "./arrayUtils";
|
2
3
|
import { _0n } from "./bigIntLiterals";
|
3
4
|
import { ensureBigInt } from "./bigIntUtils";
|
4
5
|
import { isDefined, isUndefined } from "./objectUtils";
|
5
6
|
|
6
7
|
const NANOERGS_TOKEN_ID = "nanoErgs";
|
7
8
|
|
8
|
-
export function utxoSum(boxes: MinimalBoxAmounts):
|
9
|
+
export function utxoSum(boxes: MinimalBoxAmounts): BoxSummary;
|
9
10
|
export function utxoSum(boxes: MinimalBoxAmounts, tokenId: TokenId): bigint;
|
10
|
-
export function utxoSum(boxes: MinimalBoxAmounts, tokenId?: TokenId):
|
11
|
+
export function utxoSum(boxes: MinimalBoxAmounts, tokenId?: TokenId): BoxSummary | bigint {
|
11
12
|
const balances: { [tokenId: string]: bigint } = {};
|
12
13
|
|
13
14
|
for (const box of boxes) {
|
@@ -31,20 +32,31 @@ export function utxoSum(boxes: MinimalBoxAmounts, tokenId?: TokenId): BoxAmounts
|
|
31
32
|
}
|
32
33
|
|
33
34
|
return {
|
34
|
-
nanoErgs: balances[NANOERGS_TOKEN_ID],
|
35
|
+
nanoErgs: balances[NANOERGS_TOKEN_ID] || _0n,
|
35
36
|
tokens: Object.keys(balances)
|
36
37
|
.filter((x) => x !== NANOERGS_TOKEN_ID)
|
37
38
|
.map((tokenId) => ({ tokenId, amount: balances[tokenId] }))
|
38
39
|
};
|
39
40
|
}
|
40
41
|
|
41
|
-
export function
|
42
|
+
export function utxoDiff(
|
43
|
+
minuend: BoxSummary | Box<Amount>[],
|
44
|
+
subtrahend: BoxSummary | Box<Amount>[]
|
45
|
+
): BoxSummary {
|
46
|
+
if (Array.isArray(minuend)) {
|
47
|
+
minuend = utxoSum(minuend);
|
48
|
+
}
|
49
|
+
|
50
|
+
if (Array.isArray(subtrahend)) {
|
51
|
+
subtrahend = utxoSum(subtrahend);
|
52
|
+
}
|
53
|
+
|
42
54
|
const tokens: TokenAmount<bigint>[] = [];
|
43
|
-
const nanoErgs =
|
55
|
+
const nanoErgs = minuend.nanoErgs - subtrahend.nanoErgs;
|
44
56
|
|
45
|
-
for (const token of
|
57
|
+
for (const token of minuend.tokens) {
|
46
58
|
const balance =
|
47
|
-
token.amount - (
|
59
|
+
token.amount - (subtrahend.tokens.find((t) => t.tokenId === token.tokenId)?.amount || _0n);
|
48
60
|
|
49
61
|
if (balance !== _0n) {
|
50
62
|
tokens.push({ tokenId: token.tokenId, amount: balance });
|
@@ -54,40 +66,96 @@ export function utxoSumResultDiff(amountsA: BoxAmounts, amountsB: BoxAmounts): B
|
|
54
66
|
return { nanoErgs, tokens };
|
55
67
|
}
|
56
68
|
|
57
|
-
const
|
58
|
-
const
|
69
|
+
const MIN_NON_MANDATORY_REGISTER_INDEX = 4;
|
70
|
+
const MAX_NON_MANDATORY_REGISTER_INDEX = 9;
|
59
71
|
|
60
72
|
export function areRegistersDenselyPacked(registers: NonMandatoryRegisters): boolean {
|
61
|
-
let
|
62
|
-
for (let i =
|
63
|
-
|
64
|
-
|
65
|
-
|
73
|
+
let lastIndex = 0;
|
74
|
+
for (let i = MIN_NON_MANDATORY_REGISTER_INDEX; i <= MAX_NON_MANDATORY_REGISTER_INDEX; i++) {
|
75
|
+
const key = `R${i}` as keyof NonMandatoryRegisters;
|
76
|
+
if (registers[key]) {
|
77
|
+
if (i === MIN_NON_MANDATORY_REGISTER_INDEX) {
|
78
|
+
lastIndex = i;
|
66
79
|
continue;
|
67
80
|
}
|
68
81
|
|
69
|
-
if (i -
|
82
|
+
if (i - lastIndex > 1) {
|
70
83
|
return false;
|
71
84
|
}
|
72
85
|
|
73
|
-
|
86
|
+
lastIndex = i;
|
74
87
|
}
|
75
88
|
}
|
76
89
|
|
77
90
|
return true;
|
78
91
|
}
|
79
92
|
|
80
|
-
|
81
|
-
|
82
|
-
|
93
|
+
export function utxoFilter<T extends AmountType>(
|
94
|
+
utxos: Box<T>[],
|
95
|
+
filterParams: UTxOFilterParams<T>
|
96
|
+
) {
|
97
|
+
if (isEmpty(filterParams) || isEmpty(utxos)) {
|
98
|
+
return utxos;
|
99
|
+
}
|
100
|
+
|
101
|
+
const { by, max } = filterParams;
|
102
|
+
let filtered = utxos;
|
103
|
+
|
104
|
+
if (by) {
|
105
|
+
filtered = utxos.filter(by);
|
106
|
+
if (isEmpty(filtered)) {
|
107
|
+
return filtered;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
if (!max) {
|
112
|
+
return filtered;
|
113
|
+
}
|
114
|
+
|
115
|
+
if (isDefined(max.aggregatedDistinctTokens)) {
|
116
|
+
const tokenIds = _getDistinctTokenIds(filtered, max.aggregatedDistinctTokens);
|
117
|
+
filtered = filtered.filter(
|
118
|
+
(utxo) => isEmpty(utxo.assets) || utxo.assets.every((token) => tokenIds.has(token.tokenId))
|
119
|
+
);
|
120
|
+
}
|
121
|
+
|
122
|
+
if (isDefined(max.count) && filtered.length > max.count) {
|
123
|
+
filtered = filtered.slice(0, max.count);
|
124
|
+
}
|
125
|
+
|
126
|
+
return filtered;
|
127
|
+
}
|
128
|
+
|
129
|
+
function _getDistinctTokenIds(utxos: Box<AmountType>[], max: number): Set<string> {
|
130
|
+
const tokenIds = new Set<string>();
|
131
|
+
|
132
|
+
for (let i = 0; i < utxos.length && tokenIds.size < max; i++) {
|
133
|
+
if (isEmpty(utxos[i].assets) || utxos[i].assets.length > max) {
|
134
|
+
continue;
|
135
|
+
}
|
136
|
+
|
137
|
+
for (const token of utxos[i].assets) {
|
138
|
+
tokenIds.add(token.tokenId);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
return tokenIds;
|
143
|
+
}
|
144
|
+
|
145
|
+
export type UTxOFilterParams<T extends AmountType> = {
|
146
|
+
by?: (utxo: Box<T>) => boolean;
|
147
|
+
max?: {
|
148
|
+
count?: number;
|
149
|
+
aggregatedDistinctTokens?: number;
|
150
|
+
};
|
83
151
|
};
|
84
152
|
|
85
|
-
export type
|
153
|
+
export type BoxSummary = {
|
86
154
|
nanoErgs: bigint;
|
87
155
|
tokens: TokenAmount<bigint>[];
|
88
156
|
};
|
89
157
|
|
90
|
-
type MinimalBoxAmounts = readonly {
|
158
|
+
export type MinimalBoxAmounts = readonly {
|
91
159
|
value: Amount;
|
92
160
|
assets: TokenAmount<Amount>[];
|
93
161
|
}[];
|