@xyo-network/boundwitness-builder 2.42.16
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/LICENSE +165 -0
- package/README.md +81 -0
- package/dist/cjs/Builder.d.ts +33 -0
- package/dist/cjs/Builder.d.ts.map +1 -0
- package/dist/cjs/Builder.js +104 -0
- package/dist/cjs/Builder.js.map +1 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +5 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/docs.json +1260 -0
- package/dist/esm/Builder.d.ts +33 -0
- package/dist/esm/Builder.d.ts.map +1 -0
- package/dist/esm/Builder.js +107 -0
- package/dist/esm/Builder.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -0
- package/package.json +62 -0
- package/src/Builder.spec.ts +86 -0
- package/src/Builder.ts +137 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Account } from '@xyo-network/account';
|
|
2
|
+
import { XyoBoundWitness } from '@xyo-network/boundwitness-model';
|
|
3
|
+
import { XyoPayload } from '@xyo-network/payload-model';
|
|
4
|
+
import { Logger } from '@xyo-network/shared';
|
|
5
|
+
export interface BoundWitnessBuilderConfig {
|
|
6
|
+
/** Whether or not the payloads should be included in the metadata sent to and recorded by the ArchivistApi */
|
|
7
|
+
readonly inlinePayloads?: boolean;
|
|
8
|
+
readonly meta?: boolean;
|
|
9
|
+
readonly timestamp?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare class BoundWitnessBuilder<TBoundWitness extends XyoBoundWitness<{
|
|
12
|
+
schema: string;
|
|
13
|
+
}> = XyoBoundWitness, TPayload extends XyoPayload = XyoPayload> {
|
|
14
|
+
readonly config: BoundWitnessBuilderConfig;
|
|
15
|
+
protected readonly logger?: Logger | undefined;
|
|
16
|
+
private _accounts;
|
|
17
|
+
private _payloadHashes;
|
|
18
|
+
private _payloadSchemas;
|
|
19
|
+
private _payloads;
|
|
20
|
+
private _timestamp;
|
|
21
|
+
constructor(config?: BoundWitnessBuilderConfig, logger?: Logger | undefined);
|
|
22
|
+
private get _payload_hashes();
|
|
23
|
+
private get _payload_schemas();
|
|
24
|
+
build(): [TBoundWitness, TPayload[]];
|
|
25
|
+
hashableFields(): TBoundWitness;
|
|
26
|
+
hashes(hashes: string[], schema: string[]): this;
|
|
27
|
+
payload(payload?: TPayload): this;
|
|
28
|
+
payloads(payloads?: (TPayload | null)[]): this;
|
|
29
|
+
witness(account: Account): this;
|
|
30
|
+
protected signatures(_hash: string): string[];
|
|
31
|
+
private inlinePayloads;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=Builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Builder.d.ts","sourceRoot":"","sources":["../../src/Builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAyB,MAAM,iCAAiC,CAAA;AAGxF,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAE5C,MAAM,WAAW,yBAAyB;IACxC,8GAA8G;IAC9G,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAA;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAC7B;AAED,qBAAa,mBAAmB,CAC9B,aAAa,SAAS,eAAe,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,eAAe,EAC3E,QAAQ,SAAS,UAAU,GAAG,UAAU;aAQZ,MAAM,EAAE,yBAAyB;IAA8B,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;IANrH,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,UAAU,CAAa;gBAEH,MAAM,GAAE,yBAAqD,EAAqB,MAAM,CAAC,oBAAQ;IAE7H,OAAO,KAAK,eAAe,GAO1B;IAED,OAAO,KAAK,gBAAgB,GAO3B;IAEM,KAAK,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,CAAC;IA0BpC,cAAc,IAAI,aAAa;IAuB/B,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;IAOzC,OAAO,CAAC,OAAO,CAAC,EAAE,QAAQ;IAQ1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE;IASvC,OAAO,CAAC,OAAO,EAAE,OAAO;IAK/B,SAAS,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM;IAIlC,OAAO,CAAC,cAAc;CAQvB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert';
|
|
2
|
+
import { Buffer } from '@xylabs/buffer';
|
|
3
|
+
import { XyoBoundWitnessSchema } from '@xyo-network/boundwitness-model';
|
|
4
|
+
import { BoundWitnessWrapper } from '@xyo-network/boundwitness-wrapper';
|
|
5
|
+
import { Hasher, sortFields } from '@xyo-network/core';
|
|
6
|
+
export class BoundWitnessBuilder {
|
|
7
|
+
config;
|
|
8
|
+
logger;
|
|
9
|
+
_accounts = [];
|
|
10
|
+
_payloadHashes;
|
|
11
|
+
_payloadSchemas;
|
|
12
|
+
_payloads = [];
|
|
13
|
+
_timestamp = Date.now();
|
|
14
|
+
constructor(config = { inlinePayloads: false }, logger) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
this.logger = logger;
|
|
17
|
+
}
|
|
18
|
+
get _payload_hashes() {
|
|
19
|
+
return (this._payloadHashes ??
|
|
20
|
+
this._payloads.map((payload) => {
|
|
21
|
+
return assertEx(new Hasher(payload).hash);
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
get _payload_schemas() {
|
|
25
|
+
return (this._payloadSchemas ??
|
|
26
|
+
this._payloads.map((payload) => {
|
|
27
|
+
return assertEx(payload.schema, 'Missing Schema');
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
build() {
|
|
31
|
+
const hashableFields = this.hashableFields();
|
|
32
|
+
const _hash = BoundWitnessWrapper.hash(hashableFields);
|
|
33
|
+
const ret = {
|
|
34
|
+
...hashableFields,
|
|
35
|
+
_signatures: this.signatures(_hash),
|
|
36
|
+
};
|
|
37
|
+
if (this.config?.meta ?? true) {
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
+
const bwWithMeta = ret;
|
|
40
|
+
bwWithMeta._client = 'js';
|
|
41
|
+
bwWithMeta._hash = _hash;
|
|
42
|
+
bwWithMeta._timestamp = this._timestamp;
|
|
43
|
+
}
|
|
44
|
+
if (this.config.inlinePayloads) {
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
46
|
+
const anyRet = ret;
|
|
47
|
+
//leaving this in here to prevent breaking code (for now)
|
|
48
|
+
anyRet._payloads = this.inlinePayloads();
|
|
49
|
+
}
|
|
50
|
+
return [ret, this._payloads];
|
|
51
|
+
}
|
|
52
|
+
hashableFields() {
|
|
53
|
+
const addresses = this._accounts.map((account) => account.addressValue.hex);
|
|
54
|
+
const previous_hashes = this._accounts.map((account) => account.previousHash?.hex ?? null);
|
|
55
|
+
const result = {
|
|
56
|
+
addresses: assertEx(addresses, 'Missing addresses'),
|
|
57
|
+
payload_hashes: assertEx(this._payload_hashes, 'Missing payload_hashes'),
|
|
58
|
+
payload_schemas: assertEx(this._payload_schemas, 'Missing payload_schemas'),
|
|
59
|
+
previous_hashes,
|
|
60
|
+
schema: XyoBoundWitnessSchema,
|
|
61
|
+
};
|
|
62
|
+
assertEx(result.payload_hashes?.length === result.payload_schemas?.length, 'Payload hash/schema mismatch');
|
|
63
|
+
assertEx(!result.payload_hashes.reduce((inValid, hash) => inValid || !hash, false), 'nulls found in hashes');
|
|
64
|
+
assertEx(!result.payload_schemas.reduce((inValid, schema) => inValid || !schema, false), 'nulls found in schemas');
|
|
65
|
+
if (this.config.timestamp ?? true) {
|
|
66
|
+
result.timestamp = this._timestamp;
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
hashes(hashes, schema) {
|
|
71
|
+
assertEx(this.payloads.length === 0, 'Can not set hashes when payloads already set');
|
|
72
|
+
this._payloadHashes = hashes;
|
|
73
|
+
this._payloadSchemas = schema;
|
|
74
|
+
return this;
|
|
75
|
+
}
|
|
76
|
+
payload(payload) {
|
|
77
|
+
assertEx(this._payloadHashes === undefined, 'Can not set payloads when hashes already set');
|
|
78
|
+
if (payload) {
|
|
79
|
+
this._payloads.push(assertEx(sortFields(payload)));
|
|
80
|
+
}
|
|
81
|
+
return this;
|
|
82
|
+
}
|
|
83
|
+
payloads(payloads) {
|
|
84
|
+
payloads?.forEach((payload) => {
|
|
85
|
+
if (payload !== null) {
|
|
86
|
+
this.payload(payload);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
witness(account) {
|
|
92
|
+
this._accounts?.push(account);
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
signatures(_hash) {
|
|
96
|
+
return this._accounts.map((account) => Buffer.from(account.sign(Buffer.from(_hash, 'hex'))).toString('hex'));
|
|
97
|
+
}
|
|
98
|
+
inlinePayloads() {
|
|
99
|
+
return this._payloads.map((payload, index) => {
|
|
100
|
+
return {
|
|
101
|
+
...payload,
|
|
102
|
+
schema: this._payload_schemas[index],
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=Builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Builder.js","sourceRoot":"","sources":["../../src/Builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAEvC,OAAO,EAAmB,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACxF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AACvE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAWtD,MAAM,OAAO,mBAAmB;IAUF;IAAkF;IANtG,SAAS,GAAc,EAAE,CAAA;IACzB,cAAc,CAAsB;IACpC,eAAe,CAAsB;IACrC,SAAS,GAAe,EAAE,CAAA;IAC1B,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAE/B,YAA4B,SAAoC,EAAE,cAAc,EAAE,KAAK,EAAE,EAAqB,MAAe;QAAjG,WAAM,GAAN,MAAM,CAAuD;QAAqB,WAAM,GAAN,MAAM,CAAS;IAAG,CAAC;IAEjI,IAAY,eAAe;QACzB,OAAO,CACL,IAAI,CAAC,cAAc;YACnB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,OAAO,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAA;YAC3C,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAED,IAAY,gBAAgB;QAC1B,OAAO,CACL,IAAI,CAAC,eAAe;YACpB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC7B,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;YACnD,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAEM,KAAK;QACV,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;QAC5C,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QAEtD,MAAM,GAAG,GAAkB;YACzB,GAAG,cAAc;YACjB,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;SACpC,CAAA;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI,EAAE;YAC7B,8DAA8D;YAC9D,MAAM,UAAU,GAAG,GAAU,CAAA;YAC7B,UAAU,CAAC,OAAO,GAAG,IAAI,CAAA;YACzB,UAAU,CAAC,KAAK,GAAG,KAAK,CAAA;YACxB,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAA;SACxC;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE;YAC9B,8DAA8D;YAC9D,MAAM,MAAM,GAAG,GAAU,CAAA;YACzB,yDAAyD;YACzD,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;SACzC;QACD,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IAC9B,CAAC;IAEM,cAAc;QACnB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;QAC3E,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,IAAI,IAAI,CAAC,CAAA;QAC1F,MAAM,MAAM,GAAkB;YAC5B,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC;YACnD,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,wBAAwB,CAAC;YACxE,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,yBAAyB,CAAC;YAC3E,eAAe;YACf,MAAM,EAAE,qBAAqB;SACb,CAAA;QAElB,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,KAAK,MAAM,CAAC,eAAe,EAAE,MAAM,EAAE,8BAA8B,CAAC,CAAA;QAE1G,QAAQ,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,uBAAuB,CAAC,CAAA;QAE5G,QAAQ,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,wBAAwB,CAAC,CAAA;QAElH,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,IAAI,EAAE;YACjC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,UAAU,CAAA;SACnC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAEM,MAAM,CAAC,MAAgB,EAAE,MAAgB;QAC9C,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,8CAA8C,CAAC,CAAA;QACpF,IAAI,CAAC,cAAc,GAAG,MAAM,CAAA;QAC5B,IAAI,CAAC,eAAe,GAAG,MAAM,CAAA;QAC7B,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,OAAO,CAAC,OAAkB;QAC/B,QAAQ,CAAC,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,8CAA8C,CAAC,CAAA;QAC3F,IAAI,OAAO,EAAE;YACX,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAW,OAAO,CAAC,CAAC,CAAC,CAAA;SAC7D;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,QAAQ,CAAC,QAA8B;QAC5C,QAAQ,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC5B,IAAI,OAAO,KAAK,IAAI,EAAE;gBACpB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;aACtB;QACH,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,OAAO,CAAC,OAAgB;QAC7B,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QAC7B,OAAO,IAAI,CAAA;IACb,CAAC;IAES,UAAU,CAAC,KAAa;QAChC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;IAC9G,CAAC;IAEO,cAAc;QACpB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAW,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;YACrD,OAAO;gBACL,GAAG,OAAO;gBACV,MAAM,EAAE,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;aACrC,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xyo-network/boundwitness-builder",
|
|
3
|
+
"author": {
|
|
4
|
+
"email": "support@xyo.network",
|
|
5
|
+
"name": "XYO Development Team",
|
|
6
|
+
"url": "https://xyo.network"
|
|
7
|
+
},
|
|
8
|
+
"bugs": {
|
|
9
|
+
"email": "support@xyo.network",
|
|
10
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/issues"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@xylabs/assert": "^2.6.12",
|
|
14
|
+
"@xylabs/buffer": "^2.6.12",
|
|
15
|
+
"@xyo-network/account": "^2.42.16",
|
|
16
|
+
"@xyo-network/boundwitness-model": "^2.42.16",
|
|
17
|
+
"@xyo-network/boundwitness-wrapper": "^2.42.16",
|
|
18
|
+
"@xyo-network/core": "^2.42.16",
|
|
19
|
+
"@xyo-network/payload-model": "^2.42.15",
|
|
20
|
+
"@xyo-network/shared": "^2.42.16"
|
|
21
|
+
},
|
|
22
|
+
"description": "Primary SDK for using XYO Protocol 2.0",
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@xylabs/ts-scripts-yarn3": "^2.10.25"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"axios": "^1.2.1"
|
|
28
|
+
},
|
|
29
|
+
"browser": "dist/esm/index.js",
|
|
30
|
+
"docs": "dist/docs.json",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"node": {
|
|
34
|
+
"import": "./dist/esm/index.js",
|
|
35
|
+
"require": "./dist/cjs/index.js"
|
|
36
|
+
},
|
|
37
|
+
"browser": {
|
|
38
|
+
"import": "./dist/esm/index.js",
|
|
39
|
+
"require": "./dist/cjs/index.js"
|
|
40
|
+
},
|
|
41
|
+
"default": "./dist/esm/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./dist/docs.json": {
|
|
44
|
+
"default": "./dist/docs.json"
|
|
45
|
+
},
|
|
46
|
+
"./package.json": "./package.json"
|
|
47
|
+
},
|
|
48
|
+
"main": "dist/cjs/index.js",
|
|
49
|
+
"module": "dist/esm/index.js",
|
|
50
|
+
"homepage": "https://xyo.network",
|
|
51
|
+
"license": "LGPL-3.0-only",
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
|
|
58
|
+
},
|
|
59
|
+
"sideEffects": false,
|
|
60
|
+
"types": "dist/esm/index.d.ts",
|
|
61
|
+
"version": "2.42.16"
|
|
62
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
2
|
+
/* eslint-disable sort-keys */
|
|
3
|
+
|
|
4
|
+
import { Account, AddressValue } from '@xyo-network/account'
|
|
5
|
+
import { Hasher, StringKeyObject } from '@xyo-network/core'
|
|
6
|
+
import { XyoPayload } from '@xyo-network/payload-model'
|
|
7
|
+
|
|
8
|
+
import { BoundWitnessBuilder } from './Builder'
|
|
9
|
+
|
|
10
|
+
const schema = 'network.xyo.temp'
|
|
11
|
+
const payload1: XyoPayload<StringKeyObject & { schema: string }> = {
|
|
12
|
+
number_field: 1,
|
|
13
|
+
object_field: {
|
|
14
|
+
number_value: 2,
|
|
15
|
+
string_value: 'yo',
|
|
16
|
+
},
|
|
17
|
+
schema,
|
|
18
|
+
string_field: 'there',
|
|
19
|
+
timestamp: 1618603439107,
|
|
20
|
+
}
|
|
21
|
+
const payload2: XyoPayload<StringKeyObject & { schema: string }> = {
|
|
22
|
+
timestamp: 1618603439107,
|
|
23
|
+
string_field: 'there',
|
|
24
|
+
schema,
|
|
25
|
+
object_field: {
|
|
26
|
+
string_value: 'yo',
|
|
27
|
+
number_value: 2,
|
|
28
|
+
},
|
|
29
|
+
number_field: 1,
|
|
30
|
+
}
|
|
31
|
+
const payloads = [payload1, payload2]
|
|
32
|
+
const payloadHash = '3c817871cbf24708703e907dbc344b1b2aefcc3603d14d59c3a35a5c446410d1'
|
|
33
|
+
|
|
34
|
+
describe('BoundWitnessBuilder', () => {
|
|
35
|
+
describe('hash', () => {
|
|
36
|
+
it.each(payloads)('consistently hashes equivalent payload independent of the order of the keys', (payload) => {
|
|
37
|
+
const hash = new Hasher(payload).hash
|
|
38
|
+
expect(hash).toEqual(payloadHash)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
describe('build', () => {
|
|
42
|
+
describe('_hash', () => {
|
|
43
|
+
it.each(payloads)('consistently hashes equivalent payloads independent of the order of the keys', (payload) => {
|
|
44
|
+
const address = Account.fromPhrase('test1')
|
|
45
|
+
let builder = new BoundWitnessBuilder({ timestamp: false })
|
|
46
|
+
expect(builder).toBeDefined()
|
|
47
|
+
builder = builder.witness(address)
|
|
48
|
+
expect(builder).toBeDefined()
|
|
49
|
+
builder = builder.payload(payload)
|
|
50
|
+
expect(builder).toBeDefined()
|
|
51
|
+
|
|
52
|
+
const [actual] = builder.build()
|
|
53
|
+
|
|
54
|
+
expect(actual).toBeDefined()
|
|
55
|
+
expect(Hasher.hash(actual)).toEqual('7f3203f2d191f12c26cd1aec62b718be8848471f82831a8870f82fc669a5f35b')
|
|
56
|
+
|
|
57
|
+
if (actual._signatures) {
|
|
58
|
+
const addr = new AddressValue(actual.addresses[0])
|
|
59
|
+
expect(addr.hex).toBe(actual.addresses[0])
|
|
60
|
+
const verify = new AddressValue(actual.addresses[0]).verify(Hasher.hash(actual), actual._signatures[0])
|
|
61
|
+
expect(verify).toBe(true)
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
describe('with inlinePayloads true', () => {
|
|
66
|
+
it('contains the _payloads field', () => {
|
|
67
|
+
const address = Account.fromPhrase('test2')
|
|
68
|
+
const builder = new BoundWitnessBuilder({ inlinePayloads: true }).witness(address).payload(payload1)
|
|
69
|
+
|
|
70
|
+
const [actual] = builder.build()
|
|
71
|
+
|
|
72
|
+
expect(actual).toBeDefined()
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
describe('with inlinePayloads false', () => {
|
|
76
|
+
it('omits the _payloads field', () => {
|
|
77
|
+
const address = Account.fromPhrase('test3')
|
|
78
|
+
const builder = new BoundWitnessBuilder({ inlinePayloads: false }).witness(address).payload(payload1)
|
|
79
|
+
|
|
80
|
+
const [actual] = builder.build()
|
|
81
|
+
|
|
82
|
+
expect(actual).toBeDefined()
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
})
|
package/src/Builder.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { assertEx } from '@xylabs/assert'
|
|
2
|
+
import { Buffer } from '@xylabs/buffer'
|
|
3
|
+
import { Account } from '@xyo-network/account'
|
|
4
|
+
import { XyoBoundWitness, XyoBoundWitnessSchema } from '@xyo-network/boundwitness-model'
|
|
5
|
+
import { BoundWitnessWrapper } from '@xyo-network/boundwitness-wrapper'
|
|
6
|
+
import { Hasher, sortFields } from '@xyo-network/core'
|
|
7
|
+
import { XyoPayload } from '@xyo-network/payload-model'
|
|
8
|
+
import { Logger } from '@xyo-network/shared'
|
|
9
|
+
|
|
10
|
+
export interface BoundWitnessBuilderConfig {
|
|
11
|
+
/** Whether or not the payloads should be included in the metadata sent to and recorded by the ArchivistApi */
|
|
12
|
+
readonly inlinePayloads?: boolean
|
|
13
|
+
readonly meta?: boolean
|
|
14
|
+
readonly timestamp?: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class BoundWitnessBuilder<
|
|
18
|
+
TBoundWitness extends XyoBoundWitness<{ schema: string }> = XyoBoundWitness,
|
|
19
|
+
TPayload extends XyoPayload = XyoPayload,
|
|
20
|
+
> {
|
|
21
|
+
private _accounts: Account[] = []
|
|
22
|
+
private _payloadHashes: string[] | undefined
|
|
23
|
+
private _payloadSchemas: string[] | undefined
|
|
24
|
+
private _payloads: TPayload[] = []
|
|
25
|
+
private _timestamp = Date.now()
|
|
26
|
+
|
|
27
|
+
constructor(public readonly config: BoundWitnessBuilderConfig = { inlinePayloads: false }, protected readonly logger?: Logger) {}
|
|
28
|
+
|
|
29
|
+
private get _payload_hashes(): string[] {
|
|
30
|
+
return (
|
|
31
|
+
this._payloadHashes ??
|
|
32
|
+
this._payloads.map((payload) => {
|
|
33
|
+
return assertEx(new Hasher(payload).hash)
|
|
34
|
+
})
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private get _payload_schemas(): string[] {
|
|
39
|
+
return (
|
|
40
|
+
this._payloadSchemas ??
|
|
41
|
+
this._payloads.map((payload) => {
|
|
42
|
+
return assertEx(payload.schema, 'Missing Schema')
|
|
43
|
+
})
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public build(): [TBoundWitness, TPayload[]] {
|
|
48
|
+
const hashableFields = this.hashableFields()
|
|
49
|
+
const _hash = BoundWitnessWrapper.hash(hashableFields)
|
|
50
|
+
|
|
51
|
+
const ret: TBoundWitness = {
|
|
52
|
+
...hashableFields,
|
|
53
|
+
_signatures: this.signatures(_hash),
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (this.config?.meta ?? true) {
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
58
|
+
const bwWithMeta = ret as any
|
|
59
|
+
bwWithMeta._client = 'js'
|
|
60
|
+
bwWithMeta._hash = _hash
|
|
61
|
+
bwWithMeta._timestamp = this._timestamp
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (this.config.inlinePayloads) {
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
66
|
+
const anyRet = ret as any
|
|
67
|
+
//leaving this in here to prevent breaking code (for now)
|
|
68
|
+
anyRet._payloads = this.inlinePayloads()
|
|
69
|
+
}
|
|
70
|
+
return [ret, this._payloads]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public hashableFields(): TBoundWitness {
|
|
74
|
+
const addresses = this._accounts.map((account) => account.addressValue.hex)
|
|
75
|
+
const previous_hashes = this._accounts.map((account) => account.previousHash?.hex ?? null)
|
|
76
|
+
const result: TBoundWitness = {
|
|
77
|
+
addresses: assertEx(addresses, 'Missing addresses'),
|
|
78
|
+
payload_hashes: assertEx(this._payload_hashes, 'Missing payload_hashes'),
|
|
79
|
+
payload_schemas: assertEx(this._payload_schemas, 'Missing payload_schemas'),
|
|
80
|
+
previous_hashes,
|
|
81
|
+
schema: XyoBoundWitnessSchema,
|
|
82
|
+
} as TBoundWitness
|
|
83
|
+
|
|
84
|
+
assertEx(result.payload_hashes?.length === result.payload_schemas?.length, 'Payload hash/schema mismatch')
|
|
85
|
+
|
|
86
|
+
assertEx(!result.payload_hashes.reduce((inValid, hash) => inValid || !hash, false), 'nulls found in hashes')
|
|
87
|
+
|
|
88
|
+
assertEx(!result.payload_schemas.reduce((inValid, schema) => inValid || !schema, false), 'nulls found in schemas')
|
|
89
|
+
|
|
90
|
+
if (this.config.timestamp ?? true) {
|
|
91
|
+
result.timestamp = this._timestamp
|
|
92
|
+
}
|
|
93
|
+
return result
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public hashes(hashes: string[], schema: string[]) {
|
|
97
|
+
assertEx(this.payloads.length === 0, 'Can not set hashes when payloads already set')
|
|
98
|
+
this._payloadHashes = hashes
|
|
99
|
+
this._payloadSchemas = schema
|
|
100
|
+
return this
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public payload(payload?: TPayload) {
|
|
104
|
+
assertEx(this._payloadHashes === undefined, 'Can not set payloads when hashes already set')
|
|
105
|
+
if (payload) {
|
|
106
|
+
this._payloads.push(assertEx(sortFields<TPayload>(payload)))
|
|
107
|
+
}
|
|
108
|
+
return this
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public payloads(payloads?: (TPayload | null)[]) {
|
|
112
|
+
payloads?.forEach((payload) => {
|
|
113
|
+
if (payload !== null) {
|
|
114
|
+
this.payload(payload)
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
return this
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public witness(account: Account) {
|
|
121
|
+
this._accounts?.push(account)
|
|
122
|
+
return this
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
protected signatures(_hash: string) {
|
|
126
|
+
return this._accounts.map((account) => Buffer.from(account.sign(Buffer.from(_hash, 'hex'))).toString('hex'))
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private inlinePayloads() {
|
|
130
|
+
return this._payloads.map<TPayload>((payload, index) => {
|
|
131
|
+
return {
|
|
132
|
+
...payload,
|
|
133
|
+
schema: this._payload_schemas[index],
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Builder'
|