1
0
Fork 0
mirror of https://github.com/eosswedenorg/thalos-docs synced 2026-11-02 04:56:45 +01:00

docs: align Thalos docs with current config, CLI, and API

This commit is contained in:
Henrik Hautakoski 2026-08-31 14:51:54 +02:00
parent 2d90392d97
commit 3bb8bb5c26
11 changed files with 516 additions and 450 deletions

View file

@ -1,8 +1,8 @@
# Clients
List of officially supported client libraries
| Name | Language |
| -------------------------------------------------------------------------- | -------- |
| [thalos-go](https://github.com/eosswedenorg/thalos/tree/master/api) | Golang |
| [thalos-nodejs](https://www.npmjs.com/package/@eosswedenorg/thalos-client) | Nodejs |
# Clients
List of officially supported client libraries.
| Name | Language |
| -------------------------------------------------------------------------- | -------- |
| [thalos-go](https://github.com/eosswedenorg/thalos/tree/master/api) | Go |
| [@eosswedenorg/thalos-client](https://www.npmjs.com/package/@eosswedenorg/thalos-client) | Node.js |

View file

@ -1,3 +1,7 @@
# Examples
These examples assume Thalos uses `message_codec: json` (default).
If you run with `message_codec: msgpack`, use a MessagePack decoder in your client.
## Go
@ -18,15 +22,15 @@ import (
)
func main() {
// Create redis client
// Create Redis client
rdb := redis.NewClient(&redis.Options{})
sub := api_redis.NewSubscriber(context.Background(), rdb, api_redis.Namespace{
Prefix: "ship",
ChainID: "1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4", // Wax mainnet.
ChainID: "1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4", // WAX mainnet
})
// Create client
// Create client
codec, err := message.GetCodec("json")
if err != nil {
fmt.Println("Failed to get json codec")
@ -35,7 +39,7 @@ func main() {
client := api.NewClient(sub, codec.Decoder)
// Subscribe to some channels.
// Subscribe to some channels.
err = client.Subscribe(
api.TransactionChannel,
api.ActionChannel{Contract: "eosio"}.Channel(),
@ -49,18 +53,18 @@ func main() {
return
}
// Wait for interrupt in a go routine and close the client.
// Wait for interrupt and close the client.
go func() {
sig := make(chan os.Signal)
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt)
<-sig
fmt.Println("Got interrupt")
client.Close()
_ = client.Close()
}()
// Read messages
// Read messages
for t := range client.Channel() {
switch msg := t.(type) {
case error:
@ -69,7 +73,10 @@ func main() {
fmt.Println("Transaction", msg.BlockNum, msg.ID)
fmt.Println(msg)
fmt.Println("---")
case message.HeartBeat :
case message.ActionTrace:
fmt.Println("Action", msg.Contract, msg.Name)
fmt.Println("---")
case message.HeartBeat:
fmt.Println("Heartbeat")
fmt.Println(msg)
fmt.Println("---")
@ -78,9 +85,9 @@ func main() {
}
```
## Nodejs
## Node.js
install the thalos client library:
Install the thalos client library:
`npm install --save @eosswedenorg/thalos-client`
@ -129,9 +136,9 @@ Transfer From/To: ponyslaystat -> wombatmaster Assets: [ '1099880264627' ]
## Python
This example will listen for new atomicasset transfers and print them to standard output.
This example listens for new `atomicassets::logtransfer` actions and prints them to standard output.
You can specify multiple channels to listen to by adding them to the `redis_channels` list.
Before you start this script, make sure you have the redis-server running.
Before you start this script, make sure Redis is running.
::: info NOTE
You need to have the redis-py library installed for this to work
@ -189,4 +196,4 @@ stdbuf -oL redis-cli --raw SUBSCRIBE ${CHANNEL} | while read RCMD; do
echo "Transfer From/To:" $(echo $MSG | jq -r ".data.from, \"->\", .data.to, \"Assets:\", .data.asset_ids, .data.memo")
fi
done
```
```

View file

@ -1,107 +1,137 @@
# Messages
This document describes the different messages that are sent
## Encoding
All messages are encoded in `json` format
## Types
### HeartBeat
Heartbeat messages are posted to the heartbeat channel periodically.
| Field | Datatype | Description |
| -------------------------- | -------- | ------------------------------------------- |
| blocknum | `int` | Current block number |
| head_blocknum | `int` | Head block number |
| last_irreversible_blocknum | `int` | block number of the last irreversible block |
### Transaction
### ActionTrace
| Field | Datatype | Description |
| -------------- | --------------------------------------- | ----------------------------------------------------------------- |
| tx_id | `string` | Transaction ID |
| blocknum | `int` | Block number where this action trace (and transaction) belongs to |
| blocktimestamp | `time` | Block timestamp |
| receipt | [`ActionReceipt`](#actionreceipt) | Action receipt |
| receiver | `string` | Receiver account |
| first_receiver | `bool` | True if receiver is the first account to get notified |
| contract | `string` | Contract account |
| action | `string` | What action was executed on the contract |
| data | `any` | Contract specific data (decoded using the contracts abi) |
| authorization | [`PermissionLevel[]`](#permissionlevel) | Authorization |
### ActionReceipt
| Field | Datatype | Description |
| --------------- | ----------------------------------------------- | ------------------ |
| receiver | `string` | Actor account name |
| act_digest | `string` | Action digest |
| global_sequence | `int` | Global sequence |
| recv_sequence | `int` | Receive sequence |
| auth_sequence | [`AccountAuthSequence[]`](#accountauthsequence) | Auth sequence |
| code_sequence | `int` | Code sequence |
| abi_sequence | `int` | ABI sequence |
### PermissionLevel
| Field | Datatype | Description |
| ---------- | -------- | -------------------------------- |
| actor | `string` | Actor account name |
| permission | `string` | Permission (for example: active) |
### AccountAuthSequence
| Field | Datatype | Description |
| -------- | -------- | ------------ |
| account | `string` | Account name |
| sequence | `int` | Sequence |
### RollbackMessage
| Field | Datatype | Description |
| --------- | -------- | ------------------------------------ |
| new_block | `int` | The current block number |
| old_block | `int` | Last block number that was received. |
### TableDelta
| Field | Datatype | Description |
| -------------- | ----------------------------------- | ----------------- |
| blocknum | `int` | Block number |
| blocktimestamp | `time` | Block timestamp |
| name | `string` | Table name |
| rows | [`TableDeltaRow[]`](#tabledeltarow) | Rows in the delta |
### TableDeltaRow
| Field | Datatype | Description |
| -------- | ---------------------------------------------------------- | --------------------------------- |
| present | `bool` | - |
| data | [`TableDeltaRowContract`](#tabledeltarowcontract) \| `any` | Decoded data |
| raw_data | `base64_string` | Raw data in base64 encoded string |
### TableDeltaRowContract
These messages are only relevant when listening to [Table deltas](redis-channels#table-delta) channel when name is `contract_row`.
| Field | Datatyp | Description |
| ----------- | ------------------------ | ---------------------------------------------------------- |
| table | `string` | table name |
| scope | `string` | table scope |
| primary_key | `string` \| `int` | Primary ID for the row. |
| code | `string` | Account name where that has the contract code |
| payer | `string` | Account name that payed for the ram that this row consumes |
| value | `map` \| `base64_string` | Actual data in the table |
Thalos can decode contract row data in `vaule` using the contracts abi.
If Thalos could not decode the data then `value` will contain a `base64_string` of the raw value instead.
# Messages
This document describes the message payloads published by Thalos.
## Encoding
Thalos supports two codecs (configured via `message_codec` / `--codec`):
- `json` (default)
- `msgpack`
When using JSON:
- `[]byte` fields are base64-encoded strings
- timestamps are UTC and serialized by the JSON codec
## Message types
### HeartBeat
Published on `heartbeat` channel periodically.
| Field | Type | Description |
| -------------------------- | -------- | ------------------------------------------- |
| `blocknum` | `uint32` | Current block number |
| `head_blocknum` | `uint32` | Current chain head block number |
| `last_irreversible_blocknum` | `uint32` | Last irreversible block number |
### TransactionTrace
Published on `transactions` channel (unless disabled).
| Field | Type | Description |
| ---------------- | --------------------------------- | ----------- |
| `id` | `string` | Transaction id |
| `blocknum` | `uint32` | Block number |
| `blocktimestamp` | `time` | Block timestamp |
| `status` | `string` | Transaction status |
| `cpu_usage_us` | `uint32` | CPU usage (microseconds) |
| `net_usage_words` | `uint32` | NET usage words |
| `elapsed` | `int64` | Execution time |
| `net_usage` | `uint64` | NET usage |
| `scheduled` | `bool` | Scheduled transaction flag |
| `action_traces` | [`ActionTrace[]`](#actiontrace) | Action traces for this transaction |
| `except` | `string` | Exception text (if any) |
| `error` | `uint64` | Error code |
### ActionTrace
Published on `actions` channels (unless disabled), and also nested in `TransactionTrace.action_traces`.
| Field | Type | Description |
| ---------------- | ------------------------------------------ | ----------- |
| `tx_id` | `string` | Parent transaction id |
| `blocknum` | `uint32` | Block number |
| `blocktimestamp` | `time` | Block timestamp |
| `receipt` | [`ActionReceipt`](#actionreceipt) / `null` | Action receipt |
| `name` | `string` | Action name |
| `contract` | `string` | Contract account |
| `receiver` | `string` | Receiver account |
| `first_receiver` | `bool` | True if receiver is first receiver |
| `data` | `any` | ABI-decoded action data when available |
| `authorization` | [`PermissionLevel[]`](#permissionlevel) | Authorization list |
| `except` | `string` | Exception text (if any) |
| `error` | `uint64` | Error code |
| `return` | `bytes` | Return value bytes |
> Note: the field is `name` (not `action`).
### ActionReceipt
| Field | Type | Description |
| ----------------- | ------------------------------------------------- | ----------- |
| `receiver` | `string` | Receiver account |
| `act_digest` | `string` | Action digest |
| `global_sequence` | `uint64` | Global sequence |
| `recv_sequence` | `uint64` | Receiver sequence |
| `auth_sequence` | [`AccountAuthSequence[]`](#accountauthsequence) | Auth sequence list |
| `code_sequence` | `uint32` | Code sequence |
| `abi_sequence` | `uint32` | ABI sequence |
### PermissionLevel
| Field | Type | Description |
| ------------ | -------- | ----------- |
| `actor` | `string` | Actor account |
| `permission` | `string` | Permission name |
### AccountAuthSequence
| Field | Type | Description |
| ---------- | -------- | ----------- |
| `account` | `string` | Account name |
| `sequence` | `uint64` | Sequence |
### RollbackMessage
Published on `rollback` channel on microfork rollback detection.
| Field | Type | Description |
| ----------- | -------- | ----------- |
| `old_block` | `uint32` | Previous current block |
| `new_block` | `uint32` | New current block |
### TableDelta
Published on `tabledeltas` channels (unless disabled).
| Field | Type | Description |
| ---------------- | ----------------------------------- | ----------- |
| `blocknum` | `uint32` | Block number |
| `blocktimestamp` | `time` | Block timestamp |
| `name` | `string` | SHIP delta name |
| `rows` | [`TableDeltaRow[]`](#tabledeltarow) | Rows in the delta |
### TableDeltaRow
| Field | Type | Description |
| ---------- | --------- | ----------- |
| `present` | `bool` | Row present/removed flag |
| `data` | `object` | Parsed row data when available |
| `raw_data` | `bytes` | Raw row bytes |
### TableDeltaRowContract (`name = contract_row`)
For `contract_row` deltas, `data` typically contains:
| Field | Type | Description |
| ------------- | ------------------------ | ----------- |
| `table` | `string` | Table name |
| `scope` | `string` | Table scope |
| `primary_key` | `string \| int` | Primary key |
| `code` | `string` | Contract account |
| `payer` | `string` | RAM payer |
| `value` | `object \| base64_string` | Decoded row value when ABI is available; otherwise raw bytes |
If ABI decode fails, Thalos keeps raw data and may leave decoded fields partial.

View file

@ -1,65 +1,73 @@
# Redis channels
This document describes the redis channels used by thalos to deliver messages.
## Namespace
First. all channels have a namespace attached to them. this is done to prevent other application to clash with the keys.
The namespace have the following format: `<prefix>::<chain_id>`
* `prefix` is per default `ship` but can be configured to be something else.
* `chain_id` is the chain's id and is used to separate transactions if multiple chains are setup in the same redis database.
## Transactions
All transactions are posted to the following channel:
`<namespace>::transactions`
## Actions
there is 4 types of channels for actions.
The channel where all actions are posted is:
`<namespace>::actions`
Channel where only specific actions are posted:
`<namespace>::actions/name/<action>`
Channel where only actions on a specific `<contract>` is posted:
`<namespace>::actions/contract/<contract>`
Channel where only `<action>` on a specific `<contract>` is posted:
`<namespace>::actions/contract/<contract>/name/<action>`
## Rollback
Rollback mesages are posted to this channel.
`<namespace>::rollback`
## Table delta
Table deltas are posted to the following channels
All deltas:
`<namespace>::tabledeltas`
Only deltas for a specific type.
`<namespace>::tabledeltas/name/<name>`
`<name>` can be one of
* `account_metadata`
* `contract_table`
* `contract_row`
* `contract_index64`
* `resource_usage`
* `resource_limits_state`
# Redis channels
This document describes the Redis Pub/Sub channels used by Thalos.
## Channel key format
All published channels are namespaced to avoid collisions:
`<prefix>::<chain_id>::<channel-path>`
- `prefix`: defaults to `ship` (config: `redis.prefix`)
- `chain_id`: chain id from API by default, or overridden with `ship.chain`
- `channel-path`: one of the paths below
If no chain id is available, Thalos uses an all-zero fallback chain id internally.
## Channel paths
### Heartbeat
`<namespace>::heartbeat`
Published periodically (every 10 blocks) so subscribers can detect liveness.
### Transactions
`<namespace>::transactions`
Contains `TransactionTrace` messages.
### Actions
Thalos publishes each action trace to up to 4 channels:
- All actions:
`<namespace>::actions`
- By action name:
`<namespace>::actions/name/<action>`
- By contract:
`<namespace>::actions/contract/<contract>`
- By contract + action:
`<namespace>::actions/contract/<contract>/name/<action>`
### Rollback
`<namespace>::rollback`
Contains `RollbackMessage` messages when microfork rollbacks are detected.
### Table deltas
- All table deltas:
`<namespace>::tabledeltas`
- Table deltas by SHIP delta name:
`<namespace>::tabledeltas/name/<name>`
`<name>` is the table delta name received from SHIP (for example `contract_row`,
`contract_table`, `resource_usage`, `resource_limits_state`).
## Notes
- `transactions`, `actions`, and `tabledeltas` output can be enabled/disabled via config/flags.
- If `ship.table_delta_whitelist` is configured, only matching `contract_row` deltas are published.