Skip to content

Commit

Permalink
[sdks/move-bytecode-template] Adds unit tests + fixes (#17412)
Browse files Browse the repository at this point in the history
## Description 

- Adds 2 unit tests for `update_constants` method
- Asserts that the bytecode is not updated if there is an expected type
miss match
- Asserts that the bytecode is not updated if there is an expected value
miss match
- Updates deserialize doc comments
- Updates readme's template `DECIMALS` const to align with the bytecode
that is found in the test files.

## Test plan 

Tested by running `pnpm run test` in the `move-bytecode-template` sub
folder

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
  • Loading branch information
StefPler authored Apr 30, 2024
1 parent 1c4de52 commit 47476ac
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 29 deletions.
8 changes: 8 additions & 0 deletions sdk/move-bytecode-template/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 38 additions & 25 deletions sdk/move-bytecode-template/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Move Bytecode Template

Move Bytecode Template allows updating a pre-compiled bytecode, so that a standard template could be customized and used to publish new modules on Sui directly in the browser. Hence, removing the need for a backend to compile new modules.
Move Bytecode Template allows updating a pre-compiled bytecode, so that a standard template could be
customized and used to publish new modules on Sui directly in the browser. Hence, removing the need
for a backend to compile new modules.

This crate builds a WASM binary for the `move-language/move-binary-format` allowing bytecode serialization and deserialization in various environments. The main target for this package is "web".
This crate builds a WASM binary for the `move-language/move-binary-format` allowing bytecode
serialization and deserialization in various environments. The main target for this package is
"web".

## Applications

Expand All @@ -14,7 +18,8 @@ This package is a perfect fit for the following applications:

## Example of a Template Module

The following code is a close-copy of the `Coin` example from the [Move by Example](https://examples.sui.io/samples/coin.html) book.
The following code is a close-copy of the `Coin` example from the
[Move by Example](https://examples.sui.io/samples/coin.html) book.

```move
module 0x0::template {
Expand All @@ -26,7 +31,7 @@ module 0x0::template {
/// The OTW for the Coin
struct TEMPLATE has drop {}
const DECIMALS: u8 = 0;
const DECIMALS: u8 = 6;
const SYMBOL: vector<u8> = b"TMPL";
const NAME: vector<u8> = b"Template Coin";
const DESCRIPTION: vector<u8> = b"Template Coin Description";
Expand Down Expand Up @@ -57,11 +62,13 @@ let updated = update_identifiers(bytecode, {
console.assert(updated != bytecode, 'identifiers were not updated!');
```

To update constants in the bytecode, you can use the `update_constants` function. For each constant you need to supply new value as BCS bytes, existing value as BCS, and the type of the constant (as a string: `U8`, `U16` ... `U256`, `Address`, `Vector(U8)` and so on).
To update constants in the bytecode, you can use the `update_constants` function. For each constant
you need to supply new value as BCS bytes, existing value as BCS, and the type of the constant (as a
string: `U8`, `U16` ... `U256`, `Address`, `Vector(U8)` and so on).

```ts
import * as template from '@mysten/move-bytecode-template';
import { bcs } from '@mysten/bcs';
import * as template from '@mysten/move-bytecode-template';

// please, manually scan the existing values, this operation is very sensitive
console.log(template.get_constants(bytecode));
Expand All @@ -70,32 +77,34 @@ let updated;

// Update DECIMALS
updated = update_constants(
bytecode,
bcs.u8().serialize(3).toBytes(), // new value
bcs.u8().serialize(6).toBytes(), // current value
'U8', // type of the constant
bytecode,
bcs.u8().serialize(3).toBytes(), // new value
bcs.u8().serialize(6).toBytes(), // current value
'U8', // type of the constant
);

// Update SYMBOL
updated = update_constants(
updated,
bcs.vector(bcs.string()).serialize('MYC').toBytes(), // new value
bcs.vector(bcs.string()).serialize('TMPL').toBytes(), // current value
'Vector(U8)', // type of the constant
updated,
bcs.vector(bcs.string()).serialize('MYC').toBytes(), // new value
bcs.vector(bcs.string()).serialize('TMPL').toBytes(), // current value
'Vector(U8)', // type of the constant
);

// Update NAME
updated = update_constants(
updated,
bcs.vector(bcs.string()).serialize('My Coin').toBytes(), // new value
bcs.vector(bcs.string()).serialize('Template Coin').toBytes(), // current value
'Vector(U8)', // type of the constant
updated,
bcs.vector(bcs.string()).serialize('My Coin').toBytes(), // new value
bcs.vector(bcs.string()).serialize('Template Coin').toBytes(), // current value
'Vector(U8)', // type of the constant
);
```

## Usage in Web applications

The package consists of code and a wasm binary. While the former can be imported directly, the latter should be made available in static / public assets as a Web application. Initialization needs to be performed via a URL, and once completed, other functions become available.
The package consists of code and a wasm binary. While the former can be imported directly, the
latter should be made available in static / public assets as a Web application. Initialization needs
to be performed via a URL, and once completed, other functions become available.

```ts
import init, initSync, * as template from '@mysten/move-bytecode-template';
Expand All @@ -115,7 +124,7 @@ console.assert(json == bytes, '(de)serialization failed!');
To use this package with Vite, you need to import the source file and the wasm binary.

```ts
import init, * as template from "@mysten/move-bytecode-template";
import init, * as template from '@mysten/move-bytecode-template';
import url from '@mysten/move-bytecode-template/move_bytecode_template_bg.wasm?url';
```

Expand All @@ -125,29 +134,33 @@ Later, you can initialize the package with the URL.
await init(url);
```

Lastly, once the package is initialized, you can use the functions as described in the previous section.
Lastly, once the package is initialized, you can use the functions as described in the previous
section.

```ts
const templateBytecode = fromHEX("a11ceb0b06....");
const templateBytecode = fromHEX('a11ceb0b06....');

template.deserialize(templateBytecode);
template.version();
template.update_identifiers(templateBytecode, {
"TEMPLATE": "MY_MODULE",
"template": "my_module"
TEMPLATE: 'MY_MODULE',
template: 'my_module',
});
```

## Build locally

To build the binary, you need to have Rust installed and then the `wasm-pack`. The installation script [can be found here](https://rustwasm.github.io/wasm-pack/).
To build the binary, you need to have Rust installed and then the `wasm-pack`. The installation
script [can be found here](https://rustwasm.github.io/wasm-pack/).

Building for test (nodejs) environment - required for tests.

```
pnpm build:dev
```

Building for web environment.

```
pnpm build:release
```
Expand Down
1 change: 1 addition & 0 deletions sdk/move-bytecode-template/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub fn version() -> String {

#[wasm_bindgen]
/// Deserialize the `Uint8Array`` bytecode into a JSON object.
/// The JSON object contains the ABI (Application Binary Interface) of the module.
///
/// ```javascript
/// import * as template from '@mysten/move-binary-template';
Expand Down
37 changes: 33 additions & 4 deletions sdk/move-bytecode-template/tests/universal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { bcs, fromHEX } from '@mysten/bcs';
import { describe, expect, it } from 'vitest';
import { assert, describe, expect, it } from 'vitest';

import * as template from '../pkg';

Expand Down Expand Up @@ -57,16 +57,45 @@ describe('move-binary-template', () => {
expect(
template
.get_constants(updatedConsts)
.find((c) => c.value_bcs == bcs.string().serialize('TMPL').toBytes())
.find((c) => c.value_bcs == bcs.string().serialize('TMPL').toBytes()),
).toBeFalsy();

console.log(
template
.get_constants(updatedConsts)
.find((c) => c.value_bcs == bcs.string().serialize('MCN').toBytes())
);
.find((c) => c.value_bcs == bcs.string().serialize('MCN').toBytes()),
);
});

it('should not update constants if there is an expected_value value miss-match', () => {
let bytesBefore = coinTemplateBytes();
expect(() => {
let bytesAfter = template.update_constants(
bytesBefore,
bcs.u8().serialize(8).toBytes(), // new value
bcs.u8().serialize(0).toBytes(), // incorrect expected current value (it should be 6)
'U8', // expected type
);

// If they are equal the produced bytecode should be the same
assert(template.get_constants(bytesBefore) === template.get_constants(bytesAfter));
});
});

it('should not update constants if there is an expected_type miss-match', () => {
let bytesBefore = coinTemplateBytes();
expect(() => {
let bytesAfter = template.update_constants(
bytesBefore,
bcs.u8().serialize(8).toBytes(), // new value
bcs.u8().serialize(6).toBytes(), // expected current value
'Vector(U8)', // incorrect expected type (it should be U8)
);

// If they are equal the produced bytecode should be the same
assert(template.get_constants(bytesBefore) === template.get_constants(bytesAfter));
});
});
it('should fail on incorrect identifier', () => {
expect(() => {
template.update_identifiers(pokemonBytes(), { Stats: '123123PokeStats' });
Expand Down

0 comments on commit 47476ac

Please sign in to comment.