Skip to content

Commit

Permalink
docs: updated michelson-encoder doc with generateSchema (#2740)
Browse files Browse the repository at this point in the history
  • Loading branch information
hui-an-yang authored Nov 28, 2023
1 parent 117e5e5 commit 67edd4b
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 110 deletions.
96 changes: 41 additions & 55 deletions docs/michelson_encoder.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Michelson Encoder
author: Roxane Letourneau
---

The purpose of the `Michelson-Encoder` package is to create an abstraction over the Michelson Language. It allows converting Michelson data into javascript-looking objects which are easier to use and reason about.
The purpose of the `Michelson-Encoder` package is to create an abstraction over the Michelson Language. It allows converting Michelson data into javascript-looking objects which are easier to use and reason about.

Its integration into the main `Taquito` package makes it easier to write the storage when deploying a contract and the parameter when calling a contract entry-point.

Expand All @@ -20,7 +20,8 @@ A specific token class in the package represents each different Michelson type (
- `Execute`: To convert Michelson data into familiar-looking javascript data
- `Encode`: To convert javascript array data to JSON Michelson
- `EncodeObject`: To convert javascript object data to JSON Michelson
- `ExtractSchema`: To show how the data should be structured in the javascript format
- `GenerateSchema`: To show how the data should be structured in the javascript object format
- `ExtractSchema`: [deprecated] To show how the data should be structured in the javascript array format

We can reason about Michelson types and data as tree structures. Thus, the methods of the `Token` class use recursion to iterate over a Michelson parameter and create a specific token for each Michelson type encountered (i.e., each node and leaf of the tree).

Expand All @@ -32,7 +33,7 @@ In this section, we will use the schema class to represent the storage of a smar

### Create a Schema instance

We can create an instance of `Schema` representing a contract's storage using the constructor and passing the storage type in Michelson JSON format or using the `fromRPCResponse` method. This second way allows creating the `Schema` instance with the script of the contract obtained from the `getScript` method of the `RpcClient` class.
We can create an instance of `Schema` representing a contract's storage using the constructor and passing the storage type in Michelson JSON format or using the `fromRPCResponse` method. This second way allows creating the `Schema` instance with the script of the contract obtained from the `getScript` method of the `RpcClient` class.

Here are examples:

Expand All @@ -52,21 +53,19 @@ const storageType = {
};
const storageSchema = new Schema(storageType);
```

or

---
or
```js
const script = await Tezos.rpc.getScript('KT1MTFjUeqBeZoFeW1NLSrzJdcS5apFiUXoB');
const storageSchema = Schema.fromRPCResponse({ script });
```
### The GenerateSchema method

### The ExtractSchema method

We can use this method to obtain indications on how to write the storage when deploying a contract.
We can use this method to obtain indications on how to write the storage when deploying a contract.

Here is an example with a contract storage having annotations and a `pair` at its root. The `ExtractSchema` method returns an object where the keys are the annotations, and the values show the corresponding type.

```js live noInline
```js live noInline
const storageType = {
prim: 'pair',
args: [
Expand All @@ -81,13 +80,12 @@ const storageType = {
]
};
const storageSchema = new Schema(storageType);
const extractSchema = storageSchema.ExtractSchema();
const extractSchema = storageSchema.generateSchema();
println(JSON.stringify(extractSchema, null, 2));
```

---
When there is no annotation, the keys of the object are indexes starting from 0.

```js live noInline
```js live noInline
const storageType = {
prim: 'pair',
args: [
Expand All @@ -102,14 +100,13 @@ const storageType = {
]
};
const storageSchema = new Schema(storageType);
const extractSchema = storageSchema.ExtractSchema();
const extractSchema = storageSchema.generateSchema();
println(JSON.stringify(extractSchema, null, 2));
```

---
Here is another example using a complex storage:

```js live noInline
const storageType =
```js live noInline
const storageType =
{
prim: 'pair',
args: [
Expand Down Expand Up @@ -244,15 +241,15 @@ const storageType =
]
};
const storageSchema = new Schema(storageType);
const extractSchema = storageSchema.ExtractSchema();
const extractSchema = storageSchema.generateSchema();
println(JSON.stringify(extractSchema, null, 2));
```

### The Typecheck method

We can use the `Typecheck` method to validate the storage object. The method takes the storage object as a parameter and returns `true` if the storage object is compliant with the schema type or `false`. Validation of the properties is done. For example, the key used in the following code snippet is invalid, so the returned value of the `Typecheck` method is false.

```js live noInline
```js live noInline
const storageType = {
prim: 'pair',
args: [
Expand Down Expand Up @@ -280,7 +277,7 @@ println(typecheck);
We use the `Encode` method to transform data from a javascript object to Michelson data.
Here is an example:

```js live noInline
```js live noInline
const storageType = {
prim: 'pair',
args: [
Expand Down Expand Up @@ -308,7 +305,7 @@ println(JSON.stringify(michelsonData, null, 2));
We use the `Execute` method to transform data from Michelson to a javascript object.
Here is an example:

```js live noInline
```js live noInline
const storageType = {
prim: 'pair',
args: [
Expand Down Expand Up @@ -353,11 +350,11 @@ println(JSON.stringify(data, null, 2));

The `Execute` method takes an optional parameter of type `Semantic`. It allows overriding the default representation returned by the Michelson Encoder for specific types.

Here is an example for the `big_map` type:
If we have a contract having a big map in its storage, when we fetch the contract's storage with the RPC, the returned value looks like the following `{ int: big_map_id }`.
In the Taquito main package, the `getStorage` method of the `ContractProvider` class uses the semantic parameter to override the representation of big map in the storage. When we fetch the storage of a contract using `Tezos.contract.getStorage('contractAddress')`, an instance of the `BigMapAbstraction` class is returned for the big map instead of its id.
Here is an example for the `big_map` type:
If we have a contract having a big map in its storage, when we fetch the contract's storage with the RPC, the returned value looks like the following `{ int: big_map_id }`.
In the Taquito main package, the `getStorage` method of the `ContractProvider` class uses the semantic parameter to override the representation of big map in the storage. When we fetch the storage of a contract using `Tezos.contract.getStorage('contractAddress')`, an instance of the `BigMapAbstraction` class is returned for the big map instead of its id.

```js live noInline
```js live noInline
const schema = new Schema({ prim: 'big_map', args: [{ prim: 'address' }, { prim: 'int' }] });
const dataMichelson = { int: 123456 }

Expand All @@ -369,10 +366,10 @@ println(`Default value returned by the Michelson Encoder for big_map: ${JSON.str
const dataCustom = schema.Execute(dataMichelson, { big_map: (val) => Object({ id: val.int })})
println(`Customized representation of the big_map value: ${JSON.stringify(dataCustom)}`);
```
---
Here is an example for the `ticket` type:

Here is an example for the `ticket` type:

```js live noInline
```js live noInline
const schema = new Schema({"prim":"ticket","args":[{"prim":"string"}]});
const dataMichelson = {"prim":"Pair","args":[{"string":"KT1PVuv7af4VkPsZVZ8oZz9GSSdGnGBCbFWw"},{"string":"test"},{"int":"2"}]}

Expand All @@ -397,18 +394,28 @@ The `Schema` class is internally used in Taquito:

## The ParameterSchema class

The `ParameterSchema` class is used to represent the smart contract methods. This class is similar to the `Schema` class except that the `Encode` method expects flattened parameters instead of a javascript object.
The `ParameterSchema` class is used to represent the smart contract methods. This class is similar to the `Schema` class except that the `Encode` method expects flattened parameters instead of a javascript object where `encodeObject` method expects javascript object.

Here is an example:
Here is an example of `encode`:

```js live noInline
```js live noInline
const parameterSchema = new ParameterSchema({"prim":"pair","args":[{"prim":"address","annots":[":spender"]},{"prim":"nat","annots":[":value"]}],"annots":["%approve"]});
const michelsonData = parameterSchema.Encode(
'tz1ZfrERcALBwmAqwonRXYVQBDT9BjNjBHJu',
'12'
)
println(JSON.stringify(michelsonData, null, 2));
```
---
Here is an example of `encodeObject`:
```js live noInline
const parameterSchema = new ParameterSchema({"prim":"pair","args":[{"prim":"address","annots":[":spender"]},{"prim":"nat","annots":[":value"]}],"annots":["%approve"]});
const michelsonData = parameterSchema.EncodeObject({
spender: 'tz1ZfrERcALBwmAqwonRXYVQBDT9BjNjBHJu',
value: '12'
})
println(JSON.stringify(michelsonData, null, 2));
```

### How the ParameterSchema class is used inside Taquito

Expand Down Expand Up @@ -437,9 +444,8 @@ const storageSchema = new Schema({
const annotatedSchema = storageSchema.ExtractSchema();
println(JSON.stringify(annotatedSchema, null, 2));
```

---
We can also have a similar definition without the annotations:

```js live noInline
const storageSchema = new Schema({
prim: 'pair',
Expand Down Expand Up @@ -506,16 +512,6 @@ const storageSchema = new Schema({
const mixedSchema = storageSchema.ExtractSchema();
println(JSON.stringify(mixedSchema, null, 2));
```
This results in:
```
{
"0": "nat",
"2": {
"list": "key"
},
"threshold": "nat"
}
```

### Unions
For unions (`or`), we flatten them similarly, so instead of having `left` and `right` to refer to fields, you use the field number or annotation.
Expand All @@ -537,13 +533,3 @@ const storageSchema = new Schema({
const mixedSchema = storageSchema.ExtractSchema();
println(JSON.stringify(mixedSchema, null, 2));
```
This creates:
```
{
"0": "nat",
"2": {
"list": "key"
},
"threshold": "nat"
}
```
Loading

0 comments on commit 67edd4b

Please sign in to comment.