@subsquid/evm-typegen 3.3.0 → 4.0.1

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/src/typegen.ts CHANGED
@@ -1,143 +1,260 @@
1
- import * as ethers from 'ethers'
2
- import {Logger} from '@subsquid/logger'
3
- import {def} from '@subsquid/util-internal'
4
- import {FileOutput, OutDir} from '@subsquid/util-internal-code-printer'
5
- import {getFullTupleType, getReturnType, getStructType, getTupleType, getType} from './util/types'
1
+ import { Logger } from '@subsquid/logger'
2
+ import { def } from '@subsquid/util-internal'
3
+ import { keccak256 } from '@subsquid/evm-abi'
4
+ import { getType } from './util/types'
5
+ import type { Abi, AbiEvent, AbiFunction, AbiParameter } from 'abitype'
6
+ import { FileOutput, OutDir } from '@subsquid/util-internal-code-printer'
6
7
 
8
+ function areItemEqual(item1: AbiEvent | AbiFunction, item2: AbiEvent | AbiFunction): boolean {
9
+ if (item1.name !== item2.name || item1.inputs.length !== item2.inputs.length || item1.type !== item2.type) {
10
+ return false
11
+ }
12
+ return item1.inputs.every((input, idx) => {
13
+ const input2 = item2.inputs[idx]
14
+ return input.name === input2.name && input.type === input2.type
15
+ })
16
+ }
7
17
 
8
18
  export class Typegen {
9
- private out: FileOutput
19
+ private out: FileOutput
10
20
 
11
- constructor(private dest: OutDir, private abi: ethers.Interface, private basename: string, private log: Logger) {
12
- this.out = dest.file(basename + '.ts')
13
- }
21
+ constructor(
22
+ dest: OutDir,
23
+ private abi: Abi,
24
+ basename: string,
25
+ private log: Logger,
26
+ ) {
27
+ this.out = dest.file(basename + '.ts')
28
+ }
29
+
30
+ async generate() {
31
+ this.out.line(`import * as p from '@subsquid/evm-codec'`)
32
+ this.out.line(
33
+ `import { event, fun, indexed, ContractBase } from '@subsquid/evm-abi'`,
34
+ )
35
+ this.out.line(
36
+ `import type { EventParams as EParams, FunctionArguments, FunctionReturn } from '@subsquid/evm-abi'`,
37
+ )
14
38
 
15
- generate(): void {
16
- this.out.line("import * as ethers from 'ethers'")
17
- this.out.line("import {LogEvent, Func, ContractBase} from './abi.support'")
18
- this.out.line(`import {ABI_JSON} from './${this.basename}.abi'`)
19
- this.out.line()
20
- this.out.line("export const abi = new ethers.Interface(ABI_JSON);")
39
+ this.generateEvents()
40
+ this.generateFunctions()
41
+ this.generateContract()
42
+ this.generateEventTypes()
43
+ this.generateFunctionTypes()
21
44
 
22
- this.generateEvents()
23
- this.generateFunctions()
24
- this.generateContract()
45
+ await this.out.write()
46
+ this.log.info(`saved ${this.out.file}`)
47
+ }
25
48
 
26
- this.writeAbi()
27
- this.out.write()
28
- this.log.info(`saved ${this.out.file}`)
49
+ private generateEvents() {
50
+ let events = this.getEvents()
51
+ if (events.length == 0) {
52
+ return
29
53
  }
54
+ this.out.line()
55
+ this.out.block(`export const events =`, () => {
56
+ for (let e of events) {
57
+ this.out.line(
58
+ `${this.getPropName(e)}: event("${this.topic0(e)}", {${this.toTypes(
59
+ e.inputs,
60
+ )}}),`,
61
+ )
62
+ }
63
+ })
64
+ }
30
65
 
31
- private writeAbi() {
32
- let out = this.dest.file(this.basename + '.abi.ts')
33
- let json = this.abi.formatJson()
34
- json = JSON.stringify(JSON.parse(json), null, 4)
35
- out.line(`export const ABI_JSON = ${json}`)
36
- out.write()
37
- this.log.info(`saved ${out.file}`)
66
+ private topic0(e: AbiEvent): string {
67
+ return `0x${keccak256(this.sighash(e)).toString('hex')}`
68
+ }
69
+
70
+ private toTypes(inputs: readonly AbiParameter[]): string {
71
+ return inputs.map((input, idx) => getType(input, idx)).join(', ')
72
+ }
73
+
74
+ private generateFunctions() {
75
+ let functions = this.getFunctions()
76
+ if (functions.length == 0) {
77
+ return
38
78
  }
79
+ this.out.line()
80
+ this.out.block(`export const functions =`, () => {
81
+ for (let f of functions) {
82
+ let returnType = ''
83
+ if (f.outputs?.length === 1) {
84
+ returnType = getType({ ...f.outputs[0], name: undefined })
85
+ }
86
+ if (f.outputs?.length > 1) {
87
+ returnType = `{${this.toTypes(f.outputs)}}`
88
+ }
89
+
90
+ this.out.line(
91
+ `${this.getPropName(f)}: fun("${this.functionSelector(
92
+ f,
93
+ )}", {${this.toTypes(f.inputs)}}, ${returnType}),`,
94
+ )
95
+ }
96
+ })
97
+ }
98
+
99
+ private functionSelector(f: AbiFunction): string {
100
+ const sighash = this.sighash(f)
101
+ return `0x${keccak256(sighash).slice(0, 4).toString('hex')}`
102
+ }
39
103
 
40
- private generateEvents() {
41
- let events = this.getEvents()
42
- if (events.length == 0) {
43
- return
104
+ private generateContract() {
105
+ this.out.line()
106
+ this.out.block(`export class Contract extends ContractBase`, () => {
107
+ let functions = this.getFunctions()
108
+ for (let f of functions) {
109
+ if ((f.stateMutability === 'pure' || f.stateMutability === 'view') &&
110
+ f.outputs?.length
111
+ ) {
112
+ this.out.line()
113
+ let argNames = f.inputs.map((a, idx) => a.name || `_${idx}`)
114
+ const ref = this.getPropNameGetter(f)
115
+ const [argsType] = this.toFunctionTypes(f)
116
+ let args = f.inputs
117
+ .map(
118
+ (a, idx) =>
119
+ `${argNames[idx]}: ${argsType}["${argNames[idx]}"]`,
120
+ )
121
+ .join(', ')
122
+ this.out.block(`${this.getPropName(f)}(${args})`, () => {
123
+ this.out.line(
124
+ `return this.eth_call(functions${ref}, {${argNames.join(', ')}})`,
125
+ )
126
+ })
44
127
  }
45
- this.out.line()
46
- this.out.block(`export const events =`, () => {
47
- for (let e of events) {
48
- this.out.line(`${this.getPropName(e)}: new LogEvent<${getFullTupleType(e.inputs)}>(`)
49
- this.out.indentation(() => this.out.line(`abi, '${e.topicHash}'`))
50
- this.out.line('),')
51
- }
52
- })
128
+ }
129
+ })
130
+ }
131
+
132
+ private cannonicalType(param: AbiParameter): string {
133
+ if (!param.type.startsWith('tuple')) {
134
+ return param.type
53
135
  }
136
+ const arrayBrackets = param.type.slice(5)
137
+ return `(${(param as any).components.map((param: AbiParameter) =>
138
+ this.cannonicalType(param),
139
+ )})${arrayBrackets}`
140
+ }
54
141
 
55
- private generateFunctions() {
56
- let functions = this.getFunctions()
57
- if (functions.length == 0) {
58
- return
59
- }
60
- this.out.line()
61
- this.out.block(`export const functions =`, () => {
62
- for (let f of functions) {
63
- let sighash = f.selector
64
- let pArgs = getTupleType(f.inputs)
65
- let pArgStruct = getStructType(f.inputs)
66
- let pResult = getReturnType(f.outputs)
67
- this.out.line(`${this.getPropName(f)}: new Func<${pArgs}, ${pArgStruct}, ${pResult}>(`)
68
- this.out.indentation(() => this.out.line(`abi, '${sighash}'`))
69
- this.out.line('),')
70
- }
71
- })
142
+ private sighash(item: AbiEvent | AbiFunction): string {
143
+ return `${item.name}(${item.inputs
144
+ .map((param) => this.cannonicalType(param))
145
+ .join(',')})`
146
+ }
147
+
148
+ private getPropName(item: AbiEvent | AbiFunction): string {
149
+ if (this.getOverloads(item) == 1) {
150
+ return item.name
151
+ } else {
152
+ return `"${this.sighash(item)}"`
72
153
  }
154
+ }
73
155
 
74
- private generateContract() {
75
- this.out.line()
76
- this.out.block(`export class Contract extends ContractBase`, () => {
77
- let functions = this.getFunctions()
78
- for (let f of functions) {
79
- if (f.constant && f.outputs?.length) {
80
- this.out.line()
81
- let argNames = f.inputs.map((a, idx) => a.name || `arg${idx}`)
82
- let args = f.inputs.map((a, idx) => `${argNames[idx]}: ${getType(a)}`).join(', ')
83
- this.out.block(`${this.getPropName(f)}(${args}): Promise<${getReturnType(f.outputs)}>`, () => {
84
- this.out.line(`return this.eth_call(functions${this.getRef(f)}, [${argNames.join(', ')}])`)
85
- })
86
- }
87
- }
88
- })
156
+ private getPropNameGetter(item: AbiEvent | AbiFunction): string {
157
+ if (this.getOverloads(item) == 1) {
158
+ return '.' + item.name
159
+ } else {
160
+ return `["${this.sighash(item)}"]`
89
161
  }
162
+ }
90
163
 
91
- private getRef(item: ethers.EventFragment | ethers.FunctionFragment): string {
92
- let key = this.getPropName(item)
93
- if (key[0] == "'") {
94
- return `[${key}]`
95
- } else {
96
- return '.' + key
97
- }
164
+ private getOverloads(item: AbiEvent | AbiFunction): number {
165
+ if (item.type === 'event') {
166
+ return this.eventOverloads()[item.name]
167
+ } else {
168
+ return this.functionOverloads()[item.name]
98
169
  }
170
+ }
99
171
 
100
- private getPropName(item: ethers.EventFragment | ethers.FunctionFragment): string {
101
- if (this.getOverloads(item) == 1) {
102
- return item.name
103
- } else {
104
- return `'${item.format('sighash')}'`
105
- }
172
+ private capitalize(s: string): string {
173
+ return s.charAt(0).toUpperCase() + s.slice(1)
174
+ }
175
+
176
+ private getOverloadIndex(item: AbiEvent | AbiFunction): number {
177
+ const abi = [...this.getEvents(), ...this.getFunctions()]
178
+ const overloads = abi.filter((x) => x.name === item.name)
179
+ return overloads.findIndex((x) => areItemEqual(x, item))
180
+ }
181
+
182
+ private toEventType(e: AbiEvent): string {
183
+ if (this.getOverloads(e) === 1) {
184
+ return `${this.capitalize(e.name)}EventArgs`
106
185
  }
186
+ const index = this.getOverloadIndex(e)
187
+ return `${this.capitalize(e.name)}EventArgs_${index}`
188
+ }
107
189
 
108
- private getOverloads(item: ethers.EventFragment | ethers.FunctionFragment): number {
109
- if (item instanceof ethers.EventFragment) {
110
- return this.eventOverloads()[item.name]
111
- } else {
112
- return this.functionOverloads()[item.name]
113
- }
190
+ private generateEventTypes() {
191
+ const events = this.getEvents()
192
+ if (events.length == 0) {
193
+ return
194
+ }
195
+ this.out.line()
196
+ this.out.line(`/// Event types`)
197
+ for (let e of events) {
198
+ const propName = this.getPropNameGetter(e)
199
+ this.out.line(
200
+ `export type ${this.toEventType(e)} = EParams<typeof events${propName}>`,
201
+ )
114
202
  }
203
+ }
115
204
 
116
- @def
117
- private functionOverloads(): Record<string, number> {
118
- let overloads: Record<string, number> = {}
119
- for (let item of this.getFunctions()) {
120
- overloads[item.name] = (overloads[item.name] || 0) + 1
121
- }
122
- return overloads
205
+ private toFunctionTypes(f: AbiFunction): [string, string] {
206
+ if (this.getOverloads(f) === 1) {
207
+ return [`${this.capitalize(f.name)}Params`, `${this.capitalize(f.name)}Return`]
123
208
  }
209
+ const index = this.getOverloadIndex(f)
210
+ return [`${this.capitalize(f.name)}Params_${index}`, `${this.capitalize(f.name)}Return_${index}`]
211
+ }
124
212
 
125
- @def
126
- private eventOverloads(): Record<string, number> {
127
- let overloads: Record<string, number> = {}
128
- for (let item of this.getEvents()) {
129
- overloads[item.name] = (overloads[item.name] || 0) + 1
130
- }
131
- return overloads
213
+ private generateFunctionTypes() {
214
+ let functions = this.getFunctions()
215
+ if (functions.length == 0) {
216
+ return
217
+ }
218
+ this.out.line()
219
+ this.out.line(`/// Function types`)
220
+ for (let f of functions) {
221
+ const propName = this.getPropNameGetter(f)
222
+ const [args, ret] = this.toFunctionTypes(f)
223
+ this.out.line(
224
+ `export type ${args} = FunctionArguments<typeof functions${propName}>`,
225
+ )
226
+ this.out.line(
227
+ `export type ${ret} = FunctionReturn<typeof functions${propName}>`,
228
+ )
229
+ this.out.line()
132
230
  }
231
+ }
133
232
 
134
- @def
135
- private getFunctions(): ethers.FunctionFragment[] {
136
- return this.abi.fragments.filter(f => f.type === 'function') as ethers.FunctionFragment[]
233
+ @def
234
+ private functionOverloads(): Record<string, number> {
235
+ let overloads: Record<string, number> = {}
236
+ for (let item of this.getFunctions()) {
237
+ overloads[item.name] = (overloads[item.name] || 0) + 1
137
238
  }
239
+ return overloads
240
+ }
138
241
 
139
- @def
140
- private getEvents(): ethers.EventFragment[] {
141
- return this.abi.fragments.filter(f => f.type === 'event') as ethers.EventFragment[]
242
+ @def
243
+ private eventOverloads(): Record<string, number> {
244
+ let overloads: Record<string, number> = {}
245
+ for (let item of this.getEvents()) {
246
+ overloads[item.name] = (overloads[item.name] || 0) + 1
142
247
  }
248
+ return overloads
249
+ }
250
+
251
+ @def
252
+ private getFunctions(): AbiFunction[] {
253
+ return this.abi.filter((f) => f.type === 'function') as AbiFunction[]
254
+ }
255
+
256
+ @def
257
+ private getEvents(): AbiEvent[] {
258
+ return this.abi.filter((f) => f.type === 'event') as AbiEvent[]
259
+ }
143
260
  }
package/src/util/fetch.ts CHANGED
@@ -1,13 +1,11 @@
1
- import {createLogger} from '@subsquid/logger'
2
- import {HttpClient} from '@subsquid/http-client'
3
-
1
+ import { createLogger } from '@subsquid/logger'
2
+ import { HttpClient } from '@subsquid/http-client'
4
3
 
5
4
  const http = new HttpClient({
6
- log: createLogger('sqd:evm-typegen:fetch'),
7
- retryAttempts: 3
5
+ log: createLogger('sqd:evm-typegen:fetch'),
6
+ retryAttempts: 3,
8
7
  })
9
8
 
10
-
11
- export function GET<T=any>(url: string): Promise<T> {
12
- return http.get(url)
9
+ export function GET<T = any>(url: string): Promise<T> {
10
+ return http.get(url)
13
11
  }
package/src/util/types.ts CHANGED
@@ -1,72 +1,54 @@
1
- import assert from 'assert'
2
- import type {ParamType} from 'ethers'
1
+ import type { AbiEventParameter } from 'abitype'
3
2
 
4
-
5
- // taken from: https://github.com/ethers-io/ethers.js/blob/948f77050dae884fe88932fd88af75560aac9d78/packages/cli/src.ts/typescript.ts#L10
6
- export function getType(param: ParamType): string {
7
- if (param.baseType === 'array') {
8
- assert(param.arrayChildren != null, 'Missing children for array type')
9
- return 'Array<' + getType(param.arrayChildren) + '>'
10
- }
11
-
12
- if (param.baseType === 'tuple') {
13
- assert(param.components != null, 'Missing components for tuple type')
14
- return getFullTupleType(param.components)
15
- }
16
-
17
- if (param.type === 'address' || param.type === 'string') {
18
- return 'string'
19
- }
20
-
21
- if (param.type === 'bool') {
22
- return 'boolean'
23
- }
24
-
25
- let match = param.type.match(/^(u?int)([0-9]+)$/)
26
- if (match) {
27
- return parseInt(match[2]) < 53 ? 'number' : 'bigint'
28
- }
29
-
30
- if (param.type.substring(0, 5) === 'bytes') {
31
- return 'string'
32
- }
33
-
34
- throw new Error('unknown type')
3
+ function isStaticArray(param: AbiEventParameter) {
4
+ return param.type.match(/\[\d+]$/)
35
5
  }
36
6
 
37
-
38
- export function getFullTupleType(params: ReadonlyArray<ParamType>): string {
39
- let tuple = getTupleType(params)
40
- let struct = getStructType(params)
41
- if (struct == '{}') {
42
- return tuple
43
- } else {
44
- return `(${tuple} & ${struct})`
45
- }
7
+ function isDynamicArray(param: AbiEventParameter) {
8
+ return param.type.endsWith('[]')
46
9
  }
47
10
 
48
-
49
- export function getTupleType(params: ReadonlyArray<ParamType>): string {
50
- return '[' + params.map(p => {
51
- return p.name ? `${p.name}: ${getType(p)}` : `_: ${getType(p)}`
52
- }).join(', ') + ']'
11
+ function elementsCount(param: AbiEventParameter) {
12
+ return Number(param.type.match(/\[(\d+)]$/)?.[1] ?? 0)
53
13
  }
54
14
 
55
-
56
- // https://github.com/ethers-io/ethers.js/blob/278f84174409b470fa7992e1f8b5693e6e5d2dac/src.ts/abi/coders/tuple.ts#L36
57
- export function getStructType(params: ReadonlyArray<ParamType>): string {
58
- let array: any = []
59
- let counts: Record<string, number> = {}
60
- for (let p of params) {
61
- if (p.name && array[p.name] == null) {
62
- counts[p.name] = (counts[p.name] || 0) + 1
63
- }
64
- }
65
- let fields = params.filter(p => counts[p.name] == 1)
66
- return '{' + fields.map(f => `${f.name}: ${getType(f)}`).join(', ') + '}'
15
+ function arrayChildType(param: AbiEventParameter) {
16
+ return param.type.replace(/\[\d*]$/, '')
67
17
  }
68
18
 
69
-
70
- export function getReturnType(outputs: ReadonlyArray<ParamType>) {
71
- return outputs.length == 1 ? getType(outputs[0]) : getFullTupleType(outputs)
19
+ export function getType(param: AbiEventParameter, index?: number): string {
20
+ const { name, ...namelessParam } = param
21
+
22
+ if (name) {
23
+ return `"${name}": ${getType(namelessParam as any)}`
24
+ }
25
+
26
+ if (index !== undefined) {
27
+ return `"_${index}": ${getType(namelessParam)}`
28
+ }
29
+
30
+ const { indexed, ...indexlessParam } = param
31
+ if (indexed) {
32
+ return `indexed(${getType(indexlessParam as any)})`
33
+ }
34
+ if (isStaticArray(param)) {
35
+ const elements = elementsCount(param)
36
+ return `p.fixedSizeArray(${getType({
37
+ ...param,
38
+ type: arrayChildType(param),
39
+ })}, ${elements})`
40
+ }
41
+
42
+ if (isDynamicArray(param)) {
43
+ return `p.array(${getType({
44
+ ...param,
45
+ type: arrayChildType(param),
46
+ })})`
47
+ }
48
+
49
+ if (param.type === 'tuple') {
50
+ return `p.struct({${(param as any).components.map((type: AbiEventParameter, idx: number) => getType(type, idx)).join(', ')}})`
51
+ }
52
+
53
+ return `p.${param.type}`
72
54
  }
@@ -1,57 +0,0 @@
1
- import * as ethers from 'ethers';
2
- export interface EventRecord {
3
- topics: string[];
4
- data: string;
5
- }
6
- export type LogRecord = EventRecord;
7
- export declare class LogEvent<Args> {
8
- private abi;
9
- readonly topic: string;
10
- private fragment;
11
- constructor(abi: ethers.Interface, topic: string);
12
- is(rec: EventRecord): boolean;
13
- decode(rec: EventRecord): Args;
14
- }
15
- export interface FuncRecord {
16
- sighash?: string;
17
- input: string;
18
- }
19
- export declare class Func<Args extends any[], FieldArgs, Result> {
20
- private abi;
21
- readonly sighash: string;
22
- private fragment;
23
- constructor(abi: ethers.Interface, sighash: string);
24
- is(rec: FuncRecord): boolean;
25
- decode(input: ethers.BytesLike): Args & FieldArgs;
26
- decode(rec: FuncRecord): Args & FieldArgs;
27
- encode(args: Args): string;
28
- decodeResult(output: ethers.BytesLike): Result;
29
- tryDecodeResult(output: ethers.BytesLike): Result | undefined;
30
- }
31
- export declare function isFunctionResultDecodingError(val: unknown): val is Error & {
32
- data: string;
33
- };
34
- export interface ChainContext {
35
- _chain: Chain;
36
- }
37
- export interface BlockContext {
38
- _chain: Chain;
39
- block: Block;
40
- }
41
- export interface Block {
42
- height: number;
43
- }
44
- export interface Chain {
45
- client: {
46
- call: <T = any>(method: string, params?: unknown[]) => Promise<T>;
47
- };
48
- }
49
- export declare class ContractBase {
50
- private readonly _chain;
51
- private readonly blockHeight;
52
- readonly address: string;
53
- constructor(ctx: BlockContext, address: string);
54
- constructor(ctx: ChainContext, block: Block, address: string);
55
- eth_call<Args extends any[], FieldArgs, Result>(func: Func<Args, FieldArgs, Result>, args: Args): Promise<Result>;
56
- }
57
- //# sourceMappingURL=abi.support.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"abi.support.d.ts","sourceRoot":"","sources":["../src/abi.support.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAA;AAEhC,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACf;AACD,MAAM,MAAM,SAAS,GAAG,WAAW,CAAA;AAEnC,qBAAa,QAAQ,CAAC,IAAI;IAGV,OAAO,CAAC,GAAG;aAAoC,KAAK,EAAE,MAAM;IAFxE,OAAO,CAAC,QAAQ,CAAsB;gBAElB,GAAG,EAAE,MAAM,CAAC,SAAS,EAAkB,KAAK,EAAE,MAAM;IAMxE,EAAE,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO;IAI7B,MAAM,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI;CAGjC;AAED,MAAM,WAAW,UAAU;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,qBAAa,IAAI,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,SAAS,EAAE,MAAM;IAGvC,OAAO,CAAC,GAAG;aAAoC,OAAO,EAAE,MAAM;IAF1E,OAAO,CAAC,QAAQ,CAAyB;gBAErB,GAAG,EAAE,MAAM,CAAC,SAAS,EAAkB,OAAO,EAAE,MAAM;IAM1E,EAAE,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO;IAK5B,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,GAAG,IAAI,GAAG,SAAS;IACjD,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS;IAMzC,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAI1B,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,GAAG,MAAM;IAK9C,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,GAAG,MAAM,GAAG,SAAS;CAOhE;AAGD,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,KAAK,GAAG;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAOzF;AAGD,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,KAAK,CAAA;CAChB;AAGD,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,KAAK,CAAA;IACb,KAAK,EAAE,KAAK,CAAA;CACf;AAGD,MAAM,WAAW,KAAK;IAClB,MAAM,EAAE,MAAM,CAAA;CACjB;AAGD,MAAM,WAAW,KAAK;IAClB,MAAM,EAAG;QACL,IAAI,EAAE,CAAC,CAAC,GAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;KAClE,CAAA;CACJ;AAGD,qBAAa,YAAY;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAO;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBAEZ,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM;gBAClC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM;IAetD,QAAQ,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;CAQ1H"}