forked from Irys-xyz/bundles
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathar-data-bundle.ts
85 lines (76 loc) · 2.49 KB
/
ar-data-bundle.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
import getSignatureData from "./ar-data-base";
import { longTo32ByteArray } from "./utils";
import type DataItem from "./DataItem";
import Bundle from "./Bundle";
import type { Signer } from "./signing/Signer";
import { getCryptoDriver } from "$/utils";
/**
* Unbundles a transaction into an Array of DataItems.
*
* Takes either a json string or object. Will throw if given an invalid json
* string but otherwise, it will return an empty array if
*
* a) the json object is the wrong format
* b) the object contains no valid DataItems.
*
* It will verify all DataItems and discard ones that don't pass verification.
*
* @param txData
*/
export function unbundleData(txData: Buffer): Bundle {
return new Bundle(txData);
}
/**
* Verifies all data items and returns a json object with an items array.
* Throws if any of the data items fail verification.
*
* @param dataItems
* @param signer
*/
export async function bundleAndSignData(dataItems: DataItem[], signer: Signer): Promise<Bundle> {
const headers = new Uint8Array(64 * dataItems.length);
const binaries = await Promise.all(
dataItems.map(async (d, index) => {
// Sign DataItem
const rawId = d.isSigned() ? d.rawId : await sign(d, signer);
// Create header array
const header = new Uint8Array(64);
// Set offset
header.set(longTo32ByteArray(d.getRaw().byteLength), 0);
// Set id
header.set(rawId, 32);
// Add header to array of headers
headers.set(header, 64 * index);
// Convert to array for flattening
return d.getRaw();
}),
).then((a) => {
return Buffer.concat(a);
});
const buffer = Buffer.concat([Buffer.from(longTo32ByteArray(dataItems.length)), Buffer.from(headers), binaries]);
return new Bundle(buffer);
}
/**
* Signs a single
*
* @param item
* @param signer
* @returns signings - signature and id in byte-arrays
*/
export async function getSignatureAndId(item: DataItem, signer: Signer): Promise<{ signature: Buffer; id: Buffer }> {
const signatureData = await getSignatureData(item);
const signatureBytes = await signer.sign(signatureData);
const idBytes = await getCryptoDriver().hash(signatureBytes);
return { signature: Buffer.from(signatureBytes), id: Buffer.from(idBytes) };
}
/**
* Signs and returns item id
*
* @param item
* @param jwk
*/
export async function sign(item: DataItem, signer: Signer): Promise<Buffer> {
const { signature, id } = await getSignatureAndId(item, signer);
item.getRaw().set(signature, 2);
return id;
}