@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.
- package/LICENSE +201 -0
- package/dist/codegen/run.js +19 -0
- package/dist/index.js +5 -0
- package/package.json +43 -0
- package/src/abis/0x1.json +2063 -0
- package/src/abis/0x2.json +13410 -0
- package/src/abis/0x3.json +8645 -0
- package/src/builtin/0x1.ts +2909 -0
- package/src/builtin/0x2.ts +14389 -0
- package/src/builtin/0x3.ts +4385 -0
- package/src/builtin/index.ts +6 -0
- package/src/codegen/codegen.ts +244 -0
- package/src/codegen/index.ts +1 -0
- package/src/codegen/run.ts +20 -0
- package/src/index.ts +8 -0
- package/src/models.ts +24 -0
- package/src/module-client.ts +23 -0
- package/src/move-coder.ts +147 -0
- package/src/sui-chain-adapter.ts +113 -0
- package/src/tests/abis/testnet/0x1e2b124f746a339b3cf99b9f969393a96594519aafb1d06517aacfeeae20e7a5.json +265 -0
- package/src/tests/abis/testnet/0x6c4a21e3e7e6b6d51c4604021633e1d97e24e37a696f8c082cd48f37503e602a.json +2429 -0
- package/src/tests/abis/testnet/0xdee9.json +5523 -0
- package/src/tests/abis/testnet/0xebaa2ad3eacc230f309cd933958cc52684df0a41ae7ac214d186b80f830867d2.json +10060 -0
- package/src/tests/types/testnet/0x1e2b124f746a339b3cf99b9f969393a96594519aafb1d06517aacfeeae20e7a5.ts +295 -0
- package/src/tests/types/testnet/0x6c4a21e3e7e6b6d51c4604021633e1d97e24e37a696f8c082cd48f37503e602a.ts +2745 -0
- package/src/tests/types/testnet/0xdee9.ts +3148 -0
- package/src/tests/types/testnet/0xebaa2ad3eacc230f309cd933958cc52684df0a41ae7ac214d186b80f830867d2.ts +10516 -0
- package/src/tests/types/testnet/index.ts +7 -0
- package/src/to-internal.ts +129 -0
- package/src/utils.ts +62 -0
|
@@ -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
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
|
+
}
|