@xyo-network/xl1-protocol-sdk 1.7.8 → 1.7.9
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/dist/neutral/config/index.d.ts +1 -0
- package/dist/neutral/config/index.d.ts.map +1 -1
- package/dist/neutral/config/storage/driver/Mongo.d.ts +8 -0
- package/dist/neutral/config/storage/driver/Mongo.d.ts.map +1 -1
- package/dist/neutral/config/storage/index.d.ts +1 -0
- package/dist/neutral/config/storage/index.d.ts.map +1 -1
- package/dist/neutral/index.mjs +12 -8
- package/dist/neutral/index.mjs.map +1 -1
- package/package.json +16 -14
- package/src/block/primitives/frames/spec/__snapshots__/deepCalculateFramesFromRange.spec.ts.snap +19417 -0
- package/src/block/primitives/frames/spec/calculateFramesFromRange.spec.ts +70 -0
- package/src/block/primitives/frames/spec/deepCalculateFramesFromRange.spec.ts +75 -0
- package/src/config/index.ts +1 -0
- package/src/config/storage/driver/Mongo.ts +24 -5
- package/src/config/storage/index.ts +1 -0
- package/src/transaction/primitives/spec/transactionBlockByteCount.spec.ts +242 -0
- package/src/validation/lib/spec/isLocalhost.spec.ts +20 -0
- package/xy.config.ts +0 -10
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { stepSize } from '@xyo-network/xl1-protocol'
|
|
2
|
+
import {
|
|
3
|
+
describe, expect, it,
|
|
4
|
+
} from 'vitest'
|
|
5
|
+
|
|
6
|
+
import { calculateFramesFromRange } from '../calculateFramesFromRange.ts'
|
|
7
|
+
|
|
8
|
+
describe('calculateFramesFromRange', () => {
|
|
9
|
+
it('handles range aligned with step size', () => {
|
|
10
|
+
const step = 1 // 105
|
|
11
|
+
const range: [number, number] = [0, stepSize(step) - 1]
|
|
12
|
+
const [fitted, remaining] = calculateFramesFromRange(range, step)
|
|
13
|
+
|
|
14
|
+
expect(fitted).toEqual([[0, 30]])
|
|
15
|
+
expect(remaining).toEqual([])
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('handles range starting at step boundary but incomplete', () => {
|
|
19
|
+
const step = 1
|
|
20
|
+
const range: [number, number] = [stepSize(step), stepSize(step) + 1]
|
|
21
|
+
const [fitted, remaining] = calculateFramesFromRange(range, step)
|
|
22
|
+
|
|
23
|
+
expect(fitted).toEqual([])
|
|
24
|
+
expect(remaining).toEqual([range])
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('handles range starting at step boundary (step 1)', () => {
|
|
28
|
+
const step = 1
|
|
29
|
+
const multiplier = 2
|
|
30
|
+
const additional = 1
|
|
31
|
+
const range: [number, number] = [stepSize(step), (stepSize(step) + additional) * multiplier]
|
|
32
|
+
const [fitted, remaining] = calculateFramesFromRange(range, step)
|
|
33
|
+
|
|
34
|
+
expect(fitted).toEqual([[31, 61]])
|
|
35
|
+
expect(remaining).toEqual([[62, 64]])
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('handles range starting at step boundary (step 5)', () => {
|
|
39
|
+
const step = 5
|
|
40
|
+
const multiplier = 2
|
|
41
|
+
const additional = 17
|
|
42
|
+
const range: [number, number] = [stepSize(step), (stepSize(step) + additional) * multiplier]
|
|
43
|
+
const [fitted, remaining] = calculateFramesFromRange(range, step)
|
|
44
|
+
|
|
45
|
+
expect(fitted).toEqual([[510_511, 1_021_021]])
|
|
46
|
+
expect(remaining).toEqual([[1_021_022, 1_021_056]])
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('handles range starting not at step boundary', () => {
|
|
50
|
+
const step = 1
|
|
51
|
+
const multiplier = 2
|
|
52
|
+
const additional = 1
|
|
53
|
+
const range: [number, number] = [stepSize(step) - additional, (stepSize(step) + additional) * multiplier]
|
|
54
|
+
const [fitted, remaining] = calculateFramesFromRange(range, step)
|
|
55
|
+
|
|
56
|
+
expect(fitted).toEqual([[31, 61]])
|
|
57
|
+
expect(remaining).toEqual([[range[0], 30], [62, range[1]]])
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('handles range starting not at step boundary (step 5)', () => {
|
|
61
|
+
const step = 5
|
|
62
|
+
const multiplier = 2
|
|
63
|
+
const additional = 17
|
|
64
|
+
const range: [number, number] = [stepSize(step) - additional, (stepSize(step) + additional) * multiplier]
|
|
65
|
+
const [fitted, remaining] = calculateFramesFromRange(range, step)
|
|
66
|
+
|
|
67
|
+
expect(fitted).toEqual([[510_511, 1_021_021]])
|
|
68
|
+
expect(remaining).toEqual([[range[0], 510_510], [1_021_022, range[1]]])
|
|
69
|
+
})
|
|
70
|
+
})
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {
|
|
2
|
+
describe, expect, it,
|
|
3
|
+
} from 'vitest'
|
|
4
|
+
|
|
5
|
+
import type { BlockNumberRange } from '../BlockNumberRange.ts'
|
|
6
|
+
import { deepCalculateFramesFromRange } from '../deepCalculateFramesFromRange.ts'
|
|
7
|
+
|
|
8
|
+
describe('deepCalculateFramesFromRange', () => {
|
|
9
|
+
it('calculates frames for a simple range with one step level', () => {
|
|
10
|
+
const range: BlockNumberRange = [0, 9]
|
|
11
|
+
const result = deepCalculateFramesFromRange(range)
|
|
12
|
+
|
|
13
|
+
// With step 0 (size 10), this should fit in one frame
|
|
14
|
+
expect(result).toEqual([[0, 6], [7, 7], [8, 8], [9, 9]])
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('calculates frames for a range spanning multiple step sizes', () => {
|
|
18
|
+
const range: BlockNumberRange = [0, 250]
|
|
19
|
+
const result = deepCalculateFramesFromRange(range)
|
|
20
|
+
|
|
21
|
+
expect(result).toContainEqual([0, 210])
|
|
22
|
+
|
|
23
|
+
expect(result).toMatchSnapshot(result)
|
|
24
|
+
expect(result.length).toEqual(11)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('calculates frames for range with multiple step levels - [0, 1500]', () => {
|
|
28
|
+
const range: BlockNumberRange = [0, 1500]
|
|
29
|
+
const result = deepCalculateFramesFromRange(range)
|
|
30
|
+
expect(result).toMatchSnapshot(result)
|
|
31
|
+
expect(result.length).toEqual(19)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('calculates frames for range with multiple step levels - [0, 3000]', () => {
|
|
35
|
+
const range: BlockNumberRange = [0, 3000]
|
|
36
|
+
const result = deepCalculateFramesFromRange(range)
|
|
37
|
+
expect(result).toMatchSnapshot(result)
|
|
38
|
+
expect(result.length).toEqual(31)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('calculates frames for range with multiple step levels = [45, 1599]', () => {
|
|
42
|
+
const range: BlockNumberRange = [45, 1599]
|
|
43
|
+
const result = deepCalculateFramesFromRange(range)
|
|
44
|
+
expect(result).toMatchSnapshot(result)
|
|
45
|
+
expect(result.length).toEqual(43)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('calculates frames for range with multiple step levels = [45, 3333]', () => {
|
|
49
|
+
const range: BlockNumberRange = [45, 3333]
|
|
50
|
+
const result = deepCalculateFramesFromRange(range)
|
|
51
|
+
expect(result).toMatchSnapshot(result)
|
|
52
|
+
expect(result.length).toEqual(85)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('calculates frames for range with multiple step levels - [23_145, 230_102_040]', () => {
|
|
56
|
+
const range: BlockNumberRange = [23_145, 230_102_040]
|
|
57
|
+
const result = deepCalculateFramesFromRange(range)
|
|
58
|
+
expect(result).toMatchSnapshot(result)
|
|
59
|
+
expect(result.length).toEqual(742)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('calculates frames for range with multiple step levels - [23_145, 34_548_554_394]', () => {
|
|
63
|
+
const range: BlockNumberRange = [23_145, 34_548_554_394]
|
|
64
|
+
const result = deepCalculateFramesFromRange(range)
|
|
65
|
+
expect(result).toMatchSnapshot(result)
|
|
66
|
+
expect(result.length).toEqual(1468)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('calculates frames for range with multiple step levels - [23_145, 4_598_734_539_845]', () => {
|
|
70
|
+
const range: BlockNumberRange = [23_145, 4_598_734_539_845]
|
|
71
|
+
const result = deepCalculateFramesFromRange(range)
|
|
72
|
+
expect(result).toMatchSnapshot(result)
|
|
73
|
+
expect(result.length).toEqual(2445)
|
|
74
|
+
})
|
|
75
|
+
})
|
package/src/config/index.ts
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
|
+
import { isDefined, isUndefined } from '@xylabs/typeof'
|
|
1
2
|
import z from 'zod'
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Checks if the provided MongoDB configuration contains all necessary fields
|
|
6
|
+
* for establishing a connection.
|
|
7
|
+
* @param config MongoDB configuration object
|
|
8
|
+
* @returns True if the configuration contains all necessary fields for
|
|
9
|
+
* establishing a connection
|
|
10
|
+
*/
|
|
11
|
+
export const hasMongoConfig = (config?: MongoConfig): config is Required<MongoConfig> => {
|
|
12
|
+
if (isUndefined(config)) return false
|
|
13
|
+
return (
|
|
14
|
+
isDefined(config.connectionString)
|
|
15
|
+
&& isDefined(config.database)
|
|
16
|
+
&& isDefined(config.domain)
|
|
17
|
+
&& isDefined(config.password)
|
|
18
|
+
&& isDefined(config.username)
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
3
22
|
export const MongoConfigSchema = z.object({
|
|
4
23
|
// TODO: Create from other arguments
|
|
5
|
-
connectionString: z.string().min(1).
|
|
6
|
-
database: z.string().min(1).
|
|
7
|
-
domain: z.string().min(1).
|
|
8
|
-
password: z.string().min(1).
|
|
9
|
-
username: z.string().min(1).
|
|
24
|
+
connectionString: z.string().min(1).optional().describe('MongoDB connection string'),
|
|
25
|
+
database: z.string().min(1).optional().describe('MongoDB database name'),
|
|
26
|
+
domain: z.string().min(1).optional().describe('MongoDB domain'),
|
|
27
|
+
password: z.string().min(1).optional().describe('MongoDB password'),
|
|
28
|
+
username: z.string().min(1).optional().describe('MongoDB username'),
|
|
10
29
|
})
|
|
11
30
|
|
|
12
31
|
export type MongoConfig = z.infer<typeof MongoConfigSchema>
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
2
|
+
import type { AnyPayload } from '@xyo-network/payload-model'
|
|
3
|
+
import type { HydratedTransaction, TransactionBoundWitness } from '@xyo-network/xl1-protocol'
|
|
4
|
+
import {
|
|
5
|
+
describe, expect, it,
|
|
6
|
+
} from 'vitest'
|
|
7
|
+
|
|
8
|
+
import { transactionBlockByteCount } from '../transactionBlockByteCount.ts'
|
|
9
|
+
|
|
10
|
+
const hydratedTransaction: HydratedTransaction<TransactionBoundWitness, AnyPayload> = [
|
|
11
|
+
{
|
|
12
|
+
schema: 'network.xyo.boundwitness',
|
|
13
|
+
addresses: [
|
|
14
|
+
'136c12e131f5e3eef708dbde954a2841dd72f9af',
|
|
15
|
+
],
|
|
16
|
+
payload_hashes: [
|
|
17
|
+
'6d12a4aae2d7056b5b9b1a5e078c883e7ebf887a86d16a4e5e87b5940658873d',
|
|
18
|
+
'1f9b639358aefa6f3c2467a7d571cde3b68b8fd5d9c7af6a14d0a4023832286f',
|
|
19
|
+
],
|
|
20
|
+
payload_schemas: [
|
|
21
|
+
'network.xyo.hash',
|
|
22
|
+
'network.xyo.crypto.asset',
|
|
23
|
+
],
|
|
24
|
+
previous_hashes: [
|
|
25
|
+
null,
|
|
26
|
+
],
|
|
27
|
+
$signatures: [
|
|
28
|
+
'c6c4101d2854046974cebd14a941e61ff969f7cf523f677bec2907d262ad98235e00bf829be6344241b5f25cb313c3cadeb0b0abda618b8cfee359859d4246f4',
|
|
29
|
+
],
|
|
30
|
+
nbf: 25_383,
|
|
31
|
+
exp: 26_383,
|
|
32
|
+
fees: {
|
|
33
|
+
base: '038d7ea4c68000',
|
|
34
|
+
gasLimit: '0de0b6b3a7640000',
|
|
35
|
+
gasPrice: '09184e72a000',
|
|
36
|
+
priority: '00',
|
|
37
|
+
},
|
|
38
|
+
chain: 'a82920051db4fcbb804463440dd45e03f72442fd',
|
|
39
|
+
from: '136c12e131f5e3eef708dbde954a2841dd72f9af',
|
|
40
|
+
script: [
|
|
41
|
+
'elevate|6d12a4aae2d7056b5b9b1a5e078c883e7ebf887a86d16a4e5e87b5940658873d',
|
|
42
|
+
],
|
|
43
|
+
_dataHash: '9c6c0ebf16761fc219d8235b398fa058db05f3b139a821f812683c5434e4d08b',
|
|
44
|
+
_hash: 'bd5909fa90603cba7c794ce8358140467a2aeee1845feaabcac3ad1d3e0dd48a',
|
|
45
|
+
_sequence: '0000000000000000000000003e0dd48a',
|
|
46
|
+
},
|
|
47
|
+
[
|
|
48
|
+
{
|
|
49
|
+
schema: 'network.xyo.hash',
|
|
50
|
+
hash: '1f9b639358aefa6f3c2467a7d571cde3b68b8fd5d9c7af6a14d0a4023832286f',
|
|
51
|
+
_dataHash: '6d12a4aae2d7056b5b9b1a5e078c883e7ebf887a86d16a4e5e87b5940658873d',
|
|
52
|
+
_hash: '6d12a4aae2d7056b5b9b1a5e078c883e7ebf887a86d16a4e5e87b5940658873d',
|
|
53
|
+
_sequence: '000001975b401332000000030658873d',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
describe('transactionBlockByteCount', () => {
|
|
59
|
+
it('calculates correct byte count for a transaction with no payloads', () => {
|
|
60
|
+
// Expected byte count - transaction only (no payloads)
|
|
61
|
+
const expectedCleanTransaction = PayloadBuilder.omitStorageMeta(hydratedTransaction[0])
|
|
62
|
+
const expectedCleanPayloads = PayloadBuilder.omitStorageMeta(hydratedTransaction[1])
|
|
63
|
+
const expectedByteCount = JSON.stringify(expectedCleanTransaction).length
|
|
64
|
+
+ expectedCleanPayloads.reduce((acc, payload) => acc + JSON.stringify(payload).length, 0)
|
|
65
|
+
|
|
66
|
+
// Act
|
|
67
|
+
const actualByteCount = transactionBlockByteCount(hydratedTransaction)
|
|
68
|
+
|
|
69
|
+
// Assert
|
|
70
|
+
expect(actualByteCount).toBe(expectedByteCount)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('calculates correct byte count for a transaction with multiple payloads', () => {
|
|
74
|
+
// Expected byte count - transaction + payloads (without $meta)
|
|
75
|
+
const expectedCleanTransaction = PayloadBuilder.omitStorageMeta(hydratedTransaction[0])
|
|
76
|
+
const expectedCleanPayloads = PayloadBuilder.omitStorageMeta(hydratedTransaction[1])
|
|
77
|
+
const expectedByteCount
|
|
78
|
+
= JSON.stringify(expectedCleanTransaction).length
|
|
79
|
+
+ expectedCleanPayloads.reduce((acc, payload) => acc + JSON.stringify(payload).length, 0)
|
|
80
|
+
|
|
81
|
+
// Act
|
|
82
|
+
const actualByteCount = transactionBlockByteCount(hydratedTransaction)
|
|
83
|
+
|
|
84
|
+
// Assert
|
|
85
|
+
expect(actualByteCount).toBe(expectedByteCount)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('handles transaction with empty payload array', () => {
|
|
89
|
+
// Arrange
|
|
90
|
+
const emptyPayloadsTransaction: HydratedTransaction = [
|
|
91
|
+
{ ...hydratedTransaction[0] },
|
|
92
|
+
[], // Empty payload array
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
// Expected byte count - transaction only with no payloads
|
|
96
|
+
const expectedCleanTransaction = PayloadBuilder.omitStorageMeta(emptyPayloadsTransaction[0])
|
|
97
|
+
const expectedByteCount = JSON.stringify(expectedCleanTransaction).length
|
|
98
|
+
|
|
99
|
+
// Act
|
|
100
|
+
const actualByteCount = transactionBlockByteCount(emptyPayloadsTransaction)
|
|
101
|
+
|
|
102
|
+
// Assert
|
|
103
|
+
expect(actualByteCount).toBe(expectedByteCount)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('correctly handles payloads with complex nested structures', async () => {
|
|
107
|
+
// Arrange
|
|
108
|
+
const complexPayload = await PayloadBuilder.addStorageMeta({
|
|
109
|
+
schema: 'network.xyo.complex',
|
|
110
|
+
data: {
|
|
111
|
+
nested: {
|
|
112
|
+
array: [1, 2, 3, 4, 5],
|
|
113
|
+
objects: [
|
|
114
|
+
{ id: 1, name: 'item1' },
|
|
115
|
+
{ id: 2, name: 'item2' },
|
|
116
|
+
],
|
|
117
|
+
deepNesting: { level1: { level2: { level3: 'deep value' } } },
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
const complexTransaction: HydratedTransaction = [
|
|
123
|
+
{ ...hydratedTransaction[0] },
|
|
124
|
+
[complexPayload],
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
// Expected byte count
|
|
128
|
+
const expectedCleanTransaction = PayloadBuilder.omitStorageMeta(complexTransaction[0])
|
|
129
|
+
const expectedCleanPayloads = PayloadBuilder.omitStorageMeta([complexPayload])
|
|
130
|
+
const expectedByteCount
|
|
131
|
+
= JSON.stringify(expectedCleanTransaction).length
|
|
132
|
+
+ JSON.stringify(expectedCleanPayloads[0]).length
|
|
133
|
+
|
|
134
|
+
// Act
|
|
135
|
+
const actualByteCount = transactionBlockByteCount(complexTransaction)
|
|
136
|
+
|
|
137
|
+
// Assert
|
|
138
|
+
expect(actualByteCount).toBe(expectedByteCount)
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('returns correct byte count for transaction with multiple large payloads', async () => {
|
|
142
|
+
// Arrange
|
|
143
|
+
const largePayloads = await PayloadBuilder.addStorageMeta(Array.from({ length: 5 }, (_, i) => ({
|
|
144
|
+
schema: `network.xyo.test.${i}`,
|
|
145
|
+
data: Array.from({ length: 100 }, (_, j) => `data-item-${j}`),
|
|
146
|
+
metadata: {
|
|
147
|
+
timestamp: Date.now(),
|
|
148
|
+
source: `test-source-${i}`,
|
|
149
|
+
tags: Array.from({ length: 10 }, (_, k) => `tag-${k}`),
|
|
150
|
+
},
|
|
151
|
+
_dataHash: `datahash${i}`,
|
|
152
|
+
_hash: `hash${i}`,
|
|
153
|
+
})))
|
|
154
|
+
|
|
155
|
+
const largeTransaction: HydratedTransaction = [
|
|
156
|
+
{ ...hydratedTransaction[0] },
|
|
157
|
+
largePayloads,
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
// Expected byte count
|
|
161
|
+
const expectedCleanTransaction = PayloadBuilder.omitStorageMeta(largeTransaction[0])
|
|
162
|
+
const expectedCleanPayloads = PayloadBuilder.omitStorageMeta(largePayloads)
|
|
163
|
+
|
|
164
|
+
let expectedByteCount = JSON.stringify(expectedCleanTransaction).length
|
|
165
|
+
for (const payload of expectedCleanPayloads) {
|
|
166
|
+
expectedByteCount += JSON.stringify(payload).length
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Act
|
|
170
|
+
const actualByteCount = transactionBlockByteCount(largeTransaction)
|
|
171
|
+
|
|
172
|
+
// Assert
|
|
173
|
+
expect(actualByteCount).toBe(expectedByteCount)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('handles transactions with special characters in payloads', async () => {
|
|
177
|
+
// Arrange
|
|
178
|
+
const specialCharPayload = await PayloadBuilder.addStorageMeta({
|
|
179
|
+
schema: 'network.xyo.special',
|
|
180
|
+
text: 'Special characters: 你好, ñáéíóú, 🚀 💻 🔗, \u0000\u0001\u0002',
|
|
181
|
+
escapes: '\\n\\t\\r\\"\\\'\\\\',
|
|
182
|
+
_hash: 'special-hash',
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
const specialTransaction: HydratedTransaction = [
|
|
186
|
+
{ ...hydratedTransaction[0] },
|
|
187
|
+
[specialCharPayload],
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
// Expected byte count
|
|
191
|
+
const expectedCleanTransaction = PayloadBuilder.omitStorageMeta(specialTransaction[0])
|
|
192
|
+
const expectedCleanPayload = PayloadBuilder.omitStorageMeta([specialCharPayload])
|
|
193
|
+
const expectedByteCount
|
|
194
|
+
= JSON.stringify(expectedCleanTransaction).length
|
|
195
|
+
+ JSON.stringify(expectedCleanPayload[0]).length
|
|
196
|
+
|
|
197
|
+
// Act
|
|
198
|
+
const actualByteCount = transactionBlockByteCount(specialTransaction)
|
|
199
|
+
|
|
200
|
+
// Assert
|
|
201
|
+
expect(actualByteCount).toBe(expectedByteCount)
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('correctly omits all storage metadata fields from byte count', async () => {
|
|
205
|
+
// Arrange
|
|
206
|
+
const txWithExtraMeta = await PayloadBuilder.addStorageMeta({
|
|
207
|
+
...hydratedTransaction[0],
|
|
208
|
+
_extraMeta1: 'should be omitted',
|
|
209
|
+
_extraMeta2: 'should be omitted as well',
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
const payloadWithExtraMeta = await PayloadBuilder.addStorageMeta({
|
|
213
|
+
schema: 'network.xyo.test',
|
|
214
|
+
data: 'test data',
|
|
215
|
+
_extraMeta1: 'should be omitted',
|
|
216
|
+
_extraMeta2: 'should be omitted as well',
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
const transactionWithExtraMeta: HydratedTransaction = [
|
|
220
|
+
txWithExtraMeta,
|
|
221
|
+
[payloadWithExtraMeta],
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
// Expected byte count - all meta fields should be omitted
|
|
225
|
+
const expectedCleanTransaction = PayloadBuilder.omitStorageMeta(txWithExtraMeta)
|
|
226
|
+
const expectedCleanPayload = PayloadBuilder.omitStorageMeta([payloadWithExtraMeta])
|
|
227
|
+
const expectedByteCount
|
|
228
|
+
= JSON.stringify(expectedCleanTransaction).length
|
|
229
|
+
+ JSON.stringify(expectedCleanPayload[0]).length
|
|
230
|
+
|
|
231
|
+
// Act
|
|
232
|
+
const actualByteCount = transactionBlockByteCount(transactionWithExtraMeta)
|
|
233
|
+
|
|
234
|
+
// Assert
|
|
235
|
+
expect(actualByteCount).toBe(expectedByteCount)
|
|
236
|
+
// Verify meta fields are actually omitted
|
|
237
|
+
expect(expectedCleanTransaction).not.toHaveProperty('$meta')
|
|
238
|
+
expect(expectedCleanTransaction).not.toHaveProperty('_extraMeta1')
|
|
239
|
+
expect(expectedCleanPayload[0]).not.toHaveProperty('$meta')
|
|
240
|
+
expect(expectedCleanPayload[0]).not.toHaveProperty('_extraMeta1')
|
|
241
|
+
})
|
|
242
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
describe, expect, it,
|
|
3
|
+
} from 'vitest'
|
|
4
|
+
|
|
5
|
+
import { isLocalhost } from '../isLocalhost.ts'
|
|
6
|
+
|
|
7
|
+
describe('is.ts type guards', () => {
|
|
8
|
+
describe('isLocalhost', () => {
|
|
9
|
+
it('correctly identifies localhost strings', () => {
|
|
10
|
+
expect(isLocalhost('localhost')).toBe(true)
|
|
11
|
+
expect(isLocalhost('127.0.0.1')).toBe(true)
|
|
12
|
+
expect(isLocalhost('::1')).toBe(true)
|
|
13
|
+
expect(isLocalhost('example.localhost')).toBe(true)
|
|
14
|
+
|
|
15
|
+
expect(isLocalhost('example.com')).toBe(false)
|
|
16
|
+
expect(isLocalhost('')).toBe(false)
|
|
17
|
+
expect(isLocalhost('local')).toBe(false)
|
|
18
|
+
})
|
|
19
|
+
})
|
|
20
|
+
})
|