@sentio/sdk 1.20.1 → 1.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (189) hide show
  1. package/lib/aptos/aptos-processor.d.ts +17 -12
  2. package/lib/aptos/aptos-processor.js +65 -13
  3. package/lib/aptos/aptos-processor.js.map +1 -1
  4. package/lib/aptos/bind-options.d.ts +0 -6
  5. package/lib/aptos/bind-options.js +1 -8
  6. package/lib/aptos/bind-options.js.map +1 -1
  7. package/lib/aptos/context.d.ts +5 -4
  8. package/lib/aptos/context.js +9 -6
  9. package/lib/aptos/context.js.map +1 -1
  10. package/lib/aptos/index.d.ts +3 -2
  11. package/lib/aptos/index.js +1 -2
  12. package/lib/aptos/index.js.map +1 -1
  13. package/lib/aptos/runtime.d.ts +2 -0
  14. package/lib/aptos/runtime.js +16 -0
  15. package/lib/aptos/runtime.js.map +1 -0
  16. package/lib/aptos/types.d.ts +28 -0
  17. package/lib/aptos/types.js +159 -0
  18. package/lib/aptos/types.js.map +1 -0
  19. package/lib/aptos/utils.d.ts +6 -0
  20. package/lib/aptos/utils.js +19 -0
  21. package/lib/aptos/utils.js.map +1 -0
  22. package/lib/aptos-codegen/codegen.d.ts +5 -2
  23. package/lib/aptos-codegen/codegen.js +195 -18
  24. package/lib/aptos-codegen/codegen.js.map +1 -1
  25. package/lib/aptos-codegen/typegen.d.ts +18 -0
  26. package/lib/aptos-codegen/typegen.js +196 -0
  27. package/lib/aptos-codegen/typegen.js.map +1 -0
  28. package/lib/binds.d.ts +2 -3
  29. package/lib/binds.js +6 -33
  30. package/lib/binds.js.map +1 -1
  31. package/lib/builtin/aptos/0x1.d.ts +1624 -0
  32. package/lib/builtin/aptos/0x1.js +2502 -0
  33. package/lib/builtin/aptos/0x1.js.map +1 -0
  34. package/lib/builtin/aptos/0x3.d.ts +414 -0
  35. package/lib/builtin/aptos/0x3.js +461 -0
  36. package/lib/builtin/aptos/0x3.js.map +1 -0
  37. package/lib/builtin/internal/eacaggregatorproxy_processor.d.ts +2 -2
  38. package/lib/builtin/internal/eacaggregatorproxy_processor.js +12 -11
  39. package/lib/builtin/internal/eacaggregatorproxy_processor.js.map +1 -1
  40. package/lib/builtin/internal/erc20_processor.d.ts +2 -2
  41. package/lib/builtin/internal/erc20_processor.js +12 -11
  42. package/lib/builtin/internal/erc20_processor.js.map +1 -1
  43. package/lib/builtin/internal/erc20bytes_processor.d.ts +2 -2
  44. package/lib/builtin/internal/erc20bytes_processor.js +12 -11
  45. package/lib/builtin/internal/erc20bytes_processor.js.map +1 -1
  46. package/lib/builtin/internal/weth9_processor.d.ts +2 -2
  47. package/lib/builtin/internal/weth9_processor.js +12 -11
  48. package/lib/builtin/internal/weth9_processor.js.map +1 -1
  49. package/lib/builtin/solana/types.d.ts +5 -5
  50. package/lib/builtin/solana/wormhole-processor.d.ts +6 -6
  51. package/lib/builtin/solana/wormhole-processor.js +15 -12
  52. package/lib/builtin/solana/wormhole-processor.js.map +1 -1
  53. package/lib/cli/build.js +17 -16
  54. package/lib/cli/build.js.map +1 -1
  55. package/lib/core/base-processor-template.d.ts +7 -7
  56. package/lib/core/base-processor-template.js.map +1 -1
  57. package/lib/core/base-processor.d.ts +5 -6
  58. package/lib/core/base-processor.js +6 -4
  59. package/lib/core/base-processor.js.map +1 -1
  60. package/lib/core/big-decimal.d.ts +1 -0
  61. package/lib/core/big-decimal.js +6 -0
  62. package/lib/core/big-decimal.js.map +1 -0
  63. package/lib/core/bind-options.d.ts +0 -2
  64. package/lib/core/bind-options.js +4 -4
  65. package/lib/core/bind-options.js.map +1 -1
  66. package/lib/core/context.d.ts +14 -11
  67. package/lib/core/context.js +28 -19
  68. package/lib/core/context.js.map +1 -1
  69. package/lib/core/generic-processor.js +5 -5
  70. package/lib/core/generic-processor.js.map +1 -1
  71. package/lib/core/index.d.ts +5 -5
  72. package/lib/core/index.js +6 -6
  73. package/lib/core/index.js.map +1 -1
  74. package/lib/core/logger.d.ts +2 -3
  75. package/lib/core/logger.js +6 -6
  76. package/lib/core/logger.js.map +1 -1
  77. package/lib/core/metadata.d.ts +7 -4
  78. package/lib/core/metadata.js +13 -10
  79. package/lib/core/metadata.js.map +1 -1
  80. package/lib/core/meter.d.ts +4 -7
  81. package/lib/core/meter.js +12 -13
  82. package/lib/core/meter.js.map +1 -1
  83. package/lib/core/solana-processor.d.ts +7 -4
  84. package/lib/core/solana-processor.js +14 -20
  85. package/lib/core/solana-processor.js.map +1 -1
  86. package/lib/core/sui-processor.d.ts +5 -4
  87. package/lib/core/sui-processor.js +10 -17
  88. package/lib/core/sui-processor.js.map +1 -1
  89. package/lib/error.d.ts +2 -2
  90. package/lib/error.js.map +1 -1
  91. package/lib/gen/processor/protos/processor.d.ts +23 -12
  92. package/lib/gen/processor/protos/processor.js +129 -57
  93. package/lib/gen/processor/protos/processor.js.map +1 -1
  94. package/lib/index.d.ts +1 -2
  95. package/lib/index.js +1 -4
  96. package/lib/index.js.map +1 -1
  97. package/lib/processor-state.d.ts +1 -1
  98. package/lib/processor-state.js.map +1 -1
  99. package/lib/service.js +13 -12
  100. package/lib/service.js.map +1 -1
  101. package/lib/target-ethers-sentio/codegen.js +14 -15
  102. package/lib/target-ethers-sentio/codegen.js.map +1 -1
  103. package/lib/test-abi-code-gen.js.map +1 -1
  104. package/lib/testing/metric-utils.js +2 -2
  105. package/lib/testing/metric-utils.js.map +1 -1
  106. package/lib/tests/aptos.test.js +95 -2
  107. package/lib/tests/aptos.test.js.map +1 -1
  108. package/lib/tests/erc20.js +1 -1
  109. package/lib/tests/erc20.js.map +1 -1
  110. package/lib/tests/erc20.test.js +3 -4
  111. package/lib/tests/erc20.test.js.map +1 -1
  112. package/lib/tests/solana.test.js +5 -1
  113. package/lib/tests/solana.test.js.map +1 -1
  114. package/lib/tests/souffl3.js +17 -4
  115. package/lib/tests/souffl3.js.map +1 -1
  116. package/lib/tests/sui.test.js +1 -4
  117. package/lib/tests/sui.test.js.map +1 -1
  118. package/lib/tests/types/aptos/souffle.d.ts +311 -22
  119. package/lib/tests/types/aptos/souffle.js +142 -6
  120. package/lib/tests/types/aptos/souffle.js.map +1 -1
  121. package/lib/tests/types/solana/basic_1_processor.d.ts +2 -2
  122. package/lib/tests/types/solana/basic_1_processor.js +4 -4
  123. package/lib/tests/types/solana/basic_1_processor.js.map +1 -1
  124. package/lib/tests/wormhole-token-bridge.js +2 -1
  125. package/lib/tests/wormhole-token-bridge.js.map +1 -1
  126. package/lib/utils/chain.d.ts +1 -0
  127. package/lib/utils/chain.js +15 -1
  128. package/lib/utils/chain.js.map +1 -1
  129. package/lib/utils/conversion.d.ts +1 -1
  130. package/lib/utils/conversion.js.map +1 -1
  131. package/package.json +3 -2
  132. package/src/abis/aptos/0x1.json +9205 -0
  133. package/src/abis/aptos/0x3.json +1515 -0
  134. package/src/aptos/aptos-processor.ts +88 -20
  135. package/src/aptos/bind-options.ts +0 -7
  136. package/src/aptos/context.ts +11 -8
  137. package/src/aptos/index.ts +3 -2
  138. package/src/aptos/runtime.ts +13 -0
  139. package/src/aptos/types.ts +203 -0
  140. package/src/aptos/utils.ts +18 -0
  141. package/src/aptos-codegen/codegen.ts +222 -19
  142. package/src/aptos-codegen/typegen.test.ts +29 -0
  143. package/src/aptos-codegen/typegen.ts +216 -0
  144. package/src/binds.ts +5 -39
  145. package/src/builtin/aptos/0x1.ts +3760 -0
  146. package/src/builtin/aptos/0x3.ts +798 -0
  147. package/src/builtin/internal/eacaggregatorproxy_processor.ts +14 -31
  148. package/src/builtin/internal/erc20_processor.ts +14 -25
  149. package/src/builtin/internal/erc20bytes_processor.ts +14 -25
  150. package/src/builtin/internal/weth9_processor.ts +14 -25
  151. package/src/builtin/solana/wormhole-processor.ts +21 -18
  152. package/src/cli/build.ts +19 -17
  153. package/src/core/base-processor-template.ts +7 -7
  154. package/src/core/base-processor.ts +30 -9
  155. package/src/core/big-decimal.ts +1 -0
  156. package/src/core/bind-options.ts +3 -2
  157. package/src/core/context.ts +40 -24
  158. package/src/core/generic-processor.ts +6 -7
  159. package/src/core/index.ts +5 -5
  160. package/src/core/logger.ts +7 -7
  161. package/src/core/metadata.ts +14 -12
  162. package/src/core/meter.ts +12 -14
  163. package/src/core/solana-processor.ts +24 -21
  164. package/src/core/sui-processor.ts +10 -21
  165. package/src/error.ts +2 -2
  166. package/src/gen/processor/protos/processor.ts +158 -68
  167. package/src/index.ts +1 -2
  168. package/src/processor-state.ts +1 -1
  169. package/src/service.ts +22 -15
  170. package/src/target-ethers-sentio/codegen.ts +14 -15
  171. package/src/test-abi-code-gen.ts +1 -0
  172. package/src/testing/metric-utils.ts +2 -2
  173. package/src/tests/aptos.test.ts +102 -3
  174. package/src/tests/erc20.test.ts +3 -4
  175. package/src/tests/erc20.ts +1 -1
  176. package/src/tests/solana.test.ts +5 -1
  177. package/src/tests/souffl3.ts +21 -6
  178. package/src/tests/sui.test.ts +1 -4
  179. package/src/tests/types/aptos/souffle.ts +424 -42
  180. package/src/tests/types/solana/basic_1_processor.ts +6 -6
  181. package/src/tests/wormhole-token-bridge.ts +2 -1
  182. package/src/types/global.d.ts +1 -1
  183. package/src/utils/chain.ts +14 -0
  184. package/src/utils/conversion.ts +1 -1
  185. package/lib/contract-namer.d.ts +0 -6
  186. package/lib/contract-namer.js +0 -20
  187. package/lib/contract-namer.js.map +0 -1
  188. package/src/aptos-codegen/codgen.test.ts +0 -11
  189. package/src/contract-namer.ts +0 -17
@@ -1,29 +1,81 @@
1
- import { MoveModuleBytecode } from 'aptos/src/generated'
2
1
  import fs from 'fs'
3
2
  import path from 'path'
4
- import { MoveFunction, MoveModule } from 'aptos/src/generated'
5
- import { MoveStruct } from 'aptos/src/generated/models/MoveStruct'
6
3
  import prettier from 'prettier'
4
+ import { MoveFunction, MoveModule, MoveStruct, MoveModuleBytecode } from 'aptos/src/generated'
5
+ import { generateType, AccountRegister } from './typegen'
6
+ import { isFrameworkAccount } from '../aptos/utils'
7
+
8
+ export function generate(srcDir: string, outputDir: string) {
9
+ const files = fs.readdirSync(srcDir)
10
+ outputDir = path.resolve(outputDir)
11
+
12
+ fs.mkdirSync(outputDir, { recursive: true })
13
+
14
+ const loader = new AccountRegister()
15
+
16
+ // The first path, identify import relation and module name (filename) of those imports
17
+ for (const file of files) {
18
+ if (!file.endsWith('.json')) {
19
+ continue
20
+ }
21
+ // Reading file is duplicated, but since they are small files probably file
22
+ // TODO add file manager class
23
+ const json = fs.readFileSync(path.join(srcDir, file), 'utf-8')
24
+ const modules = JSON.parse(json)
25
+
26
+ for (const module of modules) {
27
+ if (module.abi) {
28
+ loader.register(module.abi, path.basename(file, '.json'))
29
+ }
30
+ }
31
+ }
32
+
33
+ for (const file of files) {
34
+ if (!file.endsWith('.json')) {
35
+ continue
36
+ }
37
+ const codeGen = new AccountCodegen(loader, {
38
+ srcFile: path.join(srcDir, file),
39
+ outputDir: outputDir,
40
+ })
41
+
42
+ codeGen.generate()
43
+ }
44
+
45
+ // when generating user code, don't need to generate framework account
46
+ loader.pendingAccounts.delete('0x1')
47
+ loader.pendingAccounts.delete('0x2')
48
+ loader.pendingAccounts.delete('0x3')
49
+
50
+ if (loader.pendingAccounts.size > 0) {
51
+ // TODO automatic download dependencies
52
+ console.error('Missing ABIs from the following accounts', loader.pendingAccounts)
53
+ }
54
+ }
7
55
 
8
56
  interface Config {
9
57
  srcFile: string
10
58
  outputDir: string
11
59
  }
12
60
 
13
- export class AptosCodegen {
61
+ export class AccountCodegen {
14
62
  modules: MoveModuleBytecode[]
15
63
  config: Config
64
+ loader: AccountRegister
16
65
 
17
- constructor(config: Config) {
66
+ constructor(loader: AccountRegister, config: Config) {
18
67
  const json = fs.readFileSync(config.srcFile, 'utf-8')
19
68
  this.modules = JSON.parse(json)
20
69
  this.config = config
70
+ this.loader = loader
21
71
  }
22
72
 
23
73
  generate() {
24
74
  if (!this.modules) {
25
75
  return
26
76
  }
77
+ const baseName = path.basename(this.config.srcFile, '.json')
78
+
27
79
  let address: string | undefined
28
80
  for (const module of this.modules) {
29
81
  if (module.abi && module.abi.address) {
@@ -34,7 +86,37 @@ export class AptosCodegen {
34
86
  return
35
87
  }
36
88
 
37
- const imports = `import { aptos } from "@sentio/sdk"`
89
+ const imports = `
90
+ import { aptos } from "@sentio/sdk"
91
+ import { Address, MoveModule } from "aptos/src/generated"
92
+ `
93
+
94
+ const dependedAccounts: string[] = []
95
+
96
+ const moduleImports: string[] = []
97
+
98
+ const info = this.loader.accountImports.get(address)
99
+
100
+ if (info) {
101
+ for (const [account, moduleImported] of info.imports.entries()) {
102
+ // Remap to user's filename if possible, TODO codepath not well tested
103
+ let tsAccountModule = './' + (this.loader.accountImports.get(account)?.moduleName || account)
104
+ if (isFrameworkAccount(account) && !isFrameworkAccount(address)) {
105
+ // Decide where to find runtime library
106
+ let srcRoot = 'lib'
107
+ if (__dirname.includes('sdk/src/aptos-codegen')) {
108
+ srcRoot = 'src'
109
+ }
110
+ tsAccountModule = `@sentio/sdk/${srcRoot}/builtin/aptos/${account}`
111
+ }
112
+ const items = Array.from(moduleImported)
113
+ moduleImports.push(`import { ${items.join(',')} } from "${tsAccountModule}"`)
114
+
115
+ // Ideally we should use per module's load types, but it doesn't matter since we are loading the entire
116
+ // account modules anyway
117
+ items.forEach((m) => dependedAccounts.push(m))
118
+ }
119
+ }
38
120
 
39
121
  let source = `
40
122
  /* Autogenerated file. Do not edit manually. */
@@ -45,16 +127,27 @@ export class AptosCodegen {
45
127
 
46
128
  ${imports}
47
129
 
48
- ${this.modules.map(generateModule).join('\n')}
130
+ ${moduleImports.join('\n')}
131
+
132
+ ${this.modules.map((m) => generateModule(m, dependedAccounts)).join('\n')}
133
+
134
+ function loadAllTypes(registry: aptos.TypeRegistry) {
135
+ ${dependedAccounts.map((m) => `${m}.loadTypes(registry)`).join('\n')}
136
+
137
+ ${this.modules
138
+ .map((m) => {
139
+ return `registry.load(${m.abi?.name}.ABI)`
140
+ })
141
+ .join('\n')}
142
+ }
49
143
  ` // source
50
144
 
51
- const baseName = path.basename(this.config.srcFile, '.json')
52
145
  source = prettier.format(source, { parser: 'typescript' })
53
146
  fs.writeFileSync(path.join(this.config.outputDir, baseName + '.ts'), source)
54
147
  }
55
148
  }
56
149
 
57
- function generateModule(moduleByteCode: MoveModuleBytecode) {
150
+ function generateModule(moduleByteCode: MoveModuleBytecode, dependedModules: string[]) {
58
151
  if (!moduleByteCode.abi) {
59
152
  return ''
60
153
  }
@@ -62,21 +155,125 @@ function generateModule(moduleByteCode: MoveModuleBytecode) {
62
155
 
63
156
  const functions = module.exposed_functions.map((f) => generateOnEntryFunctions(module, f)).filter((s) => s !== '')
64
157
  const events = module.structs.map((e) => generateOnEvents(module, e)).filter((s) => s !== '')
158
+ const structs = module.structs.map((s) => generateStructs(module, s))
159
+ const callArgs = module.exposed_functions.map((f) => generateCallArgsStructs(module, f))
65
160
 
66
- return `
67
- export class ${module.name} extends aptos.AptosBaseProcessor {
68
- static DEFAULT_OPTIONS: aptos.NamedAptosBindOptions = {
161
+ let processor = ''
162
+ if (functions.length > 0 || events.length > 0) {
163
+ processor = `export class ${module.name} extends aptos.AptosBaseProcessor {
164
+
165
+ constructor(options: aptos.AptosBindOptions) {
166
+ super("${module.name}", options)
167
+ }
168
+ static DEFAULT_OPTIONS: aptos.AptosBindOptions = {
69
169
  address: "${module.address}",
70
170
  network: aptos.AptosNetwork.TEST_NET
71
171
  }
72
- static bind(options = ${module.name}.DEFAULT_OPTIONS): ${module.name} {
73
- return new ${module.name}({ ...options, name: "${module.name}" })
172
+
173
+ static bind(options: Partial<aptos.AptosBindOptions> = {}): ${module.name} {
174
+ return new ${module.name}({ ...${module.name}.DEFAULT_OPTIONS, ...options })
74
175
  }
75
176
 
76
177
  ${functions.join('\n')}
77
178
 
78
179
  ${events.join('\n')}
79
- }`
180
+
181
+ loadTypesInternal(registry: aptos.TypeRegistry) {
182
+ loadAllTypes(registry)
183
+ }
184
+ }
185
+ `
186
+ }
187
+
188
+ return `
189
+ ${processor}
190
+
191
+ export namespace ${module.name} {
192
+ ${structs.join('\n')}
193
+
194
+ ${callArgs.join('\n')}
195
+
196
+ export function loadTypes(registry: aptos.TypeRegistry) {
197
+ loadAllTypes(registry)
198
+ }
199
+ export const ABI: MoveModule = JSON.parse('${JSON.stringify(module)}')
200
+ }
201
+ `
202
+ }
203
+
204
+ function generateStructs(module: MoveModule, struct: MoveStruct) {
205
+ const genericString = generateStructTypeParameters(struct)
206
+
207
+ const fields = struct.fields.map((field) => {
208
+ return `${field.name}: ${generateType(field.type)}`
209
+ })
210
+
211
+ let eventPayload = ''
212
+ if (isEvent(struct)) {
213
+ eventPayload = `
214
+ export interface ${struct.name}Instance${genericString} extends
215
+ aptos.TypedEventInstance<${struct.name}${genericString}> {
216
+ data_typed: ${struct.name}${genericString}
217
+ }
218
+ `
219
+ }
220
+
221
+ return `
222
+ export class ${struct.name}${genericString} {
223
+ ${fields.join('\n')}
224
+ }
225
+
226
+ ${eventPayload}
227
+ `
228
+ }
229
+
230
+ function generateFunctionTypeParameters(func: MoveFunction) {
231
+ let genericString = ''
232
+ if (func.generic_type_params && func.generic_type_params.length > 0) {
233
+ const params = func.generic_type_params
234
+ .map((v, idx) => {
235
+ return 'T' + idx
236
+ })
237
+ .join(',')
238
+ genericString = `<${params}>`
239
+ }
240
+ return genericString
241
+ }
242
+
243
+ function generateStructTypeParameters(struct: MoveStruct) {
244
+ let genericString = ''
245
+
246
+ if (struct.generic_type_params && struct.generic_type_params.length > 0) {
247
+ const params = struct.generic_type_params
248
+ .map((v, idx) => {
249
+ return 'T' + idx
250
+ })
251
+ .join(',')
252
+ genericString = `<${params}>`
253
+ }
254
+ return genericString
255
+ }
256
+
257
+ function generateCallArgsStructs(module: MoveModule, func: MoveFunction) {
258
+ if (!func.is_entry) {
259
+ return
260
+ }
261
+
262
+ // the first param is always signer so ignore
263
+ // TODO check if there is any edge case
264
+ const fields = func.params.slice(1).map((param) => {
265
+ return `${generateType(param)}`
266
+ })
267
+
268
+ const camelFuncName = capitalizeFirstChar(camelize(func.name))
269
+
270
+ const genericString = generateFunctionTypeParameters(func)
271
+ return `
272
+ export interface ${camelFuncName}Payload${genericString}
273
+ extends aptos.TypedEntryFunctionPayload<[${fields.join(',')}]> {
274
+ arguments_typed: [${fields.join(',')}]
275
+ }
276
+ `
80
277
  }
81
278
 
82
279
  function generateOnEntryFunctions(module: MoveModule, func: MoveFunction) {
@@ -84,9 +281,11 @@ function generateOnEntryFunctions(module: MoveModule, func: MoveFunction) {
84
281
  return ''
85
282
  }
86
283
 
284
+ const genericString = generateFunctionTypeParameters(func)
285
+
87
286
  const camelFuncName = capitalizeFirstChar(camelize(func.name))
88
287
  const source = `
89
- onEntry${camelFuncName}(func: (call: aptos.TransactionPayload_EntryFunctionPayload, ctx: aptos.AptosContext) => void): ${module.name} {
288
+ onEntry${camelFuncName}${genericString}(func: (call: ${module.name}.${camelFuncName}Payload${genericString}, ctx: aptos.AptosContext) => void): ${module.name} {
90
289
  this.onEntryFunctionCall(func, {
91
290
  function: '${module.name}::${func.name}'
92
291
  })
@@ -96,15 +295,19 @@ function generateOnEntryFunctions(module: MoveModule, func: MoveFunction) {
96
295
  return source
97
296
  }
98
297
 
298
+ function isEvent(struct: MoveStruct) {
299
+ return struct.abilities.includes('drop') && struct.abilities.includes('store') && struct.name.endsWith('Event')
300
+ }
301
+
99
302
  function generateOnEvents(module: MoveModule, struct: MoveStruct): string {
100
303
  // for struct that has drop + store
101
- if (!struct.abilities.includes('drop') || !struct.abilities.includes('store') || !struct.name.endsWith('Event')) {
304
+ if (!isEvent(struct)) {
102
305
  return ''
103
306
  }
104
307
  const source = `
105
- onEvent${struct.name}(func: (event: aptos.Event, ctx: aptos.AptosContext) => void): ${module.name} {
308
+ onEvent${struct.name}(func: (event: ${module.name}.${struct.name}Instance, ctx: aptos.AptosContext) => void): ${module.name} {
106
309
  this.onEvent(func, {
107
- type: '${module.address}::${module.name}::${struct.name}'
310
+ type: '${module.name}::${struct.name}'
108
311
  })
109
312
  return this
110
313
  }
@@ -0,0 +1,29 @@
1
+ import { parseMoveType } from './typegen'
2
+ import { assert } from 'chai'
3
+
4
+ describe('type gen', () => {
5
+ test('type gen for generic', async () => {
6
+ const res = parseMoveType('x<g1<a,g2<c,d>>,b,g3<a,b>,e>')
7
+
8
+ assert(res.qname === 'x')
9
+ assert(res.typeArgs[0].typeArgs[1].qname === 'g2')
10
+ assert(res.typeArgs[0].typeArgs[1].typeArgs[1].qname === 'd')
11
+ })
12
+
13
+ test('type gen for non generic', async () => {
14
+ const res = parseMoveType('xyz')
15
+
16
+ assert(res.qname === 'xyz')
17
+ assert(res.typeArgs.length === 0)
18
+ })
19
+
20
+ // test('type type gen', async () => {
21
+ //
22
+ // const res = parseGenericType('x<g1<a,g2<c,d>>,b,g3<a,b>,e>')
23
+ // console.log(res)
24
+ //
25
+ // assert(res.symbol === 'x')
26
+ // assert(res.typeParams[0].typeParams[1].symbol === "g2")
27
+ // assert(res.typeParams[0].typeParams[1].typeParams[1].symbol === "d")
28
+ // })
29
+ })
@@ -0,0 +1,216 @@
1
+ import { MoveModule } from 'aptos/src/generated'
2
+ import { TypeDescriptor } from '../aptos/types'
3
+ import { moduleQname, moduleQnameForType, SPLITTER, VECTOR_STR } from '../aptos/utils'
4
+
5
+ function generateTypeForDescriptor(type: TypeDescriptor): string {
6
+ // TODO &signer is defintely an address, but what if &OTHER_TYPE?
7
+ if (type.qname.startsWith('&')) {
8
+ return 'Address'
9
+ }
10
+
11
+ switch (type.qname) {
12
+ case 'signer': // TODO check this
13
+ case 'address':
14
+ return 'Address'
15
+ case '0x1::string::String':
16
+ return 'string'
17
+ case 'bool':
18
+ return 'Boolean'
19
+ case 'u8':
20
+ case 'u16':
21
+ case 'u32':
22
+ return 'number'
23
+ case 'u64':
24
+ case 'u128':
25
+ return 'bigint'
26
+ }
27
+
28
+ if (type.qname === VECTOR_STR) {
29
+ // vector<u8> as hex string
30
+ const elementTypeQname = type.typeArgs[0].qname
31
+ if (elementTypeQname === 'u8') {
32
+ return 'string'
33
+ }
34
+ if (elementTypeQname.startsWith('T') && !elementTypeQname.includes(SPLITTER)) {
35
+ return `${elementTypeQname}[] | string`
36
+ }
37
+ return generateTypeForDescriptor(type.typeArgs[0]) + '[]'
38
+ }
39
+
40
+ const simpleName = generateSimpleType(type.qname)
41
+ if (simpleName.length === 0) {
42
+ console.error('unexpected error')
43
+ }
44
+ if (simpleName.includes('vector')) {
45
+ console.error('unexpected error')
46
+ }
47
+ if (type.typeArgs.length > 0) {
48
+ // return simpleName
49
+ return simpleName + '<' + type.typeArgs.map((t) => generateTypeForDescriptor(t)).join(',') + '>'
50
+ }
51
+ return simpleName
52
+ }
53
+
54
+ function generateSimpleType(type: string): string {
55
+ const parts = type.split(SPLITTER)
56
+ if (parts.length < 2) {
57
+ return parts[0]
58
+ }
59
+
60
+ return parts.slice(1).join('.')
61
+ }
62
+
63
+ export function parseMoveType(type: string) {
64
+ // type = type.replace('&', '')
65
+
66
+ type = type.replace('&mut ', '&')
67
+
68
+ // TODO replace ' ' is not exactly safe, need to double check this
69
+ type = type.replace(' ', '')
70
+
71
+ const stack: TypeDescriptor[] = [new TypeDescriptor('')]
72
+ let buffer = []
73
+
74
+ // xxx:asdf<g1<a,<c,d>>, b, g2<a,b>, e>
75
+ for (let i = 0; i < type.length; i++) {
76
+ const ch = type[i]
77
+ if (ch === '<') {
78
+ // const symbol = type.slice(symbolStart, i)
79
+ // symbolStart =
80
+ const symbol = buffer.join('')
81
+ buffer = []
82
+ stack[stack.length - 1].qname = symbol
83
+ stack.push(new TypeDescriptor(''))
84
+ continue
85
+ }
86
+ if (ch === '>') {
87
+ const typeParam = stack.pop()
88
+ if (!typeParam) {
89
+ throw Error('Uxpectecd stack size')
90
+ }
91
+ if (buffer.length > 0) {
92
+ typeParam.qname = buffer.join('')
93
+ buffer = []
94
+ }
95
+ stack[stack.length - 1].typeArgs.push(typeParam)
96
+ continue
97
+ }
98
+ if (ch === ',') {
99
+ const typeParam = stack.pop()
100
+ if (!typeParam) {
101
+ throw Error('Uxpectecd stack size')
102
+ }
103
+ if (buffer.length > 0) {
104
+ typeParam.qname = buffer.join('')
105
+ buffer = []
106
+ }
107
+
108
+ stack[stack.length - 1].typeArgs.push(typeParam)
109
+ // continue parse next param
110
+ stack.push(new TypeDescriptor(''))
111
+ continue
112
+ }
113
+
114
+ buffer.push(ch)
115
+ }
116
+
117
+ if (buffer.length > 0) {
118
+ stack[stack.length - 1].qname = buffer.join('')
119
+ }
120
+
121
+ const res = stack.pop()
122
+ if (!res || stack.length > 0) {
123
+ throw Error('Uxpectecd stack size')
124
+ }
125
+ return res
126
+ }
127
+
128
+ // TODO ctx need to have type parameters
129
+ export function generateType(type: string, ctx?: any): string {
130
+ return generateTypeForDescriptor(parseMoveType(type))
131
+ }
132
+
133
+ export class AccountModulesImportInfo {
134
+ // account to module
135
+ imports: Map<string, Set<string>>
136
+ account: string
137
+ moduleName: string
138
+
139
+ constructor(account: string, tsModuleName: string) {
140
+ this.account = account
141
+ this.moduleName = tsModuleName
142
+ this.imports = new Map<string, Set<string>>()
143
+ }
144
+
145
+ addImport(account: string, module: string) {
146
+ if (account === this.account) {
147
+ return
148
+ }
149
+ let accountModules = this.imports.get(account)
150
+ if (!accountModules) {
151
+ accountModules = new Set<string>()
152
+ this.imports.set(account, accountModules)
153
+ }
154
+ accountModules.add(module)
155
+ }
156
+ }
157
+
158
+ export class AccountRegister {
159
+ accountImports = new Map<string, AccountModulesImportInfo>()
160
+ pendingAccounts = new Set<string>()
161
+
162
+ // loadedAccount = new Set<string>()
163
+ typeRegistry = new Map<string, TypeDescriptor>()
164
+
165
+ private loadTypeDescriptor(type: string) {
166
+ let descriptor = this.typeRegistry.get(type)
167
+
168
+ // const descriptparseMoveType(type)
169
+ if (!descriptor) {
170
+ descriptor = parseMoveType(type)
171
+ this.typeRegistry.set(type, descriptor)
172
+ }
173
+ return descriptor
174
+ }
175
+
176
+ register(module: MoveModule, tsModuleName: string): AccountModulesImportInfo {
177
+ const currentModuleFqn = moduleQname(module)
178
+
179
+ let accountModuleImports = this.accountImports.get(module.address)
180
+ if (!accountModuleImports) {
181
+ accountModuleImports = new AccountModulesImportInfo(module.address, tsModuleName)
182
+ this.accountImports.set(module.address, accountModuleImports)
183
+ // the account has already be processed, delete pending task
184
+ this.pendingAccounts.delete(module.address)
185
+ }
186
+
187
+ for (const struct of module.structs) {
188
+ for (const field of struct.fields) {
189
+ for (const type of this.loadTypeDescriptor(field.type).dependedTypes()) {
190
+ const [account, module] = moduleQnameForType(type)
191
+ accountModuleImports.addImport(account, module)
192
+ if (!this.accountImports.has(account)) {
193
+ this.pendingAccounts.add(account)
194
+ }
195
+ }
196
+ }
197
+ }
198
+
199
+ for (const func of module.exposed_functions) {
200
+ if (!func.is_entry) {
201
+ continue
202
+ }
203
+ for (const param of func.params) {
204
+ for (const type of this.loadTypeDescriptor(param).dependedTypes()) {
205
+ const [account, module] = moduleQnameForType(type)
206
+ accountModuleImports.addImport(account, module)
207
+ if (!this.accountImports.has(account)) {
208
+ this.pendingAccounts.add(account)
209
+ }
210
+ }
211
+ }
212
+ }
213
+ this.accountImports.set(currentModuleFqn, accountModuleImports)
214
+ return accountModuleImports
215
+ }
216
+ }
package/src/binds.ts CHANGED
@@ -3,54 +3,20 @@ import { BaseProcessor, ContractView } from './core'
3
3
  import { Networkish } from '@ethersproject/networks'
4
4
  import { getNetwork } from '@ethersproject/providers'
5
5
  import { BaseContract } from 'ethers'
6
- import { ContractNamer } from './contract-namer'
7
6
 
8
7
  function getKey(abiName: string, address: string, network: Networkish) {
9
8
  const chainId = getNetwork(network).chainId.toString()
10
9
  return [abiName, address.toLowerCase(), chainId].join('_')
11
10
  }
12
11
 
13
- // TODO move to processor state
14
- const addressToName = new Map<string, string>()
15
- const namerMap = new Map<string, ContractNamer>()
16
-
17
- // Get contract name by ABI, and other options
18
- // If there is contract using same ABI and different (address, network) pair
19
- // It will be renamed as ABI, ABI_1, ABI_2
20
- // Otherwise just use same contract name
21
- export function getContractName(
22
- abiName: string,
23
- contractName: string | undefined,
24
- address: string,
25
- network: Networkish = 1
26
- ): string {
27
- const key = getKey(abiName, address, network)
28
- let name = addressToName.get(key)
29
- if (name) {
30
- return name
31
- }
32
- if (contractName) {
33
- addressToName.set(key, contractName)
34
- return contractName
35
- }
36
-
37
- let namer = namerMap.get(abiName)
38
- if (!namer) {
39
- namer = new ContractNamer(abiName)
40
- namerMap.set(abiName, namer)
41
- }
42
- name = namer.nextName()
43
- addressToName.set(key, name)
44
- return name
45
- }
46
-
47
- export function getProcessor(abiName: string, opts: BindOptions) {
48
- const sig = abiName + '_' + getOptionsSignature(opts)
12
+ // Dedup processor that bind multiple times
13
+ export function getProcessor(opts: BindOptions) {
14
+ const sig = getOptionsSignature(opts)
49
15
  return global.PROCESSOR_STATE.processorMap.get(sig)
50
16
  }
51
17
 
52
- export function addProcessor(abiName: string, opts: BindOptions, processor: BaseProcessor<any, any>) {
53
- const sig = abiName + '_' + getOptionsSignature(opts)
18
+ export function addProcessor(opts: BindOptions, processor: BaseProcessor<any, any>) {
19
+ const sig = getOptionsSignature(opts)
54
20
 
55
21
  global.PROCESSOR_STATE.processors.push(processor)
56
22
  global.PROCESSOR_STATE.processorMap.set(sig, processor)