Skip to content

Commit 742b7c2

Browse files
authored
Add getter to codegen bcs types (#797)
1 parent 726cf20 commit 742b7c2

File tree

154 files changed

+2251
-3812
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

154 files changed

+2251
-3812
lines changed

packages/codegen/src/generate-utils.ts

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,36 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
export const utilsContent = /* ts */ `
5-
import { bcs, BcsType, TypeTag, TypeTagSerializer, BcsStruct, BcsEnum, BcsTuple } from '@mysten/sui/bcs';
5+
import {
6+
bcs,
7+
BcsType,
8+
TypeTag,
9+
TypeTagSerializer,
10+
BcsStruct,
11+
BcsEnum,
12+
BcsTuple,
13+
} from '@mysten/sui/bcs';
614
import { normalizeSuiAddress } from '@mysten/sui/utils';
715
import { TransactionArgument, isArgument } from '@mysten/sui/transactions';
16+
import { ClientWithCoreApi, SuiClientTypes } from '@mysten/sui/client';
817
918
const MOVE_STDLIB_ADDRESS = normalizeSuiAddress('0x1');
1019
const SUI_FRAMEWORK_ADDRESS = normalizeSuiAddress('0x2');
11-
const SUI_SYSTEM_ADDRESS = normalizeSuiAddress('0x3');
1220
1321
export type RawTransactionArgument<T> = T | TransactionArgument;
1422
23+
export interface GetOptions<
24+
Include extends Omit<SuiClientTypes.ObjectInclude, 'content'> = {},
25+
> extends SuiClientTypes.GetObjectOptions<Include> {
26+
client: ClientWithCoreApi;
27+
}
28+
29+
export interface GetManyOptions<
30+
Include extends Omit<SuiClientTypes.ObjectInclude, 'content'> = {},
31+
> extends SuiClientTypes.GetObjectsOptions<Include> {
32+
client: ClientWithCoreApi;
33+
}
34+
1535
export function getPureBcsSchema(typeTag: string | TypeTag): BcsType<any> | null {
1636
const parsedTag = typeof typeTag === 'string' ? TypeTagSerializer.parseFromStr(typeTag) : typeTag;
1737
@@ -36,7 +56,7 @@ export function getPureBcsSchema(typeTag: string | TypeTag): BcsType<any> | null
3656
return type ? bcs.vector(type) : null;
3757
} else if ('struct' in parsedTag) {
3858
const structTag = parsedTag.struct;
39-
const pkg = normalizeSuiAddress(parsedTag.struct.address);
59+
const pkg = normalizeSuiAddress(structTag.address);
4060
4161
if (pkg === MOVE_STDLIB_ADDRESS) {
4262
if (
@@ -47,20 +67,28 @@ export function getPureBcsSchema(typeTag: string | TypeTag): BcsType<any> | null
4767
}
4868
4969
if (structTag.module === 'option' && structTag.name === 'Option') {
50-
const type = getPureBcsSchema(structTag.typeParams[0]!);
70+
const type = getPureBcsSchema(structTag.typeParams[0]);
5171
return type ? bcs.option(type) : null;
5272
}
5373
}
5474
55-
if (pkg === SUI_FRAMEWORK_ADDRESS && structTag.module === 'object' && (structTag.name === 'ID' || structTag.name === 'UID')) {
75+
if (
76+
pkg === SUI_FRAMEWORK_ADDRESS &&
77+
structTag.module === 'object' &&
78+
(structTag.name === 'ID' || structTag.name === 'UID')
79+
) {
5680
return bcs.Address;
5781
}
5882
}
5983
6084
return null;
6185
}
6286
63-
export function normalizeMoveArguments(args: unknown[] | object, argTypes: string[], parameterNames?: string[]) {
87+
export function normalizeMoveArguments(
88+
args: unknown[] | object,
89+
argTypes: readonly (string | null)[],
90+
parameterNames?: string[],
91+
) {
6492
const argLen = Array.isArray(args) ? args.length : Object.keys(args).length;
6593
if (parameterNames && argLen !== parameterNames.length) {
6694
throw new Error(
@@ -72,30 +100,32 @@ export function normalizeMoveArguments(args: unknown[] | object, argTypes: strin
72100
73101
let index = 0;
74102
for (const [i, argType] of argTypes.entries()) {
75-
if (argType === \`\${SUI_FRAMEWORK_ADDRESS}::deny_list::DenyList\`) {
76-
normalizedArgs.push((tx) => tx.object.denyList());
103+
if (argType === '0x2::clock::Clock') {
104+
normalizedArgs.push((tx) => tx.object.clock());
77105
continue;
78106
}
79107
80-
if (argType === \`\${SUI_FRAMEWORK_ADDRESS}::random::Random\`) {
108+
if (argType === '0x2::random::Random') {
81109
normalizedArgs.push((tx) => tx.object.random());
82110
continue;
83111
}
84112
85-
if (argType === \`\${SUI_FRAMEWORK_ADDRESS}::clock::Clock\`) {
86-
normalizedArgs.push((tx) => tx.object.clock());
113+
if (argType === '0x2::deny_list::DenyList') {
114+
normalizedArgs.push((tx) => tx.object.denyList());
87115
continue;
88116
}
89117
90-
if (argType === \`\${SUI_SYSTEM_ADDRESS}::sui_system::SuiSystemState\`) {
118+
if (argType === '0x3::sui_system::SuiSystemState') {
91119
normalizedArgs.push((tx) => tx.object.system());
92120
continue;
93121
}
94122
95-
let arg
123+
let arg;
96124
if (Array.isArray(args)) {
97125
if (index >= args.length) {
98-
throw new Error(\`Invalid number of arguments, expected at least \${index + 1}, got \${args.length}\`);
126+
throw new Error(
127+
\`Invalid number of arguments, expected at least \${index + 1}, got \${args.length}\`,
128+
);
99129
}
100130
arg = args[index];
101131
} else {
@@ -117,8 +147,8 @@ export function normalizeMoveArguments(args: unknown[] | object, argTypes: strin
117147
continue;
118148
}
119149
120-
const type = argTypes[i]!;
121-
const bcsType = getPureBcsSchema(type);
150+
const type = argTypes[i];
151+
const bcsType = type === null ? null : getPureBcsSchema(type);
122152
123153
if (bcsType) {
124154
const bytes = bcsType.serialize(arg as never);
@@ -138,7 +168,47 @@ export function normalizeMoveArguments(args: unknown[] | object, argTypes: strin
138168
export class MoveStruct<
139169
T extends Record<string, BcsType<any>>,
140170
const Name extends string = string,
141-
> extends BcsStruct<T, Name> {}
171+
> extends BcsStruct<T, Name> {
172+
async get<Include extends Omit<SuiClientTypes.ObjectInclude, 'content'> = {}>({
173+
objectId,
174+
...options
175+
}: GetOptions<Include>): Promise<
176+
SuiClientTypes.Object<Include & { content: true }> & { json: BcsStruct<T>['$inferType'] }
177+
> {
178+
const [res] = await this.getMany<Include>({
179+
...options,
180+
objectIds: [objectId],
181+
});
182+
183+
return res;
184+
}
185+
186+
async getMany<Include extends Omit<SuiClientTypes.ObjectInclude, 'content'> = {}>({
187+
client,
188+
...options
189+
}: GetManyOptions<Include>): Promise<
190+
Array<SuiClientTypes.Object<Include & { content: true }> & { json: BcsStruct<T>['$inferType'] }>
191+
> {
192+
const response = (await client.core.getObjects({
193+
...options,
194+
include: {
195+
...options.include,
196+
content: true,
197+
},
198+
})) as SuiClientTypes.GetObjectsResponse<Include & { content: true }>;
199+
200+
return response.objects.map((obj) => {
201+
if (obj instanceof Error) {
202+
throw obj;
203+
}
204+
205+
return {
206+
...obj,
207+
json: this.parse(obj.content),
208+
};
209+
});
210+
}
211+
}
142212
143213
export class MoveEnum<
144214
T extends Record<string, BcsType<any> | null>,

packages/codegen/src/move-module-builder.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,9 +607,11 @@ export class MoveModuleBuilder extends FileBuilder {
607607
resolveAddress: (address) => this.#resolveAddress(address),
608608
}),
609609
)
610-
.map((tag) => (tag.includes('{') ? `\`${tag}\`` : `'${tag}'`))
610+
.map((tag) =>
611+
tag === 'null' ? 'null' : tag.includes('{') ? `\`${tag}\`` : `'${tag}'`,
612+
)
611613
.join(',\n')}
612-
] satisfies string[]\n`
614+
] satisfies (string | null)[]\n`
613615
: ''
614616
}${hasAllParameterNames ? `const parameterNames = ${JSON.stringify(requiredParameters.map((param) => camelCase(param.name!)))}\n` : ''}
615617
return (tx: ${transactionTypeName}) => tx.moveCall({

packages/codegen/src/render-types.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,13 +214,33 @@ function renderDataType(type: Datatype, options: RenderTypeSignatureOptions): st
214214
const address = options.resolveAddress(type.module.address);
215215

216216
if (options.format === 'typeTag') {
217-
const typeArgs = type.type_arguments.map((type) => renderTypeSignature(type.argument, options));
217+
if (address === SUI_FRAMEWORK_ADDRESS) {
218+
if (type.module.name === 'clock' && type.name === 'Clock') return '0x2::clock::Clock';
219+
if (type.module.name === 'random' && type.name === 'Random') return '0x2::random::Random';
220+
if (type.module.name === 'deny_list' && type.name === 'DenyList')
221+
return '0x2::deny_list::DenyList';
222+
if (type.module.name === 'object' && (type.name === 'ID' || type.name === 'UID'))
223+
return '0x2::object::ID';
224+
}
225+
if (address === SUI_SYSTEM_ADDRESS) {
226+
if (type.module.name === 'sui_system' && type.name === 'SuiSystemState')
227+
return '0x3::sui_system::SuiSystemState';
228+
}
218229

219-
if (typeArgs.length === 0) {
220-
return `${address === options.resolveAddress(options.summary.id.address) ? '${packageAddress}' : address}::${type.module.name}::${type.name}`;
230+
if (address === MOVE_STDLIB_ADDRESS) {
231+
if (
232+
(type.module.name === 'ascii' || type.module.name === 'string') &&
233+
type.name === 'String'
234+
) {
235+
return '0x1::string::String';
236+
}
237+
if (type.module.name === 'option' && type.name === 'Option') {
238+
const innerType = renderTypeSignature(type.type_arguments[0].argument, options);
239+
return `0x1::option::Option<${innerType}>`;
240+
}
221241
}
222242

223-
return `${address === options.resolveAddress(options.summary.id.address) ? '${packageAddress}' : address}::${type.module.name}::${type.name}<${typeArgs.join(', ')}>`;
243+
return 'null';
224244
}
225245

226246
if (address === MOVE_STDLIB_ADDRESS) {

packages/codegen/tests/generated/utils/index.ts

Lines changed: 54 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,29 @@
1-
# @generated by Move, please check-in and do not edit manually.
1+
# Generated by move; do not edit
2+
# This file should be checked in.
23

34
[move]
4-
version = 3
5-
manifest_digest = "2AAADF5E2D5161A76F1DB68B03C99B92D3D615DEE2B0CF70EBCABD881BD78F2C"
6-
deps_digest = "3C4103934B1E040BB6B23F1D610B4EF9F2F1166A50A104EADCF77467C004C600"
7-
dependencies = [
8-
{ id = "Sui", name = "Sui" },
9-
{ id = "WAL", name = "WAL" },
10-
]
5+
version = 4
116

12-
[[move.package]]
13-
id = "MoveStdlib"
14-
source = { git = "https://github.com/MystenLabs/sui.git", rev = "testnet-v1.43.0", subdir = "crates/sui-framework/packages/move-stdlib" }
7+
[pinned.testnet.MoveStdlib]
8+
source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/move-stdlib", rev = "c18165e608c9ae379d6bdeebf2e068713ac43661" }
9+
use_environment = "testnet"
10+
manifest_digest = "C4FE4C91DE74CBF223B2E380AE40F592177D21870DC2D7EB6227D2D694E05363"
11+
deps = {}
1512

16-
[[move.package]]
17-
id = "Sui"
18-
source = { git = "https://github.com/MystenLabs/sui.git", rev = "testnet-v1.43.0", subdir = "crates/sui-framework/packages/sui-framework" }
13+
[pinned.testnet.Sui]
14+
source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "c18165e608c9ae379d6bdeebf2e068713ac43661" }
15+
use_environment = "testnet"
16+
manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C"
17+
deps = { MoveStdlib = "MoveStdlib" }
1918

20-
dependencies = [
21-
{ id = "MoveStdlib", name = "MoveStdlib" },
22-
]
23-
24-
[[move.package]]
25-
id = "WAL"
19+
[pinned.testnet.WAL]
2620
source = { local = "../wal" }
21+
use_environment = "testnet"
22+
manifest_digest = "5CC8004F7BFF4027210DDAE6E00EB5076761A246D655F7CEDAF75D2E7CBDEC6F"
23+
deps = { Sui = "Sui" }
2724

28-
dependencies = [
29-
{ id = "Sui", name = "Sui" },
30-
]
31-
32-
[move.toolchain-version]
33-
compiler-version = "1.44.2"
34-
edition = "2024.beta"
35-
flavor = "sui"
25+
[pinned.testnet.Walrus]
26+
source = { root = true }
27+
use_environment = "testnet"
28+
manifest_digest = "8D383FB837A9A04B13466A48CC86B8AED9457885523DC25DA28C31ADEF3D6A39"
29+
deps = { Sui = "Sui", WAL = "WAL" }

0 commit comments

Comments
 (0)