@sentio/sdk 1.20.2 → 1.21.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.
Files changed (189) hide show
  1. package/lib/aptos/aptos-processor.d.ts +10 -10
  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 +194 -17
  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 +140 -4
  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 +79 -18
  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 +221 -18
  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 +422 -40
  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,13 +295,17 @@ 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
310
  type: '${module.name}::${struct.name}'
108
311
  })
@@ -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)