Files
xahau.js/packages/xahau-binary-codec/src/enums/README.md
Denis Angell 9544e1794e xahau-patch
2025-03-14 15:08:35 +01:00

7.3 KiB

Definitions

This file is used to serialize/deserialize transactions and ledger objects for the XRPL. It's broken into 5 sections laid out below.

At the bottom of this README you can find instructions and examples for how to define your own types in a definitions file in order to work on a custom sidechain or develop new amendments.

Types

These are the types associated with a given Serialization Field. Each type has an arbitrary type_code, with lower codes sorting first.

Ledger Entry Types

Each ledger's state tree contain ledger objects, which represent all settings, balances, and relationships in the shared ledger.

Fields

These are Serialization Fields (sf) defined in rippled's SField.cpp. Fields with undefined values are omitted before encoding.

Key

The key is the string defined in the rippled source code, such as "LedgerEntry", "Transaction", etc.

nth

nth is the sort code, meaning "nth of type." It is is combined with the type code in order to construct the Field ID of this field. The Field ID is only used for sorting the fields. Since there are multiple fields with the same data type, the nth is used to deterministically order each field among other fields of the same data type.

Each field has a Field ID, which is used to sort fields that have the same type as one another with lower codes sorting first.

For example, the Account field has sort code (nth) 1, so it comes before the Destination field which has sort code 3.

Sort code numbers are reused for fields of different types, but different fields of the same type never have the same sort code. When you combine the type code with the sort code, you get the field's unique Field ID.

The unique Field ID is prefixed before the field in the final serialized blob. The size of the Field ID is one to three bytes depending on the type code and the field codes it combines.

isVLEncoded

If true, the field is Variable Length encoded and length-prefixed. The variable-length encoded fields are STI_VL/Blob, STI_ACCOUNT/AccountID, and STI_VECTOR256/Vector256.

isSerialized

Fields are serialized if they are not one of these or if they are not an SField.

isSigningField

True unless the field is specified with SField::notSigning.

Transaction Results

See:

To generate a new definitions file from rippled source code, use this tool: https://github.com/RichardAH/xrpl-codec-gen

Transaction Types

See https://github.com/ripple/rippled/blob/develop/src/ripple/protocol/TxFormats.h

Defining Your Own Definitions

If you're building your own sidechain or writing an amendment for the XRPL, you may need to create new XRPL definitions.

To do that there are a couple things you need to do:

  1. Generate your own definitions.json file from rippled source code using this tool (The default definitions.json for mainnet can be found here)
  2. Create new SerializedType classes for any new Types (So that encode/decode behavior is defined). The SerializedType classes correspond to "ST..." classes in Rippled. Note: This is very rarely required.
  • For examples of how to implement that you can look at objects in the types folder, such as Amount, UInt8, or STArray.
  1. Import your definitions.json file to construct your own XrplDefinitions object.
  2. Pass the XrplDefinitions object whenever you encode or decode a transaction.
  3. If you added any new transaction types, you should create an interface for the transaction that extends BaseTransaction from the xrpl repo to use it with the functions on Client (See the below example of adding a new transaction type)

Example of adding a new Transaction type

// newDefinitionsJson is where you can import your custom defined definitions.json file
const newDefinitionsJson = require('./new-transaction-type-definitions.json')
const { XrplDefinitions, Client } = require('xrpl')

const newDefs = new XrplDefinitions(newDefinitionsJson)

// Change to point at the server you care about
const serverAddress = 'wss://s.devnet.rippletest.net:51233'
const client = new Client(serverAddress)
const wallet1 = await client.fundWallet()

// Extending BaseTransaction allows typescript to recognize this as a transaction type
interface NewTx extends BaseTransaction {
    Amount: Amount
}

const tx: NewTx = {
    // The TransactionType here needs to match what you added in your newDefinitionsJson file
    TransactionType: 'NewTx',
    Account: wallet1.address,
    Amount: '100',
}

// By passing in your newDefs, your new transaction should be serializable.
// Rippled will still throw an error though if it's not a supported transaction type.
const result = await client.submitAndWait(tx, {
    wallet: wallet1,
    definitions: newDefs,
})

Example of adding a new serializable Type

const { XrplDefinitions } = require('../dist/coretypes')

// newDefinitionsJson is where you can import your custom defined definitions.json file
const newDefinitionsJson = require('./fixtures/new-definitions.json')


// For any new Types you create, you'll need to make a class with the same name which extends a SerializedType object
// In order to define how to serialize/deserialize that field. Here we simply make our NewType act like a UInt32.

const { UInt32 } = require('../dist/types/uint-32')
class NewType extends UInt32 {
  // Should be the same as UInt32
}

const extendedCoreTypes = { NewType }

const newDefs = new XrplDefinitions(newDefinitionsJson, extendedCoreTypes)

// From this point on, we should be able to serialize / deserialize Transactions with fields that have 'NewType' as their Type.

const encoded = encode(my_tx, newDefs)
const decoded = decode(encoded, newDefs)

Other examples

You can find other examples of how to modify definitions.json in definition.test.js which contains tests for this feature, and uses various example modified definition files. You can find the tests and the corresponding example definition files in this folder of test cases