Skip to content

Instantly share code, notes, and snippets.

@Smephite
Last active May 5, 2023 03:39
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Smephite/09b40e842ef454effe4693e0d18246d7 to your computer and use it in GitHub Desktop.
Save Smephite/09b40e842ef454effe4693e0d18246d7 to your computer and use it in GitHub Desktop.
A Simple Guide to Soroban Types

A Simple Guide to Soroban Types

Note: The following content is a written version of the XDR spec

As of js-soroban-client v0.1.3 and soroban-cli v0.2.1 it's still really funny to work with custom types required for soroban so I will explain to the best of my knowledge how to build a custom Soroban Type in JSON format (but you should probably ask @tdep...)

Note: many of these types actually have helper functions and can be entered directly using the --arg command and do not need this extended json notation.

Table of Contents

Expand to view table of contents

SCVal Value Types

Most values in the raw transaction are actually packed as a SCVal so we can assume this to be our parent class {}.

A SCVal is the parent of quite a few different subclasses, as can be seen in the SCValType enum [1].

To denote that we are working with SCValue we prefix the different subtypes with SCV_.

SCVal Low Level Description

On a lower level, SCVals are tagged 64-bit values, meaning that they can be stored as a uint64 but will contain a type identifier by setting certain bits in said number.

SCVal JSON Representation

In the JSON format a SCVal is always a JSON object with a single key<=>value pair where the key is given by the SCValType.

SCV_U63

A SCV_U63 is the single largest SCVal we encounter. Of the 64bit available, it uses 63 bits but can only display positive integers (as denoted by the unsigned prefix).

Most signed 64-bit values in Stellar are actually signed positive values (seq numbers, timestamps, amounts) and thus we can just omit the single bit denoting the sign.

SCV_U63 Low Level Description

A SCV_U63 will be denoted by having the LSByte_set to xxx0 where x denotes an arbitrary value.

SCV_U63 JSON Representation

Warning: This is actually not working (?) my guess it has something to do with u64 vs u63 what ever

The key for an SCV_U63 is u63.

A valid SCVal json is thus {"u63":value}

SCV_U32

A SCV_U32 is a 32bit unsigned integer, thus only display positive integers (as denoted by the unsigned prefix) from 0-2^32.

SCV_U32 Low Level Description

A SCV_U32 will be denoted by having the LSByte set to 0001.

SCV_U32 JSON Representation

The key for an SCV_U32 is u32. A valid SCVal json is thus {"u32":value}

SCV_I32

A SCV_I32 is a 32bit signed integer, thus displaying positive as well as negative integers from -2^31 - (2^31 - 1).

SCV_I32 Low Level Description

A SCV_I32 will be denoted by having the LSByte set to 0011.

SCV_I32 JSON Representation

The key for an SCV_i32 is i32. A valid SCVal json is thus {"i32":value}

SCV_STATIC

A SCV_STATIC an enum type currently consisting of 4 entries (SCS_*).

  • SCS_VOID
  • SCS_TRUE
  • SCS_FALSE
  • SCS_LEDGER_KEY_CONTRACT_CODE

SCV_STATIC Low Level Description

A SCV_STATIC will be denoted by having the LSByte set to 0101.

<TODO: Add SCS encoding>

SCV_STATIC JSON Representation

The key for an SCV_STATIC is static and the value can be any of ['void', 'true', 'false', 'ledgerKeyContractCode'].

An example for a valid SCVal json is thus {"static":"false"}

SCV_OBJECT

A SCV_OBJECT is the most powerful type of SCVals. It can host different structs (/objects) and is thus most versatile.

A SCV_OBJECT or also called SCO can host the following child objects:

  • SCO_VEC
  • SCO_MAP
  • SCO_U64
  • SCO_I64
  • SCO_BYTES
  • SCO_BIG_INT
  • SCO_CONTRACT_CODE
  • SCO_ACCOUNT_ID

This will most probably grow in the future.

The different SCOs and their json representation is described in more detail further down.

SCV_OBJECT Low Level Description

A SCV_OBJECT will be denoted by having the LSByte set to 0111.

SCV_OBJECT JSON Representation

The key for a SCV_OBJECT is object and it's value the json representation of its child object (as described further down).

An example would be {"object":{"u64":0}}

SCV_SYMBOL

A SCV_SYMBOL is the simplest and most commonly used form of a string representation. It is e.g. used to define function names in contracts.

A Symbol consists of 0 to 10 characters in the alphabet [0-9a-zA-Z_].

SCV_SYMBOL Low Level Description

A SCV_Symbol will be denoted by having the LSByte set to 1001.

The remaining 60 bits will be split into the 10 different possible characters. Each character can thus exist in 2^6 = 64 different states. These states were defined as follows:

  • 0x00 - empty space, trim trailing white spaces
  • 0x01 - _
  • 0x02 - 0x0B : 0-9
  • 0x0C - 0x25 : A-Z
  • 0x26 - 0x3F : a-z

SCV_SYMBOL JSON Representation

The key for an SCV_SYMBOL is symbol and the value can be a string with length of 10 or less and only containing the allowed characters.

A valid example is {"symbol": "0123456789a"}

SCV_BITSET

A SCV_BITSET contains up to 60 arbitrary bits.

SCV_BITSET Low Level Description

A SCV_BITSET will be denoted by having the LSByte set to 1011.

The remaining 60 bits denote the given arbitrary bits.

SCV_BITSET JSON Representation

The key for an SCV_BITSET is bitset and the value is given as an u64.

The final value of the 60 bit bitset will be the 60 LSB. (val & 0xf000000000000000)

<TODO: check>

SCV_STATUS

The SCV_STATUS describes different errors and return types when interacting with the soroban environment. At the time of writing, there are 8 different SCStatusTypes

  • SST_OK
  • SST_UNKNOWN_ERROR
  • SST_HOST_VALUE_ERROR
  • SST_HOST_OBJECT_ERROR
  • SST_HOST_FUNCTION_ERROR
  • SST_HOST_STORAGE_ERROR
  • SST_HOST_CONTEXT_ERROR
  • SST_VM_ERROR
  • SST_CONTRACT_ERROR

SCV_STATUS Low Level Description

A SCV_STATUS will be denoted by having the LSByte set to 1101.

The remaining 60 bits consist of MSB 32-bit code describing in detail a certain aspect of the remaining 28-bit type.

More information can be found in the XDR spec.

SCV_STATUS JSON Representation

The Key for an SCV_STATUS is status with the value being either a string if the status does not have further information or map if there are more detailed information necessary.

Example : {"status":"ok"}

SCObject Value Types

A SCObject is like a SCValue a struct type (/object). At the time of writing, there are 8 different types of SCObjects:

SCO_VEC

A SCO_VEC is the basic array type. It may at most contain 256000 entries. An entry is of the type SCValue

SCO_VEC JSON Representation

The key for an SCO_VEC is vec.

An example for a SCObject JSON is {vec":[{"u32":1}]} if passed up to a SCValue this example becomes {"object":{"vec":[{"u32":1}]}}

SCO_MAP

A SCO_MAP is an array of at most 256000 SCMapEntry objects. Each SCMapEntry object consists of a SCVal key and a SCVal val.

SCO_MAP JSON Representation

The key for an SCO_MAP is map.

An example for a SCObject JSON is {"map":[{"key": {"symbol": "key"}, "val": {"symbol" : "value"}}]}.

A SCValue can then be constructed as seen in SCO_VEC.

SCO_U64

A SCO_U64 is a simple 64-bit unsigned integer value.

SCO_U64 JSON Representation

The key for an SCO_U64 is u64.

An example for a SCObject JSON is {"u64":9999999999999999999}.

A SCValue can be then constructed as seen in SCO_VEC.

SCO_I64

A SCO_I64 is a simple 64 bit signed integer value.

SCO_I64 JSON Representation

The key for an SCO_I64 is i64. An example for a SCObject JSON is {"i64": -999999999999999999}.

A SCValue can be then constructed as seen in SCO_VEC.

SCO_BYTES

A SCO_BYTES is a byte array (?) with at most 256000 entries (or bits?)

SCO_BYTES JSON Representation

The key for an SCO_BYTES is bytes. The values are given as a hex encoded string. An example for a SCObject JSON is {"bytes": "aabbcc"}.

A SCValue can be then constructed as seen in SCO_VEC.

SCO_BIG_INT

SCO_BIG_INT JSON Representation

{"bigInt":"zero"} {"bigInt":{"positive":"hexValue"}} {"bigInt":{"negative":"hexValue"}} TODO: magnitude?!

SCO_CONTRACT_CODE

TODO

SCO_CONTRACT_CODE JSON Representation

{"contractCode": {"wasm":"rawWasmHexEncoded"}}

SCO_ACCOUNT_ID

The SCO_ACCOUNT_ID object consists of one field named accountId.

This field contains an object of the type AccountID i.e. an object consisting of the single field publicKeyTypeEd25519. This field contains the raw public key of a given stellar public key (in hex format).

SCO_ACCOUNT_ID JSON Representation

The key for an SCO_ACCOUNT_ID is accountId.

An example for a SCObject JSON is {"accountId": {"publicKeyTypeEd25519" : "rawPubKeyInHex"}}.

The raw public key in hex can be reconstructed using different tools such as the stellar python SDK Keypair.from_public_key("G....").raw_public_key().hex().

A SCValue can be then constructed as seen in SCO_VEC.

LICENSE

Also Credits to @ElliotFriend

MIT License

Copyright (c) 2022 Kai Berszin

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@w00kie
Copy link

w00kie commented Nov 28, 2022

The JSON example for SCO_MAP is wrong, it should be: {"map":[{"key": {"symbol": "key"}, "val": {"symbol" : "value"}}]} (value key changed to val)

@Smephite
Copy link
Author

The JSON example for SCO_MAP is wrong, it should be: {"map":[{"key": {"symbol": "key"}, "val": {"symbol" : "value"}}]} (value key changed to val)

👍 thanks for the note, I fixed it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment