@typemove/move 1.2.4-rc2 → 1.2.4-rc3

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 (85) hide show
  1. package/dist/cjs/abstract-codegen.d.ts +50 -0
  2. package/dist/cjs/abstract-codegen.d.ts.map +1 -0
  3. package/dist/cjs/abstract-codegen.js +417 -0
  4. package/dist/cjs/abstract-codegen.js.map +1 -0
  5. package/dist/cjs/abstract-move-coder.d.ts +26 -0
  6. package/dist/cjs/abstract-move-coder.d.ts.map +1 -0
  7. package/dist/cjs/abstract-move-coder.js +260 -0
  8. package/dist/cjs/abstract-move-coder.js.map +1 -0
  9. package/dist/cjs/account.d.ts +16 -0
  10. package/dist/cjs/account.d.ts.map +1 -0
  11. package/dist/cjs/account.js +76 -0
  12. package/dist/cjs/account.js.map +1 -0
  13. package/dist/cjs/chain-adapter.d.ts +13 -0
  14. package/dist/cjs/chain-adapter.d.ts.map +1 -0
  15. package/dist/cjs/chain-adapter.js +7 -0
  16. package/dist/cjs/chain-adapter.js.map +1 -0
  17. package/dist/cjs/index.d.ts +8 -0
  18. package/dist/cjs/index.d.ts.map +1 -0
  19. package/dist/cjs/index.js +11 -0
  20. package/dist/cjs/index.js.map +1 -0
  21. package/dist/cjs/internal-models.d.ts +36 -0
  22. package/dist/cjs/internal-models.d.ts.map +1 -0
  23. package/dist/cjs/internal-models.js +10 -0
  24. package/dist/cjs/internal-models.js.map +1 -0
  25. package/dist/cjs/ts-type.test.d.ts +2 -0
  26. package/dist/cjs/ts-type.test.d.ts.map +1 -0
  27. package/dist/cjs/ts-type.test.js.map +1 -0
  28. package/dist/cjs/types.d.ts +46 -0
  29. package/dist/cjs/types.d.ts.map +1 -0
  30. package/dist/cjs/types.js +250 -0
  31. package/dist/cjs/types.js.map +1 -0
  32. package/dist/cjs/utils.d.ts +17 -0
  33. package/dist/cjs/utils.d.ts.map +1 -0
  34. package/dist/cjs/utils.js +82 -0
  35. package/dist/cjs/utils.js.map +1 -0
  36. package/dist/cjs/utils.test.d.ts +2 -0
  37. package/dist/cjs/utils.test.d.ts.map +1 -0
  38. package/dist/cjs/utils.test.js.map +1 -0
  39. package/dist/esm/abstract-codegen.d.ts +50 -0
  40. package/dist/esm/abstract-codegen.d.ts.map +1 -0
  41. package/dist/esm/abstract-codegen.js +411 -0
  42. package/dist/esm/abstract-codegen.js.map +1 -0
  43. package/dist/esm/abstract-move-coder.d.ts +26 -0
  44. package/dist/esm/abstract-move-coder.d.ts.map +1 -0
  45. package/dist/esm/abstract-move-coder.js +256 -0
  46. package/dist/esm/abstract-move-coder.js.map +1 -0
  47. package/dist/esm/account.d.ts +16 -0
  48. package/dist/esm/account.d.ts.map +1 -0
  49. package/dist/esm/account.js +71 -0
  50. package/dist/esm/account.js.map +1 -0
  51. package/dist/esm/chain-adapter.d.ts +13 -0
  52. package/dist/esm/chain-adapter.d.ts.map +1 -0
  53. package/dist/esm/chain-adapter.js +3 -0
  54. package/dist/esm/chain-adapter.js.map +1 -0
  55. package/dist/esm/index.d.ts +8 -0
  56. package/dist/esm/index.d.ts.map +1 -0
  57. package/dist/esm/index.js +8 -0
  58. package/dist/esm/index.js.map +1 -0
  59. package/dist/esm/internal-models.d.ts +36 -0
  60. package/dist/esm/internal-models.d.ts.map +1 -0
  61. package/dist/esm/internal-models.js +7 -0
  62. package/dist/esm/internal-models.js.map +1 -0
  63. package/dist/esm/ts-type.test.d.ts +2 -0
  64. package/dist/esm/ts-type.test.d.ts.map +1 -0
  65. package/dist/esm/ts-type.test.js.map +1 -0
  66. package/dist/esm/types.d.ts +46 -0
  67. package/dist/esm/types.d.ts.map +1 -0
  68. package/dist/esm/types.js +243 -0
  69. package/dist/esm/types.js.map +1 -0
  70. package/dist/esm/utils.d.ts +17 -0
  71. package/dist/esm/utils.d.ts.map +1 -0
  72. package/dist/esm/utils.js +69 -0
  73. package/dist/esm/utils.js.map +1 -0
  74. package/dist/esm/utils.test.d.ts +2 -0
  75. package/dist/esm/utils.test.d.ts.map +1 -0
  76. package/dist/esm/utils.test.js.map +1 -0
  77. package/package.json +2 -2
  78. package/src/abstract-codegen.ts +504 -0
  79. package/src/abstract-move-coder.ts +288 -0
  80. package/src/account.ts +93 -0
  81. package/src/chain-adapter.ts +26 -0
  82. package/src/index.ts +7 -0
  83. package/src/internal-models.ts +41 -0
  84. package/src/types.ts +284 -0
  85. package/src/utils.ts +91 -0
@@ -0,0 +1,288 @@
1
+ import { accountAddressString, moduleQname, SPLITTER, VECTOR_STR } from './utils.js'
2
+ import { DecodedStruct, matchType, parseMoveType, TypeDescriptor } from './types.js'
3
+ import { InternalMoveFunction, InternalMoveModule, InternalMoveStruct } from './internal-models.js'
4
+ // import { bytesToBigInt } from '../utils/index.js'
5
+ import { ChainAdapter } from './chain-adapter.js'
6
+
7
+ export abstract class AbstractMoveCoder<ModuleType, StructType> {
8
+ protected moduleMapping = new Map<string, InternalMoveModule>()
9
+ private typeMapping = new Map<string, InternalMoveStruct>()
10
+ private funcMapping = new Map<string, InternalMoveFunction>()
11
+ // network: string
12
+ adapter: ChainAdapter<ModuleType, StructType>
13
+
14
+ protected constructor(adapter: ChainAdapter<ModuleType, StructType>) {
15
+ this.adapter = adapter
16
+ }
17
+
18
+ contains(account: string, name: string) {
19
+ return this.moduleMapping.has(moduleQname({ address: account, name }))
20
+ }
21
+
22
+ abstract load(module: ModuleType): InternalMoveModule
23
+
24
+ protected loadInternal(module: InternalMoveModule) {
25
+ const account = accountAddressString(module.address)
26
+ if (this.contains(account, module.name)) {
27
+ return
28
+ }
29
+ this.moduleMapping.set(moduleQname({ address: account, name: module.name }), module)
30
+
31
+ for (const struct of module.structs) {
32
+ // TODO move to util
33
+ const key = [account, module.name, struct.name].join(SPLITTER)
34
+ this.typeMapping.set(key, struct)
35
+ }
36
+
37
+ for (const func of module.exposedFunctions) {
38
+ // if (!func.isEntry) {
39
+ // continue
40
+ // }
41
+ const key = [account, module.name, func.name].join(SPLITTER)
42
+ this.funcMapping.set(key, func)
43
+ }
44
+ }
45
+
46
+ protected decodeBigInt(data: any): bigint {
47
+ if (Array.isArray(data)) {
48
+ throw new Error('data is in byte array')
49
+ // Only sui function need this, strange
50
+ // const bytes = data as number[]
51
+ // return bytesToBigInt(new Uint8Array(bytes.slice().reverse()))
52
+ }
53
+
54
+ return BigInt(data)
55
+ }
56
+
57
+ private requestMap = new Map<string, Promise<void>>()
58
+
59
+ async getMoveStruct(type: string): Promise<InternalMoveStruct> {
60
+ const [account_, module, typeName] = type.split(SPLITTER)
61
+ const account = accountAddressString(account_)
62
+ type = [account, module, typeName].join(SPLITTER)
63
+
64
+ let struct = this.typeMapping.get(type)
65
+ if (struct) {
66
+ return struct
67
+ }
68
+ let resp = this.requestMap.get(account)
69
+ if (!resp) {
70
+ resp = this.adapter.fetchModules(account).then((modules) => {
71
+ for (const m of modules) {
72
+ this.load(m)
73
+ }
74
+ })
75
+ this.requestMap.set(account, resp)
76
+ }
77
+ await resp
78
+ struct = this.typeMapping.get(type)
79
+ if (struct) {
80
+ return struct
81
+ }
82
+ throw new Error('Failed to load function ' + type + ' type are not imported anywhere')
83
+ }
84
+
85
+ async getMoveFunction(type: string): Promise<InternalMoveFunction> {
86
+ const [account_, module, typeName] = type.split(SPLITTER)
87
+ const account = accountAddressString(account_)
88
+ type = [account, module, typeName].join(SPLITTER)
89
+
90
+ let func = this.funcMapping.get(type)
91
+ if (func) {
92
+ return func
93
+ }
94
+ let resp = this.requestMap.get(account)
95
+ if (!resp) {
96
+ resp = this.adapter
97
+ .fetchModules(account)
98
+ .then((modules) => {
99
+ for (const m of modules) {
100
+ this.load(m)
101
+ }
102
+ })
103
+ .catch((e) => {
104
+ this.requestMap.delete(account)
105
+ })
106
+ this.requestMap.set(account, resp)
107
+ }
108
+ await resp
109
+ func = this.funcMapping.get(type)
110
+ if (func) {
111
+ return func
112
+ }
113
+ throw new Error('Failed to load function ' + type + ' type are not imported anywhere')
114
+ }
115
+
116
+ protected async decode<T>(data: any, type: TypeDescriptor<T>): Promise<T> {
117
+ // process simple type
118
+ if (type.reference) {
119
+ return data
120
+ }
121
+ switch (type.qname) {
122
+ case 'signer': // TODO check this, aptos only
123
+ case 'address':
124
+ case 'Address':
125
+ case '0x1::string::String':
126
+ case 'bool':
127
+ case 'Bool':
128
+ case 'u8':
129
+ case 'U8':
130
+ case 'u16':
131
+ case 'U16':
132
+ case 'u32':
133
+ case 'U32':
134
+ return data
135
+ case 'u64':
136
+ case 'U64':
137
+ case 'u128':
138
+ case 'U128':
139
+ case 'u256':
140
+ case 'U256':
141
+ return this.decodeBigInt(data) as any
142
+ }
143
+
144
+ // process vector
145
+ if (type.qname.toLowerCase() === VECTOR_STR) {
146
+ // vector<u8> as hex string
147
+ if (type.typeArgs[0].qname === 'u8' || type.typeArgs[0].qname === 'U8') {
148
+ return data
149
+ }
150
+
151
+ const res = []
152
+ for (const entry of data) {
153
+ res.push(await this.decode(entry, type.typeArgs[0]))
154
+ }
155
+ return res as any
156
+ }
157
+
158
+ // Process complex type
159
+ const struct = await this.getMoveStruct(type.qname)
160
+
161
+ const typeCtx = new Map<string, TypeDescriptor>()
162
+ for (const [idx, typeArg] of type.typeArgs.entries()) {
163
+ typeCtx.set('T' + idx, typeArg)
164
+ }
165
+
166
+ const typedData: any = {}
167
+
168
+ for (const field of struct.fields) {
169
+ let filedType = field.type
170
+ filedType = filedType.applyTypeArgs(typeCtx)
171
+ const fieldValue = this.adapter.getData(data)[field.name]
172
+ const value = await this.decode(fieldValue, filedType)
173
+ typedData[field.name] = value
174
+ }
175
+ return typedData
176
+ }
177
+
178
+ async decodeArray(entries: any[], types: TypeDescriptor[], strict = true): Promise<any[]> {
179
+ const entriesDecoded: any[] = []
180
+ for (const [idx, arg] of entries.entries()) {
181
+ // TODO consider apply payload.type_arguments, but this might be hard since we don't code gen for them
182
+ const argType = types[idx]
183
+ try {
184
+ if (!strict && arg === undefined) {
185
+ entriesDecoded.push(arg)
186
+ } else {
187
+ entriesDecoded.push(await this.decode(arg, argType))
188
+ }
189
+ } catch (e) {
190
+ throw Error('Decoding error for ' + JSON.stringify(arg) + 'using type' + argType + e.toString())
191
+ }
192
+ }
193
+ return entriesDecoded
194
+ }
195
+
196
+ public encode(data: any): any {
197
+ if (!data) {
198
+ return undefined
199
+ }
200
+ if (typeof data === 'bigint') {
201
+ return data.toString()
202
+ }
203
+ if (Array.isArray(data)) {
204
+ return this.encodeArray(data)
205
+ }
206
+ for (const [key, value] of Object.entries(data)) {
207
+ if (!value) {
208
+ continue
209
+ }
210
+ if (typeof value === 'bigint') {
211
+ data[key] = value.toString()
212
+ }
213
+ }
214
+ return data
215
+ }
216
+
217
+ encodeArray(entriesDecoded: any[]): any[] {
218
+ const entries: any[] = []
219
+ for (const [idx, arg] of entriesDecoded.entries()) {
220
+ entries.push(this.encode(arg))
221
+ }
222
+ return entries
223
+ }
224
+
225
+ async decodeCallResult(res: any[], func: string): Promise<any[]> {
226
+ const f = await this.getMoveFunction(func)
227
+ return this.decodeArray(res, f.return)
228
+ }
229
+
230
+ async filterAndDecodeStruct<T, ST extends StructType>(
231
+ typeMatcher: TypeDescriptor<T>,
232
+ structsWithTags: ST[]
233
+ ): Promise<DecodedStruct<ST, T>[]> {
234
+ if (!structsWithTags) {
235
+ return [] as any
236
+ }
237
+ // const typeMatcherDescriptor = parseMoveType(typeMatcher)
238
+ const results: DecodedStruct<ST, T>[] = []
239
+ for (const resource of structsWithTags) {
240
+ const resourceType = this.adapter.getType(resource)
241
+ const resourceTypeDescriptor = parseMoveType(resourceType)
242
+ if (!matchType(typeMatcher, resourceTypeDescriptor)) {
243
+ continue
244
+ }
245
+
246
+ const result = await this.decodedStruct<T, ST>(resource)
247
+ if (result) {
248
+ results.push(result)
249
+ } else {
250
+ console.error('decoding error')
251
+ }
252
+ }
253
+ return results
254
+ }
255
+
256
+ protected async decodedStruct<T, ST extends StructType>(typeStruct: ST): Promise<DecodedStruct<ST, T> | undefined> {
257
+ const typeDescriptor = parseMoveType(this.adapter.getType(typeStruct))
258
+ const typeArguments = typeDescriptor.typeArgs.map((t) => t.getSignature())
259
+
260
+ let dataTyped = undefined
261
+ try {
262
+ dataTyped = await this.decode(typeStruct, typeDescriptor)
263
+ } catch (e) {
264
+ throw Error('Decoding error for struct' + JSON.stringify(typeStruct) + e.toString())
265
+ // return undefined
266
+ }
267
+ return {
268
+ ...typeStruct,
269
+ data_decoded: dataTyped,
270
+ type_arguments: typeArguments
271
+ }
272
+ }
273
+ async decodedType<T, ST>(typeStruct: ST, type: TypeDescriptor<T>): Promise<T | undefined> {
274
+ if (typeStruct === null || typeStruct == undefined) {
275
+ return typeStruct as any
276
+ }
277
+ if (typeof typeStruct === 'object') {
278
+ if ('type' in typeStruct) {
279
+ const typeInStruct = parseMoveType((typeStruct.type as any).toString() || '')
280
+ if (!matchType(type, typeInStruct)) {
281
+ return undefined
282
+ }
283
+ }
284
+ }
285
+
286
+ return await this.decode(typeStruct, type)
287
+ }
288
+ }
package/src/account.ts ADDED
@@ -0,0 +1,93 @@
1
+ import { moduleQname, moduleQnameForType } from './utils.js'
2
+ import { InternalMoveModule } from './internal-models.js'
3
+
4
+ export class AccountModulesImportInfo {
5
+ // account to module
6
+ imports: Map<string, Set<string>>
7
+ account: string
8
+ moduleName: string
9
+
10
+ constructor(account: string, tsModuleName: string) {
11
+ this.account = account
12
+ this.moduleName = tsModuleName
13
+ this.imports = new Map<string, Set<string>>()
14
+ }
15
+
16
+ addImport(account: string, module: string) {
17
+ if (account === this.account) {
18
+ return
19
+ }
20
+ let accountModules = this.imports.get(account)
21
+ if (!accountModules) {
22
+ accountModules = new Set<string>()
23
+ this.imports.set(account, accountModules)
24
+ }
25
+ accountModules.add(module)
26
+ }
27
+ }
28
+
29
+ export class AccountRegister {
30
+ accountImports = new Map<string, AccountModulesImportInfo>()
31
+ pendingAccounts = new Set<string>()
32
+
33
+ register(
34
+ module: InternalMoveModule,
35
+ tsModuleName: string
36
+ ): AccountModulesImportInfo {
37
+ const currentModuleFqn = moduleQname(module)
38
+
39
+ let accountModuleImports = this.accountImports.get(module.address)
40
+ if (!accountModuleImports) {
41
+ accountModuleImports = new AccountModulesImportInfo(
42
+ module.address,
43
+ tsModuleName
44
+ )
45
+ this.accountImports.set(module.address, accountModuleImports)
46
+ // the account has already be processed, delete pending task
47
+ this.pendingAccounts.delete(module.address)
48
+ }
49
+
50
+ this.registerStruct(module, accountModuleImports)
51
+ this.registerFunctions(module, accountModuleImports)
52
+
53
+ this.accountImports.set(currentModuleFqn, accountModuleImports)
54
+ return accountModuleImports
55
+ }
56
+
57
+ private registerFunctions(
58
+ module: InternalMoveModule,
59
+ accountModuleImports: AccountModulesImportInfo
60
+ ): void {
61
+ for (const func of module.exposedFunctions) {
62
+ if (!func.isEntry) {
63
+ continue
64
+ }
65
+ for (const param of func.params) {
66
+ for (const type of param.dependedTypes()) {
67
+ const [account, module] = moduleQnameForType(type)
68
+ accountModuleImports.addImport(account, module)
69
+ if (!this.accountImports.has(account)) {
70
+ this.pendingAccounts.add(account)
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
+ private registerStruct(
78
+ module: InternalMoveModule,
79
+ accountModuleImports: AccountModulesImportInfo
80
+ ): void {
81
+ for (const struct of module.structs) {
82
+ for (const field of struct.fields) {
83
+ for (const type of field.type.dependedTypes()) {
84
+ const [account, module] = moduleQnameForType(type)
85
+ accountModuleImports.addImport(account, module)
86
+ if (!this.accountImports.has(account)) {
87
+ this.pendingAccounts.add(account)
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }
93
+ }
@@ -0,0 +1,26 @@
1
+ import { InternalMoveModule, InternalMoveStruct } from './internal-models.js'
2
+ import { TypeDescriptor } from './types.js'
3
+
4
+ export abstract class ChainAdapter<ModuleType, StructType> {
5
+ // endpoint: string
6
+ //
7
+ // constructor(endpoint: string) {
8
+ // this.endpoint = endpoint
9
+ // }
10
+ abstract getChainId(): Promise<string>
11
+
12
+ abstract fetchModule(account: string, module: string): Promise<ModuleType>
13
+
14
+ abstract fetchModules(account: string): Promise<ModuleType[]>
15
+ abstract toInternalModules(modules: ModuleType[]): InternalMoveModule[]
16
+
17
+ // Get all structs that represent Events
18
+ abstract getAllEventStructs(module: InternalMoveModule[]): Map<string, InternalMoveStruct>
19
+
20
+ // Get the parameters that actually have arguments in runtime
21
+ // Aptos first signer and Sui's last TxContext are no use
22
+ abstract getMeaningfulFunctionParams(params: TypeDescriptor[]): TypeDescriptor[]
23
+
24
+ abstract getType(base: StructType): string
25
+ abstract getData<T>(base: StructType): any
26
+ }
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export * from './types.js'
2
+ export * from './utils.js'
3
+ export * from './account.js'
4
+ export * from './chain-adapter.js'
5
+ export * from './abstract-codegen.js'
6
+ export * from './abstract-move-coder.js'
7
+ export * from './internal-models.js'
@@ -0,0 +1,41 @@
1
+ import { TypeDescriptor } from './types.js'
2
+
3
+ export interface InternalMoveModule {
4
+ address: string
5
+ name: string
6
+ exposedFunctions: InternalMoveFunction[]
7
+ structs: InternalMoveStruct[]
8
+ }
9
+
10
+ export interface InternalMoveFunction {
11
+ name: string
12
+ visibility: InternalMoveFunctionVisibility
13
+ isEntry: boolean
14
+ isView?: boolean
15
+ typeParams: InternalMoveTypeParam[]
16
+ params: TypeDescriptor[]
17
+ return: TypeDescriptor[]
18
+ }
19
+
20
+ export interface InternalMoveStruct {
21
+ name: string
22
+ isNative: boolean
23
+ abilities: string[]
24
+ typeParams: InternalMoveTypeParam[]
25
+ fields: InternalMoveStructField[]
26
+ }
27
+
28
+ export interface InternalMoveStructField {
29
+ name: string
30
+ type: TypeDescriptor
31
+ }
32
+
33
+ export enum InternalMoveFunctionVisibility {
34
+ PRIVATE = 'private',
35
+ PUBLIC = 'public',
36
+ FRIEND = 'friend',
37
+ }
38
+
39
+ export type InternalMoveTypeParam = {
40
+ constraints: string[]
41
+ }