owned this note
owned this note
Published
Linked with GitHub
# Zome Call Serialization API
> This document can be utilized as a reference for either writing a "conductor library" for a new coding language, or alternatively simply taking a do-it-yourself approach to making API requests to the Holochain conductor
In order to make a Zome call, there are three layers of serialization via msgpack you should perform. This corresponds to three layers of deserialization you should perform. The following is the serialization half. At a quick glance, you have the 3 layers as:
1. The data + metadata of the entire request, serialized (serialize defined in holochain conductor)
2. The specific request content, serialized (serialize defined in holochain conductor)
3. The application specific payload data for the API call, serialized (serialize defined in hApp/zome code)
The levels of serialization are layered in this way in order to improve error handling at distinctive levels.
A Websocket request must be sent as a *msgpack-serialized* message. The serialized message should be a serialized `WireMessage::Request` data structure.
A `WireMessage::Request` should look like this
```
{
id: unsigned 64 bit integer,
type: “Request”,
data: Buffer
}
```
`id: unsigned 64 bit integer` should be a number which will be unique to this request, distinct from other requests made by the client. An id in a response object asynchronously sent will match/correspond to this.
`data: Buffer` should be a msgpack-serialized `AppRequest::ZomeCall`
An `AppRequest::ZomeCall` should look like this:
```
{
type: “zome_call”,
data: {
cell_id: [Buffer, Buffer],
zome_name: string,
fn_name: string,
payload: Buffer,
cap: null | Buffer,
provenance: Buffer,
}
}
```
`payload: Buffer` should be whatever your Zome function expects as an input, *msgpack-serialized*. This is up to the application developer to define.
> All the other properties that contain Buffers should be treated as values as opposed to serialized data.
**Where can I view WireMessage::Request?**
an enum variant serialized with #[serde(tag = "type")]
WireMessage::Request
https://github.com/holochain/holochain/blob/2d9401a5e0f74934195a0bf02ca198679b53089d/crates/holochain_websocket/src/lib.rs#L150-L158
interpreted: https://github.com/holochain/holochain/blob/b8222ea979f03c001dadcf33c13113ccd686c6e8/crates/holochain_websocket/src/websocket.rs#L430-L434
**Where can I view AppRequest::ZomeCall and why is “zome_call” lower case, while “Request” is upper case?**
because of inconsistent Rust serialization settings on the Holochain side (rename_all = “snake_case” vs its absence): #[serde(rename_all = "snake_case", tag = "type", content = "data")]
AppRequest::ZomeCall
https://github.com/holochain/holochain/blob/5ec47d73654fb9016da30e3dae0c6fbc63e95f14/crates/holochain_conductor_api/src/app_interface.rs#L37
ZomeCall (inner)
https://github.com/holochain/holochain/blob/5ec47d73654fb9016da30e3dae0c6fbc63e95f14/crates/holochain_conductor_api/src/app_interface.rs#L88-L110
___
#### HoloHashB64
HoloHash is: 39 bytes. The first three bytes are a prefix. Those prefixes can be seen [here](https://github.com/holochain/holochain/blob/50120fd93ee69148b96f56760bc3f683556ecb45/crates/holo_hash/src/hash_type/primitive.rs#L43-L50). The next 32 bytes are "digest", which are unique, and the last 4 bytes represent "location".
HoloHashB64 is: a HoloHash encoded using the following procedure
1. prefix with a `u` character, indicating that the encoding is "*u*rl" safe
2. encode with base64 string encoding, with "Url Safe" and "No Padding" characteristics...
- No Padding means: there is no `=` sign
- Url Safe means: `+` is replaced with `-` and `/` is replaced with `_`
Treating HoloHashB64 values with anything other than these encoding characteristics will mean that your bytes will not match the bytes that HoloHash expects.
[Read more here](https://docs.rs/holochain_deterministic_integrity/0.0.12/holochain_deterministic_integrity/hash/index.html#self-identifying-hash-encoding)
___