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.
Expand to view table of contents
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_.
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.
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.
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.
A SCV_U63 will be denoted by having the LSByte_set to xxx0 where x denotes
an arbitrary value.
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}
A SCV_U32 is a 32bit unsigned integer, thus only display positive integers (as
denoted by the unsigned prefix) from 0-2^32.
A SCV_U32 will be denoted by having the LSByte set to 0001.
The key for an SCV_U32 is u32. A valid SCVal json is thus {"u32":value}
A SCV_I32 is a 32bit signed integer, thus displaying positive as well as
negative integers from -2^31 - (2^31 - 1).
A SCV_I32 will be denoted by having the LSByte set to 0011.
The key for an SCV_i32 is i32. A valid SCVal json is thus {"i32":value}
A SCV_STATIC an enum type currently consisting of 4 entries (SCS_*).
SCS_VOIDSCS_TRUESCS_FALSESCS_LEDGER_KEY_CONTRACT_CODE
A SCV_STATIC will be denoted by having the LSByte set to 0101.
<TODO: Add SCS encoding>
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"}
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_VECSCO_MAPSCO_U64SCO_I64SCO_BYTESSCO_BIG_INTSCO_CONTRACT_CODESCO_ACCOUNT_ID
This will most probably grow in the future.
The different SCOs and their json representation is described in more detail
further down.
A SCV_OBJECT will be denoted by having the LSByte set to 0111.
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}}
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_].
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
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"}
A SCV_BITSET contains up to 60 arbitrary bits.
A SCV_BITSET will be denoted by having the LSByte set to 1011.
The remaining 60 bits denote the given arbitrary bits.
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>
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
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.
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"}
A SCObject is like a SCValue a struct type (/object).
At the time of writing, there are 8 different types of SCObjects:
A SCO_VEC is the basic array type. It may at most contain 256000 entries.
An entry is of the type SCValue
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}]}}
A SCO_MAP is an array of at most 256000 SCMapEntry objects. Each
SCMapEntry object consists of a SCVal key and a SCVal val.
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.
A SCO_U64 is a simple 64-bit unsigned integer value.
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.
A SCO_I64 is a simple 64 bit signed integer value.
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.
A SCO_BYTES is a byte array (?) with at most 256000 entries (or bits?)
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.
{"bigInt":"zero"}
{"bigInt":{"positive":"hexValue"}}
{"bigInt":{"negative":"hexValue"}} TODO: magnitude?!
TODO
{"contractCode": {"wasm":"rawWasmHexEncoded"}}
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).
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.
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.
The JSON example for SCO_MAP is wrong, it should be:
{"map":[{"key": {"symbol": "key"}, "val": {"symbol" : "value"}}]}(valuekey changed toval)