@typemove/sui 1.0.0-rc.10

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 (30) hide show
  1. package/LICENSE +201 -0
  2. package/dist/codegen/run.js +19 -0
  3. package/dist/index.js +5 -0
  4. package/package.json +43 -0
  5. package/src/abis/0x1.json +2063 -0
  6. package/src/abis/0x2.json +13410 -0
  7. package/src/abis/0x3.json +8645 -0
  8. package/src/builtin/0x1.ts +2909 -0
  9. package/src/builtin/0x2.ts +14389 -0
  10. package/src/builtin/0x3.ts +4385 -0
  11. package/src/builtin/index.ts +6 -0
  12. package/src/codegen/codegen.ts +244 -0
  13. package/src/codegen/index.ts +1 -0
  14. package/src/codegen/run.ts +20 -0
  15. package/src/index.ts +8 -0
  16. package/src/models.ts +24 -0
  17. package/src/module-client.ts +23 -0
  18. package/src/move-coder.ts +147 -0
  19. package/src/sui-chain-adapter.ts +113 -0
  20. package/src/tests/abis/testnet/0x1e2b124f746a339b3cf99b9f969393a96594519aafb1d06517aacfeeae20e7a5.json +265 -0
  21. package/src/tests/abis/testnet/0x6c4a21e3e7e6b6d51c4604021633e1d97e24e37a696f8c082cd48f37503e602a.json +2429 -0
  22. package/src/tests/abis/testnet/0xdee9.json +5523 -0
  23. package/src/tests/abis/testnet/0xebaa2ad3eacc230f309cd933958cc52684df0a41ae7ac214d186b80f830867d2.json +10060 -0
  24. package/src/tests/types/testnet/0x1e2b124f746a339b3cf99b9f969393a96594519aafb1d06517aacfeeae20e7a5.ts +295 -0
  25. package/src/tests/types/testnet/0x6c4a21e3e7e6b6d51c4604021633e1d97e24e37a696f8c082cd48f37503e602a.ts +2745 -0
  26. package/src/tests/types/testnet/0xdee9.ts +3148 -0
  27. package/src/tests/types/testnet/0xebaa2ad3eacc230f309cd933958cc52684df0a41ae7ac214d186b80f830867d2.ts +10516 -0
  28. package/src/tests/types/testnet/index.ts +7 -0
  29. package/src/to-internal.ts +129 -0
  30. package/src/utils.ts +62 -0
@@ -0,0 +1,6 @@
1
+ /* Autogenerated file. Do not edit manually. */
2
+ /* tslint:disable */
3
+ /* eslint-disable */
4
+ export * as _0x1 from './0x1.js'
5
+ export * as _0x2 from './0x2.js'
6
+ export * as _0x3 from './0x3.js'
@@ -0,0 +1,244 @@
1
+ import {
2
+ SuiMoveNormalizedModule,
3
+ SuiEvent,
4
+ SuiMoveObject,
5
+ } from '@mysten/sui.js'
6
+
7
+ import * as fs from 'fs'
8
+ import chalk from 'chalk'
9
+ import {
10
+ InternalMoveModule,
11
+ InternalMoveStruct,
12
+ AbstractCodegen,
13
+ structQname,
14
+ InternalMoveFunction,
15
+ InternalMoveFunctionVisibility,
16
+ normalizeToJSName,
17
+ camel,
18
+ } from '@typemove/move'
19
+ import { join } from 'path'
20
+ import { SuiChainAdapter } from '../sui-chain-adapter.js'
21
+
22
+ export async function codegen(
23
+ abisDir: string,
24
+ outDir = join('src', 'types', 'sui'),
25
+ endpoint: string,
26
+ genExample = false,
27
+ builtin = false
28
+ ) {
29
+ if (!fs.existsSync(abisDir)) {
30
+ return
31
+ }
32
+ const gen = new SuiCodegen(endpoint)
33
+ const numFiles = await gen.generate(abisDir, outDir, builtin)
34
+ console.log(chalk.green(`Generated ${numFiles} for Sui`))
35
+ }
36
+
37
+ class SuiCodegen extends AbstractCodegen<
38
+ // SuiNetwork,
39
+ SuiMoveNormalizedModule,
40
+ SuiEvent | SuiMoveObject
41
+ > {
42
+ ADDRESS_TYPE = 'SuiAddress'
43
+ REFERENCE_TYPE = 'ObjectId'
44
+ SYSTEM_PACKAGE = '@mysten/sui.js'
45
+ // ADDRESS_TYPE = 'string'
46
+ // MAIN_NET = SuiNetwork.MAIN_NET
47
+ // TEST_NET = SuiNetwork.TEST_NET
48
+ PREFIX = 'Sui'
49
+ // STRUCT_FIELD_NAME = 'fields'
50
+ // GENERATE_ON_ENTRY = true
51
+ PAYLOAD_OPTIONAL = true
52
+
53
+ constructor(endpoint: string) {
54
+ super(new SuiChainAdapter(endpoint))
55
+ }
56
+
57
+ readModulesFile(fullPath: string) {
58
+ const res = super.readModulesFile(fullPath)
59
+ if (res.result) {
60
+ return res.result
61
+ }
62
+ return res
63
+ }
64
+
65
+ generateStructs(
66
+ module: InternalMoveModule,
67
+ struct: InternalMoveStruct,
68
+ events: Set<string>
69
+ ): string {
70
+ let content = ''
71
+ switch (structQname(module, struct)) {
72
+ // TODO they should still have module code generated
73
+ case '0x1::ascii::Char':
74
+ case '0x1::ascii::String':
75
+ case '0x2::object::ID':
76
+ content += `export type ${struct.name} = string`
77
+ break
78
+ case '0x2::coin::Coin':
79
+ content += `export type ${struct.name}<T> = string`
80
+ break
81
+ case '0x2::balance::Balance':
82
+ content += `export type ${struct.name}<T> = bigint`
83
+ break
84
+ case '0x1::option::Option':
85
+ content += `export type Option<T> = T | undefined`
86
+ break
87
+ }
88
+ return (
89
+ content + super.generateStructs(module, struct, events, content !== '')
90
+ )
91
+ }
92
+
93
+ generateForEvents(
94
+ module: InternalMoveModule,
95
+ struct: InternalMoveStruct
96
+ ): string {
97
+ switch (structQname(module, struct)) {
98
+ case '0x1::ascii::Char':
99
+ case '0x1::ascii::String':
100
+ case '0x2::object::ID':
101
+ case '0x2::coin::Coin':
102
+ case '0x1::option::Option':
103
+ case '0x2::balance::Balance':
104
+ return ''
105
+ }
106
+ return super.generateForEvents(module, struct)
107
+ }
108
+
109
+ protected generateBuilder(module: InternalMoveModule): string {
110
+ const funcs = module.exposedFunctions.map((f) =>
111
+ this.generateBuilderForFunction(module, f)
112
+ )
113
+
114
+ const viewFuncs = module.exposedFunctions.map((f) =>
115
+ this.generateViewFunction(module, f)
116
+ )
117
+
118
+ return `
119
+ export namespace builder {
120
+ ${funcs.join('\n')}
121
+ }
122
+ export namespace view {
123
+ ${viewFuncs.join('\n')}
124
+ }
125
+ `
126
+ }
127
+
128
+ private generateArgs(module: InternalMoveModule, func: InternalMoveFunction) {
129
+ const args = []
130
+ for (const [idx, arg] of func.params.entries()) {
131
+ if (arg.reference) {
132
+ args.push({
133
+ paramType: 'ObjectId | ObjectCallArg | TransactionArgument',
134
+ callValue: `_args.push(TransactionArgument.is(args[${idx}]) ? args[${idx}] : tx.object(args[${idx}]))`,
135
+ })
136
+ } else if (arg.isVector()) {
137
+ args.push({
138
+ paramType: '(ObjectId | ObjectCallArg)[] | TransactionArgument',
139
+ callValue: `_args.push(TransactionArgument.is(args[${idx}]) ? args[${idx}] : tx.makeMoveVec({
140
+ objects: args[${idx}].map((a: any) => tx.object(a))
141
+ // type: TODO
142
+ }))`,
143
+ })
144
+ } else {
145
+ args.push({
146
+ paramType: `${this.generateTypeForDescriptor(
147
+ arg,
148
+ module.address
149
+ )} | TransactionArgument`,
150
+ callValue: `_args.push(TransactionArgument.is(args[${idx}]) ? args[${idx}] : tx.pure(args[${idx}]))`,
151
+ })
152
+ }
153
+ }
154
+ return args
155
+ }
156
+
157
+ protected generateViewFunction(
158
+ module: InternalMoveModule,
159
+ func: InternalMoveFunction
160
+ ): string {
161
+ if (func.visibility !== InternalMoveFunctionVisibility.PUBLIC) {
162
+ return ''
163
+ }
164
+ const genericString = this.generateFunctionTypeParameters(func)
165
+
166
+ const typeParamArg = func.typeParams
167
+ .map((v, idx) => {
168
+ return `TypeDescriptor<T${idx}> | string`
169
+ })
170
+ .join(',')
171
+
172
+ const args = this.generateArgs(module, func)
173
+
174
+ return `export async function ${camel(
175
+ normalizeToJSName(func.name)
176
+ )}${genericString}(
177
+ provider: JsonRpcProvider,
178
+ args: [${args.map((a) => a.paramType).join(',')}],
179
+ ${typeParamArg.length > 0 ? `typeArguments: [${typeParamArg}]` : ``} ) {
180
+ const tx = new TransactionBlock()
181
+ builder.${camel(normalizeToJSName(func.name))}(tx, args ${
182
+ typeParamArg.length > 0 ? `, typeArguments` : ''
183
+ })
184
+ const res = await provider.devInspectTransactionBlock({
185
+ transactionBlock: tx,
186
+ sender: ZERO_ADDRESS
187
+ })
188
+ return res
189
+ }`
190
+ }
191
+
192
+ protected generateBuilderForFunction(
193
+ module: InternalMoveModule,
194
+ func: InternalMoveFunction
195
+ ): string {
196
+ if (func.visibility !== InternalMoveFunctionVisibility.PUBLIC) {
197
+ return ''
198
+ }
199
+
200
+ const args = this.generateArgs(module, func)
201
+
202
+ const genericString = this.generateFunctionTypeParameters(func)
203
+
204
+ const typeParamArg = func.typeParams
205
+ .map((v, idx) => {
206
+ return `TypeDescriptor<T${idx}> | string`
207
+ })
208
+ .join(',')
209
+ const typeParamToString = func.typeParams
210
+ .map((v, idx) => {
211
+ return `typeof typeArguments[${idx}] === 'string' ? typeArguments[${idx}] : typeArguments[${idx}].getSignature()`
212
+ })
213
+ .join(',')
214
+
215
+ return `export function ${camel(
216
+ normalizeToJSName(func.name)
217
+ )}${genericString}(tx: TransactionBlock,
218
+ args: [${args.map((a) => a.paramType).join(',')}],
219
+ ${typeParamArg.length > 0 ? `typeArguments: [${typeParamArg}]` : ``} ):
220
+ TransactionArgument & [ ${'TransactionArgument,'.repeat(
221
+ func.params.length
222
+ )} ] {
223
+ const _args: any[] = []
224
+ ${args.map((a) => a.callValue).join('\n')}
225
+
226
+ // @ts-ignore
227
+ return tx.moveCall({
228
+ target: "${module.address}::${module.name}::${func.name}",
229
+ arguments: _args,
230
+ ${
231
+ typeParamArg.length > 0 ? `typeArguments: [${typeParamToString}]` : ``
232
+ }
233
+ })
234
+ }`
235
+ }
236
+
237
+ generateImports(): string {
238
+ return `
239
+ ${super.generateImports()}
240
+ import { ZERO_ADDRESS } from '@typemove/sui'
241
+ import { TransactionBlock, TransactionArgument, ObjectCallArg, JsonRpcProvider } from '@mysten/sui.js'
242
+ `
243
+ }
244
+ }
@@ -0,0 +1 @@
1
+ export * from './codegen.js'
@@ -0,0 +1,20 @@
1
+ // #!/usr/bin/env node
2
+
3
+ import { codegen } from './codegen.js'
4
+
5
+ if (process.argv.length > 3) {
6
+ const abisDir = process.argv[2]
7
+ const targetDir = process.argv[3]
8
+ let endpoint: string | undefined = process.argv[4]
9
+ if (!endpoint || endpoint == 'mainnet') {
10
+ endpoint = 'https://fullnode.mainnet.sui.io/'
11
+ }
12
+ if (endpoint == 'testnet') {
13
+ endpoint = 'https://fullnode.testnet.sui.io/'
14
+ }
15
+
16
+ await codegen(abisDir, targetDir, endpoint, false, true)
17
+ } else {
18
+ console.error('Not enough argument')
19
+ process.exit(1)
20
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from './models.js'
2
+
3
+ export type { SuiAddress, ObjectId } from '@mysten/sui.js'
4
+ // export * as builtin from './builtin/index.js'
5
+
6
+ export { MoveCoder, defaultMoveCoder } from './move-coder.js'
7
+
8
+ export { ModuleClient } from './module-client.js'
package/src/models.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type {
2
+ SuiEvent,
3
+ MoveCallSuiTransaction,
4
+ SuiMoveObject,
5
+ } from '@mysten/sui.js'
6
+ import { DecodedStruct } from '@typemove/move'
7
+
8
+ export const ZERO_ADDRESS =
9
+ '0x0000000000000000000000000000000000000000000000000000000000000000'
10
+
11
+ export type TypedEventInstance<T> = DecodedStruct<SuiEvent, T>
12
+ export type TypedSuiMoveObject<T> = DecodedStruct<SuiMoveObject, T>
13
+
14
+ export type TypedFunctionPayload<T extends Array<any>> =
15
+ MoveCallSuiTransaction & {
16
+ /**
17
+ * decoded argument data using ABI, undefined if there is decoding error, usually because the ABI/data mismatch
18
+ */
19
+ arguments_decoded: T
20
+ }
21
+
22
+ // export interface TypedExecutionResultType<T> extends ExecutionResultType {
23
+ //
24
+ // }
@@ -0,0 +1,23 @@
1
+ import { JsonRpcProvider } from '@mysten/sui.js'
2
+
3
+ export class ModuleClient {
4
+ public async viewDecoded(
5
+ func: string,
6
+ typeArguments: string[],
7
+ args: any[],
8
+ ledger_version?: bigint
9
+ ) {
10
+ throw Error('not implemented')
11
+ }
12
+ }
13
+
14
+ // const provider: JsonRpcProvider
15
+
16
+ //
17
+ // provider.
18
+
19
+ export class TypedJsonRpcProvider extends JsonRpcProvider {
20
+ public xxx() {
21
+ this.connection.fullnode
22
+ }
23
+ }
@@ -0,0 +1,147 @@
1
+ import { TypedEventInstance, TypedFunctionPayload } from './models.js'
2
+ import {
3
+ AbstractMoveCoder,
4
+ ANY_TYPE,
5
+ DecodedStruct,
6
+ parseMoveType,
7
+ SPLITTER,
8
+ TypeDescriptor,
9
+ InternalMoveModule,
10
+ } from '@typemove/move'
11
+ import {
12
+ MoveCallSuiTransaction,
13
+ SuiCallArg,
14
+ SuiEvent,
15
+ SuiMoveNormalizedModule,
16
+ SuiMoveObject,
17
+ } from '@mysten/sui.js'
18
+ import { toInternalModule } from './to-internal.js'
19
+ import { SuiChainAdapter } from './sui-chain-adapter.js'
20
+ import { dynamic_field } from './builtin/0x2.js'
21
+
22
+ export class MoveCoder extends AbstractMoveCoder<
23
+ // SuiNetwork,
24
+ SuiMoveNormalizedModule,
25
+ SuiEvent | SuiMoveObject
26
+ > {
27
+ constructor(network: string) {
28
+ super(new SuiChainAdapter(network))
29
+ }
30
+
31
+ load(module: SuiMoveNormalizedModule): InternalMoveModule {
32
+ let m = this.moduleMapping.get(module.address + '::' + module.name)
33
+ if (m) {
34
+ return m
35
+ }
36
+ m = toInternalModule(module)
37
+ this.loadInternal(m)
38
+ return m
39
+ }
40
+
41
+ protected decode(data: any, type: TypeDescriptor): any {
42
+ switch (type.qname) {
43
+ case '0x1::ascii::Char':
44
+ case '0x1::ascii::String':
45
+ case '0x2::object::ID':
46
+ case '0x2::coin::Coin':
47
+ return data
48
+ case '0x2::balance::Balance':
49
+ return BigInt(data)
50
+ case '0x1::option::Option':
51
+ if (data === null) {
52
+ return data
53
+ }
54
+ return this.decode(data, type.typeArgs[0])
55
+ default:
56
+ return super.decode(data, type)
57
+ }
58
+ }
59
+
60
+ decodeEvent<T>(event: SuiEvent): Promise<TypedEventInstance<T> | undefined> {
61
+ return this.decodedStruct(event)
62
+ }
63
+ filterAndDecodeEvents<T>(
64
+ type: TypeDescriptor<T> | string,
65
+ resources: SuiEvent[]
66
+ ): Promise<TypedEventInstance<T>[]> {
67
+ if (typeof type === 'string') {
68
+ type = parseMoveType(type)
69
+ }
70
+ return this.filterAndDecodeStruct(type, resources)
71
+ }
72
+
73
+ async getDynamicFields<T1, T2>(
74
+ objects: SuiMoveObject[],
75
+ keyType: TypeDescriptor<T1> = ANY_TYPE,
76
+ valueType: TypeDescriptor<T2> = ANY_TYPE
77
+ ): Promise<dynamic_field.Field<T1, T2>[]> {
78
+ // const type = dynamic_field.Field.TYPE
79
+ // Not using the code above to avoid cycle initialize failed
80
+ const type = new TypeDescriptor<dynamic_field.Field<T1, T2>>(
81
+ '0x2::dynamic_field::Field'
82
+ )
83
+ type.typeArgs = [keyType, valueType]
84
+ const res = await this.filterAndDecodeObjects(type, objects)
85
+ return res.map((o) => o.data_decoded)
86
+ }
87
+
88
+ filterAndDecodeObjects<T>(
89
+ type: TypeDescriptor<T>,
90
+ objects: SuiMoveObject[]
91
+ ): Promise<DecodedStruct<SuiMoveObject, T>[]> {
92
+ return this.filterAndDecodeStruct(type, objects)
93
+ }
94
+
95
+ async decodeFunctionPayload(
96
+ payload: MoveCallSuiTransaction,
97
+ inputs: SuiCallArg[]
98
+ ): Promise<MoveCallSuiTransaction> {
99
+ const functionType = [
100
+ payload.package,
101
+ payload.module,
102
+ payload.function,
103
+ ].join(SPLITTER)
104
+ const func = await this.getMoveFunction(functionType)
105
+ const params = this.adapter.getMeaningfulFunctionParams(func.params)
106
+ const args = []
107
+ for (const value of payload.arguments || []) {
108
+ const argValue = value as any
109
+ if ('Input' in (argValue as any)) {
110
+ const idx = argValue.Input
111
+ const arg = inputs[idx]
112
+ if (arg.type === 'pure') {
113
+ args.push(arg.value)
114
+ } else if (arg.type === 'object') {
115
+ // object is not there
116
+ args.push(undefined)
117
+ } else {
118
+ console.error('unexpected function arg value')
119
+ args.push(undefined)
120
+ }
121
+ // args.push(arg) // TODO check why ts not work using arg.push(arg)
122
+ } else {
123
+ args.push(undefined)
124
+ }
125
+ }
126
+
127
+ const argumentsTyped = await this.decodeArray(args, params, false)
128
+ return {
129
+ ...payload,
130
+ arguments_decoded: argumentsTyped,
131
+ } as TypedFunctionPayload<any>
132
+ }
133
+ }
134
+
135
+ const DEFAULT_ENDPOINT = 'https://fullnode.mainnet.sui.io/'
136
+ const CODER_MAP = new Map<string, MoveCoder>()
137
+
138
+ export function defaultMoveCoder(
139
+ endpoint: string = DEFAULT_ENDPOINT
140
+ ): MoveCoder {
141
+ let coder = CODER_MAP.get(endpoint)
142
+ if (!coder) {
143
+ coder = new MoveCoder(DEFAULT_ENDPOINT)
144
+ CODER_MAP.set(endpoint, coder)
145
+ }
146
+ return coder
147
+ }
@@ -0,0 +1,113 @@
1
+ import { toInternalModule } from './to-internal.js'
2
+ import {
3
+ InternalMoveModule,
4
+ InternalMoveStruct,
5
+ ChainAdapter,
6
+ moduleQname,
7
+ SPLITTER,
8
+ TypeDescriptor,
9
+ } from '@typemove/move'
10
+ import {
11
+ Connection,
12
+ JsonRpcProvider,
13
+ SuiMoveNormalizedModule,
14
+ SuiEvent,
15
+ SuiMoveObject,
16
+ SuiParsedData,
17
+ } from '@mysten/sui.js'
18
+
19
+ export class SuiChainAdapter extends ChainAdapter<
20
+ // SuiNetwork,
21
+ SuiMoveNormalizedModule,
22
+ SuiEvent | SuiMoveObject
23
+ > {
24
+ // static INSTANCE = new SuiChainAdapter()
25
+
26
+ async fetchModule(
27
+ account: string,
28
+ module: string
29
+ // network: SuiNetwork
30
+ ): Promise<SuiMoveNormalizedModule> {
31
+ const client = getRpcClient(this.endpoint)
32
+ return await client.getNormalizedMoveModule({ package: account, module })
33
+ }
34
+
35
+ async fetchModules(
36
+ account: string
37
+ // network: SuiNetwork
38
+ ): Promise<SuiMoveNormalizedModule[]> {
39
+ const client = getRpcClient(this.endpoint)
40
+ const modules = await client.getNormalizedMoveModulesByPackage({
41
+ package: account,
42
+ })
43
+ return Object.values(modules)
44
+ }
45
+
46
+ getMeaningfulFunctionParams(params: TypeDescriptor[]): TypeDescriptor[] {
47
+ return params
48
+ // if (params.length === 0) {
49
+ // return params
50
+ // }
51
+ // return params.slice(0, params.length - 1)
52
+ }
53
+
54
+ toInternalModules(modules: SuiMoveNormalizedModule[]): InternalMoveModule[] {
55
+ return Object.values(modules).map(toInternalModule)
56
+ }
57
+
58
+ getAllEventStructs(
59
+ modules: InternalMoveModule[]
60
+ ): Map<string, InternalMoveStruct> {
61
+ const eventMap = new Map<string, InternalMoveStruct>()
62
+
63
+ for (const module of modules) {
64
+ const qname = moduleQname(module)
65
+
66
+ for (const struct of module.structs) {
67
+ const abilities = new Set(struct.abilities)
68
+ if (abilities.has('Drop') && abilities.has('Copy')) {
69
+ eventMap.set(qname + SPLITTER + struct.name, struct)
70
+ }
71
+ }
72
+ }
73
+ return eventMap
74
+ }
75
+
76
+ getType(base: SuiEvent | SuiMoveObject): string {
77
+ return base.type
78
+ }
79
+
80
+ getData(val: SuiEvent | SuiMoveObject) {
81
+ if (SuiEvent.is(val)) {
82
+ return val.parsedJson as any
83
+ }
84
+ if (SuiParsedData.is(val)) {
85
+ return val.fields as any
86
+ }
87
+ // if (SuiMoveObject.is(val)) {
88
+ // return val.fields as any
89
+ // }
90
+ // This may not be perfect, just think everything has
91
+ if ('fields' in val) {
92
+ if ('type' in val && Object.keys(val).length === 2) {
93
+ return val.fields as any
94
+ }
95
+ }
96
+ return val as any
97
+ }
98
+ // validateAndNormalizeAddress(address: string) {
99
+ // return validateAndNormalizeAddress(address)
100
+ // }
101
+ }
102
+
103
+ // function getRpcEndpoint(network: SuiNetwork): string {
104
+ // switch (network) {
105
+ // case SuiNetwork.TEST_NET:
106
+ // return 'https://fullnode.testnet.sui.io/'
107
+ // }
108
+ // return 'https://fullnode.mainnet.sui.io/'
109
+ // }
110
+
111
+ function getRpcClient(endpoint: string): JsonRpcProvider {
112
+ return new JsonRpcProvider(new Connection({ fullnode: endpoint }))
113
+ }