@beclab/olaresid 0.1.13 → 0.2.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/CLI-TREE.md +107 -0
- package/CLI.md +122 -1340
- package/README.md +30 -12
- package/SDK-TREE.md +151 -0
- package/TAG.md +95 -41
- package/config.json +6 -4
- package/dist/abi/TerminusDIDQueryABI.d.ts +397 -0
- package/dist/abi/TerminusDIDQueryABI.d.ts.map +1 -0
- package/dist/abi/TerminusDIDQueryABI.js +519 -0
- package/dist/abi/TerminusDIDQueryABI.js.map +1 -0
- package/dist/business/index.d.ts.map +1 -1
- package/dist/business/index.js +9 -23
- package/dist/business/index.js.map +1 -1
- package/dist/business/tag-context.d.ts +1 -0
- package/dist/business/tag-context.d.ts.map +1 -1
- package/dist/business/tag-context.js +13 -7
- package/dist/business/tag-context.js.map +1 -1
- package/dist/cli.js +177 -76
- package/dist/cli.js.map +1 -1
- package/dist/config/index.d.ts +16 -4
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +28 -14
- package/dist/config/index.js.map +1 -1
- package/dist/domain/core.d.ts +65 -0
- package/dist/domain/core.d.ts.map +1 -0
- package/dist/domain/core.js +317 -0
- package/dist/domain/core.js.map +1 -0
- package/dist/domain/index.d.ts +104 -57
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/index.js +188 -428
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/types.d.ts +56 -0
- package/dist/domain/types.d.ts.map +1 -0
- package/dist/domain/types.js +3 -0
- package/dist/domain/types.js.map +1 -0
- package/dist/index.d.ts +80 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +152 -143
- package/dist/index.js.map +1 -1
- package/dist/utils/crypto-utils.d.ts +110 -0
- package/dist/utils/crypto-utils.d.ts.map +1 -1
- package/dist/utils/crypto-utils.js +127 -8
- package/dist/utils/crypto-utils.js.map +1 -1
- package/dist/utils/error-parser.d.ts.map +1 -1
- package/dist/utils/error-parser.js +2 -1
- package/dist/utils/error-parser.js.map +1 -1
- package/dist/utils/event-parser.d.ts +161 -0
- package/dist/utils/event-parser.d.ts.map +1 -0
- package/dist/utils/event-parser.js +140 -0
- package/dist/utils/event-parser.js.map +1 -0
- package/dist/utils/tag-type-builder.d.ts +43 -0
- package/dist/utils/tag-type-builder.d.ts.map +1 -1
- package/dist/utils/tag-type-builder.js +122 -0
- package/dist/utils/tag-type-builder.js.map +1 -1
- package/dist/utils/tag-type-parser.d.ts +70 -0
- package/dist/utils/tag-type-parser.d.ts.map +1 -0
- package/dist/utils/tag-type-parser.js +190 -0
- package/dist/utils/tag-type-parser.js.map +1 -0
- package/examples/create-with-rpc-demo.ts +142 -0
- package/examples/fetch-all-flat-demo.ts +159 -0
- package/examples/fetch-by-indices-demo.ts +235 -0
- package/examples/fetch-domain-demo.ts +137 -0
- package/examples/fetch-domains-demo.ts +221 -0
- package/examples/frontend-demo/index.html +2 -2
- package/examples/frontend-demo/package-lock.json +4 -1
- package/examples/index.ts +3 -5
- package/jest.config.js +25 -0
- package/package.json +6 -2
- package/src/abi/TerminusDIDQueryABI.ts +516 -0
- package/src/business/index.ts +9 -33
- package/src/business/tag-context.ts +35 -7
- package/src/cli.ts +253 -90
- package/src/config/index.ts +34 -19
- package/src/domain/core.ts +382 -0
- package/src/domain/index.ts +271 -641
- package/src/domain/types.ts +59 -0
- package/src/index.ts +221 -207
- package/src/utils/crypto-utils.ts +205 -2
- package/src/utils/error-parser.ts +2 -1
- package/src/utils/event-parser.ts +353 -0
- package/src/utils/tag-type-builder.ts +138 -0
- package/src/utils/tag-type-parser.ts +246 -0
- package/tests/unit/crypto-utils.test.ts +338 -0
- package/tests/unit/ed25519-jwk.test.ts +201 -0
- package/tests/unit/event-parser.test.ts +690 -0
- package/tests/unit/generate-mnemonic.test.ts +268 -0
- package/tests/unit/olares-id-format.test.ts +321 -0
- package/tests/unit/tag-type-parser.test.ts +802 -0
- package/tests/unit/tag-types.test.ts +821 -0
- package/tsconfig.json +3 -2
- package/dist/abi/ABITypeABI.d.ts +0 -88
- package/dist/abi/ABITypeABI.d.ts.map +0 -1
- package/dist/abi/ABITypeABI.js +0 -382
- package/dist/abi/ABITypeABI.js.map +0 -1
- package/dist/abi/RegistryABI.d.ts +0 -77
- package/dist/abi/RegistryABI.d.ts.map +0 -1
- package/dist/abi/RegistryABI.js +0 -462
- package/dist/abi/RegistryABI.js.map +0 -1
- package/dist/tag/address.d.ts +0 -11
- package/dist/tag/address.d.ts.map +0 -1
- package/dist/tag/address.js +0 -44
- package/dist/tag/address.js.map +0 -1
- package/dist/tag/array.d.ts +0 -14
- package/dist/tag/array.d.ts.map +0 -1
- package/dist/tag/array.js +0 -72
- package/dist/tag/array.js.map +0 -1
- package/dist/tag/bool.d.ts +0 -11
- package/dist/tag/bool.d.ts.map +0 -1
- package/dist/tag/bool.js +0 -43
- package/dist/tag/bool.js.map +0 -1
- package/dist/tag/bytes.d.ts +0 -11
- package/dist/tag/bytes.d.ts.map +0 -1
- package/dist/tag/bytes.js +0 -37
- package/dist/tag/bytes.js.map +0 -1
- package/dist/tag/flarray.d.ts +0 -15
- package/dist/tag/flarray.d.ts.map +0 -1
- package/dist/tag/flarray.js +0 -81
- package/dist/tag/flarray.js.map +0 -1
- package/dist/tag/flbytes.d.ts +0 -11
- package/dist/tag/flbytes.d.ts.map +0 -1
- package/dist/tag/flbytes.js +0 -47
- package/dist/tag/flbytes.js.map +0 -1
- package/dist/tag/index.d.ts +0 -32
- package/dist/tag/index.d.ts.map +0 -1
- package/dist/tag/index.js +0 -121
- package/dist/tag/index.js.map +0 -1
- package/dist/tag/int.d.ts +0 -12
- package/dist/tag/int.d.ts.map +0 -1
- package/dist/tag/int.js +0 -49
- package/dist/tag/int.js.map +0 -1
- package/dist/tag/string.d.ts +0 -11
- package/dist/tag/string.d.ts.map +0 -1
- package/dist/tag/string.js +0 -37
- package/dist/tag/string.js.map +0 -1
- package/dist/tag/tag.d.ts +0 -67
- package/dist/tag/tag.d.ts.map +0 -1
- package/dist/tag/tag.js +0 -157
- package/dist/tag/tag.js.map +0 -1
- package/dist/tag/tuple.d.ts +0 -17
- package/dist/tag/tuple.d.ts.map +0 -1
- package/dist/tag/tuple.js +0 -162
- package/dist/tag/tuple.js.map +0 -1
- package/dist/tag/uint.d.ts +0 -12
- package/dist/tag/uint.d.ts.map +0 -1
- package/dist/tag/uint.js +0 -49
- package/dist/tag/uint.js.map +0 -1
- package/dist/test/did.d.ts +0 -2
- package/dist/test/did.d.ts.map +0 -1
- package/dist/test/did.js +0 -177
- package/dist/test/did.js.map +0 -1
- package/dist/utils/tag-abi-codec.d.ts +0 -69
- package/dist/utils/tag-abi-codec.d.ts.map +0 -1
- package/dist/utils/tag-abi-codec.js +0 -144
- package/dist/utils/tag-abi-codec.js.map +0 -1
- package/examples/crypto-utilities.ts +0 -140
- package/examples/ed25519-jwk.ts +0 -73
- package/examples/generate-mnemonic.ts +0 -149
- package/examples/legacy.ts +0 -33
- package/examples/olares-id-format.ts +0 -197
- package/examples/tag-builder.ts +0 -235
- package/examples/tag-nested-tuple.ts +0 -190
- package/examples/tag-simple.ts +0 -149
- package/examples/tag-tagger.ts +0 -217
- package/examples/test-nested-tuple-conversion.ts +0 -143
- package/examples/test-type-bytes-parser.ts +0 -70
- package/src/abi/ABITypeABI.ts +0 -379
- package/src/abi/RegistryABI.ts +0 -459
- package/src/tag/address.ts +0 -48
- package/src/tag/array.ts +0 -80
- package/src/tag/bool.ts +0 -43
- package/src/tag/bytes.ts +0 -38
- package/src/tag/flarray.ts +0 -99
- package/src/tag/flbytes.ts +0 -48
- package/src/tag/index.ts +0 -170
- package/src/tag/int.ts +0 -51
- package/src/tag/string.ts +0 -38
- package/src/tag/tag.ts +0 -229
- package/src/tag/tuple.ts +0 -193
- package/src/tag/uint.ts +0 -51
- package/src/test/did.ts +0 -346
- package/src/utils/tag-abi-codec.ts +0 -158
|
@@ -0,0 +1,821 @@
|
|
|
1
|
+
import { AbiCoder } from 'ethers';
|
|
2
|
+
import { TagTypeBuilder } from '../../src/utils/tag-type-builder';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Comprehensive tests for Tag type encoding/decoding
|
|
6
|
+
* Covers all tag types: basic, arrays, tuples, and nested structures
|
|
7
|
+
*
|
|
8
|
+
* Run: npm run test:unit
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
describe('Tag Type Encoding/Decoding', () => {
|
|
12
|
+
let abiCoder: AbiCoder;
|
|
13
|
+
|
|
14
|
+
beforeAll(() => {
|
|
15
|
+
abiCoder = new AbiCoder();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// ========================================
|
|
19
|
+
// Basic Types
|
|
20
|
+
// ========================================
|
|
21
|
+
|
|
22
|
+
describe('Basic Types', () => {
|
|
23
|
+
it('should handle string type', () => {
|
|
24
|
+
const builder = TagTypeBuilder.string();
|
|
25
|
+
const typeBytes = '0x' + builder.getTypeBytes();
|
|
26
|
+
const abiType = builder.getAbiTypeString();
|
|
27
|
+
|
|
28
|
+
expect(abiType).toBe('string');
|
|
29
|
+
|
|
30
|
+
// Parse back
|
|
31
|
+
const parsedType =
|
|
32
|
+
TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
33
|
+
expect(parsedType).toBe('string');
|
|
34
|
+
|
|
35
|
+
// Encode/Decode
|
|
36
|
+
const value = 'Hello World';
|
|
37
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
38
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
39
|
+
expect(decoded[0]).toBe(value);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should handle uint256 type', () => {
|
|
43
|
+
const builder = TagTypeBuilder.uint256();
|
|
44
|
+
const typeBytes = '0x' + builder.getTypeBytes();
|
|
45
|
+
const abiType = builder.getAbiTypeString();
|
|
46
|
+
|
|
47
|
+
expect(abiType).toBe('uint256');
|
|
48
|
+
expect(typeBytes).toBe('0x0120');
|
|
49
|
+
|
|
50
|
+
const parsedType =
|
|
51
|
+
TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
52
|
+
expect(parsedType).toBe('uint256');
|
|
53
|
+
|
|
54
|
+
const value = 12345n;
|
|
55
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
56
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
57
|
+
expect(decoded[0]).toBe(value);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should handle uint8 type', () => {
|
|
61
|
+
const builder = TagTypeBuilder.uint8();
|
|
62
|
+
const abiType = builder.getAbiTypeString();
|
|
63
|
+
|
|
64
|
+
expect(abiType).toBe('uint8');
|
|
65
|
+
|
|
66
|
+
const value = 255n;
|
|
67
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
68
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
69
|
+
expect(decoded[0]).toBe(value);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should handle int256 type', () => {
|
|
73
|
+
const builder = TagTypeBuilder.int256();
|
|
74
|
+
const abiType = builder.getAbiTypeString();
|
|
75
|
+
|
|
76
|
+
expect(abiType).toBe('int256');
|
|
77
|
+
|
|
78
|
+
const value = -12345n;
|
|
79
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
80
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
81
|
+
expect(decoded[0]).toBe(value);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should handle bool type', () => {
|
|
85
|
+
const builder = TagTypeBuilder.bool();
|
|
86
|
+
const abiType = builder.getAbiTypeString();
|
|
87
|
+
|
|
88
|
+
expect(abiType).toBe('bool');
|
|
89
|
+
|
|
90
|
+
const value = true;
|
|
91
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
92
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
93
|
+
expect(decoded[0]).toBe(value);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should handle address type', () => {
|
|
97
|
+
const builder = TagTypeBuilder.address();
|
|
98
|
+
const typeBytes = '0x' + builder.getTypeBytes();
|
|
99
|
+
const abiType = builder.getAbiTypeString();
|
|
100
|
+
|
|
101
|
+
expect(abiType).toBe('address');
|
|
102
|
+
expect(typeBytes).toBe('0x07');
|
|
103
|
+
|
|
104
|
+
const parsedType =
|
|
105
|
+
TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
106
|
+
expect(parsedType).toBe('address');
|
|
107
|
+
|
|
108
|
+
const value = '0x742d35cc6634c0532925a3b844bc9e7595f0beb0';
|
|
109
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
110
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
111
|
+
expect(decoded[0].toLowerCase()).toBe(value.toLowerCase());
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should handle bytes type', () => {
|
|
115
|
+
const builder = TagTypeBuilder.bytes();
|
|
116
|
+
const abiType = builder.getAbiTypeString();
|
|
117
|
+
|
|
118
|
+
expect(abiType).toBe('bytes');
|
|
119
|
+
|
|
120
|
+
const value = '0x1234567890abcdef';
|
|
121
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
122
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
123
|
+
expect(decoded[0]).toBe(value);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should handle bytes32 type', () => {
|
|
127
|
+
const builder = TagTypeBuilder.bytes32();
|
|
128
|
+
const typeBytes = '0x' + builder.getTypeBytes();
|
|
129
|
+
const abiType = builder.getAbiTypeString();
|
|
130
|
+
|
|
131
|
+
expect(abiType).toBe('bytes32');
|
|
132
|
+
expect(typeBytes).toBe('0x0820');
|
|
133
|
+
|
|
134
|
+
const parsedType =
|
|
135
|
+
TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
136
|
+
expect(parsedType).toBe('bytes32');
|
|
137
|
+
|
|
138
|
+
const value =
|
|
139
|
+
'0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef';
|
|
140
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
141
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
142
|
+
expect(decoded[0]).toBe(value);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should handle bytes4 type', () => {
|
|
146
|
+
const builder = TagTypeBuilder.fixedBytes(4);
|
|
147
|
+
const abiType = builder.getAbiTypeString();
|
|
148
|
+
|
|
149
|
+
expect(abiType).toBe('bytes4');
|
|
150
|
+
|
|
151
|
+
const value = '0x12345678';
|
|
152
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
153
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
154
|
+
expect(decoded[0]).toBe(value);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// ========================================
|
|
159
|
+
// Array Types
|
|
160
|
+
// ========================================
|
|
161
|
+
|
|
162
|
+
describe('Array Types', () => {
|
|
163
|
+
it('should handle string[] type', () => {
|
|
164
|
+
const builder = TagTypeBuilder.stringArray();
|
|
165
|
+
const typeBytes = '0x' + builder.getTypeBytes();
|
|
166
|
+
const abiType = builder.getAbiTypeString();
|
|
167
|
+
|
|
168
|
+
expect(abiType).toBe('string[]');
|
|
169
|
+
|
|
170
|
+
const parsedType =
|
|
171
|
+
TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
172
|
+
expect(parsedType).toBe('string[]');
|
|
173
|
+
|
|
174
|
+
const value = ['hello', 'world', 'test'];
|
|
175
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
176
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
177
|
+
expect(decoded[0]).toEqual(value);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should handle uint256[] type', () => {
|
|
181
|
+
const builder = TagTypeBuilder.uint256Array();
|
|
182
|
+
const abiType = builder.getAbiTypeString();
|
|
183
|
+
|
|
184
|
+
expect(abiType).toBe('uint256[]');
|
|
185
|
+
|
|
186
|
+
const value = [1n, 2n, 3n, 100n];
|
|
187
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
188
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
189
|
+
expect(decoded[0]).toEqual(value);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('should handle address[] type', () => {
|
|
193
|
+
const builder = TagTypeBuilder.addressArray();
|
|
194
|
+
const abiType = builder.getAbiTypeString();
|
|
195
|
+
|
|
196
|
+
expect(abiType).toBe('address[]');
|
|
197
|
+
|
|
198
|
+
const value = [
|
|
199
|
+
'0x742d35cc6634c0532925a3b844bc9e7595f0beb0',
|
|
200
|
+
'0x1234567890123456789012345678901234567890'
|
|
201
|
+
];
|
|
202
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
203
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
204
|
+
expect(decoded[0].map((a: string) => a.toLowerCase())).toEqual(
|
|
205
|
+
value.map((a) => a.toLowerCase())
|
|
206
|
+
);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('should handle bool[] type', () => {
|
|
210
|
+
const builder = TagTypeBuilder.array(TagTypeBuilder.bool());
|
|
211
|
+
const abiType = builder.getAbiTypeString();
|
|
212
|
+
|
|
213
|
+
expect(abiType).toBe('bool[]');
|
|
214
|
+
|
|
215
|
+
const value = [true, false, true, true];
|
|
216
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
217
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
218
|
+
expect(decoded[0]).toEqual(value);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('should handle fixed-length array string[3]', () => {
|
|
222
|
+
const builder = TagTypeBuilder.fixedArray(
|
|
223
|
+
TagTypeBuilder.string(),
|
|
224
|
+
3
|
|
225
|
+
);
|
|
226
|
+
const typeBytes = '0x' + builder.getTypeBytes();
|
|
227
|
+
const abiType = builder.getAbiTypeString();
|
|
228
|
+
|
|
229
|
+
expect(abiType).toBe('string[3]');
|
|
230
|
+
|
|
231
|
+
const parsedType =
|
|
232
|
+
TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
233
|
+
expect(parsedType).toBe('string[3]');
|
|
234
|
+
|
|
235
|
+
const value = ['a', 'b', 'c'];
|
|
236
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
237
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
238
|
+
expect(decoded[0]).toEqual(value);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// ========================================
|
|
243
|
+
// Tuple Types
|
|
244
|
+
// ========================================
|
|
245
|
+
|
|
246
|
+
describe('Tuple Types', () => {
|
|
247
|
+
it('should handle simple tuple(string,uint8)', () => {
|
|
248
|
+
const builder = TagTypeBuilder.tuple({
|
|
249
|
+
name: TagTypeBuilder.string(),
|
|
250
|
+
age: TagTypeBuilder.uint8()
|
|
251
|
+
});
|
|
252
|
+
const typeBytes = '0x' + builder.getTypeBytes();
|
|
253
|
+
const abiType = builder.getAbiTypeString();
|
|
254
|
+
const fieldNames = builder.getFieldNames();
|
|
255
|
+
|
|
256
|
+
expect(abiType).toBe('tuple(string,uint8)');
|
|
257
|
+
expect(fieldNames).toEqual([['name', 'age']]);
|
|
258
|
+
|
|
259
|
+
const parsedType =
|
|
260
|
+
TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
261
|
+
expect(parsedType).toBe('tuple(string,uint8)');
|
|
262
|
+
|
|
263
|
+
// Array format
|
|
264
|
+
const value = ['Alice', 30n];
|
|
265
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
266
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
267
|
+
expect(decoded[0]).toEqual(value);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('should handle tuple(address,uint256,bool)', () => {
|
|
271
|
+
const builder = TagTypeBuilder.tuple({
|
|
272
|
+
owner: TagTypeBuilder.address(),
|
|
273
|
+
balance: TagTypeBuilder.uint256(),
|
|
274
|
+
active: TagTypeBuilder.bool()
|
|
275
|
+
});
|
|
276
|
+
const abiType = builder.getAbiTypeString();
|
|
277
|
+
const fieldNames = builder.getFieldNames();
|
|
278
|
+
|
|
279
|
+
expect(abiType).toBe('tuple(address,uint256,bool)');
|
|
280
|
+
expect(fieldNames).toEqual([['owner', 'balance', 'active']]);
|
|
281
|
+
|
|
282
|
+
const value = [
|
|
283
|
+
'0x742d35cc6634c0532925a3b844bc9e7595f0beb0',
|
|
284
|
+
1000n,
|
|
285
|
+
true
|
|
286
|
+
];
|
|
287
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
288
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
289
|
+
expect((decoded[0][0] as string).toLowerCase()).toBe(
|
|
290
|
+
(value[0] as string).toLocaleLowerCase()
|
|
291
|
+
);
|
|
292
|
+
expect(decoded[0][1]).toBe(value[1]);
|
|
293
|
+
expect(decoded[0][2]).toBe(value[2]);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('should handle nested tuple(string,tuple(uint8,bool))', () => {
|
|
297
|
+
const builder = TagTypeBuilder.tuple({
|
|
298
|
+
name: TagTypeBuilder.string(),
|
|
299
|
+
profile: TagTypeBuilder.tuple({
|
|
300
|
+
age: TagTypeBuilder.uint8(),
|
|
301
|
+
verified: TagTypeBuilder.bool()
|
|
302
|
+
})
|
|
303
|
+
});
|
|
304
|
+
const typeBytes = '0x' + builder.getTypeBytes();
|
|
305
|
+
const abiType = builder.getAbiTypeString();
|
|
306
|
+
const fieldNames = builder.getFieldNames();
|
|
307
|
+
|
|
308
|
+
expect(abiType).toBe('tuple(string,tuple(uint8,bool))');
|
|
309
|
+
expect(fieldNames).toEqual([
|
|
310
|
+
['name', 'profile'],
|
|
311
|
+
['age', 'verified']
|
|
312
|
+
]);
|
|
313
|
+
|
|
314
|
+
const parsedType =
|
|
315
|
+
TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
316
|
+
expect(parsedType).toBe('tuple(string,tuple(uint8,bool))');
|
|
317
|
+
|
|
318
|
+
const value = ['Bob', [25n, false]];
|
|
319
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
320
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
321
|
+
expect(decoded[0]).toEqual(value);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
it('should handle deeply nested tuple', () => {
|
|
325
|
+
const builder = TagTypeBuilder.tuple({
|
|
326
|
+
id: TagTypeBuilder.uint256(),
|
|
327
|
+
data: TagTypeBuilder.tuple({
|
|
328
|
+
name: TagTypeBuilder.string(),
|
|
329
|
+
meta: TagTypeBuilder.tuple({
|
|
330
|
+
created: TagTypeBuilder.uint256(),
|
|
331
|
+
active: TagTypeBuilder.bool()
|
|
332
|
+
})
|
|
333
|
+
})
|
|
334
|
+
});
|
|
335
|
+
const abiType = builder.getAbiTypeString();
|
|
336
|
+
const fieldNames = builder.getFieldNames();
|
|
337
|
+
|
|
338
|
+
expect(abiType).toBe(
|
|
339
|
+
'tuple(uint256,tuple(string,tuple(uint256,bool)))'
|
|
340
|
+
);
|
|
341
|
+
expect(fieldNames).toEqual([
|
|
342
|
+
['id', 'data'],
|
|
343
|
+
['name', 'meta'],
|
|
344
|
+
['created', 'active']
|
|
345
|
+
]);
|
|
346
|
+
|
|
347
|
+
const value = [1n, ['Test', [1234567890n, true]]];
|
|
348
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
349
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
350
|
+
expect(decoded[0]).toEqual(value);
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// ========================================
|
|
355
|
+
// Array of Tuples
|
|
356
|
+
// ========================================
|
|
357
|
+
|
|
358
|
+
describe('Array of Tuples', () => {
|
|
359
|
+
it('should handle tuple(string,uint8)[] type', () => {
|
|
360
|
+
const builder = TagTypeBuilder.array(
|
|
361
|
+
TagTypeBuilder.tuple({
|
|
362
|
+
name: TagTypeBuilder.string(),
|
|
363
|
+
age: TagTypeBuilder.uint8()
|
|
364
|
+
})
|
|
365
|
+
);
|
|
366
|
+
const typeBytes = '0x' + builder.getTypeBytes();
|
|
367
|
+
const abiType = builder.getAbiTypeString();
|
|
368
|
+
const fieldNames = builder.getFieldNames();
|
|
369
|
+
|
|
370
|
+
expect(abiType).toBe('tuple(string,uint8)[]');
|
|
371
|
+
expect(fieldNames).toEqual([['name', 'age']]);
|
|
372
|
+
|
|
373
|
+
const parsedType =
|
|
374
|
+
TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
375
|
+
expect(parsedType).toBe('tuple(string,uint8)[]');
|
|
376
|
+
|
|
377
|
+
const value = [
|
|
378
|
+
['Alice', 30n],
|
|
379
|
+
['Bob', 25n],
|
|
380
|
+
['Charlie', 35n]
|
|
381
|
+
];
|
|
382
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
383
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
384
|
+
expect(decoded[0]).toEqual(value);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it('should handle nested tuple array', () => {
|
|
388
|
+
const builder = TagTypeBuilder.array(
|
|
389
|
+
TagTypeBuilder.tuple({
|
|
390
|
+
id: TagTypeBuilder.uint256(),
|
|
391
|
+
data: TagTypeBuilder.tuple({
|
|
392
|
+
name: TagTypeBuilder.string(),
|
|
393
|
+
active: TagTypeBuilder.bool()
|
|
394
|
+
})
|
|
395
|
+
})
|
|
396
|
+
);
|
|
397
|
+
const abiType = builder.getAbiTypeString();
|
|
398
|
+
const fieldNames = builder.getFieldNames();
|
|
399
|
+
|
|
400
|
+
expect(abiType).toBe('tuple(uint256,tuple(string,bool))[]');
|
|
401
|
+
expect(fieldNames).toEqual([
|
|
402
|
+
['id', 'data'],
|
|
403
|
+
['name', 'active']
|
|
404
|
+
]);
|
|
405
|
+
|
|
406
|
+
const value = [
|
|
407
|
+
[1n, ['Item1', true]],
|
|
408
|
+
[2n, ['Item2', false]]
|
|
409
|
+
];
|
|
410
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
411
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
412
|
+
expect(decoded[0]).toEqual(value);
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
// ========================================
|
|
417
|
+
// Complex Mixed Types
|
|
418
|
+
// ========================================
|
|
419
|
+
|
|
420
|
+
describe('Complex Mixed Types', () => {
|
|
421
|
+
it('should handle tuple with array field', () => {
|
|
422
|
+
const builder = TagTypeBuilder.tuple({
|
|
423
|
+
name: TagTypeBuilder.string(),
|
|
424
|
+
tags: TagTypeBuilder.stringArray(),
|
|
425
|
+
count: TagTypeBuilder.uint256()
|
|
426
|
+
});
|
|
427
|
+
const abiType = builder.getAbiTypeString();
|
|
428
|
+
|
|
429
|
+
expect(abiType).toBe('tuple(string,string[],uint256)');
|
|
430
|
+
|
|
431
|
+
const value = ['Project', ['tag1', 'tag2', 'tag3'], 100n];
|
|
432
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
433
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
434
|
+
expect(decoded[0]).toEqual(value);
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
it('should handle tuple with multiple nested structures', () => {
|
|
438
|
+
const builder = TagTypeBuilder.tuple({
|
|
439
|
+
owner: TagTypeBuilder.address(),
|
|
440
|
+
metadata: TagTypeBuilder.tuple({
|
|
441
|
+
name: TagTypeBuilder.string(),
|
|
442
|
+
tags: TagTypeBuilder.stringArray()
|
|
443
|
+
}),
|
|
444
|
+
settings: TagTypeBuilder.tuple({
|
|
445
|
+
enabled: TagTypeBuilder.bool(),
|
|
446
|
+
maxValue: TagTypeBuilder.uint256()
|
|
447
|
+
})
|
|
448
|
+
});
|
|
449
|
+
const abiType = builder.getAbiTypeString();
|
|
450
|
+
const fieldNames = builder.getFieldNames();
|
|
451
|
+
|
|
452
|
+
expect(abiType).toBe(
|
|
453
|
+
'tuple(address,tuple(string,string[]),tuple(bool,uint256))'
|
|
454
|
+
);
|
|
455
|
+
expect(fieldNames.length).toBe(3);
|
|
456
|
+
|
|
457
|
+
const value = [
|
|
458
|
+
'0x742d35cc6634c0532925a3b844bc9e7595f0beb0',
|
|
459
|
+
['MyProject', ['web3', 'defi']],
|
|
460
|
+
[true, 1000n]
|
|
461
|
+
];
|
|
462
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
463
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
464
|
+
expect((decoded[0][0] as string).toLowerCase()).toBe(
|
|
465
|
+
(value[0] as string).toLowerCase()
|
|
466
|
+
);
|
|
467
|
+
expect(decoded[0][1]).toEqual(value[1]);
|
|
468
|
+
expect(decoded[0][2]).toEqual(value[2]);
|
|
469
|
+
});
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// ========================================
|
|
473
|
+
// Type Bytes Parsing
|
|
474
|
+
// ========================================
|
|
475
|
+
|
|
476
|
+
describe('Type Bytes Parsing', () => {
|
|
477
|
+
it('should parse simple type bytes correctly', () => {
|
|
478
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x03')).toBe(
|
|
479
|
+
'string'
|
|
480
|
+
);
|
|
481
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x0101')).toBe(
|
|
482
|
+
'uint8'
|
|
483
|
+
);
|
|
484
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x0120')).toBe(
|
|
485
|
+
'uint256'
|
|
486
|
+
);
|
|
487
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x02')).toBe(
|
|
488
|
+
'bool'
|
|
489
|
+
);
|
|
490
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x07')).toBe(
|
|
491
|
+
'address'
|
|
492
|
+
);
|
|
493
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x09')).toBe(
|
|
494
|
+
'bytes'
|
|
495
|
+
);
|
|
496
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x0820')).toBe(
|
|
497
|
+
'bytes32'
|
|
498
|
+
);
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
it('should parse array type bytes correctly', () => {
|
|
502
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x0403')).toBe(
|
|
503
|
+
'string[]'
|
|
504
|
+
);
|
|
505
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x0407')).toBe(
|
|
506
|
+
'address[]'
|
|
507
|
+
);
|
|
508
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x040120')).toBe(
|
|
509
|
+
'uint256[]'
|
|
510
|
+
);
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
it('should parse fixed array type bytes correctly', () => {
|
|
514
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x05000303')).toBe(
|
|
515
|
+
'string[3]'
|
|
516
|
+
);
|
|
517
|
+
expect(TagTypeBuilder.parseTypeBytesToAbiString('0x05000507')).toBe(
|
|
518
|
+
'address[5]'
|
|
519
|
+
);
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
it('should parse simple tuple type bytes correctly', () => {
|
|
523
|
+
// tuple(string,uint8)
|
|
524
|
+
expect(
|
|
525
|
+
TagTypeBuilder.parseTypeBytesToAbiString('0x060002030101')
|
|
526
|
+
).toBe('tuple(string,uint8)');
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
it('should parse complex tuple type bytes correctly', () => {
|
|
530
|
+
// tuple(string,uint8,address[],bool) - from tag-management.ts
|
|
531
|
+
expect(
|
|
532
|
+
TagTypeBuilder.parseTypeBytesToAbiString('0x060004030101040702')
|
|
533
|
+
).toBe('tuple(string,uint8,address[],bool)');
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
it('should parse nested tuple type bytes correctly', () => {
|
|
537
|
+
// Build nested tuple and verify parsing
|
|
538
|
+
const builder = TagTypeBuilder.tuple({
|
|
539
|
+
name: TagTypeBuilder.string(),
|
|
540
|
+
profile: TagTypeBuilder.tuple({
|
|
541
|
+
age: TagTypeBuilder.uint8(),
|
|
542
|
+
active: TagTypeBuilder.bool()
|
|
543
|
+
})
|
|
544
|
+
});
|
|
545
|
+
const typeBytes = '0x' + builder.getTypeBytes();
|
|
546
|
+
const parsed = TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
547
|
+
expect(parsed).toBe('tuple(string,tuple(uint8,bool))');
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it('should roundtrip: build -> parse -> build', () => {
|
|
551
|
+
const original = TagTypeBuilder.tuple({
|
|
552
|
+
id: TagTypeBuilder.uint256(),
|
|
553
|
+
data: TagTypeBuilder.stringArray(),
|
|
554
|
+
owner: TagTypeBuilder.address()
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
const typeBytes = '0x' + original.getTypeBytes();
|
|
558
|
+
const parsedAbi =
|
|
559
|
+
TagTypeBuilder.parseTypeBytesToAbiString(typeBytes);
|
|
560
|
+
|
|
561
|
+
expect(parsedAbi).toBe('tuple(uint256,string[],address)');
|
|
562
|
+
expect(parsedAbi).toBe(original.getAbiTypeString());
|
|
563
|
+
});
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
// ========================================
|
|
567
|
+
// Object to Array Conversion
|
|
568
|
+
// ========================================
|
|
569
|
+
|
|
570
|
+
describe('Object to Array Conversion', () => {
|
|
571
|
+
it('should return non-object values as-is', () => {
|
|
572
|
+
expect(TagTypeBuilder.convertObjectToArray('string', 'hello')).toBe(
|
|
573
|
+
'hello'
|
|
574
|
+
);
|
|
575
|
+
expect(TagTypeBuilder.convertObjectToArray('uint256', 123n)).toBe(
|
|
576
|
+
123n
|
|
577
|
+
);
|
|
578
|
+
expect(TagTypeBuilder.convertObjectToArray('bool', true)).toBe(
|
|
579
|
+
true
|
|
580
|
+
);
|
|
581
|
+
expect(TagTypeBuilder.convertObjectToArray('address', null)).toBe(
|
|
582
|
+
null
|
|
583
|
+
);
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
it('should return arrays as-is', () => {
|
|
587
|
+
const arr = ['Alice', 30];
|
|
588
|
+
expect(
|
|
589
|
+
TagTypeBuilder.convertObjectToArray('tuple(string,uint8)', arr)
|
|
590
|
+
).toBe(arr);
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
it('should return non-tuple types as-is', () => {
|
|
594
|
+
const obj = { foo: 'bar' };
|
|
595
|
+
expect(TagTypeBuilder.convertObjectToArray('string', obj)).toBe(
|
|
596
|
+
obj
|
|
597
|
+
);
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
it('should convert simple tuple object to array', () => {
|
|
601
|
+
const obj = { name: 'Alice', age: 30 };
|
|
602
|
+
const result = TagTypeBuilder.convertObjectToArray(
|
|
603
|
+
'tuple(string,uint8)',
|
|
604
|
+
obj
|
|
605
|
+
);
|
|
606
|
+
expect(result).toEqual(['Alice', 30]);
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
it('should convert nested tuple object to array', () => {
|
|
610
|
+
const obj = {
|
|
611
|
+
name: 'Bob',
|
|
612
|
+
profile: {
|
|
613
|
+
age: 25,
|
|
614
|
+
verified: true
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
const result = TagTypeBuilder.convertObjectToArray(
|
|
618
|
+
'tuple(string,tuple(uint8,bool))',
|
|
619
|
+
obj
|
|
620
|
+
);
|
|
621
|
+
expect(result).toEqual(['Bob', [25, true]]);
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
it('should convert deeply nested tuple object to array', () => {
|
|
625
|
+
const obj = {
|
|
626
|
+
id: 1,
|
|
627
|
+
data: {
|
|
628
|
+
name: 'Test',
|
|
629
|
+
meta: {
|
|
630
|
+
created: 1234567890,
|
|
631
|
+
active: true
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
const result = TagTypeBuilder.convertObjectToArray(
|
|
636
|
+
'tuple(uint256,tuple(string,tuple(uint256,bool)))',
|
|
637
|
+
obj
|
|
638
|
+
);
|
|
639
|
+
expect(result).toEqual([1, ['Test', [1234567890, true]]]);
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
it('should handle tuple with mixed types', () => {
|
|
643
|
+
const obj = {
|
|
644
|
+
owner: '0x1234567890123456789012345678901234567890',
|
|
645
|
+
balance: 1000n,
|
|
646
|
+
active: true
|
|
647
|
+
};
|
|
648
|
+
const result = TagTypeBuilder.convertObjectToArray(
|
|
649
|
+
'tuple(address,uint256,bool)',
|
|
650
|
+
obj
|
|
651
|
+
);
|
|
652
|
+
expect(result).toEqual([
|
|
653
|
+
'0x1234567890123456789012345678901234567890',
|
|
654
|
+
1000n,
|
|
655
|
+
true
|
|
656
|
+
]);
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
it('should throw error on field count mismatch', () => {
|
|
660
|
+
const obj = { name: 'Alice' }; // Missing 'age' field
|
|
661
|
+
expect(() => {
|
|
662
|
+
TagTypeBuilder.convertObjectToArray('tuple(string,uint8)', obj);
|
|
663
|
+
}).toThrow('Tuple field count mismatch');
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
it('should convert tuple array (tuple[]) correctly', () => {
|
|
667
|
+
const objArray = [
|
|
668
|
+
{
|
|
669
|
+
algorithm: 0,
|
|
670
|
+
addr: '0x742d35cc6634c0532925a3b844bc9e7595f0beb0'
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
algorithm: 1,
|
|
674
|
+
addr: '0x1111111111111111111111111111111111111111'
|
|
675
|
+
}
|
|
676
|
+
];
|
|
677
|
+
const result = TagTypeBuilder.convertObjectToArray(
|
|
678
|
+
'tuple(uint8,address)[]',
|
|
679
|
+
objArray
|
|
680
|
+
);
|
|
681
|
+
expect(result).toEqual([
|
|
682
|
+
[0, '0x742d35cc6634c0532925a3b844bc9e7595f0beb0'],
|
|
683
|
+
[1, '0x1111111111111111111111111111111111111111']
|
|
684
|
+
]);
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
it('should handle nested tuple within tuple array', () => {
|
|
688
|
+
const objArray = [
|
|
689
|
+
{
|
|
690
|
+
id: 1,
|
|
691
|
+
data: {
|
|
692
|
+
name: 'Alice',
|
|
693
|
+
active: true
|
|
694
|
+
}
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
id: 2,
|
|
698
|
+
data: {
|
|
699
|
+
name: 'Bob',
|
|
700
|
+
active: false
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
];
|
|
704
|
+
const result = TagTypeBuilder.convertObjectToArray(
|
|
705
|
+
'tuple(uint256,tuple(string,bool))[]',
|
|
706
|
+
objArray
|
|
707
|
+
);
|
|
708
|
+
expect(result).toEqual([
|
|
709
|
+
[1, ['Alice', true]],
|
|
710
|
+
[2, ['Bob', false]]
|
|
711
|
+
]);
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
it('should handle empty tuple array', () => {
|
|
715
|
+
const objArray: any[] = [];
|
|
716
|
+
const result = TagTypeBuilder.convertObjectToArray(
|
|
717
|
+
'tuple(uint8,address)[]',
|
|
718
|
+
objArray
|
|
719
|
+
);
|
|
720
|
+
expect(result).toEqual([]);
|
|
721
|
+
});
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
// ========================================
|
|
725
|
+
// Parse Tuple Field Types
|
|
726
|
+
// ========================================
|
|
727
|
+
|
|
728
|
+
describe('Parse Tuple Field Types', () => {
|
|
729
|
+
it('should parse simple tuple fields', () => {
|
|
730
|
+
const fields = TagTypeBuilder.parseTupleFieldTypes(
|
|
731
|
+
'tuple(string,uint8)'
|
|
732
|
+
);
|
|
733
|
+
expect(fields).toEqual(['string', 'uint8']);
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
it('should parse tuple with multiple fields', () => {
|
|
737
|
+
const fields = TagTypeBuilder.parseTupleFieldTypes(
|
|
738
|
+
'tuple(address,uint256,bool,string)'
|
|
739
|
+
);
|
|
740
|
+
expect(fields).toEqual(['address', 'uint256', 'bool', 'string']);
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
it('should parse nested tuple fields', () => {
|
|
744
|
+
const fields = TagTypeBuilder.parseTupleFieldTypes(
|
|
745
|
+
'tuple(string,tuple(uint8,bool))'
|
|
746
|
+
);
|
|
747
|
+
expect(fields).toEqual(['string', 'tuple(uint8,bool)']);
|
|
748
|
+
});
|
|
749
|
+
|
|
750
|
+
it('should parse deeply nested tuple fields', () => {
|
|
751
|
+
const fields = TagTypeBuilder.parseTupleFieldTypes(
|
|
752
|
+
'tuple(uint256,tuple(string,tuple(uint256,bool)))'
|
|
753
|
+
);
|
|
754
|
+
expect(fields).toEqual([
|
|
755
|
+
'uint256',
|
|
756
|
+
'tuple(string,tuple(uint256,bool))'
|
|
757
|
+
]);
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
it('should parse tuple with array fields', () => {
|
|
761
|
+
const fields = TagTypeBuilder.parseTupleFieldTypes(
|
|
762
|
+
'tuple(string,string[],uint256)'
|
|
763
|
+
);
|
|
764
|
+
expect(fields).toEqual(['string', 'string[]', 'uint256']);
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
it('should return empty array for non-tuple types', () => {
|
|
768
|
+
expect(TagTypeBuilder.parseTupleFieldTypes('string')).toEqual([]);
|
|
769
|
+
expect(TagTypeBuilder.parseTupleFieldTypes('uint256')).toEqual([]);
|
|
770
|
+
expect(TagTypeBuilder.parseTupleFieldTypes('address[]')).toEqual(
|
|
771
|
+
[]
|
|
772
|
+
);
|
|
773
|
+
});
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
// ========================================
|
|
777
|
+
// Edge Cases
|
|
778
|
+
// ========================================
|
|
779
|
+
|
|
780
|
+
describe('Edge Cases', () => {
|
|
781
|
+
it('should handle empty string', () => {
|
|
782
|
+
const builder = TagTypeBuilder.string();
|
|
783
|
+
const abiType = builder.getAbiTypeString();
|
|
784
|
+
|
|
785
|
+
const value = '';
|
|
786
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
787
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
788
|
+
expect(decoded[0]).toBe(value);
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
it('should handle empty array', () => {
|
|
792
|
+
const builder = TagTypeBuilder.stringArray();
|
|
793
|
+
const abiType = builder.getAbiTypeString();
|
|
794
|
+
|
|
795
|
+
const value: string[] = [];
|
|
796
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
797
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
798
|
+
expect(decoded[0]).toEqual(value);
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
it('should handle zero values', () => {
|
|
802
|
+
const builder = TagTypeBuilder.uint256();
|
|
803
|
+
const abiType = builder.getAbiTypeString();
|
|
804
|
+
|
|
805
|
+
const value = 0n;
|
|
806
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
807
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
808
|
+
expect(decoded[0]).toBe(value);
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
it('should handle max uint256', () => {
|
|
812
|
+
const builder = TagTypeBuilder.uint256();
|
|
813
|
+
const abiType = builder.getAbiTypeString();
|
|
814
|
+
|
|
815
|
+
const value = 2n ** 256n - 1n;
|
|
816
|
+
const encoded = abiCoder.encode([abiType], [value]);
|
|
817
|
+
const decoded = abiCoder.decode([abiType], encoded);
|
|
818
|
+
expect(decoded[0]).toBe(value);
|
|
819
|
+
});
|
|
820
|
+
});
|
|
821
|
+
});
|