zenith-docs/docs/api/zenith-desk-api.md
2025-11-28 15:34:21 -05:00

39 KiB

Zenith Developer API Documentation

This document provides comprehensive documentation for developers who want to use the %zenith agent or library to access the Zenith blockchain in their own applications.

Pokes (Agent Interactions)

Configuration Pokes

%config-zenith-host

Purpose: Sets the hostname or IP address for the Zenith blockchain node (zenithd).

Input Type: @t (cord/text string)

Output: Updates the agent's configuration state. No return value.

Default: 'localhost'

Description: Configures the hostname or IP address where your zenithd instance is running, whether standalone or as part of a Laconic stack. This setting is used in combination with the port configuration pokes to build complete endpoint URLs for accessing the Zenith blockchain APIs.

If an invalid or unreachable host is set, the agent's healthchecks will fail and connection status will be %.n (false).

Examples:

Dojo command:

:zenith &config-zenith-host 'mynode.example.com'

Card for use in other agents:

[%pass /config %agent [our.bowl %zenith] %poke %config-zenith-host !>('192.168.1.100')]

%config-rpc-port

Purpose: Sets the port number for the CometBFT RPC endpoint.

Input Type: @t (cord/text string)

Output: Updates the agent's configuration state. No return value.

Default: '26657' (standard CometBFT RPC port)

Description: Configures the port number for consensus layer communication with the CometBFT node. This is used in combination with the zenith-host setting to form complete RPC endpoint URLs. The port accepts any cord value without validation.

The RPC endpoint provides access to CometBFT's consensus and blockchain query APIs. See the CometBFT RPC documentation for available endpoints. Note that while CometBFT documentation shows endpoints starting with /v1, zenithd exposes this API without that prefix.

Examples:

Dojo command:

:zenith &config-rpc-port '26657'

Card for use in other agents:

[%pass /config %agent [our.bowl %zenith] %poke %config-rpc-port !>('8545')]

%config-http-api-port

Purpose: Sets the port number for the Zenith HTTP REST API endpoint.

Input Type: @t (cord/text string)

Output: Updates the agent's configuration state. No return value.

Default: '1317' (standard Cosmos SDK REST API port)

Description: Configures the port number for accessing Zenith's extended REST API. This is used in combination with the zenith-host setting to form complete HTTP API endpoint URLs. The API provides access to module state queries, balance information, treasury operations, oracle queries, and some specific transaction types (like token claiming).

The REST API has been significantly extended beyond the standard Cosmos SDK to include Zenith-specific functionality like scry oracle queries, Azimuth point lookups, and treasury operations.

Examples:

Dojo command:

:zenith &config-http-api-port '1317'

Card for use in other agents:

[%pass /config %agent [our.bowl %zenith] %poke %config-http-api-port !>('8080')]

%config-oracle-port

Purpose: Sets the port number for the Zenith scryoracle long polling endpoint.

Input Type: @t (cord/text string)

Output: Updates the agent's configuration state. No return value.

Default: '9473' (zenithd-specific port)

Description: Configures the port number for accessing Zenith's scryoracle subscription service. This endpoint provides a long polling API at /api/scrybindings/poll that returns new scry bindings as they are added to the blockchain. The %zenith agent uses this endpoint to watch for new scry bindings and provide them to client applications through oracle subscriptions.

The long polling endpoint responds with mappings from block numbers to scry bindings (path→hash mappings), enabling real-time notifications when new data is canonicalized on the Scry Oracle.

Examples:

Dojo command:

:zenith &config-oracle-port '9473'

Card for use in other agents:

[%pass /config %agent [our.bowl %zenith] %poke %config-oracle-port !>('9000')]

%config-rpc

Purpose: Sets both the hostname and RPC port for the CometBFT endpoint in a single poke.

Input Type: [zenith-host=@t rpc-port=@t] (cell of two cords)

Output: Updates both zenith-host and rpc-port in the agent's configuration state. No return value.

Description: Convenience poke that combines %config-zenith-host and %config-rpc-port functionality. Sets both the hostname/IP and port number for consensus layer communication with the CometBFT node in a single operation.

Examples:

Dojo command:

:zenith &config-rpc ['mynode.example.com' '26657']

Card for use in other agents:

[%pass /config %agent [our.bowl %zenith] %poke %config-rpc !>(['192.168.1.100' '8545'])]

%config-http-api

Purpose: Sets both the hostname and HTTP API port for the Zenith REST API endpoint in a single poke.

Input Type: [zenith-host=@t http-api-port=@t] (cell of two cords)

Output: Updates both zenith-host and http-api-port in the agent's configuration state. No return value.

Description: Convenience poke that combines %config-zenith-host and %config-http-api-port functionality. Sets both the hostname/IP and port number for accessing Zenith's extended REST API in a single operation.

Examples:

Dojo command:

:zenith &config-http-api ['mynode.example.com' '1317']

Card for use in other agents:

[%pass /config %agent [our.bowl %zenith] %poke %config-http-api !>(['192.168.1.100' '8080'])]

%config-chain-id

Purpose: Sets the chain ID for the Zenith blockchain.

Input Type: @t (cord/text string)

Output: Updates the chain-id in the agent's configuration state. No return value.

Default: 'zenith-localtestnet'

Description: Configures the chain ID that must match the chain ID of the zenithd instance you're connecting to. This is critical for transaction signing - transactions cannot be properly signed without using the correct chain ID of the target chain.

Common chain IDs include:

  • 'zenith-localtestnet' - Local development
  • 'zenith-testnet-stage0' - Testnet stage 0
  • 'zenith-mainnet-stage1' - Mainnet stage 1

Examples:

Dojo command:

:zenith &config-chain-id 'zenith-mainnet-stage1'

Card for use in other agents:

[%pass /config %agent [our.bowl %zenith] %poke %config-chain-id !>('zenith-testnet-stage0')]

%config-janus-endpoint

Purpose: Sets the Janus endpoint URL for transaction and scry binding submission.

Input Type: @t (cord/text string)

Output: Updates the janus-endpoint in the agent's configuration state. No return value.

Default: 'http://localhost:8090'

Description: Configures the endpoint URL for the Janus service, which handles transaction and scry binding aggregation between Urbit ships and the Zenith blockchain. Janus is operated by Star nodes and serves as an intermediary that bundles transactions from all ships (Galaxies, Stars, and Planets) before submitting them to Galaxy zenithd nodes for block creation.

In the Zenith architecture, all transactions flow: Any Ship → Star Janus → zenithd (on Galaxy). Every ship, regardless of type, must send their transactions to a Star running Janus to get them bundled and submitted to their sponsoring galaxy's zenithd for inclusion in blocks.

Examples:

Dojo command:

:zenith &config-janus-endpoint 'http://mystar.example.com:8090'

Card for use in other agents:

[%pass /config %agent [our.bowl %zenith] %poke %config-janus-endpoint !>('http://192.168.1.100:8080')]

Account Management Pokes

%add-account

Purpose: Creates a new account from a private key and stores it in the agent.

Input Type: [name=acc-name priv-key=@ux] (cell of account name and hexadecimal private key)

Output: Adds the account to the agent's accounts map. No return value.

Description: Creates a new blockchain account by deriving the public key and Zenith address from the provided secp256k1 private key. The account name can be either ~ (null) for a default account, or a cord (text string) for a named account. If an account with the same name already exists, it will be overwritten.

Security Warning: This is a temporary system for testing only. Private keys stored this way can be easily accessed by malicious Urbit applications with knowledge of the %zenith agent. Do not use this with real funds or important keys.

The private key must be provided as a hexadecimal atom (@ux) with dots separating groups for valid Hoon syntax.

Examples:

Dojo command (default account):

:zenith &add-account [~ 0xb9e6.9d23.a396.4287.63c1.220b.f46d.936b.bd00.52e2.a124.ac0b.e2d6.237d.5c6b.e8ed]

Dojo command (named account):

:zenith &add-account ['alice' 0xb9e6.9d23.a396.4287.63c1.220b.f46d.936b.bd00.52e2.a124.ac0b.e2d6.237d.5c6b.e8ed]

Card for use in other agents:

[%pass /account %agent [our.bowl %zenith] %poke %add-account !>(['myaccount' 0x1234.5678.9abc.def0.1234.5678.9abc.def0.1234.5678.9abc.def0.1234.5678.9abc.def0])]

%update-account

Purpose: Updates the Cosmos SDK account number and sequence number for an existing account.

Input Type: [name=acc-name acc-num=@ud seq-num=@ud] (account name, account number, sequence number)

Output: Updates the account in the accounts map if it exists. No return value.

Description: Updates %zenith's internal record of the Cosmos SDK account number and sequence number for an existing account. This only affects the locally stored values and is useful for tracking what happened during transaction processing, but doesn't actually affect transaction signing behavior.

For Informational Purposes Only: This poke is called automatically by the %zenith agent during transaction processing. Developers should not use this poke manually, as any values set here will be overwritten with fresh values from the blockchain before they are used for transaction signing.

%delete-account

Purpose: Removes an account from the agent's storage.

Input Type: acc-name (account name - either ~ for default account or a cord for named account)

Output: Removes the account from the accounts map. No return value.

Description: Completely removes an account and its associated private key, public key, and address information from the %zenith agent's storage. This action is irreversible - if you delete an account, you'll need to re-add it with %add-account to use it again.

The operation silently succeeds even if the specified account doesn't exist.

Examples:

Dojo command (delete default account):

:zenith &delete-account ~

Dojo command (delete named account):

:zenith &delete-account 'alice'

Card for use in other agents:

[%pass /cleanup %agent [our.bowl %zenith] %poke %delete-account !>('testaccount')]

Blockchain Interaction Pokes

%post-scry-binding

Purpose: Submits a scry binding to the Scry Oracle for canonicalization on the blockchain.

Input Type: [pat=path hash=@t] (scry path and content hash)

Output: Adds the binding to pending-bindings for submission to the blockchain. No return value.

Description: This is the primary method for developers to canonicalize data on the Scry Oracle. The poke accepts a scry path and the hash of the data at that path, adding it to the agent's pending bindings which are exposed via the /zenith/scry-bindings HTTP endpoint for zenithd to query and include in future blocks.

The scry path must be non-empty and start with a valid Urbit ship (@p). Remote scry paths typically follow the format /~ship/g/x/1/app-name//1/resource. The hash should be a cord representing 32 bytes in hexadecimal format (e.g., 'd3bb0d59e354ea843e790801303a46e880219996c6850ddd4c85a83e08c41d92'), typically generated using the hash-noun-to-cord function from the zenith library.

Future Architecture: In upcoming versions, this will transition to submitting scry bindings through Janus (operated by Stars) rather than the direct HTTP endpoint system.

Examples:

Dojo command:

:zenith &post-scry-binding [/~zod/g/x/1/my-app//1/posts/latest/json 'd3bb0d59e354ea843e790801303a46e880219996c6850ddd4c85a83e08c41d92']

Card for use in other agents:

[%pass /scry %agent [our.bowl %zenith] %poke %post-scry-binding !>([/~our/g/x/1/my-app//1/data/json 'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'])]

%listen-oracle

Purpose: Subscribe to oracle updates for scry bindings matching a specific path prefix.

Input Type: [prefix=path from=(unit @ud)] (path prefix and optional starting block number)

Output: Sets up subscription and begins polling for new bindings. Returns cards for oracle polling.

Description: Establishes a subscription to receive new scry bindings that match the specified path prefix. This poke must be paired with a watch on the corresponding /oracle/[prefix] path to actually receive updates.

If a starting block number (from) is provided, the subscription will begin from that block. If ~ (null) is provided, it will start from the current block height.

If %zenith is already polling that path prefix, the poke will be ignored, but the subscription will still succeed and the subscriber will receive updates along with other subscribers.

Examples:

Card for use in other agents (must include both poke and watch):

:~  [%pass /listen %agent [our.bowl %zenith] %poke %listen-oracle !>([/~zod/my-app ~])]
    [%pass /oracle/updates %agent [our.bowl %zenith] %watch [%oracle /~zod/my-app]]
==

Scries (Data Queries)

Configuration and Status Scries

/x/config

Purpose: Retrieves the current agent configuration.

Input: None

Output: config structure with the following fields:

  • rpc-endpoint=@t - Complete RPC endpoint URL
  • http-api-endpoint=@t - Complete HTTP API endpoint URL
  • bindings-endpoint=@t - Complete oracle endpoint URL
  • zenith-host=@t - Configured hostname
  • rpc-port=@t - RPC port
  • http-api-port=@t - HTTP API port
  • bindings-port=@t - Oracle port
  • chain-id=@t - Blockchain chain ID
  • janus-endpoint=@t - Janus endpoint URL

Description: Returns the complete configuration structure including both individual settings and computed endpoint URLs formed by combining host and port values.

Examples:

Dojo command:

.^(config %gx /=zenith=/config/noun)

From other agents:

.^  config
  %gx
  (scot %p our.bowl)
  %zenith
  (scot %da now.bowl)
  /config/noun
==

/x/account/[name]

Purpose: Retrieves information for a specific account.

Input: Account name in the path (~ encoded as empty string for default account, or a cord for named accounts)

Output: (unit account) - Either ~ if account doesn't exist, or [~ u=account] where account structure contains:

  • addr=@t - Zenith blockchain address
  • pub-key=@ux - Public key
  • priv-key=@ux - Private key (security warning applies)
  • acc-num=@ud - Cosmos SDK account number
  • seq-num=@ud - Cosmos SDK sequence number

Description: Returns the complete account information for the specified account name. Returns ~ if the account doesn't exist, or [~ u=account] if it exists. To access fields from the response, use wings like addr.u.res where res is the response.

The private key is included in the response, so the same security warnings about private key storage apply.

Examples:

Dojo command (default account, ~ encoded as empty string):

.^((unit account) %gx /=zenith=/account//noun)

Dojo command (named account):

.^((unit account) %gx /=zenith=/account/alice/noun)

From other agents:

.^  (unit account)
  %gx
  (scot %p our.bowl)
  %zenith
  (scot %da now.bowl)
  /account/alice/noun
==

/x/rpc-connected

Purpose: Checks if the RPC connection is active.

Output: [connected=?] - Boolean indicating RPC connection status

Examples:

.^([connected=?] %gx /=zenith=/rpc-connected/noun)

/x/http-api-connected

Purpose: Checks if the HTTP API connection is active.

Output: [connected=?] - Boolean indicating HTTP API connection status

Examples:

.^([connected=?] %gx /=zenith=/http-api-connected/noun)

/x/oracle-connected

Purpose: Checks if the oracle connection is active.

Output: [connected=?] - Boolean indicating oracle connection status

Examples:

.^([connected=?] %gx /=zenith=/oracle-connected/noun)

/x/connected

Purpose: Checks if all connections (RPC, HTTP API, and oracle) are active.

Output: [connected=?] - Boolean indicating overall connection status (true only if all connections are active)

Examples:

.^([connected=?] %gx /=zenith=/connected/noun)

/x/latest-block-height

Purpose: Retrieves the latest known block height.

Output: @ud - Latest block height as recorded by the healthcheck system

Description: Returns the latest block height that the agent has observed through its healthcheck polling. This value is updated regularly during healthcheck operations.

Examples:

.^(@ud %gx /=zenith=/latest-block-height/noun)

Subscriptions

/oracle/[prefix]

Purpose: Subscribe to receive new scry bindings for a specific path prefix.

Input: Path prefix in the subscription path

Output: Receives %scry-bindings facts containing new scry bindings as they are discovered

Description: Subscribes to oracle updates for the specified path prefix. When new scry bindings matching the prefix are discovered, they will be sent as %scry-bindings facts containing a scry-bindings map (path→hash mappings).

This subscription must be paired with a %listen-oracle poke to establish the polling mechanism. The agent will continuously monitor for new bindings and broadcast them to all subscribers of the matching prefix.

Examples:

From other agents:

[%pass /oracle/updates %agent [our.bowl %zenith] %watch [%oracle /~zod/my-app]]

Complete setup (poke + watch):

:~  [%pass /listen %agent [our.bowl %zenith] %poke %listen-oracle !>([/~zod/my-app ~])]
    [%pass /oracle/updates %agent [our.bowl %zenith] %watch [%oracle /~zod/my-app]]
==

Fact Processing:

++  on-agent
  |=  [=wire =sign:agent:gall]
  ^-  (quip card _this)
  ?+  wire  (on-agent:def wire sign)
    [%oracle %updates ~]
      ?+  -.sign  (on-agent:def wire sign)
        %fact
          ?+  p.cage.sign  (on-agent:def wire sign)
            %scry-bindings
              =/  bindings  !<(scry-bindings q.cage.sign)
              :: Process new bindings here
              `this
          ==
      ==
  ==

Threads

Threads provide specific operations that can be called via the Spider agent or %khan vane. Threads can also be run manually from the dojo through convenience pokes in the %zenith agent.

Account and Balance Operations

get-zenith-address

Purpose: Retrieves the Zenith blockchain address for a given Urbit ship.

Input: ship - Urbit ship (@p)

Output: @t - Zenith address

Description: Queries the Zenith HTTP API endpoint /laconic/zenith/v1/address_by_point to get the blockchain address associated with an Urbit ship. This uses the configured HTTP API endpoint from the %zenith agent.

Examples:

Via %zenith poke:

:zenith &zenith-address ~bitnet

Using %khan vane:

[%pass /zenith-addr %arvo %k %fard %zenith %get-zenith-address %noun !>(~bitnet)]

Using %spider agent:

[%pass /zenith-addr %agent [our.bowl %spider] %poke %spider-start !>([~ ``@ta`(cat 3 'thread_' (scot %uv (sham eny.bowl))) byk.bowl(r da+now.bowl) %get-zenith-address !>(~bitnet)])]

Thread name and vase for other uses:

[%get-zenith-address !>(~bitnet)]

get-balances-by-ship

Purpose: Retrieves token balances for a given Urbit ship.

Input: ship - Urbit ship (@p)

Output: balances - List of [denom=@t amount=@ud] balance entries

Description: Queries the Zenith HTTP API endpoint /laconic/zenith/v1/balances_by_point to get all token balances for the Zenith address associated with an Urbit ship.

Examples:

Via %zenith poke:

:zenith &balances-by-ship ~bitnet

Using %khan vane:

[%pass /balances %arvo %k %fard %zenith %get-balances-by-ship %noun !>(~bitnet)]

Thread name and vase for other uses:

[%get-balances-by-ship !>(~bitnet)]

get-balances-by-addr

Purpose: Retrieves token balances for a given Zenith address.

Input: @t - Zenith address as a cord

Output: balances - List of [denom=@t amount=@ud] balance entries

Description: Queries the standard Cosmos bank module endpoint /cosmos/bank/v1beta1/balances/[address] to get all token balances for the specified Zenith address.

Examples:

Via %zenith poke:

:zenith &balances-by-addr 'zenith1abc123...'

Thread name and vase for other uses:

[%get-balances-by-addr !>('zenith1abc123...')]

Transaction Operations

send-to-ship

Purpose: Sends tokens from an account to an Urbit ship's Zenith address.

Input: [acc-name=acc-name to=@p amount=@ud denom=@t] - Account name, recipient ship, amount, and denomination

Output: Transaction result

Description: Sends tokens from the specified account to an Urbit ship by first resolving the ship's Zenith address and then executing the transfer. This thread combines get-zenith-address and send-to-account operations.

Note: Success of this thread only indicates that the transaction was successfully passed to Janus for bundling, not that it was actually confirmed on-chain.

Examples:

Via %zenith poke:

:zenith &send-to-ship [~ ~bitnet 1.000.000 'znt']

Thread name and vase for other uses:

[%send-to-ship !>([~ ~bitnet 1.000.000 'znt'])]

send-to-addr

Purpose: Sends tokens from an account to a Zenith address.

Input: [acc-name=acc-name to=@t amount=@ud denom=@t] - Account name, recipient address, amount, and denomination

Output: Transaction result message from Janus

Description: Sends tokens from the specified account to a Zenith blockchain address. The thread fetches the latest account numbers from the chain, creates a signed transaction, and submits it to Janus for bundling. The account sequence numbers are automatically updated after submission.

Note: Success only indicates the transaction was accepted by Janus for bundling, not on-chain confirmation.

Examples:

Via %zenith poke:

:zenith &send-to-addr [~ 'zenith1abc123...' 1.000.000 'znt']

Thread name and vase for other uses:

[%send-to-addr !>([~ 'zenith1abc123...' 1.000.000 'znt'])]

Oracle Operations

get-scry-bindings

Purpose: Retrieves multiple scry bindings matching a path prefix with pagination support.

Input: query:oracle - Query structure with prefix and pagination parameters

Output: response:oracle - Structure containing:

  • bindings=scry-bindings - Map of paths to hashes (map path @t)
  • page-info=page-info - Pagination info with:
    • next-key=(unit @t) - Key for next page (if any)
    • total=@ud - Total count (always returned due to current zenithd implementation)

Description: Queries the Zenith HTTP API endpoint /laconic/scryoracle/v1/bindings_by_prefix to get scry bindings that match the specified path prefix. Supports pagination with either key-based or offset/limit pagination, and can return results in reverse order.

Note: This thread is designed to support more complex query structures in the future, but currently there's no indexer or functionality built into zenithd that can provide a backend for more advanced query features.

Examples:

Via %zenith poke:

:zenith &scry-bindings [/~zod [offset=0 limit=10] count-total=%.y reverse=%.n]

Thread name and vase for other uses:

[%get-scry-bindings !>([/~zod [offset=0 limit=10] count-total=%.y reverse=%.n])]

get-scry-binding

Purpose: Retrieves the hash for a specific scry path.

Input: path - Scry path

Output: @t - 32-byte hash value encoded as a hex string

Description: Queries the Zenith HTTP API endpoint /laconic/scryoracle/v1/hashes to get the canonicalized hash for a specific scry path. Returns the hash if the binding exists on the Scry Oracle.

Examples:

Via %zenith poke:

:zenith &scry-binding /~zod/g/x/1/my-app//1/data/json

Thread name and vase for other uses:

[%get-scry-binding !>(/~zod/g/x/1/my-app//1/data/json)]

verified-scry

Purpose: Performs a remote scry and verifies the result against the Scry Oracle.

Input: remote-scry:oracle - Structure containing:

  • kind=?(%keen %chum %shut) - Scry type (unencrypted, two-party, or multi-party encrypted)
  • spar:ames - Remote scry target (ship and path)
  • timeout=(unit @dr) - Optional timeout duration (strongly recommended)

Output: (unit [roar:ames verified=(unit ?)]) - Either ~ if no data, or tuple containing:

  • roar:ames - The remote scry response
  • verified=(unit ?) - Verification result: ~ if no oracle hash, %.y if verified, %.n if hash mismatch

Description: Performs a remote scry via %ames and simultaneously fetches the expected hash from the Scry Oracle. The thread verifies that the received data matches the canonicalized hash, providing Byzantine fault tolerance for remote scry operations.

Important: If no timeout is provided and the target ship doesn't respond to the remote scry request, the thread will hang indefinitely. A timeout is very strongly recommended.

Examples:

Via %zenith poke:

:zenith &verified-scry [%keen [~zod /g/x/1/my-app//1/data/json] `~s30]

Thread name and vase for other uses:

[%verified-scry !>([%keen [~zod /g/x/1/my-app//1/data/json] `~s30])]

verify-scry

Purpose: Verifies that a provided hash matches the canonical hash in the Scry Oracle.

Input: [spar:ames hash=@ux] - Target ship and path, plus hash to verify

Output: ? - Boolean indicating whether the hash matches the oracle

Description: Queries the Scry Oracle to get the canonical hash for the specified path and compares it against the provided hash. Returns %.y if they match, %.n if they don't match or if no oracle hash exists.

Examples:

Via %zenith poke:

:zenith &verify-scry [[~zod /g/x/1/my-app//1/data/json] 0xd3bb.0d59.e354.ea84.3e79.0801.303a.46e8.8021.9996.c685.0ddd.4c85.a83e.08c4.1d92]

Thread name and vase for other uses:

[%verify-scry !>([[~zod /g/x/1/my-app//1/data/json] 0xd3bb.0d59.e354.ea84.3e79.0801.303a.46e8.8021.9996.c685.0ddd.4c85.a83e.08c4.1d92])]

Network and Utility Operations

get-rpc-status

Purpose: Retrieves comprehensive status information from the CometBFT RPC endpoint.

Input: None (unit value)

Output: status - Structure containing:

  • node-info - Node protocol version, ID, network info, version, etc.
  • sync-info - Latest/earliest block info, sync status, block heights and times
  • validator-info - Validator address, public key, and voting power

Description: Queries the CometBFT RPC endpoint /status to get detailed information about the blockchain node's current state, including sync status, block information, and validator details.

Examples:

Via %zenith poke:

:zenith &rpc-status ~

Thread name and vase for other uses:

[%get-rpc-status !>(~)]

get-eth-height

Purpose: Retrieves the latest Ethereum block height as seen by the Zenith chain.

Input: None (null value)

Output: @ud - Ethereum block height

Description: Queries the Zenith HTTP API endpoint /laconic/zenith/v1/eth_height to get the latest Ethereum block height that the Zenith chain has observed. This is used for cross-chain coordination and monitoring.

Examples:

Via %zenith poke:

:zenith &eth-height ~

Thread name and vase for other uses:

[%get-eth-height !>(~)]

get-http-api-request

Purpose: Makes a generic HTTP GET request to the Zenith HTTP API endpoint.

Input: tape - URL path to append to the HTTP API endpoint (must include leading slash)

Output: json - Raw JSON response from the API

Description: Makes a generic HTTP GET request by appending the provided URL path to the configured HTTP API endpoint. This is a utility thread for accessing any HTTP API endpoint that isn't covered by more specific threads.

The path must include a leading slash (e.g., "/cosmos/bank/v1beta1/balances/zenith1abc123").

Examples:

Thread name and vase for other uses:

[%get-http-api-request !>("/cosmos/bank/v1beta1/balances/zenith1abc123")]

get-rpc-request

Purpose: Makes a generic HTTP GET request to the CometBFT RPC endpoint.

Input: tape - URL path to append to the RPC endpoint (must include leading slash)

Output: json - Raw JSON response from the RPC API

Description: Makes a generic HTTP GET request by appending the provided URL path to the configured CometBFT RPC endpoint. This is a utility thread for accessing any CometBFT RPC endpoint that isn't covered by more specific threads.

The path must include a leading slash (e.g., "/block?height=1000").

Examples:

Thread name and vase for other uses:

[%get-rpc-request !>("/block?height=1000")]

Library Arms and Types

The %zenith library provides utility functions that can be imported and used in your own applications. Make sure to include all files in the zenith-dev directory in your desk. Import the library with /+ *zenith or /+ zenith in your Hoon code.

Arms

+gen-account

Purpose: Generates a complete account structure from a private key.

Input: @ux - secp256k1 private key

Output: account - Complete account structure with address, keys, and initial sequence numbers

Description: Creates a complete account by deriving the public key and Zenith address from a secp256k1 private key. The account structure includes the Bech32-encoded Zenith address, compressed public key, private key, and initialized account/sequence numbers (both set to 0).

Examples:

=/  priv-key  0xb9e6.9d23.a396.4287.63c1.220b.f46d.936b.bd00.52e2.a124.ac0b.e2d6.237d.5c6b.e8ed
=/  new-account  (gen-account:zenith priv-key)

+pub-to-bech32

Purpose: Converts a compressed secp256k1 public key to a Zenith Bech32 address.

Input: @ux - Compressed secp256k1 public key (33 bytes)

Output: @t - Zenith Bech32 address starting with "zenith"

Description: Converts a compressed public key to a Zenith blockchain address using the Bech32 encoding standard with "zenith" as the human-readable part. The address is derived by taking the RIPEMD160 hash of the SHA256 hash of the public key (Hash160).

Examples:

=/  pub-key  0x3.1c17.7888.02b4.50d4.a1aa.a9eb.95c6.dc0f.2c6c.1021.ac53.3b20.d899.0076.ffc7.5582
=/  address  (pub-to-bech32:zenith pub-key)

+hash-noun

Purpose: Computes a hash of any Hoon noun.

Input: * - Any Hoon noun

Output: @ - Hash value as an atom

Description: Computes a hash of a Hoon noun by first jamming it to bytes and then applying SHA256 hash (shax). This is useful for creating content hashes for scry bindings.

Examples:

=/  data  [%my %sample %data]
=/  data-hash  (hash-noun:zenith data)

+hash-noun-to-cord

Purpose: Computes a hash of any Hoon noun and returns it as a hexadecimal cord.

Input: * - Any Hoon noun

Output: @t - Hash value as a 64-character hexadecimal string (32 bytes)

Description: Combines hash-noun with hexadecimal encoding to produce a cord suitable for use with scry binding operations. This is the standard format expected by the Scry Oracle. The output is always exactly 64 characters (32 bytes in hex).

Examples:

=/  data  [%my %sample %data]
=/  hash-cord  (hash-noun-to-cord:zenith data)
:: hash-cord will be something like 'd3bb0d59e354ea843e790801303a46e880219996c6850ddd4c85a83e08c41d92'

+post-scry-binding

Purpose: Creates the cards needed to grow a scry endpoint and post its binding to the Scry Oracle.

Input: [our=ship dap=term now=@da pat=path data=*] - Ship, app name, current time, path, and data to bind

Output: (list card:agent:gall) - List of cards to send

Description: Convenience function that creates both a %grow card to establish a scry endpoint and a %zenith poke card to submit the scry binding to the oracle. This automates the two-step process of making data available via scry and registering it with the Scry Oracle.

The function automatically determines the next revision number for the scry path by checking existing scry endpoints, constructs the full scry path in the format /(scot %p our)/g/x/(scot %ud rev)/[dap]//1/[pat], and computes the hash of the data automatically.

Examples:

=/  my-data  [%posts ~[%latest %announcement]]
=/  cards  (post-scry-binding:zenith our.bowl %my-app now.bowl /posts/latest my-data)
:: Send the cards to establish scry endpoint and register with oracle
cards

Types

The %zenith library defines several important types that developers will encounter when working with the Zenith blockchain. Import these types with /- *zenith in your Hoon code.

$config

Description: Agent configuration structure containing all endpoint and connection settings.

Structure:

+$  config
  $:  rpc-endpoint=@t
      http-api-endpoint=@t
      bindings-endpoint=@t
      zenith-host=@t
      rpc-port=@t
      http-api-port=@t
      bindings-port=@t
      chain-id=@t
      janus-endpoint=@t
  ==

Fields:

  • rpc-endpoint - Complete CometBFT RPC endpoint URL
  • http-api-endpoint - Complete Zenith HTTP API endpoint URL
  • bindings-endpoint - Complete oracle polling endpoint URL
  • zenith-host - Hostname/IP of zenithd instance
  • rpc-port - CometBFT RPC port
  • http-api-port - HTTP API port
  • bindings-port - Oracle polling port
  • chain-id - Blockchain chain identifier
  • janus-endpoint - Janus service endpoint URL

$account

Description: Blockchain account structure containing keys, address, and sequence information.

Structure:

+$  account
  $:  addr=@t
      pub-key=@ux
      priv-key=@ux
      acc-num=@ud  :: index in chain state
      seq-num=@ud
  ==

Fields:

  • addr - Bech32-encoded Zenith blockchain address (e.g., "zenith1abc123...")
  • pub-key - Compressed secp256k1 public key (33 bytes)
  • priv-key - secp256k1 private key (32 bytes)
  • acc-num - Cosmos SDK account number (index in chain state)
  • seq-num - Current sequence number for transaction ordering

Security Warning: Private keys stored in this structure can be accessed by any Urbit application with knowledge of the %zenith agent. This is intended for testing only.

$acc-name

Description: Account name type used to identify accounts in the %zenith agent.

Structure:

+$  acc-name  ?(~ @t)

Values:

  • ~ - Represents the default account
  • @t - Named account (any cord/text string)

Note: An empty string '' is equivalent to ~ and will also point to the default account.

Usage: Used in pokes like %add-account, %delete-account and threads like send-to-ship, send-to-addr to specify which account to operate on.

$balances

Description: List of token balances for an account.

Structure:

+$  balances  (list [denom=@t amount=@ud])

Fields:

  • denom - Token denomination (e.g., "znt", "$Z", etc.)
  • amount - Token amount in base units (smallest denomination)

Usage: Returned by balance query threads like get-balances-by-ship and get-balances-by-addr.

$scry-bindings

Description: Map of scry paths to their canonical hashes stored on the Scry Oracle.

Structure:

+$  scry-bindings  (map path @t)

Fields:

  • Key: path - Scry path (e.g., /~zod/g/x/1/my-app//1/data/json)
  • Value: @t - 64-character hex string representing the 32-byte hash of the data

Usage: Used in oracle subscriptions, get-scry-bindings thread responses, and throughout the Scry Oracle system to represent path→hash mappings.

$query:oracle

Description: Query structure for retrieving scry bindings with pagination support.

Structure:

+$  query
  $:  prefix=path
      page=page-params
  ==

+$  page-params
  $:  $@(key=@t [offset=@ud limit=@ud])
      count-total=?
      reverse=$~(%.n ?)
  ==

Fields:

  • prefix - Path prefix to filter scry bindings
  • page - Pagination parameters:
    • Either key=@t for key-based pagination, or [offset=@ud limit=@ud] for offset-based pagination
    • count-total - Whether to return total count in response
    • reverse - Whether to return results in reverse order (defaults to %.n)

Usage: Used as input to the get-scry-bindings thread to specify which bindings to retrieve and how to paginate results.

$response:oracle

Description: Response structure returned by scry binding queries with pagination information.

Structure:

+$  response
  $:  bindings=scry-bindings
      page-info=page-info
  ==

+$  page-info
  $:  next-key=(unit @t)
      total=@ud
  ==

Fields:

  • bindings - Map of scry paths to hashes (see scry-bindings type)
  • page-info - Pagination information:
    • next-key - Key for next page if more results available, ~ if this is the last page
    • total - Total count of matching results

Usage: Returned by the get-scry-bindings thread to provide both the requested bindings and pagination metadata.

$remote-scry:oracle

Description: Input structure for performing verified remote scry operations.

Structure:

+$  remote-scry
  $:  kind=?(%keen %chum %shut)  :: unencrypted, two-party, or multi-party encrypted
      =spar:ames
      timeout=(unit @dr)
  ==

Fields:

  • kind - Type of remote scry:
    • %keen - Unencrypted remote scry (most common)
    • %chum - Two-party encrypted remote scry
    • %shut - Multi-party encrypted remote scry
  • spar:ames - Remote scry target (pair ship path) containing target ship and scry path
  • timeout - Optional timeout duration (strongly recommended to prevent hanging)

Usage: Used as input to the verified-scry thread to specify the remote scry operation to perform and verify against the Scry Oracle.

$status

Description: Comprehensive status information from the CometBFT RPC endpoint.

Structure:

+$  status
  $:  =node-info
      =sync-info
      =validator-info
  ==

+$  node-info
  $:  protocol-version=[p2p=@ud block=@ud app=@ud]
      id=@t
      listen-addr=@t
      network=@t
      version=@t
      channels=@t
      moniker=@t
      other=[tx-index=@t rpc-address=@t]
  ==

+$  sync-info
  $:  latest-block-hash=@t
      latest-app-hash=@t
      latest-block-height=@ud
      latest-block-time=@t
      earliest-block-hash=@t
      earliest-app-hash=@t
      earliest-block-height=@ud
      earliest-block-time=@t
      catching-up=?
  ==

+$  validator-info
  $:  address=@t
      pub-key=[type=@t value=@t]
      voting-power=@t
  ==

Fields:

  • node-info - Node protocol version, ID, network info, version, etc.
  • sync-info - Latest/earliest block info, sync status, block heights and times
  • validator-info - Validator address, public key, and voting power

Usage: Returned by the get-rpc-status thread to provide detailed information about the blockchain node's current state.