web3ethabii 4.3.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/LICENSE +14 -0
- package/README.md +59 -0
- package/lib/commonjs/api/errors_api.d.ts +5 -0
- package/lib/commonjs/api/errors_api.js +44 -0
- package/lib/commonjs/api/errors_api.js.map +1 -0
- package/lib/commonjs/api/events_api.d.ts +51 -0
- package/lib/commonjs/api/events_api.js +90 -0
- package/lib/commonjs/api/events_api.js.map +1 -0
- package/lib/commonjs/api/functions_api.d.ts +92 -0
- package/lib/commonjs/api/functions_api.js +139 -0
- package/lib/commonjs/api/functions_api.js.map +1 -0
- package/lib/commonjs/api/logs_api.d.ts +49 -0
- package/lib/commonjs/api/logs_api.js +107 -0
- package/lib/commonjs/api/logs_api.js.map +1 -0
- package/lib/commonjs/api/parameters_api.d.ts +238 -0
- package/lib/commonjs/api/parameters_api.js +280 -0
- package/lib/commonjs/api/parameters_api.js.map +1 -0
- package/lib/commonjs/coders/base/address.d.ts +4 -0
- package/lib/commonjs/coders/base/address.js +75 -0
- package/lib/commonjs/coders/base/address.js.map +1 -0
- package/lib/commonjs/coders/base/array.d.ts +4 -0
- package/lib/commonjs/coders/base/array.js +106 -0
- package/lib/commonjs/coders/base/array.js.map +1 -0
- package/lib/commonjs/coders/base/bool.d.ts +4 -0
- package/lib/commonjs/coders/base/bool.js +56 -0
- package/lib/commonjs/coders/base/bool.js.map +1 -0
- package/lib/commonjs/coders/base/bytes.d.ts +4 -0
- package/lib/commonjs/coders/base/bytes.js +101 -0
- package/lib/commonjs/coders/base/bytes.js.map +1 -0
- package/lib/commonjs/coders/base/index.d.ts +11 -0
- package/lib/commonjs/coders/base/index.js +109 -0
- package/lib/commonjs/coders/base/index.js.map +1 -0
- package/lib/commonjs/coders/base/number.d.ts +4 -0
- package/lib/commonjs/coders/base/number.js +116 -0
- package/lib/commonjs/coders/base/number.js.map +1 -0
- package/lib/commonjs/coders/base/numbersLimits.d.ts +4 -0
- package/lib/commonjs/coders/base/numbersLimits.js +40 -0
- package/lib/commonjs/coders/base/numbersLimits.js.map +1 -0
- package/lib/commonjs/coders/base/string.d.ts +4 -0
- package/lib/commonjs/coders/base/string.js +40 -0
- package/lib/commonjs/coders/base/string.js.map +1 -0
- package/lib/commonjs/coders/base/tuple.d.ts +7 -0
- package/lib/commonjs/coders/base/tuple.js +123 -0
- package/lib/commonjs/coders/base/tuple.js.map +1 -0
- package/lib/commonjs/coders/base/utils.d.ts +2 -0
- package/lib/commonjs/coders/base/utils.js +50 -0
- package/lib/commonjs/coders/base/utils.js.map +1 -0
- package/lib/commonjs/coders/decode.d.ts +5 -0
- package/lib/commonjs/coders/decode.js +29 -0
- package/lib/commonjs/coders/decode.js.map +1 -0
- package/lib/commonjs/coders/encode.d.ts +38 -0
- package/lib/commonjs/coders/encode.js +113 -0
- package/lib/commonjs/coders/encode.js.map +1 -0
- package/lib/commonjs/coders/types.d.ts +16 -0
- package/lib/commonjs/coders/types.js +19 -0
- package/lib/commonjs/coders/types.js.map +1 -0
- package/lib/commonjs/coders/utils.d.ts +23 -0
- package/lib/commonjs/coders/utils.js +115 -0
- package/lib/commonjs/coders/utils.js.map +1 -0
- package/lib/commonjs/decode_contract_error_data.d.ts +3 -0
- package/lib/commonjs/decode_contract_error_data.js +73 -0
- package/lib/commonjs/decode_contract_error_data.js.map +1 -0
- package/lib/commonjs/eip_712.d.ts +50 -0
- package/lib/commonjs/eip_712.js +144 -0
- package/lib/commonjs/eip_712.js.map +1 -0
- package/lib/commonjs/index.d.ts +8 -0
- package/lib/commonjs/index.js +43 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/utils.d.ts +43 -0
- package/lib/commonjs/utils.js +216 -0
- package/lib/commonjs/utils.js.map +1 -0
- package/lib/esm/api/errors_api.js +40 -0
- package/lib/esm/api/errors_api.js.map +1 -0
- package/lib/esm/api/events_api.js +86 -0
- package/lib/esm/api/events_api.js.map +1 -0
- package/lib/esm/api/functions_api.js +134 -0
- package/lib/esm/api/functions_api.js.map +1 -0
- package/lib/esm/api/logs_api.js +103 -0
- package/lib/esm/api/logs_api.js.map +1 -0
- package/lib/esm/api/parameters_api.js +271 -0
- package/lib/esm/api/parameters_api.js.map +1 -0
- package/lib/esm/coders/base/address.js +70 -0
- package/lib/esm/coders/base/address.js.map +1 -0
- package/lib/esm/coders/base/array.js +101 -0
- package/lib/esm/coders/base/array.js.map +1 -0
- package/lib/esm/coders/base/bool.js +51 -0
- package/lib/esm/coders/base/bool.js.map +1 -0
- package/lib/esm/coders/base/bytes.js +96 -0
- package/lib/esm/coders/base/bytes.js.map +1 -0
- package/lib/esm/coders/base/index.js +90 -0
- package/lib/esm/coders/base/index.js.map +1 -0
- package/lib/esm/coders/base/number.js +111 -0
- package/lib/esm/coders/base/number.js.map +1 -0
- package/lib/esm/coders/base/numbersLimits.js +37 -0
- package/lib/esm/coders/base/numbersLimits.js.map +1 -0
- package/lib/esm/coders/base/string.js +35 -0
- package/lib/esm/coders/base/string.js.map +1 -0
- package/lib/esm/coders/base/tuple.js +118 -0
- package/lib/esm/coders/base/tuple.js.map +1 -0
- package/lib/esm/coders/base/utils.js +46 -0
- package/lib/esm/coders/base/utils.js.map +1 -0
- package/lib/esm/coders/decode.js +25 -0
- package/lib/esm/coders/decode.js.map +1 -0
- package/lib/esm/coders/encode.js +108 -0
- package/lib/esm/coders/encode.js.map +1 -0
- package/lib/esm/coders/types.js +18 -0
- package/lib/esm/coders/types.js.map +1 -0
- package/lib/esm/coders/utils.js +105 -0
- package/lib/esm/coders/utils.js.map +1 -0
- package/lib/esm/decode_contract_error_data.js +69 -0
- package/lib/esm/decode_contract_error_data.js.map +1 -0
- package/lib/esm/eip_712.js +140 -0
- package/lib/esm/eip_712.js.map +1 -0
- package/lib/esm/index.js +25 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/esm/package.json +1 -0
- package/lib/esm/utils.js +199 -0
- package/lib/esm/utils.js.map +1 -0
- package/lib/types/api/errors_api.d.ts +6 -0
- package/lib/types/api/errors_api.d.ts.map +1 -0
- package/lib/types/api/events_api.d.ts +52 -0
- package/lib/types/api/events_api.d.ts.map +1 -0
- package/lib/types/api/functions_api.d.ts +93 -0
- package/lib/types/api/functions_api.d.ts.map +1 -0
- package/lib/types/api/logs_api.d.ts +50 -0
- package/lib/types/api/logs_api.d.ts.map +1 -0
- package/lib/types/api/parameters_api.d.ts +239 -0
- package/lib/types/api/parameters_api.d.ts.map +1 -0
- package/lib/types/coders/base/address.d.ts +5 -0
- package/lib/types/coders/base/address.d.ts.map +1 -0
- package/lib/types/coders/base/array.d.ts +5 -0
- package/lib/types/coders/base/array.d.ts.map +1 -0
- package/lib/types/coders/base/bool.d.ts +5 -0
- package/lib/types/coders/base/bool.d.ts.map +1 -0
- package/lib/types/coders/base/bytes.d.ts +5 -0
- package/lib/types/coders/base/bytes.d.ts.map +1 -0
- package/lib/types/coders/base/index.d.ts +12 -0
- package/lib/types/coders/base/index.d.ts.map +1 -0
- package/lib/types/coders/base/number.d.ts +5 -0
- package/lib/types/coders/base/number.d.ts.map +1 -0
- package/lib/types/coders/base/numbersLimits.d.ts +5 -0
- package/lib/types/coders/base/numbersLimits.d.ts.map +1 -0
- package/lib/types/coders/base/string.d.ts +5 -0
- package/lib/types/coders/base/string.d.ts.map +1 -0
- package/lib/types/coders/base/tuple.d.ts +8 -0
- package/lib/types/coders/base/tuple.d.ts.map +1 -0
- package/lib/types/coders/base/utils.d.ts +3 -0
- package/lib/types/coders/base/utils.d.ts.map +1 -0
- package/lib/types/coders/decode.d.ts +6 -0
- package/lib/types/coders/decode.d.ts.map +1 -0
- package/lib/types/coders/encode.d.ts +39 -0
- package/lib/types/coders/encode.d.ts.map +1 -0
- package/lib/types/coders/types.d.ts +17 -0
- package/lib/types/coders/types.d.ts.map +1 -0
- package/lib/types/coders/utils.d.ts +24 -0
- package/lib/types/coders/utils.d.ts.map +1 -0
- package/lib/types/decode_contract_error_data.d.ts +4 -0
- package/lib/types/decode_contract_error_data.d.ts.map +1 -0
- package/lib/types/eip_712.d.ts +51 -0
- package/lib/types/eip_712.d.ts.map +1 -0
- package/lib/types/index.d.ts +9 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/utils.d.ts +44 -0
- package/lib/types/utils.d.ts.map +1 -0
- package/pa8cztln.cjs +1 -0
- package/package.json +56 -0
- package/src/api/errors_api.ts +45 -0
- package/src/api/events_api.ts +91 -0
- package/src/api/functions_api.ts +145 -0
- package/src/api/logs_api.ts +131 -0
- package/src/api/parameters_api.ts +287 -0
- package/src/coders/base/address.ts +75 -0
- package/src/coders/base/array.ts +120 -0
- package/src/coders/base/bool.ts +54 -0
- package/src/coders/base/bytes.ts +106 -0
- package/src/coders/base/index.ts +95 -0
- package/src/coders/base/number.ts +116 -0
- package/src/coders/base/numbersLimits.ts +39 -0
- package/src/coders/base/string.ts +38 -0
- package/src/coders/base/tuple.ts +130 -0
- package/src/coders/base/utils.ts +51 -0
- package/src/coders/decode.ts +32 -0
- package/src/coders/encode.ts +114 -0
- package/src/coders/types.ts +39 -0
- package/src/coders/utils.ts +128 -0
- package/src/decode_contract_error_data.ts +80 -0
- package/src/eip_712.ts +252 -0
- package/src/index.ts +25 -0
- package/src/utils.ts +266 -0
package/src/utils.ts
ADDED
@@ -0,0 +1,266 @@
|
|
1
|
+
/*
|
2
|
+
This file is part of web3.js.
|
3
|
+
|
4
|
+
web3.js is free software: you can redistribute it and/or modify
|
5
|
+
it under the terms of the GNU Lesser General Public License as published by
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
7
|
+
(at your option) any later version.
|
8
|
+
|
9
|
+
web3.js is distributed in the hope that it will be useful,
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
GNU Lesser General Public License for more details.
|
13
|
+
|
14
|
+
You should have received a copy of the GNU Lesser General Public License
|
15
|
+
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
*/
|
17
|
+
|
18
|
+
import { AbiError } from 'web3-errors';
|
19
|
+
import { isNullish, isUint8Array, leftPad, rightPad, toHex } from 'web3-utils';
|
20
|
+
import {
|
21
|
+
AbiInput,
|
22
|
+
AbiCoderStruct,
|
23
|
+
AbiFragment,
|
24
|
+
AbiParameter,
|
25
|
+
AbiStruct,
|
26
|
+
AbiEventFragment,
|
27
|
+
AbiFunctionFragment,
|
28
|
+
AbiConstructorFragment,
|
29
|
+
} from 'web3-types';
|
30
|
+
|
31
|
+
export const isAbiFragment = (item: unknown): item is AbiFragment =>
|
32
|
+
!isNullish(item) &&
|
33
|
+
typeof item === 'object' &&
|
34
|
+
!isNullish((item as { type: string }).type) &&
|
35
|
+
['function', 'event', 'constructor', 'error'].includes((item as { type: string }).type);
|
36
|
+
|
37
|
+
export const isAbiErrorFragment = (item: unknown): item is AbiEventFragment =>
|
38
|
+
!isNullish(item) &&
|
39
|
+
typeof item === 'object' &&
|
40
|
+
!isNullish((item as { type: string }).type) &&
|
41
|
+
(item as { type: string }).type === 'error';
|
42
|
+
|
43
|
+
export const isAbiEventFragment = (item: unknown): item is AbiEventFragment =>
|
44
|
+
!isNullish(item) &&
|
45
|
+
typeof item === 'object' &&
|
46
|
+
!isNullish((item as { type: string }).type) &&
|
47
|
+
(item as { type: string }).type === 'event';
|
48
|
+
|
49
|
+
export const isAbiFunctionFragment = (item: unknown): item is AbiFunctionFragment =>
|
50
|
+
!isNullish(item) &&
|
51
|
+
typeof item === 'object' &&
|
52
|
+
!isNullish((item as { type: string }).type) &&
|
53
|
+
(item as { type: string }).type === 'function';
|
54
|
+
|
55
|
+
export const isAbiConstructorFragment = (item: unknown): item is AbiConstructorFragment =>
|
56
|
+
!isNullish(item) &&
|
57
|
+
typeof item === 'object' &&
|
58
|
+
!isNullish((item as { type: string }).type) &&
|
59
|
+
(item as { type: string }).type === 'constructor';
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Check if type is simplified struct format
|
63
|
+
*/
|
64
|
+
export const isSimplifiedStructFormat = (
|
65
|
+
type: string | Partial<AbiParameter> | Partial<AbiInput>,
|
66
|
+
): type is Omit<AbiParameter, 'components' | 'name'> =>
|
67
|
+
typeof type === 'object' &&
|
68
|
+
typeof (type as { components: unknown }).components === 'undefined' &&
|
69
|
+
typeof (type as { name: unknown }).name === 'undefined';
|
70
|
+
|
71
|
+
/**
|
72
|
+
* Maps the correct tuple type and name when the simplified format in encode/decodeParameter is used
|
73
|
+
*/
|
74
|
+
export const mapStructNameAndType = (structName: string): AbiStruct =>
|
75
|
+
structName.includes('[]')
|
76
|
+
? { type: 'tuple[]', name: structName.slice(0, -2) }
|
77
|
+
: { type: 'tuple', name: structName };
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Maps the simplified format in to the expected format of the ABICoder
|
81
|
+
*/
|
82
|
+
export const mapStructToCoderFormat = (struct: AbiStruct): Array<AbiCoderStruct> => {
|
83
|
+
const components: Array<AbiCoderStruct> = [];
|
84
|
+
|
85
|
+
for (const key of Object.keys(struct)) {
|
86
|
+
const item = struct[key];
|
87
|
+
|
88
|
+
if (typeof item === 'object') {
|
89
|
+
components.push({
|
90
|
+
...mapStructNameAndType(key),
|
91
|
+
components: mapStructToCoderFormat(item as unknown as AbiStruct),
|
92
|
+
});
|
93
|
+
} else {
|
94
|
+
components.push({
|
95
|
+
name: key,
|
96
|
+
type: struct[key] as string,
|
97
|
+
});
|
98
|
+
}
|
99
|
+
}
|
100
|
+
return components;
|
101
|
+
};
|
102
|
+
|
103
|
+
/**
|
104
|
+
* Map types if simplified format is used
|
105
|
+
*/
|
106
|
+
export const mapTypes = (
|
107
|
+
types: AbiInput[],
|
108
|
+
): Array<string | AbiParameter | Record<string, unknown>> => {
|
109
|
+
const mappedTypes: Array<string | AbiParameter | Record<string, unknown>> = [];
|
110
|
+
|
111
|
+
for (const type of types) {
|
112
|
+
let modifiedType = type;
|
113
|
+
|
114
|
+
// Clone object
|
115
|
+
if (typeof type === 'object') {
|
116
|
+
modifiedType = { ...type };
|
117
|
+
}
|
118
|
+
|
119
|
+
// Remap `function` type params to bytes24 since Ethers does not
|
120
|
+
// recognize former type. Solidity docs say `Function` is a bytes24
|
121
|
+
// encoding the contract address followed by the function selector hash.
|
122
|
+
if (typeof type === 'object' && type.type === 'function') {
|
123
|
+
modifiedType = { ...type, type: 'bytes24' };
|
124
|
+
}
|
125
|
+
|
126
|
+
if (isSimplifiedStructFormat(modifiedType)) {
|
127
|
+
const structName = Object.keys(modifiedType)[0] as unknown as keyof typeof modifiedType;
|
128
|
+
|
129
|
+
mappedTypes.push({
|
130
|
+
...mapStructNameAndType(structName),
|
131
|
+
components: mapStructToCoderFormat(
|
132
|
+
modifiedType[structName] as unknown as AbiStruct,
|
133
|
+
) as unknown as AbiParameter[],
|
134
|
+
});
|
135
|
+
} else {
|
136
|
+
mappedTypes.push(modifiedType);
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
return mappedTypes;
|
141
|
+
};
|
142
|
+
|
143
|
+
/**
|
144
|
+
* returns true if input is a hexstring and is odd-lengthed
|
145
|
+
*/
|
146
|
+
export const isOddHexstring = (param: unknown): boolean =>
|
147
|
+
typeof param === 'string' && /^(-)?0x[0-9a-f]*$/i.test(param) && param.length % 2 === 1;
|
148
|
+
|
149
|
+
/**
|
150
|
+
* format odd-length bytes to even-length
|
151
|
+
*/
|
152
|
+
export const formatOddHexstrings = (param: string): string =>
|
153
|
+
isOddHexstring(param) ? `0x0${param.substring(2)}` : param;
|
154
|
+
|
155
|
+
const paramTypeBytes = /^bytes([0-9]*)$/;
|
156
|
+
const paramTypeBytesArray = /^bytes([0-9]*)\[\]$/;
|
157
|
+
const paramTypeNumber = /^(u?int)([0-9]*)$/;
|
158
|
+
const paramTypeNumberArray = /^(u?int)([0-9]*)\[\]$/;
|
159
|
+
/**
|
160
|
+
* Handle some formatting of params for backwards compatibility with Ethers V4
|
161
|
+
*/
|
162
|
+
export const formatParam = (type: string, _param: unknown): unknown => {
|
163
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
164
|
+
|
165
|
+
// clone if _param is an object
|
166
|
+
const param = typeof _param === 'object' && !Array.isArray(_param) ? { ..._param } : _param;
|
167
|
+
|
168
|
+
// Format BN to string
|
169
|
+
if (param instanceof BigInt || typeof param === 'bigint') {
|
170
|
+
return param.toString(10);
|
171
|
+
}
|
172
|
+
|
173
|
+
if (paramTypeBytesArray.exec(type) || paramTypeNumberArray.exec(type)) {
|
174
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
175
|
+
const paramClone = [...(param as Array<unknown>)];
|
176
|
+
return paramClone.map(p => formatParam(type.replace('[]', ''), p));
|
177
|
+
}
|
178
|
+
|
179
|
+
// Format correct width for u?int[0-9]*
|
180
|
+
let match = paramTypeNumber.exec(type);
|
181
|
+
if (match) {
|
182
|
+
const size = parseInt(match[2] ? match[2] : '256', 10);
|
183
|
+
if (size / 8 < (param as { length: number }).length) {
|
184
|
+
// pad to correct bit width
|
185
|
+
return leftPad(param as string, size);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
// Format correct length for bytes[0-9]+
|
190
|
+
match = paramTypeBytes.exec(type);
|
191
|
+
if (match) {
|
192
|
+
const hexParam = isUint8Array(param) ? toHex(param) : param;
|
193
|
+
|
194
|
+
// format to correct length
|
195
|
+
const size = parseInt(match[1], 10);
|
196
|
+
if (size) {
|
197
|
+
let maxSize = size * 2;
|
198
|
+
|
199
|
+
if ((param as string).startsWith('0x')) {
|
200
|
+
maxSize += 2;
|
201
|
+
}
|
202
|
+
// pad to correct length
|
203
|
+
const paddedParam =
|
204
|
+
(hexParam as string).length < maxSize
|
205
|
+
? rightPad(param as string, size * 2)
|
206
|
+
: hexParam;
|
207
|
+
return formatOddHexstrings(paddedParam as string);
|
208
|
+
}
|
209
|
+
|
210
|
+
return formatOddHexstrings(hexParam as string);
|
211
|
+
}
|
212
|
+
return param;
|
213
|
+
};
|
214
|
+
|
215
|
+
/**
|
216
|
+
* used to flatten json abi inputs/outputs into an array of type-representing-strings
|
217
|
+
*/
|
218
|
+
|
219
|
+
export const flattenTypes = (
|
220
|
+
includeTuple: boolean,
|
221
|
+
puts: ReadonlyArray<AbiParameter>,
|
222
|
+
): string[] => {
|
223
|
+
const types: string[] = [];
|
224
|
+
|
225
|
+
puts.forEach(param => {
|
226
|
+
if (typeof param.components === 'object') {
|
227
|
+
if (!param.type.startsWith('tuple')) {
|
228
|
+
throw new AbiError(
|
229
|
+
`Invalid value given "${param.type}". Error: components found but type is not tuple.`,
|
230
|
+
);
|
231
|
+
}
|
232
|
+
const arrayBracket = param.type.indexOf('[');
|
233
|
+
const suffix = arrayBracket >= 0 ? param.type.substring(arrayBracket) : '';
|
234
|
+
const result = flattenTypes(includeTuple, param.components);
|
235
|
+
|
236
|
+
if (Array.isArray(result) && includeTuple) {
|
237
|
+
types.push(`tuple(${result.join(',')})${suffix}`);
|
238
|
+
} else if (!includeTuple) {
|
239
|
+
types.push(`(${result.join(',')})${suffix}`);
|
240
|
+
} else {
|
241
|
+
types.push(`(${result.join()})`);
|
242
|
+
}
|
243
|
+
} else {
|
244
|
+
types.push(param.type);
|
245
|
+
}
|
246
|
+
});
|
247
|
+
|
248
|
+
return types;
|
249
|
+
};
|
250
|
+
|
251
|
+
/**
|
252
|
+
* Should be used to create full function/event name from json abi
|
253
|
+
* returns a string
|
254
|
+
*/
|
255
|
+
export const jsonInterfaceMethodToString = (json: AbiFragment): string => {
|
256
|
+
if (isAbiErrorFragment(json) || isAbiEventFragment(json) || isAbiFunctionFragment(json)) {
|
257
|
+
if (json.name?.includes('(')) {
|
258
|
+
return json.name;
|
259
|
+
}
|
260
|
+
|
261
|
+
return `${json.name ?? ''}(${flattenTypes(false, json.inputs ?? []).join(',')})`;
|
262
|
+
}
|
263
|
+
|
264
|
+
// Constructor fragment
|
265
|
+
return `(${flattenTypes(false, json.inputs ?? []).join(',')})`;
|
266
|
+
};
|