Skip to content

Commit 4d59aec

Browse files
authored
Merge pull request #630 from Anastasia-Labs/595-transactionmetadatumlabelsts
TransactionMetadatumLabels initial version
2 parents b54f49b + 7535b2c commit 4d59aec

2 files changed

Lines changed: 274 additions & 0 deletions

File tree

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
import { Data, Inspectable, Schema } from "effect";
2+
3+
/**
4+
* CDDL spec:
5+
* ```
6+
* transaction_metadatum_label = uint .size 8
7+
* ```
8+
*
9+
* @since 2.0.0
10+
* @category model
11+
*/
12+
export const TransactionMetadatumLabel = Schema.Uint8;
13+
14+
/**
15+
* Type representing a transaction metadatum label.
16+
*
17+
* @since 2.0.0
18+
* @category model
19+
*/
20+
export type TransactionMetadatumLabel = typeof TransactionMetadatumLabel.Type;
21+
22+
/**
23+
* Error thrown when transaction metadatum labels operations fail
24+
*
25+
* @since 2.0.0
26+
* @category model
27+
*/
28+
export class TransactionMetadatumLabelsError extends Data.TaggedError(
29+
"TransactionMetadatumLabelsError",
30+
)<{
31+
message: string;
32+
cause?: unknown;
33+
}> {}
34+
35+
/**
36+
* Transaction metadatum labels from an array of `TransactionMetadatumLabel`
37+
*
38+
* @since 2.0.0
39+
* @category schemas
40+
*/
41+
export class TransactionMetadatumLabels extends Schema.TaggedClass<TransactionMetadatumLabels>(
42+
"TransactionMetadatumLabels",
43+
)("TransactionMetadatumLabels", {
44+
fromLabels: Schema.mutable(Schema.Array(TransactionMetadatumLabel)),
45+
}) {
46+
[Inspectable.NodeInspectSymbol]() {
47+
return {
48+
_tag: "TransactionMetadatumLabels",
49+
fromLabels: this.fromLabels,
50+
};
51+
}
52+
53+
/**
54+
* Gets the size of the labels.
55+
* @returns The length of `fromLabels`
56+
*/
57+
size() {
58+
return this.fromLabels.length;
59+
}
60+
61+
/**
62+
* Gets the label located at the specified index. If the index is out-of-bound,
63+
* returns `undefined`
64+
*
65+
* @param index The index of the label
66+
* @returns Returns `TransactionMetadatumLabel` located at the specified index
67+
*/
68+
get(index: number) {
69+
return this.fromLabels.at(index);
70+
}
71+
72+
/**
73+
* Overrides the existing labels with the specified ones.
74+
* @param overideLabels The new set of labels
75+
*/
76+
set(overideLabels: TransactionMetadatumLabel[]) {
77+
while (this.fromLabels.at(0) !== undefined) {
78+
this.fromLabels.pop();
79+
}
80+
81+
for (const label of overideLabels) {
82+
this.add(label);
83+
}
84+
}
85+
86+
/**
87+
* Appends a new label to the **end**
88+
*
89+
* @param label The label to append
90+
* @returns The size of the labels after appended. This is a number one higher than the previous labels count.
91+
*/
92+
add(label: TransactionMetadatumLabel) {
93+
return this.fromLabels.push(label);
94+
}
95+
96+
/**
97+
* Removes the first occurence of the specified label from the collection.
98+
* @param label The label to remove from the collection
99+
*/
100+
removeFirst(label: TransactionMetadatumLabel) {
101+
const skip = this.fromLabels.indexOf(label);
102+
103+
const overideLabels: TransactionMetadatumLabel[] = [];
104+
for (let i = 0; i < this.size(); i++) {
105+
if (i === skip) continue;
106+
overideLabels.push(this.fromLabels[i]);
107+
}
108+
109+
this.set(overideLabels);
110+
}
111+
112+
/**
113+
* Removes the last occurence of the specified label from the collection.
114+
* @param label The label to remove from the collection
115+
*/
116+
removeLast(label: TransactionMetadatumLabel) {
117+
const skip = this.fromLabels.lastIndexOf(label);
118+
119+
const overideLabels: TransactionMetadatumLabel[] = [];
120+
for (let i = 0; i < this.size(); i++) {
121+
if (i === skip) continue;
122+
overideLabels.push(this.fromLabels[i]);
123+
}
124+
125+
this.set(overideLabels);
126+
}
127+
128+
/**
129+
* Removes all occurences of the specified label from the collection.
130+
* @param label The label to remove from the collection
131+
*/
132+
removeAll(label: TransactionMetadatumLabel) {
133+
this.set(this.fromLabels.filter((fromLabel) => fromLabel !== label));
134+
}
135+
136+
/**
137+
* Removes the label at the specified index from the collection.
138+
* @param index The index of the label to remove from the collection
139+
*/
140+
removeAt(index: number) {
141+
const overideLabels: TransactionMetadatumLabel[] = [];
142+
for (let i = 0; i < this.size(); i++) {
143+
if (i === index) continue;
144+
overideLabels.push(this.fromLabels[i]);
145+
}
146+
147+
this.set(overideLabels);
148+
}
149+
150+
/**
151+
* Determines whether the collection contains the specified label.
152+
*
153+
* @param label The label to look for
154+
* @returns True or False as appropriate
155+
*/
156+
has(label: TransactionMetadatumLabel) {
157+
return this.fromLabels.includes(label);
158+
}
159+
}
160+
161+
const _LABEL_DESCRIPTIONS = new Map<number, string>([
162+
[94, "CIP-0094 - On-chain governance polls"],
163+
[674, "CIP-0020 - Transaction message/comment metadata"],
164+
[721, "CIP-0025 - NFT Token Standard"],
165+
[777, "CIP-0027 - Royalties Standard"],
166+
[867, "CIP-0088 - Token Policy Registration Standard"],
167+
[1667, "CIP-72: dApp registration & Discovery"],
168+
[3692, "CIP-0149 - Optional DRep compensation"],
169+
[61284, "CIP-0015 - Catalyst registration"],
170+
[61285, "CIP-0015 - Catalyst witness"],
171+
[61286, "CIP-0015 - Catalyst deregistration"],
172+
]);
173+
174+
/**
175+
* Describe transaction metadatum label as per
176+
* [CIP-10](https://github.com/cardano-foundation/CIPs/blob/master/CIP-0010/registry.json) standard.
177+
*
178+
* **NOTE**: Only labels associated with CIPs will be described.
179+
*
180+
* @since 2.0.0
181+
* @category utils
182+
*/
183+
export const describeTransactionMetadatumLabel = (
184+
label: TransactionMetadatumLabel,
185+
): string | undefined => {
186+
return _LABEL_DESCRIPTIONS.get(label);
187+
};
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { describe, expect, it } from "vitest";
2+
import {
3+
describeTransactionMetadatumLabel,
4+
TransactionMetadatumLabel,
5+
TransactionMetadatumLabels,
6+
} from "../src/TransactionMetadatumLabels.js";
7+
8+
describe("TransactionMetadatumLabels Validation", () => {
9+
it("should behave as expected", () => {
10+
const labels: TransactionMetadatumLabels = new TransactionMetadatumLabels({
11+
fromLabels: [],
12+
});
13+
expect(labels.size()).toStrictEqual(0);
14+
expect(labels.get(0)).toStrictEqual(undefined);
15+
16+
// Test add a label:
17+
labels.add(674);
18+
expect(labels.size()).toStrictEqual(1);
19+
expect(labels.get(0)).toStrictEqual(674);
20+
expect(labels.get(1)).toStrictEqual(undefined);
21+
22+
// Test add another label:
23+
labels.add(721);
24+
expect(labels.size()).toStrictEqual(2);
25+
expect(labels.get(0)).toStrictEqual(674);
26+
expect(labels.get(1)).toStrictEqual(721);
27+
expect(labels.get(2)).toStrictEqual(undefined);
28+
29+
// Test override labels:
30+
labels.set([61284, 61285, 61286]);
31+
expect(labels.size()).toStrictEqual(3);
32+
expect(labels.get(0)).toStrictEqual(61284);
33+
expect(labels.get(1)).toStrictEqual(61285);
34+
expect(labels.get(2)).toStrictEqual(61286);
35+
expect(labels.get(3)).toStrictEqual(undefined);
36+
37+
// Test removeFirst:
38+
labels.set([674, 721, 721, 61284, 61285, 61286, 61285]);
39+
expect(labels.size()).toStrictEqual(7);
40+
labels.removeFirst(61285);
41+
expect(labels.size()).toStrictEqual(6);
42+
expect(labels.get(4)).toStrictEqual(61286);
43+
44+
// Test removeLast:
45+
labels.set([674, 721, 721, 61284, 61285, 61286, 61285]);
46+
expect(labels.size()).toStrictEqual(7);
47+
labels.removeLast(61285);
48+
expect(labels.size()).toStrictEqual(6);
49+
expect(labels.get(4)).toStrictEqual(61285);
50+
51+
// Test removeAll:
52+
labels.set([674, 721, 721, 61284, 61285, 61286, 61285]);
53+
expect(labels.size()).toStrictEqual(7);
54+
expect(labels.has(721)).to.be.true;
55+
labels.removeAll(721);
56+
expect(labels.has(721)).to.be.false;
57+
58+
// Test removeAt:
59+
labels.set([674, 721, 721, 61284, 61285, 61286, 61285]);
60+
expect(labels.size()).toStrictEqual(7);
61+
labels.removeAt(3); // 61284
62+
expect(labels.size()).toStrictEqual(6);
63+
expect(labels.get(3)).toStrictEqual(61285);
64+
});
65+
66+
it("should describe correctly", () => {
67+
const labels: TransactionMetadatumLabel[] = [
68+
674, 721, 721, 61284, 61285, 61286, 61285,
69+
];
70+
71+
const expectedDescriptions: string[] = [
72+
"CIP-0020 - Transaction message/comment metadata",
73+
"CIP-0025 - NFT Token Standard",
74+
"CIP-0025 - NFT Token Standard",
75+
"CIP-0015 - Catalyst registration",
76+
"CIP-0015 - Catalyst witness",
77+
"CIP-0015 - Catalyst deregistration",
78+
"CIP-0015 - Catalyst witness",
79+
];
80+
81+
for (let i = 0; i < labels.length; i++) {
82+
expect(describeTransactionMetadatumLabel(labels[i])).toStrictEqual(
83+
expectedDescriptions[i],
84+
);
85+
}
86+
});
87+
});

0 commit comments

Comments
 (0)