@xyo-network/payload-builder 4.3.0 → 5.0.0
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/package.json +16 -12
- package/src/spec/Builder.spec.ts +172 -0
- package/src/spec/ObjectHasher.toMap.spec.ts +98 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xyo-network/payload-builder",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "Primary SDK for using XYO Protocol 2.0",
|
|
5
5
|
"homepage": "https://xyo.network",
|
|
6
6
|
"bugs": {
|
|
@@ -28,20 +28,24 @@
|
|
|
28
28
|
},
|
|
29
29
|
"module": "dist/neutral/index.mjs",
|
|
30
30
|
"types": "dist/neutral/index.d.ts",
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"src"
|
|
34
|
+
],
|
|
31
35
|
"dependencies": {
|
|
32
|
-
"@xylabs/assert": "^
|
|
33
|
-
"@xylabs/exists": "^
|
|
34
|
-
"@xylabs/hex": "^
|
|
35
|
-
"@xylabs/logger": "^
|
|
36
|
-
"@xylabs/object": "^
|
|
37
|
-
"@xylabs/promise": "^
|
|
38
|
-
"@xyo-network/hash": "^
|
|
39
|
-
"@xyo-network/payload-model": "^
|
|
36
|
+
"@xylabs/assert": "^5.0.0",
|
|
37
|
+
"@xylabs/exists": "^5.0.0",
|
|
38
|
+
"@xylabs/hex": "^5.0.0",
|
|
39
|
+
"@xylabs/logger": "^5.0.0",
|
|
40
|
+
"@xylabs/object": "^5.0.0",
|
|
41
|
+
"@xylabs/promise": "^5.0.0",
|
|
42
|
+
"@xyo-network/hash": "^5.0.0",
|
|
43
|
+
"@xyo-network/payload-model": "^5.0.0"
|
|
40
44
|
},
|
|
41
45
|
"devDependencies": {
|
|
42
|
-
"@xylabs/ts-scripts-yarn3": "^7.0.
|
|
43
|
-
"@xylabs/tsconfig": "^7.0.
|
|
44
|
-
"@xylabs/vitest-extended": "^
|
|
46
|
+
"@xylabs/ts-scripts-yarn3": "^7.0.2",
|
|
47
|
+
"@xylabs/tsconfig": "^7.0.2",
|
|
48
|
+
"@xylabs/vitest-extended": "^5.0.0",
|
|
45
49
|
"typescript": "^5.8.3",
|
|
46
50
|
"vitest": "^3.2.4"
|
|
47
51
|
},
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { Payload } from '@xyo-network/payload-model'
|
|
2
|
+
|
|
3
|
+
import { PayloadBuilder } from '../Builder.ts'
|
|
4
|
+
|
|
5
|
+
const schema = 'network.xyo.temp'
|
|
6
|
+
|
|
7
|
+
import '@xylabs/vitest-extended'
|
|
8
|
+
|
|
9
|
+
import { ObjectHasher } from '@xyo-network/hash'
|
|
10
|
+
import {
|
|
11
|
+
describe, expect, test,
|
|
12
|
+
} from 'vitest'
|
|
13
|
+
|
|
14
|
+
describe('PayloadBuilder', () => {
|
|
15
|
+
test('build', () => {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
let builder = new PayloadBuilder<any>({ schema })
|
|
18
|
+
expect(builder).toBeDefined()
|
|
19
|
+
builder = builder.fields({
|
|
20
|
+
_testUnderscore: 1,
|
|
21
|
+
testArray: [1, 2, 3],
|
|
22
|
+
testBoolean: true,
|
|
23
|
+
testDollarObject: { $test: 1 },
|
|
24
|
+
testDollarObjectInArray: [{ $test: 1 }],
|
|
25
|
+
testNull: null,
|
|
26
|
+
testNullObject: { t: null, x: undefined },
|
|
27
|
+
testNumber: 5,
|
|
28
|
+
testObject: { t: 1 },
|
|
29
|
+
testSomeNullObject: {
|
|
30
|
+
s: 1, t: null, x: undefined,
|
|
31
|
+
},
|
|
32
|
+
testString: 'hi',
|
|
33
|
+
testUndefined: undefined,
|
|
34
|
+
testUnderscoreObject: { _test: 1 },
|
|
35
|
+
testUnderscoreObjectInArray: [{ _test: 1 }],
|
|
36
|
+
}).meta({ $testDollar: 1 })
|
|
37
|
+
expect(builder).toBeDefined()
|
|
38
|
+
|
|
39
|
+
const actual = builder.build()
|
|
40
|
+
|
|
41
|
+
expect(actual).toBeDefined()
|
|
42
|
+
expect(actual._timestamp).toBeUndefined()
|
|
43
|
+
expect(actual._client).toBeUndefined()
|
|
44
|
+
expect(actual._hash).toBeUndefined()
|
|
45
|
+
expect(actual._testUnderscore).toBeUndefined()
|
|
46
|
+
expect(actual.$testDollar).toBeDefined()
|
|
47
|
+
expect(actual.schema).toBeDefined()
|
|
48
|
+
expect(Object.keys(actual).length).toBeGreaterThan(1)
|
|
49
|
+
expect(Object.keys(actual.testSomeNullObject as object).length).toBe(2)
|
|
50
|
+
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
|
+
expect((actual as any).testUnderscoreObject._test).toBeDefined()
|
|
53
|
+
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
+
expect((actual as any).testUnderscoreObjectInArray[0]._test).toBeDefined()
|
|
56
|
+
|
|
57
|
+
// TODO: Determine how we want to handle nested meta
|
|
58
|
+
// expect((actual as any).testDollarObject.$test).toBeDefined()
|
|
59
|
+
|
|
60
|
+
// expect((actual as any).testDollarObjectInArray[0].$test).toBeDefined()
|
|
61
|
+
|
|
62
|
+
let builderNoStamp = new PayloadBuilder<Payload<Record<string, unknown>>>({ schema })
|
|
63
|
+
expect(builderNoStamp).toBeDefined()
|
|
64
|
+
builderNoStamp = builderNoStamp.fields({
|
|
65
|
+
testArray: [1, 2, 3],
|
|
66
|
+
testBoolean: true,
|
|
67
|
+
testNull: null,
|
|
68
|
+
testNullObject: { t: null, x: undefined },
|
|
69
|
+
testNumber: 5,
|
|
70
|
+
testObject: { t: 1 },
|
|
71
|
+
testSomeNullObject: {
|
|
72
|
+
s: 1, t: null, x: undefined,
|
|
73
|
+
},
|
|
74
|
+
testString: 'hi',
|
|
75
|
+
testUndefined: undefined,
|
|
76
|
+
})
|
|
77
|
+
expect(builderNoStamp).toBeDefined()
|
|
78
|
+
|
|
79
|
+
const actualNoStamp = builderNoStamp.build()
|
|
80
|
+
|
|
81
|
+
expect(actualNoStamp).toBeDefined()
|
|
82
|
+
expect(actualNoStamp._timestamp).toBeUndefined()
|
|
83
|
+
expect(actualNoStamp._client).toBeUndefined()
|
|
84
|
+
expect(actualNoStamp._hash).toBeUndefined()
|
|
85
|
+
expect(actualNoStamp.schema).toBeDefined()
|
|
86
|
+
expect(Object.keys(actualNoStamp).length).toBeGreaterThan(1)
|
|
87
|
+
expect(Object.keys(actualNoStamp.testSomeNullObject as object).length).toBe(2)
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
describe('PayloadBuilder', () => {
|
|
92
|
+
test('hash', async () => {
|
|
93
|
+
const value = {
|
|
94
|
+
$meta_field: 'yo',
|
|
95
|
+
currentLocation: {
|
|
96
|
+
coords: {
|
|
97
|
+
accuracy: 5,
|
|
98
|
+
altitude: 15,
|
|
99
|
+
altitudeAccuracy: 15,
|
|
100
|
+
heading: 90,
|
|
101
|
+
latitude: 37.7749,
|
|
102
|
+
longitude: -122.4194,
|
|
103
|
+
speed: 2.5,
|
|
104
|
+
},
|
|
105
|
+
timestamp: 1_609_459_200_000,
|
|
106
|
+
},
|
|
107
|
+
schema: 'network.xyo.location.current',
|
|
108
|
+
}
|
|
109
|
+
const dh = await PayloadBuilder.dataHash(value)
|
|
110
|
+
const h = await PayloadBuilder.hash(value)
|
|
111
|
+
expect(dh).toBe('0c1f0c80481b0f391a677eab542a594a192081325b6416acc3dc99db23355ee2')
|
|
112
|
+
expect(h).toBe('d1685b23bbc87c0260620fa6ff3581ffd48574bd326cb472425d4db787af487f')
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
describe('PayloadBuilder', () => {
|
|
117
|
+
test('hash', async () => {
|
|
118
|
+
const value = {
|
|
119
|
+
$hash: '6f731b3956114fd0d18820dbbe1116f9e36dc8d803b0bb049302f7109037468f',
|
|
120
|
+
$meta: {
|
|
121
|
+
client: 'ios',
|
|
122
|
+
signatures: ['fad86c98252b937a65be61f2307ce6d427a08425b4aee1c90fea0b446e9c862f46b6a36fea69450f83dadf9a2409c4f9ddc2e39a3dc222ae06f81b19eb2a17e6'],
|
|
123
|
+
},
|
|
124
|
+
addresses: ['e3b3bb3cdc49e13f9ac5f48d52915368de43afec'],
|
|
125
|
+
payload_hashes: ['c915c56dd93b5e0db509d1a63ca540cfb211e11f03039b05e19712267bb8b6db'],
|
|
126
|
+
payload_schemas: ['network.xyo.test'],
|
|
127
|
+
previous_hashes: [null],
|
|
128
|
+
schema: 'network.xyo.boundwitness',
|
|
129
|
+
}
|
|
130
|
+
const value2 = {
|
|
131
|
+
addresses: ['e3b3bb3cdc49e13f9ac5f48d52915368de43afec'],
|
|
132
|
+
payload_hashes: ['c915c56dd93b5e0db509d1a63ca540cfb211e11f03039b05e19712267bb8b6db'],
|
|
133
|
+
payload_schemas: ['network.xyo.test'],
|
|
134
|
+
previous_hashes: [null],
|
|
135
|
+
schema: 'network.xyo.boundwitness',
|
|
136
|
+
}
|
|
137
|
+
console.log('payload', PayloadBuilder.omitMeta(value))
|
|
138
|
+
const dh = await PayloadBuilder.dataHash(value)
|
|
139
|
+
const dh2 = await PayloadBuilder.dataHash(value2)
|
|
140
|
+
const h = await PayloadBuilder.hash(value)
|
|
141
|
+
expect(dh).toBe(dh2)
|
|
142
|
+
expect(dh).toBe('6f731b3956114fd0d18820dbbe1116f9e36dc8d803b0bb049302f7109037468f')
|
|
143
|
+
expect(h).toBe('c267291c8169e428aaedbbf52792f9378ee03910401ef882b653a75f85370722')
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
describe('temp', () => {
|
|
148
|
+
test('kotlin-data-hash', async () => {
|
|
149
|
+
const payload = {
|
|
150
|
+
$meta: {
|
|
151
|
+
client: 'android',
|
|
152
|
+
signatures: ['493178d0b896818e2185ca424738cd6d4cac94990af9c1a238c02e51baa387b3354058c32ef0e601c8e6201ff677bf97885169140e6e36778dc41ecd6bf362d7'],
|
|
153
|
+
},
|
|
154
|
+
addresses: ['9858effd232b4033e47d90003d41ec34ecaeda94'],
|
|
155
|
+
payload_hashes: ['4ca087085f26a7c3961b450457a8e44307f331ecf2580bb952fdacdcb7be4cd7'],
|
|
156
|
+
payload_schemas: ['network.xyo.test'],
|
|
157
|
+
previous_hashes: [null],
|
|
158
|
+
schema: 'network.xyo.boundwitness',
|
|
159
|
+
}
|
|
160
|
+
const payload2String = ObjectHasher.stringifyHashFields(payload)
|
|
161
|
+
const enc = new TextEncoder()
|
|
162
|
+
const data = enc.encode(payload2String)
|
|
163
|
+
var total = 0
|
|
164
|
+
for (const datum of data) {
|
|
165
|
+
total += datum
|
|
166
|
+
}
|
|
167
|
+
console.log('total', total)
|
|
168
|
+
console.log('len', data.length)
|
|
169
|
+
const hash2 = await ObjectHasher.hash(payload)
|
|
170
|
+
expect(hash2).toBe('79f9ff8083f5b1dde361d48b583821bd2b78723a29b422c8d6aefaed5bcba981')
|
|
171
|
+
})
|
|
172
|
+
})
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import '@xylabs/vitest-extended'
|
|
2
|
+
|
|
3
|
+
import type { AnyObject } from '@xylabs/object'
|
|
4
|
+
import { ObjectHasher } from '@xyo-network/hash'
|
|
5
|
+
import type { Payload } from '@xyo-network/payload-model'
|
|
6
|
+
import {
|
|
7
|
+
beforeAll,
|
|
8
|
+
describe, expect, it,
|
|
9
|
+
} from 'vitest'
|
|
10
|
+
|
|
11
|
+
import { PayloadBuilder } from '../Builder.ts'
|
|
12
|
+
|
|
13
|
+
describe('PayloadBuilder', () => {
|
|
14
|
+
const testObject = {
|
|
15
|
+
schema: 'network.xyo.test',
|
|
16
|
+
testArray: [1, 2, 3],
|
|
17
|
+
testBoolean: true,
|
|
18
|
+
testNull: null,
|
|
19
|
+
testNullObject: { t: null, x: null },
|
|
20
|
+
testNumber: 5,
|
|
21
|
+
testObject: { t: 1 },
|
|
22
|
+
testSomeNullObject: {
|
|
23
|
+
s: 1, t: null, x: null,
|
|
24
|
+
},
|
|
25
|
+
testString: 'hello there. this is a pretty long string. what do you think?',
|
|
26
|
+
}
|
|
27
|
+
const bigObject = {
|
|
28
|
+
schema: 'network.xyo.test',
|
|
29
|
+
testArray: [1, 2, 3],
|
|
30
|
+
testBoolean: true,
|
|
31
|
+
testNull: null,
|
|
32
|
+
testNullObject: { t: null, x: null },
|
|
33
|
+
testNumber: 5,
|
|
34
|
+
testObjArray: [testObject],
|
|
35
|
+
testObject: { t: 1 },
|
|
36
|
+
testSomeNullObject: { s: 1, t: null },
|
|
37
|
+
testString: 'hello there. this is a pretty long string. what do you think?',
|
|
38
|
+
}
|
|
39
|
+
for (let i = 0; i < 1000; i++) {
|
|
40
|
+
bigObject.testObjArray.push(testObject)
|
|
41
|
+
}
|
|
42
|
+
const cases: [string, Payload<AnyObject>[]][] = [
|
|
43
|
+
[
|
|
44
|
+
'Hashes input payloads to a map',
|
|
45
|
+
[
|
|
46
|
+
{ a: 0, schema: 'network.xyo.test.a' },
|
|
47
|
+
{ b: 1, schema: 'network.xyo.test.b' },
|
|
48
|
+
] satisfies Payload<AnyObject>[],
|
|
49
|
+
],
|
|
50
|
+
[
|
|
51
|
+
'Preserves ordering of input payloads when creating object keys',
|
|
52
|
+
[
|
|
53
|
+
{ a: 0, schema: 'network.xyo.test.a' },
|
|
54
|
+
{ b: 1, schema: 'network.xyo.test.b' },
|
|
55
|
+
{ c: 2, schema: 'network.xyo.test.c' },
|
|
56
|
+
{ d: 3, schema: 'network.xyo.test.d' },
|
|
57
|
+
{ e: 4, schema: 'network.xyo.test.e' },
|
|
58
|
+
{ f: 5, schema: 'network.xyo.test.f' },
|
|
59
|
+
{ g: 6, schema: 'network.xyo.test.g' },
|
|
60
|
+
{ h: 7, schema: 'network.xyo.test.h' },
|
|
61
|
+
{ i: 8, schema: 'network.xyo.test.i' },
|
|
62
|
+
{ j: 9, schema: 'network.xyo.test.j' },
|
|
63
|
+
{ k: 10, schema: 'network.xyo.test.k' },
|
|
64
|
+
{ l: 11, schema: 'network.xyo.test.l' },
|
|
65
|
+
{ m: 12, schema: 'network.xyo.test.m' },
|
|
66
|
+
bigObject,
|
|
67
|
+
{ n: 13, schema: 'network.xyo.test.n' },
|
|
68
|
+
{ o: 14, schema: 'network.xyo.test.o' },
|
|
69
|
+
{ p: 15, schema: 'network.xyo.test.p' },
|
|
70
|
+
{ q: 16, schema: 'network.xyo.test.q' },
|
|
71
|
+
{ r: 17, schema: 'network.xyo.test.r' },
|
|
72
|
+
{ s: 18, schema: 'network.xyo.test.s' },
|
|
73
|
+
{ schema: 'network.xyo.test.t', t: 19 },
|
|
74
|
+
{ schema: 'network.xyo.test.u', u: 20 },
|
|
75
|
+
{ schema: 'network.xyo.test.v', v: 21 },
|
|
76
|
+
{ schema: 'network.xyo.test.w', w: 22 },
|
|
77
|
+
{ schema: 'network.xyo.test.x', x: 23 },
|
|
78
|
+
{ schema: 'network.xyo.test.y', y: 24 },
|
|
79
|
+
{ schema: 'network.xyo.test.z', z: 25 },
|
|
80
|
+
] satisfies Payload<AnyObject>[],
|
|
81
|
+
],
|
|
82
|
+
]
|
|
83
|
+
beforeAll(async () => {
|
|
84
|
+
ObjectHasher.wasmSupport.allowWasm = true
|
|
85
|
+
await ObjectHasher.wasmInitialized
|
|
86
|
+
})
|
|
87
|
+
it.each(cases)('%s', async (_title, sources) => {
|
|
88
|
+
const map = await PayloadBuilder.toDataHashMap(sources)
|
|
89
|
+
expect(Object.keys(map).length).toBe(sources.length)
|
|
90
|
+
await Promise.all(Object.entries(map).map(async ([hash, payload], index) => {
|
|
91
|
+
const source = sources[index]
|
|
92
|
+
const { $meta: m1, ...sourceWithoutMeta } = source
|
|
93
|
+
const { $meta: m2, ...payloadWithoutMeta } = payload
|
|
94
|
+
expect(sourceWithoutMeta).toEqual(payloadWithoutMeta)
|
|
95
|
+
expect(await PayloadBuilder.dataHash(sourceWithoutMeta)).toEqual(hash)
|
|
96
|
+
}))
|
|
97
|
+
})
|
|
98
|
+
})
|