@typemove/sui 1.2.4-rc4 → 1.2.5-rc.1
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/dist/cjs/builtin/0x1.d.ts +496 -0
- package/dist/cjs/builtin/0x1.d.ts.map +1 -0
- package/dist/cjs/builtin/0x1.js +2038 -0
- package/dist/cjs/builtin/0x1.js.map +1 -0
- package/dist/cjs/builtin/0x2.d.ts +2933 -0
- package/dist/cjs/builtin/0x2.d.ts.map +1 -0
- package/dist/cjs/builtin/0x2.js +9511 -0
- package/dist/cjs/builtin/0x2.js.map +1 -0
- package/dist/cjs/builtin/0x3.d.ts +1208 -0
- package/dist/cjs/builtin/0x3.d.ts.map +1 -0
- package/dist/cjs/builtin/0x3.js +2455 -0
- package/dist/cjs/builtin/0x3.js.map +1 -0
- package/dist/cjs/builtin/index.d.ts +4 -0
- package/dist/cjs/builtin/index.d.ts.map +1 -0
- package/dist/cjs/builtin/index.js +11 -0
- package/dist/cjs/builtin/index.js.map +1 -0
- package/dist/cjs/codegen/codegen.d.ts +19 -0
- package/dist/cjs/codegen/codegen.d.ts.map +1 -0
- package/dist/cjs/codegen/codegen.js +178 -0
- package/dist/cjs/codegen/codegen.js.map +1 -0
- package/dist/cjs/codegen/index.d.ts +2 -0
- package/dist/cjs/codegen/index.d.ts.map +1 -0
- package/dist/cjs/codegen/index.js +5 -0
- package/dist/cjs/codegen/index.js.map +1 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +11 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/models.d.ts +18 -0
- package/dist/cjs/models.d.ts.map +1 -0
- package/dist/cjs/models.js +5 -0
- package/dist/cjs/models.js.map +1 -0
- package/dist/cjs/move-coder.d.ts +25 -0
- package/dist/cjs/move-coder.d.ts.map +1 -0
- package/dist/cjs/move-coder.js +229 -0
- package/dist/cjs/move-coder.js.map +1 -0
- package/dist/cjs/move-coder.test.d.ts +2 -0
- package/dist/cjs/move-coder.test.d.ts.map +1 -0
- package/dist/cjs/move-coder.test.js.map +1 -0
- package/dist/cjs/sui-chain-adapter.d.ts +15 -0
- package/dist/cjs/sui-chain-adapter.d.ts.map +1 -0
- package/dist/cjs/sui-chain-adapter.js +95 -0
- package/dist/cjs/sui-chain-adapter.js.map +1 -0
- package/dist/cjs/to-internal.d.ts +4 -0
- package/dist/cjs/to-internal.d.ts.map +1 -0
- package/dist/cjs/to-internal.js +85 -0
- package/dist/cjs/to-internal.js.map +1 -0
- package/dist/cjs/transaction.d.ts +6 -0
- package/dist/cjs/transaction.d.ts.map +1 -0
- package/dist/cjs/transaction.js +35 -0
- package/dist/cjs/transaction.js.map +1 -0
- package/dist/esm/builtin/0x1.d.ts +496 -0
- package/dist/esm/builtin/0x1.d.ts.map +1 -0
- package/dist/esm/builtin/0x1.js +2034 -0
- package/dist/esm/builtin/0x1.js.map +1 -0
- package/dist/esm/builtin/0x2.d.ts +2933 -0
- package/dist/esm/builtin/0x2.d.ts.map +1 -0
- package/dist/esm/builtin/0x2.js +9506 -0
- package/dist/esm/builtin/0x2.js.map +1 -0
- package/dist/esm/builtin/0x3.d.ts +1208 -0
- package/dist/esm/builtin/0x3.d.ts.map +1 -0
- package/dist/esm/builtin/0x3.js +2450 -0
- package/dist/esm/builtin/0x3.js.map +1 -0
- package/dist/esm/builtin/index.d.ts +4 -0
- package/dist/esm/builtin/index.d.ts.map +1 -0
- package/dist/esm/builtin/index.js +7 -0
- package/dist/esm/builtin/index.js.map +1 -0
- package/dist/esm/codegen/codegen.d.ts +19 -0
- package/dist/esm/codegen/codegen.d.ts.map +1 -0
- package/dist/esm/codegen/codegen.js +172 -0
- package/dist/esm/codegen/codegen.js.map +1 -0
- package/dist/esm/codegen/index.d.ts +2 -0
- package/dist/esm/codegen/index.d.ts.map +1 -0
- package/dist/esm/codegen/index.js +2 -0
- package/dist/esm/codegen/index.js.map +1 -0
- package/dist/esm/codegen/run.d.ts +2 -0
- package/dist/esm/codegen/run.d.ts.map +1 -0
- package/dist/esm/codegen/run.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/models.d.ts +18 -0
- package/dist/esm/models.d.ts.map +1 -0
- package/dist/esm/models.js +2 -0
- package/dist/esm/models.js.map +1 -0
- package/dist/esm/move-coder.d.ts +25 -0
- package/dist/esm/move-coder.d.ts.map +1 -0
- package/dist/esm/move-coder.js +223 -0
- package/dist/esm/move-coder.js.map +1 -0
- package/dist/esm/move-coder.test.d.ts +2 -0
- package/dist/esm/move-coder.test.d.ts.map +1 -0
- package/dist/esm/move-coder.test.js.map +1 -0
- package/dist/esm/sui-chain-adapter.d.ts +15 -0
- package/dist/esm/sui-chain-adapter.d.ts.map +1 -0
- package/dist/esm/sui-chain-adapter.js +91 -0
- package/dist/esm/sui-chain-adapter.js.map +1 -0
- package/dist/esm/to-internal.d.ts +4 -0
- package/dist/esm/to-internal.d.ts.map +1 -0
- package/dist/esm/to-internal.js +81 -0
- package/dist/esm/to-internal.js.map +1 -0
- package/dist/esm/transaction.d.ts +6 -0
- package/dist/esm/transaction.d.ts.map +1 -0
- package/dist/esm/transaction.js +28 -0
- package/dist/esm/transaction.js.map +1 -0
- package/package.json +2 -2
- 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 +3000 -0
- package/src/builtin/0x2.ts +14596 -0
- package/src/builtin/0x3.ts +4188 -0
- package/src/builtin/index.ts +6 -0
- package/src/codegen/codegen.ts +211 -0
- package/src/codegen/index.ts +1 -0
- package/src/codegen/run.ts +20 -0
- package/src/index.ts +4 -0
- package/src/models.ts +21 -0
- package/src/move-coder.ts +276 -0
- package/src/sui-chain-adapter.ts +121 -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 +303 -0
- package/src/tests/types/testnet/0x6c4a21e3e7e6b6d51c4604021633e1d97e24e37a696f8c082cd48f37503e602a.ts +2697 -0
- package/src/tests/types/testnet/0xdee9.ts +3099 -0
- package/src/tests/types/testnet/0xebaa2ad3eacc230f309cd933958cc52684df0a41ae7ac214d186b80f830867d2.ts +10215 -0
- package/src/tests/types/testnet/index.ts +7 -0
- package/src/to-internal.ts +109 -0
- package/src/transaction.ts +31 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { SuiMoveNormalizedModule, SuiEvent, SuiMoveObject, SuiClient } from '@mysten/sui.js/client'
|
|
2
|
+
|
|
3
|
+
import * as fs from 'fs'
|
|
4
|
+
import chalk from 'chalk'
|
|
5
|
+
import {
|
|
6
|
+
InternalMoveModule,
|
|
7
|
+
InternalMoveStruct,
|
|
8
|
+
AbstractCodegen,
|
|
9
|
+
structQname,
|
|
10
|
+
InternalMoveFunction,
|
|
11
|
+
InternalMoveFunctionVisibility,
|
|
12
|
+
normalizeToJSName,
|
|
13
|
+
camel
|
|
14
|
+
} from '@typemove/move'
|
|
15
|
+
import { join } from 'path'
|
|
16
|
+
import { SuiChainAdapter } from '../sui-chain-adapter.js'
|
|
17
|
+
|
|
18
|
+
export async function codegen(
|
|
19
|
+
abisDir: string,
|
|
20
|
+
outDir = join('src', 'types', 'sui'),
|
|
21
|
+
endpoint: string,
|
|
22
|
+
genExample = false,
|
|
23
|
+
builtin = false
|
|
24
|
+
) {
|
|
25
|
+
if (!fs.existsSync(abisDir)) {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
const gen = new SuiCodegen(endpoint)
|
|
29
|
+
const numFiles = await gen.generate(abisDir, outDir, builtin)
|
|
30
|
+
console.log(chalk.green(`Generated ${numFiles} for Sui`))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class SuiCodegen extends AbstractCodegen<
|
|
34
|
+
// SuiNetwork,
|
|
35
|
+
SuiMoveNormalizedModule,
|
|
36
|
+
SuiEvent | SuiMoveObject
|
|
37
|
+
> {
|
|
38
|
+
ADDRESS_TYPE = 'string'
|
|
39
|
+
SYSTEM_PACKAGE = '@typemove/sui'
|
|
40
|
+
// ADDRESS_TYPE = 'string'
|
|
41
|
+
// MAIN_NET = SuiNetwork.MAIN_NET
|
|
42
|
+
// TEST_NET = SuiNetwork.TEST_NET
|
|
43
|
+
PREFIX = 'Sui'
|
|
44
|
+
// STRUCT_FIELD_NAME = 'fields'
|
|
45
|
+
// GENERATE_ON_ENTRY = true
|
|
46
|
+
PAYLOAD_OPTIONAL = true
|
|
47
|
+
|
|
48
|
+
constructor(endpoint: string) {
|
|
49
|
+
super(new SuiChainAdapter(new SuiClient({ url: endpoint })))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
readModulesFile(fullPath: string) {
|
|
53
|
+
const res = super.readModulesFile(fullPath)
|
|
54
|
+
if (res.result) {
|
|
55
|
+
return res.result
|
|
56
|
+
}
|
|
57
|
+
return res
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
generateStructs(module: InternalMoveModule, struct: InternalMoveStruct, events: Set<string>): string {
|
|
61
|
+
let content = ''
|
|
62
|
+
switch (structQname(module, struct)) {
|
|
63
|
+
// TODO they should still have module code generated
|
|
64
|
+
case '0x1::ascii::Char':
|
|
65
|
+
case '0x1::ascii::String':
|
|
66
|
+
case '0x2::object::ID':
|
|
67
|
+
content += `export type ${struct.name} = string`
|
|
68
|
+
break
|
|
69
|
+
case '0x2::coin::Coin':
|
|
70
|
+
content += `export type ${struct.name}<T> = string`
|
|
71
|
+
break
|
|
72
|
+
case '0x2::balance::Balance':
|
|
73
|
+
content += `export type ${struct.name}<T> = bigint`
|
|
74
|
+
break
|
|
75
|
+
case '0x1::option::Option':
|
|
76
|
+
content += `export type Option<T> = T | undefined`
|
|
77
|
+
break
|
|
78
|
+
}
|
|
79
|
+
return content + super.generateStructs(module, struct, events, content !== '')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
generateForEvents(module: InternalMoveModule, struct: InternalMoveStruct): string {
|
|
83
|
+
switch (structQname(module, struct)) {
|
|
84
|
+
case '0x1::ascii::Char':
|
|
85
|
+
case '0x1::ascii::String':
|
|
86
|
+
case '0x2::object::ID':
|
|
87
|
+
case '0x2::coin::Coin':
|
|
88
|
+
case '0x1::option::Option':
|
|
89
|
+
case '0x2::balance::Balance':
|
|
90
|
+
return ''
|
|
91
|
+
}
|
|
92
|
+
return super.generateForEvents(module, struct)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
protected generateExtra(module: InternalMoveModule): string {
|
|
96
|
+
const funcs = module.exposedFunctions.map((f) => this.generateBuilderForFunction(module, f))
|
|
97
|
+
|
|
98
|
+
const viewFuncs = module.exposedFunctions.map((f) => this.generateViewFunction(module, f))
|
|
99
|
+
|
|
100
|
+
return `
|
|
101
|
+
export namespace builder {
|
|
102
|
+
${funcs.join('\n')}
|
|
103
|
+
}
|
|
104
|
+
export namespace view {
|
|
105
|
+
${viewFuncs.join('\n')}
|
|
106
|
+
}
|
|
107
|
+
`
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private generateArgs(module: InternalMoveModule, func: InternalMoveFunction) {
|
|
111
|
+
const args = []
|
|
112
|
+
for (const [idx, arg] of func.params.entries()) {
|
|
113
|
+
if (arg.reference) {
|
|
114
|
+
args.push({
|
|
115
|
+
paramType: `${this.ADDRESS_TYPE} | ObjectCallArg | TransactionArgument`,
|
|
116
|
+
callValue: `_args.push(transactionArgumentOrObject(args[${idx}], tx))`
|
|
117
|
+
})
|
|
118
|
+
} else if (arg.isVector()) {
|
|
119
|
+
args.push({
|
|
120
|
+
paramType: `(${this.ADDRESS_TYPE} | ObjectCallArg)[] | TransactionArgument`,
|
|
121
|
+
callValue: `_args.push(transactionArgumentOrVec(args[${idx}], tx))`
|
|
122
|
+
})
|
|
123
|
+
} else {
|
|
124
|
+
args.push({
|
|
125
|
+
paramType: `${this.generateTypeForDescriptor(arg, module.address)} | TransactionArgument`,
|
|
126
|
+
callValue: `_args.push(transactionArgumentOrPure(args[${idx}], tx))`
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return args
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
protected generateViewFunction(module: InternalMoveModule, func: InternalMoveFunction): string {
|
|
134
|
+
if (func.visibility !== InternalMoveFunctionVisibility.PUBLIC) {
|
|
135
|
+
return ''
|
|
136
|
+
}
|
|
137
|
+
const genericString = this.generateFunctionTypeParameters(func)
|
|
138
|
+
|
|
139
|
+
const typeParamArg = func.typeParams
|
|
140
|
+
.map((v, idx) => {
|
|
141
|
+
return `TypeDescriptor<T${idx}> | string`
|
|
142
|
+
})
|
|
143
|
+
.join(',')
|
|
144
|
+
|
|
145
|
+
const args = this.generateArgs(module, func)
|
|
146
|
+
const returnType = `${this.generateFunctionReturnTypeParameters(func, module.address)}`
|
|
147
|
+
|
|
148
|
+
return `export async function ${camel(normalizeToJSName(func.name))}${genericString}(
|
|
149
|
+
client: SuiClient,
|
|
150
|
+
args: [${args.map((a) => a.paramType).join(',')}],
|
|
151
|
+
${
|
|
152
|
+
typeParamArg.length > 0 ? `typeArguments: [${typeParamArg}]` : ``
|
|
153
|
+
} ): Promise<TypedDevInspectResults<${returnType}>> {
|
|
154
|
+
const tx = new TransactionBlock()
|
|
155
|
+
builder.${camel(normalizeToJSName(func.name))}(tx, args ${typeParamArg.length > 0 ? `, typeArguments` : ''})
|
|
156
|
+
const insepctRes = await client.devInspectTransactionBlock({
|
|
157
|
+
transactionBlock: tx,
|
|
158
|
+
sender: ZERO_ADDRESS
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
return (await getMoveCoder(client)).decodeDevInspectResult<${returnType}>(insepctRes)
|
|
162
|
+
}`
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
protected generateBuilderForFunction(module: InternalMoveModule, func: InternalMoveFunction): string {
|
|
166
|
+
if (func.visibility !== InternalMoveFunctionVisibility.PUBLIC) {
|
|
167
|
+
return ''
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const args = this.generateArgs(module, func)
|
|
171
|
+
|
|
172
|
+
const genericString = this.generateFunctionTypeParameters(func)
|
|
173
|
+
|
|
174
|
+
const typeParamArg = func.typeParams
|
|
175
|
+
.map((v, idx) => {
|
|
176
|
+
return `TypeDescriptor<T${idx}> | string`
|
|
177
|
+
})
|
|
178
|
+
.join(',')
|
|
179
|
+
const typeParamToString = func.typeParams
|
|
180
|
+
.map((v, idx) => {
|
|
181
|
+
return `typeof typeArguments[${idx}] === 'string' ? typeArguments[${idx}] : typeArguments[${idx}].getSignature()`
|
|
182
|
+
})
|
|
183
|
+
.join(',')
|
|
184
|
+
|
|
185
|
+
return `export function ${camel(normalizeToJSName(func.name))}${genericString}(tx: TransactionBlock,
|
|
186
|
+
args: [${args.map((a) => a.paramType).join(',')}],
|
|
187
|
+
${typeParamArg.length > 0 ? `typeArguments: [${typeParamArg}]` : ``} ):
|
|
188
|
+
TransactionArgument & [ ${'TransactionArgument,'.repeat(func.params.length)} ] {
|
|
189
|
+
const _args: any[] = []
|
|
190
|
+
${args.map((a) => a.callValue).join('\n')}
|
|
191
|
+
|
|
192
|
+
// @ts-ignore
|
|
193
|
+
return tx.moveCall({
|
|
194
|
+
target: "${module.address}::${module.name}::${func.name}",
|
|
195
|
+
arguments: _args,
|
|
196
|
+
${typeParamArg.length > 0 ? `typeArguments: [${typeParamToString}]` : ``}
|
|
197
|
+
})
|
|
198
|
+
}`
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
generateImports(): string {
|
|
202
|
+
return `
|
|
203
|
+
${super.generateImports()}
|
|
204
|
+
import { ZERO_ADDRESS, TypedDevInspectResults, getMoveCoder } from '@typemove/sui'
|
|
205
|
+
import { TransactionBlock, TransactionArgument } from '@mysten/sui.js/transactions'
|
|
206
|
+
import { SuiClient } from '@mysten/sui.js/client'
|
|
207
|
+
import { type ObjectCallArg } from "@mysten/sui.js/dist/esm/builder/Inputs.js";
|
|
208
|
+
import { transactionArgumentOrObject, transactionArgumentOrPure, transactionArgumentOrVec } from '@typemove/sui'
|
|
209
|
+
`
|
|
210
|
+
}
|
|
211
|
+
}
|
|
@@ -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,21 @@
|
|
|
1
|
+
import type { SuiEvent, MoveCallSuiTransaction, SuiMoveObject, DevInspectResults } from '@mysten/sui.js/client'
|
|
2
|
+
import { DecodedStruct } from '@typemove/move'
|
|
3
|
+
|
|
4
|
+
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
5
|
+
|
|
6
|
+
export type TypedEventInstance<T> = DecodedStruct<SuiEvent, T>
|
|
7
|
+
export type TypedSuiMoveObject<T> = DecodedStruct<SuiMoveObject, T>
|
|
8
|
+
|
|
9
|
+
export type TypedFunctionPayload<T extends Array<any>> = MoveCallSuiTransaction & {
|
|
10
|
+
/**
|
|
11
|
+
* decoded argument data using ABI, undefined if there is decoding error, usually because the ABI/data mismatch
|
|
12
|
+
*/
|
|
13
|
+
arguments_decoded: T
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type TypedDevInspectResults<T extends Array<any>> = DevInspectResults & {
|
|
17
|
+
/**
|
|
18
|
+
* Decoded return values using ABI, undefined if there is decoding error, usually because the ABI/data mismatch
|
|
19
|
+
*/
|
|
20
|
+
results_decoded?: T
|
|
21
|
+
}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { TypedDevInspectResults, 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
|
+
DevInspectResults,
|
|
18
|
+
SuiClient
|
|
19
|
+
} from '@mysten/sui.js/client'
|
|
20
|
+
import { toInternalModule } from './to-internal.js'
|
|
21
|
+
import { SuiChainAdapter } from './sui-chain-adapter.js'
|
|
22
|
+
import { dynamic_field } from './builtin/0x2.js'
|
|
23
|
+
import { BCS, getSuiMoveConfig, StructTypeDefinition } from '@mysten/bcs'
|
|
24
|
+
|
|
25
|
+
// import { Encoding } from '@mysten/bcs/types', this doesn't get exported correctly
|
|
26
|
+
export type Encoding = 'base58' | 'base64' | 'hex'
|
|
27
|
+
|
|
28
|
+
import { normalizeSuiObjectId, normalizeSuiAddress } from '@mysten/sui.js/utils'
|
|
29
|
+
|
|
30
|
+
export class MoveCoder extends AbstractMoveCoder<
|
|
31
|
+
// SuiNetwork,
|
|
32
|
+
SuiMoveNormalizedModule,
|
|
33
|
+
SuiEvent | SuiMoveObject
|
|
34
|
+
> {
|
|
35
|
+
bcs = new BCS(getSuiMoveConfig())
|
|
36
|
+
|
|
37
|
+
constructor(client: SuiClient) {
|
|
38
|
+
super(new SuiChainAdapter(client))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
load(module: SuiMoveNormalizedModule): InternalMoveModule {
|
|
42
|
+
let m = this.moduleMapping.get(module.address + '::' + module.name)
|
|
43
|
+
if (m) {
|
|
44
|
+
return m
|
|
45
|
+
}
|
|
46
|
+
m = toInternalModule(module)
|
|
47
|
+
this.loadInternal(m)
|
|
48
|
+
return m
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
protected async decode(data: any, type: TypeDescriptor): Promise<any> {
|
|
52
|
+
switch (type.qname) {
|
|
53
|
+
case '0x1::ascii::Char':
|
|
54
|
+
if (data !== undefined && typeof data !== 'string') {
|
|
55
|
+
// bcs
|
|
56
|
+
const byte = (await super.decode(data, type)).byte as number
|
|
57
|
+
return String.fromCharCode(byte)
|
|
58
|
+
}
|
|
59
|
+
case '0x1::ascii::String':
|
|
60
|
+
if (data !== undefined && typeof data !== 'string') {
|
|
61
|
+
// bcs verified
|
|
62
|
+
const bytes = (await super.decode(data, type)).bytes as number[]
|
|
63
|
+
return new TextDecoder().decode(new Uint8Array(bytes))
|
|
64
|
+
}
|
|
65
|
+
case '0x2::object::ID':
|
|
66
|
+
if (data !== undefined && typeof data !== 'string') {
|
|
67
|
+
// bcs verified
|
|
68
|
+
const bytes = (await super.decode(data, type)).bytes as string
|
|
69
|
+
return normalizeSuiObjectId(bytes)
|
|
70
|
+
}
|
|
71
|
+
case '0x2::url::Url':
|
|
72
|
+
if (data !== undefined && typeof data !== 'string') {
|
|
73
|
+
// bcs
|
|
74
|
+
return (await super.decode(data, type)).url
|
|
75
|
+
}
|
|
76
|
+
case '0x2::coin::Coin':
|
|
77
|
+
if (data !== undefined && typeof data !== 'string') {
|
|
78
|
+
// bcs
|
|
79
|
+
const bytes = (await super.decode(data, type)).id.id.bytes as number[]
|
|
80
|
+
return new TextDecoder().decode(new Uint8Array(bytes))
|
|
81
|
+
}
|
|
82
|
+
return data
|
|
83
|
+
case '0x2::balance::Balance':
|
|
84
|
+
if (data.value) {
|
|
85
|
+
// bcs verfied
|
|
86
|
+
const balance = await super.decode(data, type)
|
|
87
|
+
return balance.value
|
|
88
|
+
}
|
|
89
|
+
return BigInt(data)
|
|
90
|
+
case '0x1::option::Option':
|
|
91
|
+
if (data === null) {
|
|
92
|
+
return data
|
|
93
|
+
}
|
|
94
|
+
if (data.vec) {
|
|
95
|
+
// bcs verifed
|
|
96
|
+
let vec = await super.decode(data, type)
|
|
97
|
+
vec = vec.vec
|
|
98
|
+
if (vec.length === 0) {
|
|
99
|
+
return null
|
|
100
|
+
}
|
|
101
|
+
return vec[0]
|
|
102
|
+
}
|
|
103
|
+
return this.decode(data, type.typeArgs[0])
|
|
104
|
+
case 'Address':
|
|
105
|
+
const str = data as string
|
|
106
|
+
return normalizeSuiAddress(str)
|
|
107
|
+
case '0x1::string::String':
|
|
108
|
+
if (typeof data !== 'string') {
|
|
109
|
+
// bcs
|
|
110
|
+
return new TextDecoder().decode(new Uint8Array(data.bytes))
|
|
111
|
+
}
|
|
112
|
+
default:
|
|
113
|
+
return super.decode(data, type)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
decodeEvent<T>(event: SuiEvent): Promise<TypedEventInstance<T> | undefined> {
|
|
118
|
+
return this.decodedStruct(event)
|
|
119
|
+
}
|
|
120
|
+
filterAndDecodeEvents<T>(type: TypeDescriptor<T> | string, resources: SuiEvent[]): Promise<TypedEventInstance<T>[]> {
|
|
121
|
+
if (typeof type === 'string') {
|
|
122
|
+
type = parseMoveType(type)
|
|
123
|
+
}
|
|
124
|
+
return this.filterAndDecodeStruct(type, resources)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async getDynamicFields<T1, T2>(
|
|
128
|
+
objects: SuiMoveObject[],
|
|
129
|
+
keyType: TypeDescriptor<T1> = ANY_TYPE,
|
|
130
|
+
valueType: TypeDescriptor<T2> = ANY_TYPE
|
|
131
|
+
): Promise<dynamic_field.Field<T1, T2>[]> {
|
|
132
|
+
// const type = dynamic_field.Field.TYPE
|
|
133
|
+
// Not using the code above to avoid cycle initialize failed
|
|
134
|
+
const type = new TypeDescriptor<dynamic_field.Field<T1, T2>>('0x2::dynamic_field::Field')
|
|
135
|
+
type.typeArgs = [keyType, valueType]
|
|
136
|
+
const res = await this.filterAndDecodeObjects(type, objects)
|
|
137
|
+
return res.map((o) => o.data_decoded)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
filterAndDecodeObjects<T>(
|
|
141
|
+
type: TypeDescriptor<T>,
|
|
142
|
+
objects: SuiMoveObject[]
|
|
143
|
+
): Promise<DecodedStruct<SuiMoveObject, T>[]> {
|
|
144
|
+
return this.filterAndDecodeStruct(type, objects)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async decodeFunctionPayload(payload: MoveCallSuiTransaction, inputs: SuiCallArg[]): Promise<MoveCallSuiTransaction> {
|
|
148
|
+
const functionType = [payload.package, payload.module, payload.function].join(SPLITTER)
|
|
149
|
+
const func = await this.getMoveFunction(functionType)
|
|
150
|
+
const params = this.adapter.getMeaningfulFunctionParams(func.params)
|
|
151
|
+
const args = []
|
|
152
|
+
for (const value of payload.arguments || []) {
|
|
153
|
+
const argValue = value as any
|
|
154
|
+
if ('Input' in (argValue as any)) {
|
|
155
|
+
const idx = argValue.Input
|
|
156
|
+
const arg = inputs[idx]
|
|
157
|
+
if (arg.type === 'pure') {
|
|
158
|
+
args.push(arg.value)
|
|
159
|
+
} else if (arg.type === 'object') {
|
|
160
|
+
// object is not there
|
|
161
|
+
args.push(undefined)
|
|
162
|
+
} else {
|
|
163
|
+
console.error('unexpected function arg value')
|
|
164
|
+
args.push(undefined)
|
|
165
|
+
}
|
|
166
|
+
// args.push(arg) // TODO check why ts not work using arg.push(arg)
|
|
167
|
+
} else {
|
|
168
|
+
args.push(undefined)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const argumentsTyped = await this.decodeArray(args, params, false)
|
|
173
|
+
return {
|
|
174
|
+
...payload,
|
|
175
|
+
arguments_decoded: argumentsTyped
|
|
176
|
+
} as TypedFunctionPayload<any>
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private async _registerBCSType(qname: string): Promise<void> {
|
|
180
|
+
if (this.bcs.hasType(qname)) {
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
const moveStruct = await this.getMoveStruct(qname)
|
|
184
|
+
const structDef: StructTypeDefinition = {}
|
|
185
|
+
|
|
186
|
+
for (const field of moveStruct.fields) {
|
|
187
|
+
structDef[field.name] = field.type.getNormalizedSignature()
|
|
188
|
+
}
|
|
189
|
+
let typeName = qname
|
|
190
|
+
const generics = moveStruct.typeParams.map((p, idx) => 'T' + idx).join(', ')
|
|
191
|
+
if (generics) {
|
|
192
|
+
typeName = typeName + '<' + generics + '>'
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
this.bcs.registerStructType(typeName, structDef)
|
|
196
|
+
|
|
197
|
+
for (const field of moveStruct.fields) {
|
|
198
|
+
await this.registerBCSTypes(field.type)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private bcsRegistered = new Set<string>()
|
|
203
|
+
|
|
204
|
+
async registerBCSTypes(type: TypeDescriptor): Promise<void> {
|
|
205
|
+
const sig = type.getNormalizedSignature()
|
|
206
|
+
if (this.bcsRegistered.has(sig)) {
|
|
207
|
+
return
|
|
208
|
+
}
|
|
209
|
+
this.bcsRegistered.add(sig)
|
|
210
|
+
|
|
211
|
+
await this._registerBCSType('0x1::string::String')
|
|
212
|
+
|
|
213
|
+
for (const typeArg of type.dependedTypes()) {
|
|
214
|
+
await this._registerBCSType(typeArg)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async decodeBCS(type: TypeDescriptor, data: Uint8Array | string, encoding?: Encoding): Promise<any> {
|
|
219
|
+
await this.registerBCSTypes(type)
|
|
220
|
+
return this.bcs.de(type.getNormalizedSignature(), data, encoding)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async decodeDevInspectResult<T extends any[]>(insepctRes: DevInspectResults): Promise<TypedDevInspectResults<T>> {
|
|
224
|
+
const returnValues = []
|
|
225
|
+
if (insepctRes.results != null) {
|
|
226
|
+
for (const r of insepctRes.results) {
|
|
227
|
+
if (r.returnValues) {
|
|
228
|
+
const type = parseMoveType(r.returnValues[0][1])
|
|
229
|
+
const value = r.returnValues[0][0]
|
|
230
|
+
const bcsDecoded = await this.decodeBCS(type, new Uint8Array(value))
|
|
231
|
+
const decoded = await this.decodedType(bcsDecoded, type)
|
|
232
|
+
returnValues.push(decoded)
|
|
233
|
+
} else {
|
|
234
|
+
returnValues.push(null)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return { ...insepctRes, results_decoded: returnValues as any }
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const DEFAULT_ENDPOINT = 'https://fullnode.mainnet.sui.io/'
|
|
243
|
+
const CODER_MAP = new Map<string, MoveCoder>()
|
|
244
|
+
const CHAIN_ID_CODER_MAP = new Map<string, MoveCoder>()
|
|
245
|
+
|
|
246
|
+
export function defaultMoveCoder(endpoint: string = DEFAULT_ENDPOINT): MoveCoder {
|
|
247
|
+
let coder = CODER_MAP.get(endpoint)
|
|
248
|
+
if (!coder) {
|
|
249
|
+
coder = new MoveCoder(new SuiClient({ url: DEFAULT_ENDPOINT }))
|
|
250
|
+
CODER_MAP.set(endpoint, coder)
|
|
251
|
+
}
|
|
252
|
+
return coder
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const PROVIDER_CODER_MAP = new Map<SuiClient, MoveCoder>()
|
|
256
|
+
|
|
257
|
+
let DEFAULT_CHAIN_ID: string | undefined
|
|
258
|
+
|
|
259
|
+
export async function getMoveCoder(client: SuiClient): Promise<MoveCoder> {
|
|
260
|
+
let coder = PROVIDER_CODER_MAP.get(client)
|
|
261
|
+
if (!coder) {
|
|
262
|
+
coder = new MoveCoder(client)
|
|
263
|
+
// TODO how to dedup
|
|
264
|
+
const id = await client.getChainIdentifier()
|
|
265
|
+
const defaultCoder = defaultMoveCoder()
|
|
266
|
+
if (!DEFAULT_CHAIN_ID) {
|
|
267
|
+
DEFAULT_CHAIN_ID = await defaultCoder.adapter.getChainId()
|
|
268
|
+
}
|
|
269
|
+
if (id === DEFAULT_CHAIN_ID) {
|
|
270
|
+
coder = defaultCoder
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
PROVIDER_CODER_MAP.set(client, coder)
|
|
274
|
+
}
|
|
275
|
+
return coder
|
|
276
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
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
|
+
|
|
11
|
+
import { SuiMoveNormalizedModule, SuiEvent, SuiMoveObject, SuiClient } from '@mysten/sui.js/client'
|
|
12
|
+
|
|
13
|
+
export class SuiChainAdapter extends ChainAdapter<
|
|
14
|
+
// SuiNetwork,
|
|
15
|
+
SuiMoveNormalizedModule,
|
|
16
|
+
SuiEvent | SuiMoveObject
|
|
17
|
+
> {
|
|
18
|
+
async getChainId() {
|
|
19
|
+
return this.client.getChainIdentifier()
|
|
20
|
+
}
|
|
21
|
+
// static INSTANCE = new SuiChainAdapter()
|
|
22
|
+
|
|
23
|
+
client: SuiClient
|
|
24
|
+
constructor(client: SuiClient) {
|
|
25
|
+
super()
|
|
26
|
+
this.client = client
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async fetchModule(
|
|
30
|
+
account: string,
|
|
31
|
+
module: string
|
|
32
|
+
// network: SuiNetwork
|
|
33
|
+
): Promise<SuiMoveNormalizedModule> {
|
|
34
|
+
return await this.client.getNormalizedMoveModule({ package: account, module })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async fetchModules(
|
|
38
|
+
account: string
|
|
39
|
+
// network: SuiNetwork
|
|
40
|
+
): Promise<SuiMoveNormalizedModule[]> {
|
|
41
|
+
const modules = await this.client.getNormalizedMoveModulesByPackage({
|
|
42
|
+
package: account
|
|
43
|
+
})
|
|
44
|
+
return Object.values(modules)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
getMeaningfulFunctionParams(params: TypeDescriptor[]): TypeDescriptor[] {
|
|
48
|
+
return params
|
|
49
|
+
// if (params.length === 0) {
|
|
50
|
+
// return params
|
|
51
|
+
// }
|
|
52
|
+
// return params.slice(0, params.length - 1)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
toInternalModules(modules: SuiMoveNormalizedModule[]): InternalMoveModule[] {
|
|
56
|
+
return Object.values(modules).map(toInternalModule)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getAllEventStructs(modules: InternalMoveModule[]): Map<string, InternalMoveStruct> {
|
|
60
|
+
const eventMap = new Map<string, InternalMoveStruct>()
|
|
61
|
+
|
|
62
|
+
for (const module of modules) {
|
|
63
|
+
const qname = moduleQname(module)
|
|
64
|
+
|
|
65
|
+
for (const struct of module.structs) {
|
|
66
|
+
const abilities = new Set(struct.abilities)
|
|
67
|
+
if (abilities.has('Drop') && abilities.has('Copy')) {
|
|
68
|
+
eventMap.set(qname + SPLITTER + struct.name, struct)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return eventMap
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
getType(base: SuiEvent | SuiMoveObject): string {
|
|
76
|
+
return base.type
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
getData(val: SuiEvent | SuiMoveObject) {
|
|
80
|
+
// if (val.parsedJson) {
|
|
81
|
+
// return val.parsedJson as any
|
|
82
|
+
// }
|
|
83
|
+
if (val === undefined) {
|
|
84
|
+
throw Error('val is undefined')
|
|
85
|
+
}
|
|
86
|
+
if ('parsedJson' in val) {
|
|
87
|
+
return val.parsedJson as any
|
|
88
|
+
}
|
|
89
|
+
// if (SuiParsedData.is(val)) {
|
|
90
|
+
// return val.fields as any
|
|
91
|
+
// }
|
|
92
|
+
if (val.dataType === 'moveObject') {
|
|
93
|
+
return val.fields as any
|
|
94
|
+
}
|
|
95
|
+
// if (SuiMoveObject.is(val)) {
|
|
96
|
+
// return val.fields as any
|
|
97
|
+
// }
|
|
98
|
+
// This may not be perfect, just think everything has
|
|
99
|
+
if ('fields' in val) {
|
|
100
|
+
if ('type' in val && Object.keys(val).length === 2) {
|
|
101
|
+
return val.fields as any
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return val as any
|
|
105
|
+
}
|
|
106
|
+
// validateAndNormalizeAddress(address: string) {
|
|
107
|
+
// return validateAndNormalizeAddress(address)
|
|
108
|
+
// }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// function getRpcEndpoint(network: SuiNetwork): string {
|
|
112
|
+
// switch (network) {
|
|
113
|
+
// case SuiNetwork.TEST_NET:
|
|
114
|
+
// return 'https://fullnode.testnet.sui.io/'
|
|
115
|
+
// }
|
|
116
|
+
// return 'https://fullnode.mainnet.sui.io/'
|
|
117
|
+
// }
|
|
118
|
+
|
|
119
|
+
function getRpcClient(endpoint: string): SuiClient {
|
|
120
|
+
return new SuiClient({ url: endpoint })
|
|
121
|
+
}
|