@beclab/olaresid 0.1.1 → 0.1.2

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.
Files changed (87) hide show
  1. package/CLI.md +1300 -0
  2. package/README.md +37 -31
  3. package/TAG.md +589 -0
  4. package/dist/abi/RootResolver2ABI.d.ts +54 -0
  5. package/dist/abi/RootResolver2ABI.d.ts.map +1 -0
  6. package/dist/abi/RootResolver2ABI.js +240 -0
  7. package/dist/abi/RootResolver2ABI.js.map +1 -0
  8. package/dist/business/index.d.ts +302 -0
  9. package/dist/business/index.d.ts.map +1 -0
  10. package/dist/business/index.js +1209 -0
  11. package/dist/business/index.js.map +1 -0
  12. package/dist/business/tag-context.d.ts +219 -0
  13. package/dist/business/tag-context.d.ts.map +1 -0
  14. package/dist/business/tag-context.js +537 -0
  15. package/dist/business/tag-context.js.map +1 -0
  16. package/dist/cli.js +2085 -39
  17. package/dist/cli.js.map +1 -1
  18. package/dist/debug.d.ts.map +1 -1
  19. package/dist/debug.js +14 -2
  20. package/dist/debug.js.map +1 -1
  21. package/dist/index.d.ts +50 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +229 -9
  24. package/dist/index.js.map +1 -1
  25. package/dist/utils/crypto-utils.d.ts +130 -0
  26. package/dist/utils/crypto-utils.d.ts.map +1 -0
  27. package/dist/utils/crypto-utils.js +402 -0
  28. package/dist/utils/crypto-utils.js.map +1 -0
  29. package/dist/utils/error-parser.d.ts +35 -0
  30. package/dist/utils/error-parser.d.ts.map +1 -0
  31. package/dist/utils/error-parser.js +202 -0
  32. package/dist/utils/error-parser.js.map +1 -0
  33. package/dist/utils/tag-abi-codec.d.ts +69 -0
  34. package/dist/utils/tag-abi-codec.d.ts.map +1 -0
  35. package/dist/utils/tag-abi-codec.js +144 -0
  36. package/dist/utils/tag-abi-codec.js.map +1 -0
  37. package/dist/utils/tag-type-builder.d.ts +158 -0
  38. package/dist/utils/tag-type-builder.d.ts.map +1 -0
  39. package/dist/utils/tag-type-builder.js +410 -0
  40. package/dist/utils/tag-type-builder.js.map +1 -0
  41. package/examples/crypto-utilities.ts +140 -0
  42. package/examples/domain-context.ts +80 -0
  43. package/examples/generate-mnemonic.ts +149 -0
  44. package/examples/index.ts +1 -1
  45. package/examples/ip.ts +171 -0
  46. package/examples/legacy.ts +10 -10
  47. package/examples/list-wallets.ts +81 -0
  48. package/examples/quasar-demo/.eslintrc.js +23 -0
  49. package/examples/quasar-demo/.quasar/app.js +43 -0
  50. package/examples/quasar-demo/.quasar/client-entry.js +38 -0
  51. package/examples/quasar-demo/.quasar/client-prefetch.js +130 -0
  52. package/examples/quasar-demo/.quasar/quasar-user-options.js +16 -0
  53. package/examples/quasar-demo/README.md +49 -0
  54. package/examples/quasar-demo/index.html +11 -0
  55. package/examples/quasar-demo/package-lock.json +6407 -0
  56. package/examples/quasar-demo/package.json +36 -0
  57. package/examples/quasar-demo/quasar.config.js +73 -0
  58. package/examples/quasar-demo/src/App.vue +13 -0
  59. package/examples/quasar-demo/src/css/app.scss +1 -0
  60. package/examples/quasar-demo/src/layouts/MainLayout.vue +21 -0
  61. package/examples/quasar-demo/src/pages/IndexPage.vue +905 -0
  62. package/examples/quasar-demo/src/router/index.ts +25 -0
  63. package/examples/quasar-demo/src/router/routes.ts +11 -0
  64. package/examples/quasar-demo/tsconfig.json +28 -0
  65. package/examples/register-subdomain.ts +152 -0
  66. package/examples/rsa-keypair.ts +148 -0
  67. package/examples/tag-builder.ts +235 -0
  68. package/examples/tag-management.ts +534 -0
  69. package/examples/tag-nested-tuple.ts +190 -0
  70. package/examples/tag-simple.ts +149 -0
  71. package/examples/tag-tagger.ts +217 -0
  72. package/examples/test-nested-tuple-conversion.ts +143 -0
  73. package/examples/test-type-bytes-parser.ts +70 -0
  74. package/examples/transfer-domain.ts +197 -0
  75. package/examples/wallet-management.ts +196 -0
  76. package/package.json +24 -15
  77. package/src/abi/RootResolver2ABI.ts +237 -0
  78. package/src/business/index.ts +1490 -0
  79. package/src/business/tag-context.ts +713 -0
  80. package/src/cli.ts +2755 -39
  81. package/src/debug.ts +17 -2
  82. package/src/index.ts +300 -14
  83. package/src/utils/crypto-utils.ts +459 -0
  84. package/src/utils/error-parser.ts +225 -0
  85. package/src/utils/tag-abi-codec.ts +158 -0
  86. package/src/utils/tag-type-builder.ts +469 -0
  87. package/tsconfig.json +1 -1
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ /**
3
+ * Contract Error Parser Utility
4
+ *
5
+ * This module provides utilities for parsing contract errors from ethers.js
6
+ * and converting them into user-friendly error messages.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.parseContractError = parseContractError;
10
+ /**
11
+ * Complete error selector mapping for all contracts (TerminusDID, RootResolver, RootTagger2, TagRegistry)
12
+ */
13
+ const ERROR_SELECTORS = {
14
+ // TerminusDID contract errors
15
+ '0x89c62b64': 'ERC721InvalidOwner',
16
+ '0x7e273289': 'ERC721NonexistentToken',
17
+ '0x64283d7b': 'ERC721IncorrectOwner',
18
+ '0x73c6ac6e': 'ERC721InvalidSender',
19
+ '0x64a0ae92': 'ERC721InvalidReceiver',
20
+ '0x177e802f': 'ERC721InsufficientApproval',
21
+ '0xa9fbf51f': 'ERC721InvalidApprover',
22
+ '0x5b08ba18': 'ERC721InvalidOperator',
23
+ '0x6db122af': 'DomainNotExist',
24
+ '0x27e1f1e5': 'OnlyOperator',
25
+ '0xfb5c3755': 'InvalidDomain',
26
+ '0xc668cf69': 'SubdomainNotAllowed',
27
+ // RootTagger2 contract errors
28
+ '0xa3114200': 'RootTagNoExists',
29
+ '0xe7c4886e': 'AddressNoExists',
30
+ '0xca7dc5c3': 'AddressHasExisted',
31
+ '0x390642d4': 'SignatureIsValidOnlyInOneHour',
32
+ '0x9cc5a685': 'InvalidAddressSignature',
33
+ '0x871a1000': 'InvalidSolanaAddressSignature',
34
+ // RootResolver contract errors
35
+ '0x4a7f394f': 'InvalidAction',
36
+ '0xfde625f6': 'TagNotExist',
37
+ '0x4bdbac1b': 'InvalidBytes',
38
+ // TagRegistry contract errors
39
+ '0x651e7ee4': 'UndefinedTag',
40
+ '0x7417940b': 'RedefinedTag',
41
+ '0x1f7fe073': 'InvalidTagDefinition',
42
+ '0xc2d32a00': 'TagInvalidOp',
43
+ '0xe3f3bb98': 'TagTypeIncompatible',
44
+ '0xa6df187b': 'IncompatibleArrayLengthsForEncode',
45
+ '0xb62b06eb': 'TagTooManyEntries',
46
+ // ABI utility errors
47
+ '0x63df8171': 'InvalidIndex',
48
+ '0x93c19f61': 'InvalidOp',
49
+ '0xb9688461': 'InvalidType',
50
+ '0xaa7feadc': 'InvalidValue',
51
+ // Common errors
52
+ '0x82b42900': 'Unauthorized'
53
+ };
54
+ /**
55
+ * Network error codes that indicate connectivity issues
56
+ */
57
+ const NETWORK_ERROR_CODES = [
58
+ 'NETWORK_ERROR',
59
+ 'TIMEOUT',
60
+ 'SERVER_ERROR',
61
+ 'ETIMEDOUT',
62
+ 'ECONNREFUSED',
63
+ 'ENOTFOUND'
64
+ ];
65
+ /**
66
+ * Parse contract error and determine if it's a network error or contract error
67
+ * @param error - The error object from ethers.js
68
+ * @returns Parsed error information with friendly message
69
+ *
70
+ * @example
71
+ * ```typescript
72
+ * try {
73
+ * await contract.someFunction();
74
+ * } catch (error) {
75
+ * const parsed = parseContractError(error);
76
+ * if (parsed.isNetworkError) {
77
+ * throw new Error(`Network error: ${parsed.message}`);
78
+ * }
79
+ * console.log(parsed.message); // User-friendly message
80
+ * }
81
+ * ```
82
+ */
83
+ function parseContractError(error) {
84
+ const errorCode = error.code || '';
85
+ const errorMessage = error.message || String(error);
86
+ // Check if it's a network error
87
+ const isNetworkError = NETWORK_ERROR_CODES.some((code) => errorCode.includes(code) || errorMessage.includes(code));
88
+ let errorName;
89
+ let errorArgs;
90
+ // Check for revert with custom error
91
+ if (error.data && typeof error.data === 'string') {
92
+ try {
93
+ const errorSelector = error.data.slice(0, 10);
94
+ errorName = ERROR_SELECTORS[errorSelector];
95
+ }
96
+ catch (e) {
97
+ // Ignore parsing errors
98
+ }
99
+ }
100
+ // Check error message for known patterns (fallback)
101
+ if (!errorName && errorMessage) {
102
+ Object.values(ERROR_SELECTORS).forEach((name) => {
103
+ if (errorMessage.includes(name)) {
104
+ errorName = name;
105
+ }
106
+ });
107
+ }
108
+ // Build friendly error message
109
+ const friendlyMessage = errorName
110
+ ? getFriendlyErrorMessage(errorName)
111
+ : errorMessage;
112
+ return {
113
+ message: friendlyMessage,
114
+ isNetworkError,
115
+ errorName,
116
+ errorArgs
117
+ };
118
+ }
119
+ /**
120
+ * Get user-friendly error message for a given error name
121
+ * @param errorName - The contract error name
122
+ * @returns User-friendly error message
123
+ */
124
+ function getFriendlyErrorMessage(errorName) {
125
+ switch (errorName) {
126
+ // RootTagger2 errors
127
+ case 'RootTagNoExists':
128
+ return `Tag does not exist for this domain`;
129
+ case 'AddressNoExists':
130
+ return `Wallet address does not exist`;
131
+ case 'AddressHasExisted':
132
+ return `This wallet address has already been added to the domain`;
133
+ case 'SignatureIsValidOnlyInOneHour':
134
+ return `Signature expired: Signatures are only valid for 1 hour`;
135
+ case 'InvalidAddressSignature':
136
+ return `Invalid signature: The wallet signature verification failed`;
137
+ case 'InvalidSolanaAddressSignature':
138
+ return `Invalid Solana signature: The wallet signature verification failed`;
139
+ // TerminusDID errors
140
+ case 'ERC721InvalidOwner':
141
+ return `Invalid owner address`;
142
+ case 'ERC721NonexistentToken':
143
+ return `Domain does not exist`;
144
+ case 'ERC721IncorrectOwner':
145
+ return `Incorrect owner: You are not the owner of this domain`;
146
+ case 'ERC721InvalidSender':
147
+ return `Invalid sender address`;
148
+ case 'ERC721InvalidReceiver':
149
+ return `Invalid receiver address`;
150
+ case 'ERC721InsufficientApproval':
151
+ return `Insufficient approval: Caller is not approved to operate this domain`;
152
+ case 'ERC721InvalidApprover':
153
+ return `Invalid approver address`;
154
+ case 'ERC721InvalidOperator':
155
+ return `Invalid operator address`;
156
+ case 'DomainNotExist':
157
+ return `Domain does not exist`;
158
+ case 'OnlyOperator':
159
+ return `Only operator can perform this action`;
160
+ case 'InvalidDomain':
161
+ return `Invalid domain name format`;
162
+ case 'SubdomainNotAllowed':
163
+ return `Subdomain creation is not allowed for this domain`;
164
+ // RootResolver errors
165
+ case 'InvalidAction':
166
+ return `Invalid action`;
167
+ case 'TagNotExist':
168
+ return `Tag does not exist`;
169
+ case 'InvalidBytes':
170
+ return `Invalid bytes data format`;
171
+ // TagRegistry errors
172
+ case 'UndefinedTag':
173
+ return `Tag is not defined: You must define the tag type before using it`;
174
+ case 'RedefinedTag':
175
+ return `Tag already exists: This tag has already been defined for this domain`;
176
+ case 'InvalidTagDefinition':
177
+ return `Invalid tag definition: The tag type definition is malformed`;
178
+ case 'TagInvalidOp':
179
+ return `Invalid tag operation: The operation is not supported for this tag type or state`;
180
+ case 'TagTypeIncompatible':
181
+ return `Tag type mismatch: The value type does not match the defined tag type`;
182
+ case 'IncompatibleArrayLengthsForEncode':
183
+ return `Array encoding error: Mismatched array lengths during encoding`;
184
+ case 'TagTooManyEntries':
185
+ return `Too many tag entries: The maximum number of tags has been reached`;
186
+ // ABI utility errors
187
+ case 'InvalidIndex':
188
+ return `Invalid array index: The index is out of bounds`;
189
+ case 'InvalidOp':
190
+ return `Invalid ABI operation: The operation is not supported for this type`;
191
+ case 'InvalidType':
192
+ return `Invalid ABI type: The type definition is malformed`;
193
+ case 'InvalidValue':
194
+ return `Invalid value: The value cannot be encoded with the specified type`;
195
+ // Common errors
196
+ case 'Unauthorized':
197
+ return `Unauthorized: You do not have permission to perform this action`;
198
+ default:
199
+ return `Contract error: ${errorName}`;
200
+ }
201
+ }
202
+ //# sourceMappingURL=error-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-parser.js","sourceRoot":"","sources":["../../src/utils/error-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Tag ABI Codec
3
+ * Unified encoding/decoding utility for Tag values
4
+ *
5
+ * Key Principle: ALL values use abi.encode()
6
+ * - Simple values: abi.encode("value")
7
+ * - Arrays: abi.encode(["a", "b", "c"])
8
+ * - Tuples: abi.encode(struct)
9
+ * - Elements for push: abi.encode(singleElement)
10
+ */
11
+ export declare class TagAbiCodec {
12
+ private static abiCoder;
13
+ /**
14
+ * Parse tuple field types from ABI type string
15
+ * @param abiType e.g., "tuple(string,uint8,tuple(bool,address))"
16
+ * @returns Array of field types: ["string", "uint8", "tuple(bool,address)"]
17
+ */
18
+ private static parseTupleFields;
19
+ /**
20
+ * Convert object to array based on ABI type structure
21
+ * Supports nested tuples recursively
22
+ *
23
+ * @param abiType ABI type string
24
+ * @param value Value (can be object or array)
25
+ * @returns Array value
26
+ */
27
+ private static convertObjectToArray;
28
+ /**
29
+ * Encode a value with given ABI type
30
+ *
31
+ * @param abiType ABI type string (e.g., "string", "uint256", "tuple(string,uint8)")
32
+ * @param value Value to encode (objects are automatically converted to arrays)
33
+ * @returns Encoded bytes (with 0x prefix)
34
+ *
35
+ * @example
36
+ * // Simple value
37
+ * TagAbiCodec.encode("string", "hello");
38
+ *
39
+ * // Array value
40
+ * TagAbiCodec.encode("string[]", ["a", "b", "c"]);
41
+ *
42
+ * // Tuple with object input
43
+ * TagAbiCodec.encode("tuple(string,uint8)", {name: "Alice", age: 30});
44
+ *
45
+ * // Nested tuple with object input
46
+ * TagAbiCodec.encode(
47
+ * "tuple(string,tuple(uint8,bool))",
48
+ * {name: "Alice", profile: {age: 30, verified: true}}
49
+ * );
50
+ *
51
+ * // Tuple with array input (still supported)
52
+ * TagAbiCodec.encode("tuple(string,uint8)", ["Alice", 30]);
53
+ */
54
+ static encode(abiType: string, value: any): string;
55
+ /**
56
+ * Decode bytes with given ABI type
57
+ *
58
+ * @param abiType ABI type string
59
+ * @param encodedData Encoded bytes (with or without 0x prefix)
60
+ * @returns Decoded value
61
+ *
62
+ * @example
63
+ * TagAbiCodec.decode("string", encodedBytes); // → "hello"
64
+ * TagAbiCodec.decode("uint256", encodedBytes); // → 123n (BigInt)
65
+ * TagAbiCodec.decode("tuple(string,uint8)", encodedBytes); // → ["Alice", 30n]
66
+ */
67
+ static decode(abiType: string, encodedData: string): any;
68
+ }
69
+ //# sourceMappingURL=tag-abi-codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag-abi-codec.d.ts","sourceRoot":"","sources":["../../src/utils/tag-abi-codec.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,qBAAa,WAAW;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkB;IAEzC;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAkC/B;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IA6CnC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,MAAM;IAQlD;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,GAAG;CAIxD"}
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TagAbiCodec = void 0;
4
+ const ethers_1 = require("ethers");
5
+ /**
6
+ * Tag ABI Codec
7
+ * Unified encoding/decoding utility for Tag values
8
+ *
9
+ * Key Principle: ALL values use abi.encode()
10
+ * - Simple values: abi.encode("value")
11
+ * - Arrays: abi.encode(["a", "b", "c"])
12
+ * - Tuples: abi.encode(struct)
13
+ * - Elements for push: abi.encode(singleElement)
14
+ */
15
+ class TagAbiCodec {
16
+ /**
17
+ * Parse tuple field types from ABI type string
18
+ * @param abiType e.g., "tuple(string,uint8,tuple(bool,address))"
19
+ * @returns Array of field types: ["string", "uint8", "tuple(bool,address)"]
20
+ */
21
+ static parseTupleFields(abiType) {
22
+ if (!abiType.startsWith('tuple(')) {
23
+ return [];
24
+ }
25
+ const innerTypes = abiType.slice(6, -1); // Remove "tuple(" and ")"
26
+ const fields = [];
27
+ let depth = 0;
28
+ let currentField = '';
29
+ for (let i = 0; i < innerTypes.length; i++) {
30
+ const char = innerTypes[i];
31
+ if (char === '(') {
32
+ depth++;
33
+ currentField += char;
34
+ }
35
+ else if (char === ')') {
36
+ depth--;
37
+ currentField += char;
38
+ }
39
+ else if (char === ',' && depth === 0) {
40
+ fields.push(currentField.trim());
41
+ currentField = '';
42
+ }
43
+ else {
44
+ currentField += char;
45
+ }
46
+ }
47
+ if (currentField) {
48
+ fields.push(currentField.trim());
49
+ }
50
+ return fields;
51
+ }
52
+ /**
53
+ * Convert object to array based on ABI type structure
54
+ * Supports nested tuples recursively
55
+ *
56
+ * @param abiType ABI type string
57
+ * @param value Value (can be object or array)
58
+ * @returns Array value
59
+ */
60
+ static convertObjectToArray(abiType, value) {
61
+ // If already an array or not an object, return as-is
62
+ if (Array.isArray(value) ||
63
+ typeof value !== 'object' ||
64
+ value === null) {
65
+ return value;
66
+ }
67
+ // If not a tuple type, return as-is
68
+ if (!abiType.startsWith('tuple(')) {
69
+ return value;
70
+ }
71
+ // Parse tuple field types
72
+ const fieldTypes = this.parseTupleFields(abiType);
73
+ const fieldNames = Object.keys(value);
74
+ if (fieldNames.length !== fieldTypes.length) {
75
+ throw new Error(`Tuple field count mismatch: expected ${fieldTypes.length} fields, got ${fieldNames.length} (${fieldNames.join(', ')})`);
76
+ }
77
+ // Convert object to array, recursively handling nested tuples
78
+ const result = [];
79
+ for (let i = 0; i < fieldNames.length; i++) {
80
+ const fieldName = fieldNames[i];
81
+ const fieldType = fieldTypes[i];
82
+ const fieldValue = value[fieldName];
83
+ // Recursively convert nested tuples
84
+ if (fieldType.startsWith('tuple(')) {
85
+ result.push(this.convertObjectToArray(fieldType, fieldValue));
86
+ }
87
+ else {
88
+ result.push(fieldValue);
89
+ }
90
+ }
91
+ return result;
92
+ }
93
+ /**
94
+ * Encode a value with given ABI type
95
+ *
96
+ * @param abiType ABI type string (e.g., "string", "uint256", "tuple(string,uint8)")
97
+ * @param value Value to encode (objects are automatically converted to arrays)
98
+ * @returns Encoded bytes (with 0x prefix)
99
+ *
100
+ * @example
101
+ * // Simple value
102
+ * TagAbiCodec.encode("string", "hello");
103
+ *
104
+ * // Array value
105
+ * TagAbiCodec.encode("string[]", ["a", "b", "c"]);
106
+ *
107
+ * // Tuple with object input
108
+ * TagAbiCodec.encode("tuple(string,uint8)", {name: "Alice", age: 30});
109
+ *
110
+ * // Nested tuple with object input
111
+ * TagAbiCodec.encode(
112
+ * "tuple(string,tuple(uint8,bool))",
113
+ * {name: "Alice", profile: {age: 30, verified: true}}
114
+ * );
115
+ *
116
+ * // Tuple with array input (still supported)
117
+ * TagAbiCodec.encode("tuple(string,uint8)", ["Alice", 30]);
118
+ */
119
+ static encode(abiType, value) {
120
+ // Convert object to array if needed (handles nested tuples recursively)
121
+ const convertedValue = this.convertObjectToArray(abiType, value);
122
+ // Use ethers AbiCoder to encode
123
+ return this.abiCoder.encode([abiType], [convertedValue]);
124
+ }
125
+ /**
126
+ * Decode bytes with given ABI type
127
+ *
128
+ * @param abiType ABI type string
129
+ * @param encodedData Encoded bytes (with or without 0x prefix)
130
+ * @returns Decoded value
131
+ *
132
+ * @example
133
+ * TagAbiCodec.decode("string", encodedBytes); // → "hello"
134
+ * TagAbiCodec.decode("uint256", encodedBytes); // → 123n (BigInt)
135
+ * TagAbiCodec.decode("tuple(string,uint8)", encodedBytes); // → ["Alice", 30n]
136
+ */
137
+ static decode(abiType, encodedData) {
138
+ const decoded = this.abiCoder.decode([abiType], encodedData);
139
+ return decoded[0];
140
+ }
141
+ }
142
+ exports.TagAbiCodec = TagAbiCodec;
143
+ TagAbiCodec.abiCoder = new ethers_1.AbiCoder();
144
+ //# sourceMappingURL=tag-abi-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag-abi-codec.js","sourceRoot":"","sources":["../../src/utils/tag-abi-codec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Tag Type Builder
3
+ * Calculate ABI type bytes offline without contract calls
4
+ * Does NOT handle encoding/decoding - use TagAbiCodec for that
5
+ *
6
+ * Encoding Rules:
7
+ * - uint: 0x01 + size (size = bits/8)
8
+ * - int: 0x00 + size
9
+ * - bool: 0x02
10
+ * - string: 0x03
11
+ * - array: 0x04 + elementType
12
+ * - fixedArray: 0x05 + length (2 bytes) + elementType
13
+ * - tuple: 0x06 + fieldCount (2 bytes) + fieldTypes...
14
+ * - address: 0x07
15
+ * - fixedBytes: 0x08 + size
16
+ * - bytes: 0x09
17
+ */
18
+ export declare class TagTypeBuilder {
19
+ private typeBytes;
20
+ private abiTypeString;
21
+ protected constructor(typeBytes: string, abiTypeString?: string);
22
+ /**
23
+ * Get ABI type bytes (without 0x prefix)
24
+ */
25
+ getTypeBytes(): string;
26
+ /**
27
+ * Get ABI type string (e.g., "string", "uint256", "tuple(string,uint8)")
28
+ */
29
+ getAbiTypeString(): string;
30
+ /**
31
+ * Parse type bytes to ABI type string
32
+ * This is the reverse operation of building type bytes
33
+ * @param typeBytes Hex string of type bytes (with or without 0x prefix)
34
+ * @returns ABI type string
35
+ */
36
+ static parseTypeBytesToAbiString(typeBytes: string): string;
37
+ /**
38
+ * Calculate the byte length of a type bytes string (without 0x prefix)
39
+ * @private
40
+ */
41
+ private static getTypeBytesLength;
42
+ /**
43
+ * Get field names (for Tuple types)
44
+ * Returns format: string[][], each element is a tuple's field name array
45
+ */
46
+ getFieldNames(): string[][];
47
+ /**
48
+ * uint type
49
+ * @param bits Bit count: 8, 16, 24, ..., 256 (must be divisible by 8)
50
+ * @example
51
+ * TagTypeBuilder.uint(8) → "0101"
52
+ * TagTypeBuilder.uint(256) → "0120"
53
+ */
54
+ static uint(bits?: number): TagTypeBuilder;
55
+ /**
56
+ * int type
57
+ * @param bits Bit count: 8, 16, 24, ..., 256 (must be divisible by 8)
58
+ * @example
59
+ * TagTypeBuilder.int(8) → "0001"
60
+ * TagTypeBuilder.int(256) → "0020"
61
+ */
62
+ static int(bits?: number): TagTypeBuilder;
63
+ /**
64
+ * bool type
65
+ * @example
66
+ * TagTypeBuilder.bool() → "02"
67
+ */
68
+ static bool(): TagTypeBuilder;
69
+ /**
70
+ * string type
71
+ * @example
72
+ * TagTypeBuilder.string() → "03"
73
+ */
74
+ static string(): TagTypeBuilder;
75
+ /**
76
+ * address type
77
+ * @example
78
+ * TagTypeBuilder.address() → "07"
79
+ */
80
+ static address(): TagTypeBuilder;
81
+ /**
82
+ * bytes type (dynamic length)
83
+ * @example
84
+ * TagTypeBuilder.bytes() → "09"
85
+ */
86
+ static bytes(): TagTypeBuilder;
87
+ /**
88
+ * bytesN type (fixed length)
89
+ * @param size Byte count: 1-32
90
+ * @example
91
+ * TagTypeBuilder.fixedBytes(32) → "0820"
92
+ */
93
+ static fixedBytes(size: number): TagTypeBuilder;
94
+ /**
95
+ * Dynamic array
96
+ * @param elementType Element type
97
+ * @example
98
+ * TagTypeBuilder.array(TagTypeBuilder.address()) → "0407"
99
+ */
100
+ static array(elementType: TagTypeBuilder): TagTypeBuilder;
101
+ /**
102
+ * Fixed-length array
103
+ * @param elementType Element type
104
+ * @param length Array length (1-65535)
105
+ * @example
106
+ * TagTypeBuilder.fixedArray(TagTypeBuilder.address(), 5) → "05000507"
107
+ */
108
+ static fixedArray(elementType: TagTypeBuilder, length: number): TagTypeBuilder;
109
+ /**
110
+ * tuple type
111
+ * @param fields Field definitions, format: { fieldName: fieldType }
112
+ * @example
113
+ * TagTypeBuilder.tuple({
114
+ * name: TagTypeBuilder.string(),
115
+ * age: TagTypeBuilder.uint8()
116
+ * }) → "060002" + "03" + "0101"
117
+ *
118
+ * Field names are collected in pre-order traversal (DFS pre-order) for nested tuples.
119
+ * Pre-order: Visit root first, then recursively visit children left-to-right.
120
+ *
121
+ * Example tree structure: A{B{D{E, F}}, C}
122
+ * fieldNames = [
123
+ * ["i", "j"], // A's fields (root)
124
+ * ["i"], // B's fields (A's 1st child)
125
+ * ["i", "j"], // D's fields (B's child)
126
+ * ["i", "j"], // E's fields (D's 1st child)
127
+ * ["i", "j"], // F's fields (D's 2nd child)
128
+ * ["i"] // C's fields (A's 2nd child)
129
+ * ]
130
+ */
131
+ static tuple(fields: Record<string, TagTypeBuilder>): TupleTypeBuilder;
132
+ static uint8(): TagTypeBuilder;
133
+ static uint16(): TagTypeBuilder;
134
+ static uint32(): TagTypeBuilder;
135
+ static uint64(): TagTypeBuilder;
136
+ static uint128(): TagTypeBuilder;
137
+ static uint256(): TagTypeBuilder;
138
+ static int8(): TagTypeBuilder;
139
+ static int16(): TagTypeBuilder;
140
+ static int32(): TagTypeBuilder;
141
+ static int64(): TagTypeBuilder;
142
+ static int128(): TagTypeBuilder;
143
+ static int256(): TagTypeBuilder;
144
+ static bytes32(): TagTypeBuilder;
145
+ static addressArray(): TagTypeBuilder;
146
+ static stringArray(): TagTypeBuilder;
147
+ static uint256Array(): TagTypeBuilder;
148
+ }
149
+ /**
150
+ * Tuple Type Builder (supports field names and object encoding)
151
+ */
152
+ export declare class TupleTypeBuilder extends TagTypeBuilder {
153
+ private fieldNames;
154
+ private fieldTypes?;
155
+ constructor(typeBytes: string, fieldNames: string[][], abiTypeString?: string, fieldTypes?: Record<string, TagTypeBuilder>);
156
+ getFieldNames(): string[][];
157
+ }
158
+ //# sourceMappingURL=tag-type-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag-type-builder.d.ts","sourceRoot":"","sources":["../../src/utils/tag-type-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,cAAc;IAC1B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAc;IAEnC,SAAS,aAAa,SAAS,EAAE,MAAM,EAAE,aAAa,GAAE,MAAW;IAKnE;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;;;;OAKG;IACH,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAsF3D;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAgDjC;;;OAGG;IACH,aAAa,IAAI,MAAM,EAAE,EAAE;IAS3B;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,CAAC,IAAI,GAAE,MAAY,GAAG,cAAc;IAS/C;;;;;;OAMG;IACH,MAAM,CAAC,GAAG,CAAC,IAAI,GAAE,MAAY,GAAG,cAAc;IAS9C;;;;OAIG;IACH,MAAM,CAAC,IAAI,IAAI,cAAc;IAI7B;;;;OAIG;IACH,MAAM,CAAC,MAAM,IAAI,cAAc;IAI/B;;;;OAIG;IACH,MAAM,CAAC,OAAO,IAAI,cAAc;IAIhC;;;;OAIG;IACH,MAAM,CAAC,KAAK,IAAI,cAAc;IAI9B;;;;;OAKG;IACH,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAY/C;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,cAAc,GAAG,cAAc;IAYzD;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,CAChB,WAAW,EAAE,cAAc,EAC3B,MAAM,EAAE,MAAM,GACZ,cAAc;IAoBjB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,gBAAgB;IAyCtE,MAAM,CAAC,KAAK;IAGZ,MAAM,CAAC,MAAM;IAGb,MAAM,CAAC,MAAM;IAGb,MAAM,CAAC,MAAM;IAGb,MAAM,CAAC,OAAO;IAGd,MAAM,CAAC,OAAO;IAId,MAAM,CAAC,IAAI;IAGX,MAAM,CAAC,KAAK;IAGZ,MAAM,CAAC,KAAK;IAGZ,MAAM,CAAC,KAAK;IAGZ,MAAM,CAAC,MAAM;IAGb,MAAM,CAAC,MAAM;IAIb,MAAM,CAAC,OAAO;IAId,MAAM,CAAC,YAAY;IAGnB,MAAM,CAAC,WAAW;IAGlB,MAAM,CAAC,YAAY;CAGnB;AAED;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,cAAc;IACnD,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,UAAU,CAAC,CAAiC;gBAGnD,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAAE,EAAE,EACtB,aAAa,GAAE,MAAW,EAC1B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC;IAO5C,aAAa,IAAI,MAAM,EAAE,EAAE;CAG3B"}