-
Notifications
You must be signed in to change notification settings - Fork 55
/
Anchor.ts
148 lines (127 loc) · 3.65 KB
/
Anchor.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import * as Cardano from '../../Cardano';
import * as Crypto from '@cardano-sdk/crypto';
import { CborReader, CborWriter } from '../CBOR';
import { HexBlob, InvalidArgumentError } from '@cardano-sdk/util';
const EMBEDDED_GROUP_SIZE = 2;
const MAX_URL_SIZE_STR_LENGTH = 128;
/**
* An anchor is a pair of:
*
* - a URL to a JSON payload of metadata.
* - a hash of the contents of the metadata URL.
*
* The on-chain rules will not check either the URL or the hash. Client applications should,
* however, perform the usual sanity checks when fetching content from the provided URL.
*/
export class Anchor {
#url: string;
#dataHash: Crypto.Hash32ByteBase16;
#originalBytes: HexBlob | undefined = undefined;
/**
* Initializes a new instance of the Anchor class.
*
* @param url The URL to a JSON payload of metadata.
* @param dataHash The hash of the contents of the metadata URL.
*/
constructor(url: string, dataHash: Crypto.Hash32ByteBase16) {
if (url.length > MAX_URL_SIZE_STR_LENGTH)
throw new InvalidArgumentError(
'url',
`url must be less or equal to 64 characters long, actual size ${url.length}`
);
this.#url = url;
this.#dataHash = dataHash;
}
/**
* Serializes an Anchor into CBOR format.
*
* @returns The Anchor in CBOR format.
*/
toCbor(): HexBlob {
const writer = new CborWriter();
if (this.#originalBytes) return this.#originalBytes;
// CDDL
// anchor =
// [ anchor_url : url
// , anchor_data_hash : $hash32
// ]
writer.writeStartArray(EMBEDDED_GROUP_SIZE);
writer.writeTextString(this.#url);
writer.writeByteString(Buffer.from(this.#dataHash, 'hex'));
return writer.encodeAsHex();
}
/**
* Deserializes the Anchor from a CBOR byte array.
*
* @param cbor The CBOR encoded Anchor object.
* @returns The new Anchor instance.
*/
static fromCbor(cbor: HexBlob): Anchor {
const reader = new CborReader(cbor);
const length = reader.readStartArray();
if (length !== EMBEDDED_GROUP_SIZE)
throw new InvalidArgumentError(
'cbor',
`Expected an array of ${EMBEDDED_GROUP_SIZE} elements, but got an array of ${length} elements`
);
const url = reader.readTextString();
const hash = Crypto.Hash32ByteBase16(HexBlob.fromBytes(reader.readByteString()));
reader.readEndArray();
const anchor = new Anchor(url, hash);
anchor.#originalBytes = cbor;
return anchor;
}
/**
* Creates a Core Anchor object from the current Anchor object.
*
* @returns The Core Anchor object.
*/
toCore(): Cardano.Anchor {
return {
dataHash: this.#dataHash,
url: this.#url
};
}
/**
* Creates a Anchor object from the given Core Anchor object.
*
* @param anchor core Anchor object.
*/
static fromCore(anchor: Cardano.Anchor) {
return new Anchor(anchor.url, anchor.dataHash);
}
/**
* Gets the URL to a JSON payload of metadata.
*
* @returns The URL to a JSON payload of metadata.
*/
url() {
return this.#url;
}
/**
* Sets the URL to a JSON payload of metadata.
*
* @param url The URL to a JSON payload of metadata.
*/
setUrl(url: string) {
this.#url = url;
this.#originalBytes = undefined;
}
/**
* Gets the hash of the contents of the metadata URL.
*
* @returns The hash of the contents.
*/
dataHash(): Crypto.Hash32ByteBase16 {
return this.#dataHash;
}
/**
* Sets the hash of the contents of the metadata URL.
*
* @param dataHash The hash of the contents.
*/
setDataHash(dataHash: Crypto.Hash32ByteBase16) {
this.#dataHash = dataHash;
this.#originalBytes = undefined;
}
}