mirror of
https://github.com/Xahau/xahau-web.git
synced 2026-07-31 11:00:11 +00:00
@@ -156,6 +156,16 @@ const t = featuresTranslations[locale] ?? featuresTranslations.en
|
||||
<p>{t.checks_para2}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PRICE ORACLES ─ solo wide ───────────────────────────────────────── -->
|
||||
<div class="xf-solo">
|
||||
<span class="xf-lbl lbl-fin">{t.oracle_label}</span>
|
||||
<h4>{t.oracle_h4}</h4>
|
||||
<div class="xf-solo-cols">
|
||||
<p>{t.oracle_para1}</p>
|
||||
<p>{t.oracle_para2}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /act-fin -->
|
||||
|
||||
<!-- ══════════════════════════════════════════════════════════════════════
|
||||
@@ -439,7 +449,8 @@ const t = featuresTranslations[locale] ?? featuresTranslations.en
|
||||
.act-proto .xf-solo h4 {
|
||||
color: var(--grn2);
|
||||
}
|
||||
.act-fin .xf-detail h4 {
|
||||
.act-fin .xf-detail h4,
|
||||
.act-fin .xf-solo h4 {
|
||||
color: var(--teal2);
|
||||
}
|
||||
.act-gov .xf-detail h4,
|
||||
|
||||
@@ -81,6 +81,30 @@ Core amendment enabling Hook smart contract functionality on Xahau. _(Added by t
|
||||
|
||||
Updates and improvements to the Hooks system.
|
||||
|
||||
##### HookAPISerializedType240
|
||||
|
||||
Fixes incorrect parsing of `STPathSet` fields (used by `sfPaths` in Payment transactions) within all `sto_` Hook API functions ([sto_subfield](/docs/hooks/functions/serialization/sto_subfield), [sto_subarray](/docs/hooks/functions/serialization/sto_subarray), [sto_emplace](/docs/hooks/functions/serialization/sto_emplace), [sto_erase](/docs/hooks/functions/serialization/sto_erase), [sto_validate](/docs/hooks/functions/serialization/sto_validate)). Before this amendment, PathSet fields were incorrectly treated as VL-encoded data, causing the internal parser (`get_stobject_length`) to misread the field boundary and corrupt the parsing of all subsequent fields in the object. PathSet fields are self-delimiting (using `0xFF` path-separator bytes and a `0x00` end-of-set byte) and are now parsed correctly. Also raises the maximum supported serialized type from `STI_VECTOR256` (19) to `STI_CURRENCY` (26), adding correct support for `STI_ISSUE` (24), `STI_XCHAIN_BRIDGE` (25), and `STI_CURRENCY` (26) within all `sto_` functions. _(Introduced in 2026.6.21-release+3350)_
|
||||
|
||||
##### NamedHooks
|
||||
|
||||
Adds an optional `HookName` field (4–16 bytes, UTF-8) to the Hook slot in a [SetHook transaction](/docs/protocol-reference/transactions/transaction-types/sethook). When a hook installation carries a `HookName`, that hook will **only execute** if the incoming transaction also includes a matching top-level `HookName` field. Transactions without `HookName`, or with a different value, silently skip the named hook. `HookName` is also added as an optional common field on all transaction types so that submitters can target specific named hooks. This enables multiple hooks to coexist on an account with different entry points activated by different callers. _(Introduced in 2026.6.21-release+3350)_
|
||||
|
||||
##### HooksUpdate2
|
||||
|
||||
Adds the `prepare()` Hook API function. `prepare(write_ptr, write_len, read_ptr, read_len)` accepts a partial serialized transaction containing only transaction-type-specific fields and automatically injects all fields required for emission: `Account`, `Sequence`, `SigningPubKey`, `Fee`, `FirstLedgerSequence`, `LastLedgerSequence`, and `EmitDetails`. The output can be passed directly to `emit()`, eliminating the need to manually construct these boilerplate fields in hook code. _(Introduced in 2026.6.21-release+3350)_
|
||||
|
||||
##### HookOnV2
|
||||
|
||||
Hooks may continue to specify `HookOn` with the existing behaviour, or optionally replace it with two separate fields: `HookOnIncoming` and `HookOnOutgoing`. Both use the same bitmask syntax as `HookOn` but differentiate between transactions originating from the Hook account (`HookOnOutgoing`) and transactions originating from another account (`HookOnIncoming`). _(Introduced in 2026.6.21-release+3350)_
|
||||
|
||||
##### PriceOracle
|
||||
|
||||
A port of the XRPL PriceOracle (XLS-47d) standard. Enables on-chain price feeds by allowing accounts to publish asset price data as [Oracle ledger objects](/docs/protocol-reference/ledger-data/ledger-objects-types/oracle). Introduces two new transactions: [OracleSet](/docs/protocol-reference/transactions/transaction-types/oracleset) (create or update an Oracle) and [OracleDelete](/docs/protocol-reference/transactions/transaction-types/oracledelete) (remove an Oracle). Also adds the `get_aggregate_price` RPC method for querying aggregated prices across multiple oracles. Each Oracle object stores 1–10 asset/quote price pairs (1–5 pairs consume 1 owner reserve; 6–10 consume 2). The integer `AssetPrice`, together with `Scale`, encodes the price as `AssetPrice` × 10^(-`Scale`). _(Introduced in 2026.6.21-release+3350)_
|
||||
|
||||
##### IOURewardClaim
|
||||
|
||||
Expands the [ClaimReward](/docs/protocol-reference/transactions/transaction-types/claimreward) transaction type beyond genesis balance adjustments to other IOU currencies. Reward counters are held within the trustline (`LowReward`/`HighReward` objects on the [RippleState](/docs/protocol-reference/ledger-data/ledger-objects-types/ripple-state) object) and do not affect genesis balance adjustments. The transaction triggers any Hook installed on the account specified by the `Issuer` field, allowing that Hook to process and optionally pay out the reward. The reward-paying account does not need to be the issuer of the IOU currency. _(Introduced in 2026.6.21-release+3350)_
|
||||
|
||||
##### Remit
|
||||
|
||||
Implements [XLS-55](https://github.com/XRPLF/XRPL-Standards/discussions/156). A new simple but powerful what-you-see-is-what-you-get push payment transaction type. Enables [Remit transactions](/docs/protocol-reference/transactions/transaction-types/remit) that allow paying multiple currencies and URITokens in the same transaction to the same destination. The transaction automatically pays to create missing trustlines, automatically pays the reserves on transferred tokens, and automatically pays to create the destination account if it doesn't exist. You can mint a receipt or bonus URIToken in-line within the transaction. Optionally inform a third party Hook about the transaction. No partial payments and no pathing.
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
title: get_aggregate_price
|
||||
description: >-
|
||||
Retrieves aggregated price statistics across multiple Price Oracle objects
|
||||
for a given asset pair.
|
||||
---
|
||||
_(Added by the [PriceOracle amendment](/docs/features/amendments/#priceoracle).)_
|
||||
|
||||
The `get_aggregate_price` method queries the price data stored in one or more [Oracle ledger objects](/docs/protocol-reference/ledger-data/ledger-objects-types/oracle) for a specified asset pair and returns aggregated statistics (mean, median, standard deviation). Optionally, outliers can be trimmed and a time window filter applied.
|
||||
|
||||
### Request Format
|
||||
|
||||
```json
|
||||
{
|
||||
"command": "get_aggregate_price",
|
||||
"ledger_index": "current",
|
||||
"base_asset": "XAH",
|
||||
"quote_asset": "USD",
|
||||
"trim": 20,
|
||||
"time_threshold": 300,
|
||||
"oracles": [
|
||||
{
|
||||
"account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"oracle_document_id": 1
|
||||
},
|
||||
{
|
||||
"account": "rN7n3473SaZBCG4dFL83w7PB8LTfHBEDP",
|
||||
"oracle_document_id": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Request Parameters
|
||||
|
||||
| Field | JSON Type | Required? | Description |
|
||||
| ---------------- | --------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `base_asset` | String | Yes | The currency code of the asset being priced (e.g. `"XAH"`, `"BTC"`). |
|
||||
| `quote_asset` | String | Yes | The currency code of the denomination (e.g. `"USD"`, `"EUR"`). |
|
||||
| `oracles` | Array | Yes | Array of up to **200** oracle references. Each entry must contain `account` (String, AccountID) and `oracle_document_id` (Number, UInt32). |
|
||||
| `trim` | Number | No | Percentage (1–25) of outliers to remove from both ends of the price distribution before computing `trimmed_set` statistics. |
|
||||
| `time_threshold` | Number | No | Maximum age in seconds for a price to be included. Prices with `LastUpdateTime < (latestTime - time_threshold)` are excluded. If omitted, all prices are included. |
|
||||
| `ledger_index` | String or Number | No | The ledger to query. Defaults to `"current"`. |
|
||||
|
||||
### Response Format
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"entire_set": {
|
||||
"mean": "7.456",
|
||||
"size": 5,
|
||||
"standard_deviation": "0.12"
|
||||
},
|
||||
"trimmed_set": {
|
||||
"mean": "7.45",
|
||||
"size": 3,
|
||||
"standard_deviation": "0.08"
|
||||
},
|
||||
"median": "7.46",
|
||||
"time": 816348900,
|
||||
"status": "success"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Response Fields
|
||||
|
||||
| Field | JSON Type | Description |
|
||||
| ------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| `entire_set.mean` | String | Mean price across all collected data points (as a decimal string). |
|
||||
| `entire_set.size` | Number | Number of price data points used to compute the statistics. |
|
||||
| `entire_set.standard_deviation` | String | Standard deviation of prices in the full set. |
|
||||
| `trimmed_set.mean` | String | Mean price after removing the top and bottom `trim%` outliers. Only present if `trim` was specified. |
|
||||
| `trimmed_set.size` | Number | Number of data points remaining after trimming. Only present if `trim` was specified. |
|
||||
| `trimmed_set.standard_deviation`| String | Standard deviation after trimming. Only present if `trim` was specified. |
|
||||
| `median` | String | Median price across the full set. |
|
||||
| `time` | Number | The most recent `LastUpdateTime` (Ripple Epoch) found across all queried Oracle objects. |
|
||||
|
||||
### Algorithm
|
||||
|
||||
1. Iterates through up to **200** oracle accounts and retrieves their `Oracle` ledger entries.
|
||||
2. For each Oracle, searches up to **3** historical transaction metadata entries to find a price for the requested `base_asset`/`quote_asset` pair.
|
||||
3. Applies the `time_threshold` filter: keeps only prices where `LastUpdateTime ≥ (latestTime - time_threshold)`.
|
||||
4. Computes mean, standard deviation, and median over the filtered set.
|
||||
5. If `trim` > 0: removes the top and bottom `trim%` by price value and recomputes statistics for `trimmed_set`.
|
||||
|
||||
### Error Cases
|
||||
|
||||
| Error Code | Description |
|
||||
| --------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| `rpcORACLE_MALFORMED` | An entry in `oracles` is missing or has an invalid `account` or `oracle_document_id`. |
|
||||
| `rpcINVALID_PARAMS` | Invalid parameter type, empty asset string, or `trim` outside the 1–25 range. |
|
||||
| `rpcOBJECT_NOT_FOUND` | No matching price data found for the requested asset pair across all queried Oracle objects. |
|
||||
| `rpcINTERNAL` | All data points were excluded by the `time_threshold` filter, leaving an empty result set. |
|
||||
|
||||
### Limits
|
||||
|
||||
| Parameter | Limit |
|
||||
| ------------- | -------------------------- |
|
||||
| `oracles` | Max 200 entries per request |
|
||||
| History depth | Max 3 historical metadata entries searched per oracle |
|
||||
| `trim` | 1–50 (%) |
|
||||
@@ -78,6 +78,14 @@ Interact directly with an xahaud server using public API methods. These methods
|
||||
| server_state | Get server status in machine-readable format. |
|
||||
| manifest | Retrieve public key details for a validator. |
|
||||
|
||||
### Oracle Methods
|
||||
|
||||
_(Requires the [PriceOracle amendment](/docs/features/amendments/#priceoracle).)_
|
||||
|
||||
| Method | Description |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------ |
|
||||
| [get_aggregate_price](/docs/features/http-websocket-apis/get-aggregate-price) | Retrieve aggregated price statistics across multiple Oracle objects for an asset pair. |
|
||||
|
||||
### Utility Methods
|
||||
|
||||
|
||||
|
||||
@@ -18,3 +18,25 @@ A `ClaimReward` transaction allows an account to claim the rewards it has accumu
|
||||
The `GenesisMint` transaction type is also associated with the Balance Rewards feature. This is an Emitted transaction that is executed through the Reward Hook every time a user claims balance rewards.
|
||||
|
||||
<LinkCard title="GenesisMint - (Emitted Txn)" href="/docs/protocol-reference/transactions/transaction-types/genesismint-emitted-txn" />
|
||||
|
||||
### IOU Reward Claim
|
||||
|
||||
_(Requires the [IOURewardClaim amendment](/docs/features/amendments/#iourewardclaim).)_
|
||||
|
||||
The `IOURewardClaim` amendment extends the reward mechanic to IOU currencies issued by any account. The same area-under-the-curve calculation (hold time × hold amount) that governs XAH genesis rewards is applied to IOU token holders, with the issuer's Hook controlling payout logic.
|
||||
|
||||
#### How it works
|
||||
|
||||
1. **Opt-in**: A token holder submits a `ClaimReward` transaction with the `ClaimCurrency` field specifying the IOU. This initialises reward-tracking counters (`LowReward` or `HighReward`) directly on the trustline ([RippleState](/docs/protocol-reference/ledger-data/ledger-objects-types/ripple-state) ledger object).
|
||||
2. **Accumulation**: After every transaction that modifies the trustline balance, the ledger automatically updates the `TrustLineRewardAccumulator` field. This tracks the cumulative product of balance × ledgers elapsed since the last reset.
|
||||
3. **Claim**: When the holder submits another `ClaimReward` with `ClaimCurrency`, the ledger resets the counters and fires the issuer's Hook (which must be installed and must fire on `ClaimReward` transaction). The Hook reads the accumulated value and emits a reward payment in whatever form the issuer chooses.
|
||||
|
||||
#### Key differences from XAH genesis rewards
|
||||
|
||||
| | XAH Genesis Rewards | IOU Rewards |
|
||||
|---|---|---|
|
||||
| Amendment | `BalanceRewards` | `IOURewardClaim` |
|
||||
| Counters stored on | AccountRoot | RippleState (trustline) |
|
||||
| Accumulator type | UInt64 (drops / 1,000,000) | Amount (in the token's units) |
|
||||
| Payout handled by | Genesis account Hook | Issuer account Hook |
|
||||
| Issuer restriction | Must be genesis account | Any account with a Hook on `ClaimReward` transaction, except AMM accounts |
|
||||
|
||||
@@ -18,13 +18,13 @@ The solution: **Emitted Transactions**. We allow the Originating Transaction to
|
||||
|
||||
Emitted Transactions are _new_ transactions created by the execution of a Hook and entered into consensus for processing in the next ledger. The transaction may be of any Transaction Type but must follow strict emission rules.
|
||||
|
||||
To emit a transaction the Hook first prepares the serialized transaction then calls [emit](/docs/hooks/functions/emitted-transaction/emit-1).
|
||||
To emit a transaction the Hook first prepares the serialized transaction then calls [emit](/docs/hooks/functions/emitted-transaction/emit). With the [HooksUpdate2 amendment](/docs/features/amendments/#hooksupdate2), the [prepare()](/docs/hooks/functions/emitted-transaction/prepare) API can build the complete emission-ready transaction automatically from a partial input, removing the need to manually set `Account`, `Sequence`, `SigningPubKey`, `Fee`, `FirstLedgerSequence`, `LastLedgerSequence`, and `EmitDetails`.
|
||||
|
||||
Because emitted transactions can trigger Hooks in the next ledger which in turn may emit more transactions, all emitted transactions carry a `burden` and a `generation` field in their `EmitDetails` block. The `EmitDetails` block replaces the signature field in a traditional transaction.
|
||||
|
||||
The `burden` and `generation` fields collectively prevent [Fork bomb](https://en.wikipedia.org/wiki/Fork_bomb) attacks on the ledger by exponentially increasing the cost of exponentially expanding emtited transactions.
|
||||
|
||||
It is important to note that the Hooks API follows the strict rule of _no rewriting_. You _must_ present an emitted transaction in full, valid and canonically formed to xahaud for emission or it will be rejected. It is not xahaud's job to build your transaction for you. The Hook must do this itself.
|
||||
It is important to note that the Hooks API follows the strict rule of _no rewriting_. You _must_ present an emitted transaction in full, valid and canonically formed to xahaud for emission or it will be rejected. With the [HooksUpdate2 amendment](/docs/features/amendments/#hooksupdate2), the [prepare()](/docs/hooks/functions/emitted-transaction/prepare) API automates this: the Hook provides only the transaction-type-specific fields and the runtime injects all required emission boilerplate. Without HooksUpdate2, the Hook must construct the complete transaction itself.
|
||||
|
||||
### Callbacks
|
||||
|
||||
@@ -34,7 +34,7 @@ If an emitted transaction expires before it can be accepted into a ledger (for a
|
||||
|
||||
### Emission Rules
|
||||
|
||||
The [emit](/docs/hooks/functions/emitted-transaction/emit-1) Hook API will enforce the following rules on a proposed (to be emitted) transaction.
|
||||
The [emit](/docs/hooks/functions/emitted-transaction/emit) Hook API will enforce the following rules on a proposed (to be emitted) transaction.
|
||||
|
||||
| # | Emission Rule | Explanation |
|
||||
| - | ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|
||||
@@ -42,3 +42,27 @@ Examples (assuming a 256-bit unsigned integer type):
|
||||
### HookOn Calculator
|
||||
|
||||
<LinkCard title="HookOn Calculator" href="https://richardah.github.io/xrpl-hookon-calculator/" />
|
||||
|
||||
### HookCanEmit Field
|
||||
|
||||
_(Added by the [HookCanEmit amendment](/docs/features/amendments/#hookcanemit).)_
|
||||
|
||||
`HookCanEmit` uses the same 256-bit bitmask syntax as `HookOn` but controls which transaction types a Hook is allowed to **emit**, rather than which types trigger it.
|
||||
|
||||
- Uses the same active-low semantics as `HookOn`, with bit 22 (`ttHOOK_SET`) being active high.
|
||||
- If `HookCanEmit` is absent, the Hook may emit any transaction type, including `SetHook`.
|
||||
|
||||
### HookOnIncoming and HookOnOutgoing Fields
|
||||
|
||||
_(Added by the [HookOnV2 amendment](/docs/features/amendments/#hookonv2).)_
|
||||
|
||||
Instead of specifying a single `HookOn` field, Hooks may optionally replace it with two separate fields that differentiate the direction of the triggering transaction:
|
||||
|
||||
- **`HookOnIncoming`** — triggers the Hook on transactions **originating from another account** (the Hook account is not the initiator).
|
||||
- **`HookOnOutgoing`** — triggers the Hook on transactions **originating from the Hook account itself**.
|
||||
|
||||
Both fields use the same bit-field syntax as `HookOn`. `HookOnIncoming` and `HookOnOutgoing` are mutually exclusive with `HookOn` — you must use either `HookOn` alone or the `HookOnIncoming`/`HookOnOutgoing` pair, not both. If only one of the pair is specified, the Hook will not fire on the unspecified direction.
|
||||
|
||||
_Note: The `HookOnIncoming` and `HookOnOutgoing` fields cannot be configured with exactly the same settings. If you need a Hook to respond to both directions using identical criteria, use the `HookOn` field instead, as it provides a simpler and more appropriate way to define shared trigger behavior._
|
||||
|
||||
Using `HookOn` alone continues to work exactly as before.
|
||||
|
||||
105
src/content/docs/docs/hooks/concepts/named-hooks.mdx
Normal file
105
src/content/docs/docs/hooks/concepts/named-hooks.mdx
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
title: Named Hooks
|
||||
description: Selectively activate specific hooks on an account using a name-based execution gate.
|
||||
---
|
||||
|
||||
_(Added by the [NamedHooks amendment](/docs/features/amendments/#namedhooks).)_
|
||||
|
||||
### Overview
|
||||
|
||||
By default, every installed hook on an account executes on every transaction type it has been configured for via `HookOn`. Named Hooks allow an installed hook to declare an **execution gate**: the hook only runs if the triggering transaction carries a matching `HookName` value.
|
||||
|
||||
This enables multiple hooks to coexist on the same account, each serving a different use case, with callers selecting which hook to activate by including the appropriate `HookName` in their transaction.
|
||||
|
||||
### How It Works
|
||||
|
||||
**1. Name the hook at installation time**
|
||||
|
||||
Set the `HookName` field inside the `Hook` slot of a [SetHook transaction](/docs/protocol-reference/transactions/transaction-types/sethook):
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "SetHook",
|
||||
"Account": "rHookOwner...",
|
||||
"Hooks": [
|
||||
{
|
||||
"Hook": {
|
||||
"HookHash": "A5663784D04ED1B4408C6B97193464D27C9C3334AAF8BBB4FA5EB8E557FC4A2C",
|
||||
"HookOn": "0000000000000000",
|
||||
"HookNamespace": "...",
|
||||
"HookName": "6D795F68616E646C6572"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`HookName` is a hex-encoded UTF-8 string (e.g. `6D795F68616E646C6572` = `"my_handler"`). It is stored per-installation on the account's [Hook ledger object](/docs/protocol-reference/ledger-data/ledger-objects-types/hook) and is not shared with the [HookDefinition](/docs/protocol-reference/ledger-data/ledger-objects-types/hook-definition).
|
||||
|
||||
**2. Activate the hook by name in a transaction**
|
||||
|
||||
Any transaction type can include the top-level `HookName` field to target the named hook:
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "Payment",
|
||||
"Account": "rSender...",
|
||||
"Destination": "rHookOwner...",
|
||||
"Amount": "1000000",
|
||||
"HookName": "6D795F68616E646C6572"
|
||||
}
|
||||
```
|
||||
|
||||
When the ledger processes this transaction and reaches the hook chain on `rHookOwner`:
|
||||
|
||||
- Hooks **without** a `HookName` set → execute normally (unchanged behaviour).
|
||||
- Hooks **with** a `HookName` that matches the transaction's `HookName` → execute.
|
||||
- Hooks **with** a `HookName` that does **not** match → silently skipped (no error).
|
||||
|
||||
Transactions that carry **no** `HookName` field will skip all named hooks on the account.
|
||||
|
||||
### HookName Constraints
|
||||
|
||||
| Constraint | Value |
|
||||
| ---------- | ----- |
|
||||
| Minimum length | 4 bytes (8 hex chars in JSON) |
|
||||
| Maximum length | 16 bytes (32 hex chars in JSON) |
|
||||
| Encoding | Valid UTF-8 |
|
||||
| Remove name | Set to empty blob (`""`) in an update operation |
|
||||
|
||||
### Removing a Name
|
||||
|
||||
To remove a previously assigned name from a hook slot, submit an Update Operation with `HookName` set to an empty blob:
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "SetHook",
|
||||
"Account": "rHookOwner...",
|
||||
"Hooks": [
|
||||
{
|
||||
"Hook": {
|
||||
"HookName": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
After removal, the hook reverts to unconditional execution (governed only by its `HookOn` / `HookOnIncoming` / `HookOnOutgoing` settings).
|
||||
|
||||
### Fee Calculation
|
||||
|
||||
Hook fee calculation respects the same gating logic: named hooks that would be skipped by a transaction (name mismatch or absent) are **not** counted when computing the hook execution fee for that transaction.
|
||||
|
||||
### Error Cases
|
||||
|
||||
| Error Code | Condition |
|
||||
| -------------- | --------- |
|
||||
| `temDISABLED` | `HookName` is present in a Hook slot but the `NamedHooks` amendment is not enabled. |
|
||||
| `temMALFORMED` | `HookName` present as a top-level transaction field but `Hooks` or `NamedHooks` is not active; or the value fails UTF-8 / length validation. |
|
||||
|
||||
### Use Cases
|
||||
|
||||
- **Multi-purpose accounts**: install several specialised hooks (e.g. payment processor, governance handler, escrow manager), each gated by a different name.
|
||||
- **Selective invocation**: external contracts or users can selectively trigger only the hook relevant to their interaction without affecting others.
|
||||
- **Gradual migration**: deploy a new hook version under a different name and migrate callers incrementally without removing the old hook.
|
||||
@@ -2,6 +2,8 @@
|
||||
title: Serialized Objects
|
||||
description: Manipulate raw serialized xahaud objects!
|
||||
---
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
### What are Serialized Objects?
|
||||
|
||||
Xahau has canonical [serialized](/docs/protocol-reference/binary-format) forms of all objects subject to consensus. When writing a Hook it is inevitable you will come across serialized objects. These manifest as buffers containing what might appear to the developer as opaque binary blobs. In fact you can read these with the [XRPL-Binary-Visualiser](https://richardah.github.io/xrpl-binary-visualizer/).
|
||||
@@ -44,6 +46,34 @@ for (int i = 0; GUARD(3), i < 3; ++i)
|
||||
}
|
||||
```
|
||||
|
||||
### PathSet Support and Supported Serialized Types
|
||||
|
||||
<Aside type="caution" title="PathSet parsing bug (pre-HookAPISerializedType240)">
|
||||
Without the [HookAPISerializedType240 amendment](/docs/features/amendments/#hookapiserializedtype240), all `sto_` functions incorrectly parse `sfPaths` (STPathSet fields, used in Payment transactions with cross-currency routing). The internal parser misreads the PathSet boundary, corrupting the results for any field that appears after `sfPaths` in the serialized object. Hook developers processing Payment transactions with cross-currency paths must ensure this amendment is enabled.
|
||||
</Aside>
|
||||
|
||||
With the [HookAPISerializedType240 amendment](/docs/features/amendments/#hookapiserializedtype240), the following serialized types are correctly handled by all `sto_` functions:
|
||||
|
||||
| STI Type | Code | Examples |
|
||||
|---|---|---|
|
||||
| `STI_UINT16` | 1 | `sfTransactionType` |
|
||||
| `STI_UINT32` | 2 | `sfFlags`, `sfSequence`, `sfOfferSequence` |
|
||||
| `STI_UINT64` | 3 | `sfHookOn` |
|
||||
| `STI_HASH128` | 4 | `sfEmailHash` |
|
||||
| `STI_HASH256` | 5 | `sfLedgerHash`, `sfTransactionHash` |
|
||||
| `STI_AMOUNT` | 6 | `sfAmount`, `sfFee` |
|
||||
| `STI_VL` | 7 | `sfPublicKey`, blobs |
|
||||
| `STI_ACCOUNT` | 8 | `sfAccount`, `sfDestination` |
|
||||
| `STI_OBJECT` | 14 | `sfTransaction`, inner objects |
|
||||
| `STI_ARRAY` | 15 | `sfHooks`, `sfMemos`, `sfSigners` |
|
||||
| `STI_UINT8` | 16 | `sfCloseResolution` |
|
||||
| `STI_UINT160` | 17 | `sfTakerPaysCurrency` |
|
||||
| `STI_PATHSET` | 18 | `sfPaths` _(fixed by HookAPISerializedType240)_ |
|
||||
| `STI_VECTOR256` | 19 | `sfHookNamespaces` |
|
||||
| `STI_ISSUE` | 24 | _(added by HookAPISerializedType240)_ |
|
||||
| `STI_XCHAIN_BRIDGE` | 25 | _(added by HookAPISerializedType240)_ |
|
||||
| `STI_CURRENCY` | 26 | _(added by HookAPISerializedType240)_ |
|
||||
|
||||
### Overlap with slots
|
||||
|
||||
You may notice some overlap between slot APIs and STO APIs. The key difference here is who _owns_ the underlying data:
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
---
|
||||
title: emit
|
||||
description: Emit a new transaction from the hook
|
||||
---
|
||||
import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components';
|
||||
|
||||
### Concepts
|
||||
|
||||
<LinkButton href="/docs/hooks/concepts/emitted-transactions">Emitted Transactions</LinkButton>
|
||||
|
||||
### Behaviour
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
* Read a transaction from `read_ptr`
|
||||
* Validate the transaction against the emission rules
|
||||
* Emit the transaction into consensus when valid
|
||||
* Write canonical transaction hash to `write_ptr`
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
* This function emits the provided transaction JSON.
|
||||
* On success, it returns the number of emitted transaction hashes. 
|
||||
* If there is an error, it returns an error code.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Definition
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
```c
|
||||
int64_t emit (
|
||||
uint32_t write_ptr,
|
||||
uint32_t write_len,
|
||||
uint32_t read_ptr,
|
||||
uint32_t read_len
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
```javascript
|
||||
function emit(
|
||||
txJson: Record<string, any> | Transaction
|
||||
): ErrorCode | ByteArray
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
```c
|
||||
if (emit(tx, tx_len) < 0)
|
||||
rollback("Failed to emit!", 15, 1);
|
||||
```
|
||||
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
```javascript
|
||||
const emitResult = emit(txJson)
|
||||
if(typeof emitResult === 'number')
|
||||
rollback("Failed to emit!", 1)
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
|
||||
### Parameters
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
<table><thead><tr><th>Name</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td>write_ptr</td><td>uint32_t</td><td>Pointer to a buffer to write the transaction hash to</td></tr><tr><td>write_len</td><td>uint32_t</td><td>The size of the buffer to write the transaction hash to (should be 32.)</td></tr><tr><td>read_ptr</td><td>uint32_t</td><td>Pointer to the transaction to emit</td></tr><tr><td>read_len</td><td>uint32_t</td><td>The length of the transaction</td></tr></tbody></table>
|
||||
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
|
||||
|
||||
<table><thead><tr><th>Name</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td>txJson</td><td>Record<string, any> | Transaction</td><td>The TX JSON to emit.</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
|
||||
### Return Code
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
<table><thead><tr><th width="127">Type</th><th>Description</th></tr></thead><tbody><tr><td>int64_t</td><td>On success, the number of bytes of transaction hash written (32), or:<br /><br />If negative, an error:<br /><code>OUT_OF_BOUNDS</code><br />- pointers/lengths specified outside of hook memory.<br /><br /><code>PREREQUISITE_NOT_MET</code><br />- <code>emit_reserve</code> must be called first<br /><br /><code>TOO_MANY_EMITTED_TXN</code><br />- the number of emitted transactions is now greater than the promise made when <code>emit_reserve</code> was called earlier<br /><br /><code>EMISSION_FAILURE</code><br />- the transaction was malformed according to the emission rules.</td></tr></tbody></table>
|
||||
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
|
||||
|
||||
<table><thead><tr><th width="231">Type</th><th>Description</th></tr></thead><tbody><tr><td>ErrorCode | ByteArray</td><td>Returns an ErrorCode if there is an error, or an array of emitted transaction hashes on success.</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -1,30 +1,54 @@
|
||||
---
|
||||
title: prepare
|
||||
description: Prepares a JSON transaction for emission.
|
||||
title: emit
|
||||
description: Emit a new transaction from the hook
|
||||
---
|
||||
import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components';
|
||||
|
||||
### Concepts
|
||||
|
||||
<LinkButton href="/docs/protocol-reference/transactions/">Transactions</LinkButton>
|
||||
<LinkButton href="/docs/hooks/concepts/emitted-transactions">Emitted Transactions</LinkButton>
|
||||
<LinkButton href="/docs/hooks/functions/emitted-transaction/prepare">prepare()</LinkButton>
|
||||
|
||||
### Behaviour
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
* Read a transaction from `read_ptr`
|
||||
* Validate the transaction against the emission rules
|
||||
* Emit the transaction into consensus when valid
|
||||
* Write canonical transaction hash to `write_ptr`
|
||||
|
||||
With the [HooksUpdate2 amendment](/docs/features/amendments/#hooksupdate2), use [`prepare()`](/docs/hooks/functions/emitted-transaction/prepare) before `emit()` to automatically inject all required emission fields (`Account`, `Sequence`, `SigningPubKey`, `Fee`, `EmitDetails`, etc.) from a partial transaction.
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
* This function takes a transaction JSON object and prepares it for emission.
|
||||
* The transaction must be complete except for the Account field, which should always be the Hook account.
|
||||
* This function emits the provided transaction JSON.
|
||||
* On success, it returns the emitted transaction hashes. 
|
||||
* If there is an error, it returns an error code.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Definition
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
```c
|
||||
int64_t emit (
|
||||
uint32_t write_ptr,
|
||||
uint32_t write_len,
|
||||
uint32_t read_ptr,
|
||||
uint32_t read_len
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
```javascript
|
||||
function prepare(
|
||||
function emit(
|
||||
txJson: Record<string, any> | Transaction
|
||||
): ErrorCode | Record<string, any> | Transaction
|
||||
): ErrorCode | ByteArray
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@@ -34,13 +58,21 @@ function prepare(
|
||||
### Example
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
```c
|
||||
uint8_t emithash[32];
|
||||
if (emit(SBUF(emithash), SBUF(tx)) < 0)
|
||||
rollback(SBUF("hook: emit failed"), __LINE__);
|
||||
```
|
||||
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
```javascript
|
||||
const prepared_txn = prepare({
|
||||
TransactionType: "Payment",
|
||||
Destination: util_raddr(p1address_ns),
|
||||
Amount: parseFloat(drops_sent)*2
|
||||
})
|
||||
const emitResult = emit(txJson)
|
||||
if(typeof emitResult === 'number')
|
||||
rollback("Failed to emit!", 1)
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@@ -50,10 +82,16 @@ const prepared_txn = prepare({
|
||||
### Parameters
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
<table><thead><tr><th>Name</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td>write_ptr</td><td>uint32_t</td><td>Pointer to a buffer to write the transaction hash to</td></tr><tr><td>write_len</td><td>uint32_t</td><td>The size of the buffer to write the transaction hash to (should be 32.)</td></tr><tr><td>read_ptr</td><td>uint32_t</td><td>Pointer to the transaction to emit</td></tr><tr><td>read_len</td><td>uint32_t</td><td>The length of the transaction</td></tr></tbody></table>
|
||||
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
|
||||
|
||||
<table><thead><tr><th>Name</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td>txJson</td><td>Record<string, any> | Transaction</td><td>The transaction JSON, must be a complete transaction except for Account (always the Hook account).</td></tr></tbody></table>
|
||||
<table><thead><tr><th>Name</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td>txJson</td><td>Record<string, any> | Transaction</td><td>The TX JSON to emit.</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -62,10 +100,16 @@ const prepared_txn = prepare({
|
||||
### Return Code
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
<table><thead><tr><th width="127">Type</th><th>Description</th></tr></thead><tbody><tr><td>int64_t</td><td>On success, the number of bytes of transaction hash written (32), or:<br /><br />If negative, an error:<br /><code>OUT_OF_BOUNDS</code><br />- pointers/lengths specified outside of hook memory.<br /><br /><code>PREREQUISITE_NOT_MET</code><br />- <code>etxn_reserve</code> must be called first<br /><br /><code>TOO_MANY_EMITTED_TXN</code><br />- the number of emitted transactions is now greater than the promise made when <code>etxn_reserve</code> was called earlier<br /><br /><code>EMISSION_FAILURE</code><br />- the transaction was malformed according to the emission rules.</td></tr></tbody></table>
|
||||
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
|
||||
|
||||
<table><thead><tr><th width="231">Type</th><th>Description</th></tr></thead><tbody><tr><td>ErrorCode | Record<string, any> | Transaction</td><td>Returns an ErrorCode if there is an error, or the prepared transaction JSON or Transaction object.</td></tr></tbody></table>
|
||||
<table><thead><tr><th width="231">Type</th><th>Description</th></tr></thead><tbody><tr><td>ErrorCode | ByteArray</td><td>Returns an ErrorCode if there is an error, or an array of emitted transaction hashes on success.</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
---
|
||||
title: prepare
|
||||
description: Prepares a transaction for emission by automatically injecting all required emission fields.
|
||||
---
|
||||
import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components';
|
||||
|
||||
### Concepts
|
||||
|
||||
<LinkButton href="/docs/hooks/concepts/emitted-transactions">Emitted Transactions</LinkButton>
|
||||
|
||||
### Behaviour
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
|
||||
_(Requires the [HooksUpdate2 amendment](/docs/features/amendments/#hooksupdate2).)_
|
||||
|
||||
* Reads a partial serialized transaction from `read_ptr`/`read_len`. The input must contain at minimum the `TransactionType` and all fields required by that transaction type, but included emission-specific fields will be **overwritten**.
|
||||
* Automatically injects all fields required for emission: `Account` (the Hook account), `Sequence` (0), `SigningPubKey` (all zeros), `Fee` (computed), `FirstLedgerSequence` (current ledger + 1), `LastLedgerSequence` (current ledger + 5), and `EmitDetails`.
|
||||
* Writes the complete, emission-ready transaction blob to `write_ptr`.
|
||||
* The output can be passed directly to [`emit()`](/docs/hooks/functions/emitted-transaction/emit).
|
||||
* `etxn_reserve()` must be called before `prepare()`.
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
* This function takes a transaction JSON object and prepares it for emission.
|
||||
* The transaction must be complete except for the Account, Sequence, SigningPubKey, Fee, FirstLedgerSequence, LastLedgerSequence, and EmitDetails fields.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Definition
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
```c
|
||||
int64_t prepare (
|
||||
uint32_t write_ptr,
|
||||
uint32_t write_len,
|
||||
uint32_t read_ptr,
|
||||
uint32_t read_len
|
||||
);
|
||||
```
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
```javascript
|
||||
function prepare(
|
||||
txJson: Record<string, any> | Transaction
|
||||
): ErrorCode | Record<string, any> | Transaction
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Example
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
```c
|
||||
etxn_reserve(1);
|
||||
|
||||
// Build a minimal payment transaction (TransactionType + required fields only)
|
||||
uint8_t tx[256];
|
||||
// ... populate tx with TransactionType, Destination, Amount ...
|
||||
int64_t tx_len = /* size of tx */;
|
||||
|
||||
// prepare() fills in Account, Sequence, Fee, EmitDetails, etc.
|
||||
uint8_t prepared[512];
|
||||
int64_t prepared_len = prepare(prepared, sizeof(prepared), tx, tx_len);
|
||||
if (prepared_len < 0)
|
||||
rollback("Prepare failed", 14, prepared_len);
|
||||
|
||||
// emit() submits the fully-formed transaction
|
||||
uint8_t txid[32];
|
||||
if (emit(txid, 32, prepared, prepared_len) != 32)
|
||||
rollback("Emit failed", 11, EMISSION_FAILURE);
|
||||
```
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
```javascript
|
||||
const prepared_txn = prepare({
|
||||
TransactionType: "Payment",
|
||||
Destination: util_raddr(p1address_ns),
|
||||
Amount: parseFloat(drops_sent)*2
|
||||
})
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Parameters
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---------- | --------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `write_ptr` | uint32_t | Pointer to a buffer to receive the complete prepared transaction blob. |
|
||||
| `write_len` | uint32_t | Length of the write buffer. Must be large enough to hold the prepared transaction (input size + injected fields). |
|
||||
| `read_ptr` | uint32_t | Pointer to a partial serialized transaction. Must include `TransactionType` and all type-specific required fields. |
|
||||
| `read_len` | uint32_t | Length of the input transaction. |
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
|
||||
<table><thead><tr><th>Name</th><th width="124">Type</th><th>Description</th></tr></thead><tbody><tr><td>txJson</td><td>Record<string, any> | Transaction</td><td>The transaction JSON, must be a complete transaction except for Account (always the Hook account).</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Return Code
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
|
||||
| Type | Description |
|
||||
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| int64_t | On success, the number of bytes written to `write_ptr` (the size of the prepared transaction blob). The returned value is the length of the prepared transaction. Pass the original buffer as `read_ptr` and the returned length as `read_len` when calling `emit()`.<br /><br />If negative, an error:<br />`OUT_OF_BOUNDS` — pointers/lengths fall outside hook memory.<br />`PREREQUISITE_NOT_MET` — `etxn_reserve()` must be called before `prepare()`.<br />`INVALID_ARGUMENT` — the input blob is not a valid serialized transaction, or the transaction cannot be prepared (e.g. fee computation failed).<br />`INTERNAL_ERROR` — failed to generate `EmitDetails` or re-serialize the transaction. |
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
|
||||
<table><thead><tr><th width="231">Type</th><th>Description</th></tr></thead><tbody><tr><td>ErrorCode | Record<string, any> | Transaction</td><td>Returns an ErrorCode if there is an error, or the prepared transaction JSON or Transaction object.</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@@ -13,11 +13,12 @@ A `HookDefinition` object describes a hook, which is a piece of code that is exe
|
||||
{
|
||||
"HookHash": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0",
|
||||
"HookOn": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"HookCanEmit": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"HookNamespace": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"HookParameters": {
|
||||
"HookParameter": {
|
||||
"HookParameterName": "DEADBEEF",
|
||||
"HookParameterValue": "DEADBEEF",
|
||||
"HookParameterValue": "DEADBEEF"
|
||||
}
|
||||
},
|
||||
"HookApiVersion": 1,
|
||||
@@ -37,10 +38,12 @@ A `HookDefinition` object has the following fields:
|
||||
|
||||
| Field | JSON Type | \[Internal Type]\[] | Required? | Description |
|
||||
| ----------------- | --------- | ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `HookHash` | String | Hash256 | Yes | The unique identifier of the hook. |
|
||||
| `HookOn` | String | Hash256 | Yes | The transaction/s on which the hook is triggered. |
|
||||
| `HookCanEmit` | String | Hash256 | No | The transaction/s which the hook can emit. |
|
||||
| `HookNamespace` | String | Hash256 | Yes | The namespace of the hook. |
|
||||
| `HookHash` | String | Hash256 | Yes | The unique identifier of the hook. |
|
||||
| `HookOn` | String | Hash256 | No | The transaction/s on which the hook is triggered. Mutually exclusive with `HookOnIncoming`/`HookOnOutgoing`. |
|
||||
| `HookOnIncoming` | String | Hash256 | No | _(HookOnV2)_ Same syntax as `HookOn`. Triggers the hook on transactions originating from another account. Mutually exclusive with `HookOn`. |
|
||||
| `HookOnOutgoing` | String | Hash256 | No | _(HookOnV2)_ Same syntax as `HookOn`. Triggers the hook on transactions originating from the Hook account itself. Mutually exclusive with `HookOn`. |
|
||||
| `HookCanEmit` | String | Hash256 | No | Same syntax as `HookOn`. Controls which transaction types the hook is allowed to emit. If absent, the hook may emit any transaction type. |
|
||||
| `HookNamespace` | String | Hash256 | Yes | The namespace of the hook. |
|
||||
| `HookParameters` | String | Vector | Yes | The parameters that the hook accepts. |
|
||||
| `HookApiVersion` | Number | UInt16 | Yes | The version of the hook API that the hook uses. |
|
||||
| `CreateCode` | String | VL | Yes | The code that is executed when the hook is created. |
|
||||
|
||||
@@ -36,7 +36,7 @@ A `Hook` object has the following fields:
|
||||
| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the owner's directory links to this object, in case the directory consists of multiple pages. |
|
||||
| `PreviousTxnID` | String | Hash256 | Yes | The ID of the transaction that most recently modified this object. |
|
||||
| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[ledger index]\[] of the ledger that contains the transaction that most recently modified this object. |
|
||||
| `Hooks` | Array | Array | Yes | An array of hook objects. Each object has the following fields: `HookHash`, `CreateCode`, `HookGrants`, `HookNamespace`, `HookParameters`, `HookOn`, `HookApiVersion`, `Flags`. |
|
||||
| `Hooks` | Array | Array | Yes | An array of hook objects. Each object has the following fields: `HookHash`, `CreateCode`, `HookGrants`, `HookNamespace`, `HookParameters`, `HookOn`, `HookOnIncoming`, `HookOnOutgoing`, `HookCanEmit`, `HookName`, `HookApiVersion`, `Flags`. |
|
||||
| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0043`, mapped to the string `Hook`, indicates that this object is a Hook object. |
|
||||
|
||||
### Hook Fields
|
||||
@@ -45,9 +45,18 @@ The following fields are used in the hook object:
|
||||
|
||||
| Field | JSON Type | Internal Type | Description |
|
||||
| ---------------- | --------- | ------------- | ------------------------------ |
|
||||
| `HookHash` | String | Hash256 | The hash of the hook. |
|
||||
| `HookParameters` | Array | Array | The parameters of the hook. |
|
||||
| `Flags` | Number | UInt32 | Additional flags for the hook. |
|
||||
| `HookHash` | String | Hash256 | The hash of the hook. |
|
||||
| `CreateCode` | String | Blob | The hex-encoded WebAssembly binary (WASM) that defines the hook's logic. Present when the hook was installed with inline code rather than referencing an existing `HookDefinition` object. |
|
||||
| `HookGrants` | Array | Array | An array of grant objects specifying which accounts are permitted to set or modify this hook on the hook account's behalf. |
|
||||
| `HookNamespace` | String | Hash256 | A 32-byte (64 hex character) namespace that segregates this hook's state data from other hooks on the same account. Must be unique per hook slot. |
|
||||
| `HookParameters` | Array | Array | The parameters of the hook. |
|
||||
| `HookApiVersion` | Number | UInt16 | The version of the Hooks API used by this hook. Determines which hook API functions are available to the WASM binary at runtime. |
|
||||
| `HookOn` | String | Hash256 | The transaction type(s) on which the hook is triggered. Mutually exclusive with `HookOnIncoming`/`HookOnOutgoing`. |
|
||||
| `HookOnIncoming` | String | Hash256 | _(HookOnV2)_ Same syntax as `HookOn`. Triggers the hook on transactions originating from another account. Mutually exclusive with `HookOn`. |
|
||||
| `HookOnOutgoing` | String | Hash256 | _(HookOnV2)_ Same syntax as `HookOn`. Triggers the hook on transactions originating from the Hook account itself. Mutually exclusive with `HookOn`. |
|
||||
| `HookCanEmit` | String | Hash256 | Same syntax as `HookOn`. Controls which transaction types the hook is allowed to emit. If absent, the hook may emit any transaction type. |
|
||||
| `HookName` | String | Blob | _(NamedHooks)_ UTF-8 string (4–16 bytes, hex-encoded) assigned to this hook slot. When present, the hook only executes if the triggering transaction carries a matching top-level `HookName` field. |
|
||||
| `Flags` | Number | UInt32 | Additional flags for the hook. |
|
||||
|
||||
#### Hook ID Format
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Oracle
|
||||
---
|
||||
\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/xrpld/app/tx/detail/SetOracle.cpp)]
|
||||
|
||||
_(Added by the [PriceOracle amendment](/docs/features/amendments/#priceoracle).)_
|
||||
|
||||
An `Oracle` ledger object represents a Price Oracle created by an account on the Xahau ledger. It stores one or more asset price data points and is identified by the owner account together with a document ID. Oracle objects are created and updated via [OracleSet transactions](/docs/protocol-reference/transactions/transaction-types/oracleset) and deleted via [OracleDelete transactions](/docs/protocol-reference/transactions/transaction-types/oracledelete).
|
||||
|
||||
### Example JSON
|
||||
|
||||
```json
|
||||
{
|
||||
"LedgerEntryType": "Oracle",
|
||||
"Owner": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"OracleDocumentID": 1,
|
||||
"Provider": "70726F7669646572",
|
||||
"AssetClass": "63757272656E6379",
|
||||
"LastUpdateTime": 816348759,
|
||||
"PriceDataSeries": [
|
||||
{
|
||||
"PriceData": {
|
||||
"BaseAsset": "XAH",
|
||||
"QuoteAsset": "USD",
|
||||
"AssetPrice": 74560,
|
||||
"Scale": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"PriceData": {
|
||||
"BaseAsset": "BTC",
|
||||
"QuoteAsset": "USD",
|
||||
"AssetPrice": 6800000,
|
||||
"Scale": 2
|
||||
}
|
||||
}
|
||||
],
|
||||
"URI": "697066733A2F2F",
|
||||
"OwnerNode": "0000000000000000",
|
||||
"PreviousTxnID": "5463C6E08862A1FAE5EDAC12D70ADB16546A1F674930521295BC082494B62924",
|
||||
"PreviousTxnLgrSeq": 6,
|
||||
"index": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0"
|
||||
}
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
An `Oracle` object has the following fields:
|
||||
|
||||
| Field | JSON Type | \[Internal Type]\[] | Required? | Description |
|
||||
| ------------------- | --------- | ------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `Owner` | String | AccountID | Yes | The account that created and owns this Oracle. Only this account can update or delete it. |
|
||||
| `OracleDocumentID` | Number | UInt32 | Yes | The unique identifier for this Oracle within the owner account. |
|
||||
| `Provider` | String | Blob | Yes | Hex-encoded identifier of the data provider (e.g. the oracle service name). Max 256 bytes. |
|
||||
| `AssetClass` | String | Blob | Yes | Hex-encoded string describing the category of assets (e.g. `63757272656E6379` = "currency"). Max 16 bytes. |
|
||||
| `LastUpdateTime` | Number | UInt32 | Yes | Ripple Epoch timestamp (seconds since January 1, 2000) of the last price update. |
|
||||
| `PriceDataSeries` | Array | Array | Yes | Array of `PriceData` objects (1–10 entries). Entries are stored in canonical sorted order by `BaseAsset`/`QuoteAsset` pair. |
|
||||
| `URI` | String | Blob | No | Hex-encoded URI pointing to supplementary off-chain data (e.g. an IPFS CID). Max 256 bytes. |
|
||||
| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the owner's directory links to this object. |
|
||||
| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. |
|
||||
| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The ledger index of the ledger that contains the transaction that most recently modified this object. |
|
||||
| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0080`, mapped to the string `Oracle`, indicates this is an Oracle object. |
|
||||
|
||||
### PriceData Object
|
||||
|
||||
Each entry in `PriceDataSeries` contains a `PriceData` object:
|
||||
|
||||
| Field | JSON Type | \[Internal Type]\[] | Required? | Description |
|
||||
| ------------ | --------- | ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `BaseAsset` | String | Currency | Yes | The asset being priced (e.g. `"XAH"`, `"BTC"`). |
|
||||
| `QuoteAsset` | String | Currency | Yes | The denomination currency (e.g. `"USD"`, `"EUR"`). |
|
||||
| `AssetPrice` | Number | UInt64 | No | The price as a scaled integer. The effective price is `AssetPrice × 10^(-Scale)`. |
|
||||
| `Scale` | Number | UInt8 | No | Decimal exponent (0–10) used to derive the effective price. Example: `AssetPrice = 74560`, `Scale = 4` → effective price = 7.456. |
|
||||
|
||||
### Reserve
|
||||
|
||||
An Oracle object consumes owner reserves based on the number of `PriceData` pairs stored:
|
||||
|
||||
| Pairs | Owner reserves consumed |
|
||||
| ----- | ----------------------- |
|
||||
| 1–5 | 1 |
|
||||
| 6–10 | 2 |
|
||||
|
||||
### Oracle ID Format
|
||||
|
||||
The ID of an `Oracle` object is the \[SHA-512Half]\[] of the following values, concatenated in order:
|
||||
|
||||
* The Oracle space key (`0x0152`)
|
||||
* The AccountID of the `Owner`
|
||||
* The `OracleDocumentID` as a 32-bit unsigned integer
|
||||
@@ -41,7 +41,17 @@ The "issuer" for the balance in a trust line depends on whether the balance is p
|
||||
"currency": "USD",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"value": "10"
|
||||
}
|
||||
},
|
||||
"LowReward": {
|
||||
"RewardLgrFirst": 1000000,
|
||||
"RewardLgrLast": 1001234,
|
||||
"RewardTime": 744000000,
|
||||
"TrustLineRewardAccumulator": {
|
||||
"currency": "USD",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"value": "500"
|
||||
}
|
||||
},
|
||||
"index": "9CA88CDEDFF9252B3DE183CE35B038F57282BC9503CDFA1923EF9A95DF0D6F7B"
|
||||
}
|
||||
```
|
||||
@@ -65,8 +75,23 @@ A `RippleState` object has the following fields:
|
||||
| `LowQualityOut` | Number | UInt32 | No | The outbound quality set by the low account, as an integer in the implied ratio `LowQualityOut`:1,000,000,000. As a special case, the value 0 is equivalent to 1 billion, or face value. |
|
||||
| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. |
|
||||
| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[index of the ledger]\[Ledger Index] that contains the transaction that most recently modified this object. |
|
||||
| `LockCount` | Number | UInt32 | No | The total number of lock balances on a RippleState ledger object |
|
||||
| `LockedBalance` | Object | Amount | No | The current amount of locked tokens for a specific trustline |
|
||||
| `LockCount` | Number | UInt32 | No | The total number of lock balances on a RippleState ledger object. |
|
||||
| `LockedBalance` | Object | Amount | No | The current amount of locked tokens for a specific trustline. |
|
||||
| `LowReward` | Object | STObject | No | _(IOURewardClaim)_ IOU reward-tracking counters for the low account. Present only after the low account opts in via `ClaimReward` with `ClaimCurrency`. Contains `RewardLgrFirst`, `RewardLgrLast`, `RewardTime`, and `TrustLineRewardAccumulator`. |
|
||||
| `HighReward` | Object | STObject | No | _(IOURewardClaim)_ IOU reward-tracking counters for the high account. Present only after the high account opts in via `ClaimReward` with `ClaimCurrency`. Contains `RewardLgrFirst`, `RewardLgrLast`, `RewardTime`, and `TrustLineRewardAccumulator`. |
|
||||
|
||||
### LowReward / HighReward Fields
|
||||
|
||||
_(Added by the [IOURewardClaim amendment](/docs/features/amendments/#iourewardclaim).)_
|
||||
|
||||
Both `LowReward` and `HighReward` are inner objects with the same structure. `LowReward` is present if the low account has opted in to IOU rewards for this trustline, and `HighReward` is present if the high account has opted in. Both can be present if both accounts have opted in. The canonical high/low ordering only determines which side an account maps to.
|
||||
|
||||
| Field | JSON Type | Internal Type | Description |
|
||||
| ---------------------------- | --------- | ------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| `RewardLgrFirst` | Number | UInt32 | The ledger sequence when the account first opted in to IOU rewards for this trustline. It gets updated every time `ClaimReward` is executed. The field will be deleted if the account opts out |
|
||||
| `RewardLgrLast` | Number | UInt32 | The ledger sequence of the last time the reward accumulator was updated. |
|
||||
| `RewardTime` | Number | UInt32 | The ledger close time (Ripple epoch seconds) when the counters were last reset by a `ClaimReward` transaction. |
|
||||
| `TrustLineRewardAccumulator` | Object | Amount | The running total of `balance × ledgers elapsed` since the last `ClaimReward`. Expressed in the trustline's currency. This is the value the issuer's Hook reads to calculate the reward payout. |
|
||||
|
||||
### RippleState Flags
|
||||
|
||||
|
||||
@@ -3,13 +3,15 @@ title: ClaimReward
|
||||
description: >-
|
||||
A ClaimReward transaction allows an account to claim the rewards it has
|
||||
accumulated. The rewards can be claimed by the account owner or by a specified
|
||||
issuer. The account can also opt-out of rewards.
|
||||
issuer. The account can also opt-out of rewards. With the IOURewardClaim
|
||||
amendment, this transaction also supports claiming rewards for IOU currencies
|
||||
with a reward Hook installed.
|
||||
---
|
||||
\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/ClaimReward.cpp)]
|
||||
|
||||
_(Added by the \[BalanceRewards amendment]\[].)_
|
||||
|
||||
### Opt-in + Claim
|
||||
### Opt-in + Claim (XAH genesis rewards)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -19,7 +21,7 @@ _(Added by the \[BalanceRewards amendment]\[].)_
|
||||
}
|
||||
```
|
||||
|
||||
### Opt-out
|
||||
### Opt-out (XAH genesis rewards)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -29,34 +31,68 @@ _(Added by the \[BalanceRewards amendment]\[].)_
|
||||
}
|
||||
```
|
||||
|
||||
### IOU Reward Claim
|
||||
|
||||
_(Requires the \[IOURewardClaim amendment]\[].)_
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "ClaimReward",
|
||||
"Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm",
|
||||
"Issuer": "rIssuerAccountXXXXXXXXXXXXXXXXXXX",
|
||||
"ClaimCurrency": {
|
||||
"currency": "USD",
|
||||
"issuer": "rIssuerAccountXXXXXXXXXXXXXXXXXXX"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | JSON Type | \[Internal Type]\[] | Description |
|
||||
| --------- | --------- | ------------------- | ------------------------------------------------------- |
|
||||
| `Account` | String | AccountID | The address of the account that is claiming the reward. |
|
||||
| `Flags` | Number | UInt32 | _(Optional)_ Can have flag 1 set to opt-out of rewards. |
|
||||
| `Issuer` | String | AccountID | _(Optional)_ The genesis account. |
|
||||
| Field | JSON Type | \[Internal Type]\[] | Description |
|
||||
| --------------- | --------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `Account` | String | AccountID | The address of the account that is claiming the reward. |
|
||||
| `Flags` | Number | UInt32 | _(Optional)_ Can have flag 1 set to opt-out of rewards. |
|
||||
| `Issuer` | String | AccountID | _(Optional)_ The genesis account (XAH rewards) or an IOU account (IOU rewards). |
|
||||
| `ClaimCurrency` | Object | Issue | _(Optional, IOURewardClaim)_ The IOU currency to claim rewards for, as `{"currency": "...", "issuer": "..."}`. Cannot be XAH. The issuer must not be the genesis account and must not equal `Account`. Requires a trustline to exist between `Account` and the issuer. |
|
||||
|
||||
### ClaimReward Flags
|
||||
|
||||
Transactions of the ClaimReward type support additional values in the `Flags` field, as follows:
|
||||
|
||||
| Flag Name | Hex Value | Decimal Value | Description |
|
||||
| ---------- | ------------ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `tfOptOut` | `0x00000001` | 1 | The `isOptOut` flag in the ClaimReward code is used to opt-out an account from rewards by removing reward-related fields from the account object in the ledger if the `sfFlags` field in the transaction is set to 1. |
|
||||
| Flag Name | Hex Value | Decimal Value | Description |
|
||||
| ---------- | ------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `tfOptOut` | `0x00000001` | 1 | Opts the account out of rewards by removing reward-related fields from the account's ledger object. |
|
||||
|
||||
### Special Transaction Cost
|
||||
|
||||
The ClaimReward transaction has a standard transaction cost, which is the minimum transaction cost required for all transactions.
|
||||
|
||||
### IOU Reward Behaviour
|
||||
|
||||
_(Requires the \[IOURewardClaim amendment]\[].)_
|
||||
|
||||
When `ClaimCurrency` is specified, the transaction follows the IOU reward path:
|
||||
|
||||
1. The `Issuer` account must have a Hook installed that fires on a `ClaimReward` transaction. The Hook is responsible for calculating and distributing the reward payout.
|
||||
2. On first claim, a `LowReward` or `HighReward` reward-tracking object is initialised on the trustline ([RippleState](/docs/protocol-reference/ledger-data/ledger-objects-types/ripple-state) ledger object) between `Account` and the issuer. Which side is used depends on the canonical high/low ordering of the two accounts.
|
||||
3. After every subsequent transaction that changes the trustline balance, the ledger automatically updates `TrustLineRewardAccumulator` inside the tracking object using the same area-under-the-curve formula as genesis XAH rewards.
|
||||
4. When a `ClaimReward` with `ClaimCurrency` is submitted, the ledger resets the reward counters on the trustline and fires the issuer's Hook, which reads the accumulated value and emits a reward payment.
|
||||
|
||||
The IOU reward counters are entirely independent of the genesis XAH reward fields on the AccountRoot object.
|
||||
|
||||
### Error Cases
|
||||
|
||||
Besides errors that can occur for all transactions, ClaimReward transactions can result in the following transaction result codes:
|
||||
|
||||
| Error Code | Description |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| `temDISABLED` | Occurs if the feature is not enabled. |
|
||||
| `temINVALID_FLAG` | Occurs if the flag is set to a value other than 1. |
|
||||
| `temMALFORMED` | Occurs if the issuer is the same as the source account or if the flag and issuer are not correctly set. |
|
||||
| `tecNO_ISSUER` | Occurs if the issuer does not exist. |
|
||||
| `terNO_ACCOUNT` | Occurs if the sending account does not exist. |
|
||||
| Error Code | Description |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `temDISABLED` | Occurs if the required amendment (`BalanceRewards` or `IOURewardClaim`) is not enabled. |
|
||||
| `temINVALID_FLAG` | Occurs if the flag is set to a value other than 1. _(Requires the \[fixRewardClaimFlags amendment]\[].)_ |
|
||||
| `temMALFORMED` | Occurs if `ClaimCurrency` is a non-currency or XAH type, if the issuer equals `Account`, or if the transaction fields are otherwise incorrectly set. |
|
||||
| `temBAD_ISSUER` | Occurs if `ClaimCurrency` is set but the issuer is the genesis account, or if `Issuer` is the genesis account but `ClaimCurrency` is also set. |
|
||||
| `terNO_ACCOUNT` | Occurs if the sending account does not exist. |
|
||||
| `tecNO_ISSUER` | Occurs if the `Issuer` account does not exist. |
|
||||
| `tecNO_PERMISSION` | Occurs if the issuer account is an AMM account. AMM accounts cannot have reward Hooks. |
|
||||
| `tecNO_TARGET` | Occurs if the issuer account has no Hooks, or none of its Hooks fires on a `ClaimReward` transaction. |
|
||||
| `tecNO_LINE` | Occurs if no trustline exists between `Account` and the issuer for the specified `ClaimCurrency`. |
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: OracleDelete
|
||||
description: >-
|
||||
An OracleDelete transaction removes an existing Price Oracle object from the
|
||||
ledger, releasing the owner reserves held by it.
|
||||
---
|
||||
\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/xrpld/app/tx/detail/DeleteOracle.cpp)]
|
||||
|
||||
_(Added by the [PriceOracle amendment](/docs/features/amendments/#priceoracle).)_
|
||||
|
||||
### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "OracleDelete",
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"OracleDocumentID": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | JSON Type | \[Internal Type]\[] | Description |
|
||||
| ------------------ | --------- | ------------------- | -------------------------------------------------------------------------------------------- |
|
||||
| `Account` | String | AccountID | The address of the account that owns the Oracle. Only the owner can delete the object. |
|
||||
| `OracleDocumentID` | Number | UInt32 | The document ID of the Oracle object to delete. |
|
||||
|
||||
### Special Transaction Cost
|
||||
|
||||
OracleDelete transactions have the standard transaction cost.
|
||||
|
||||
### Error Cases
|
||||
|
||||
| Error Code | Description |
|
||||
| --------------- | -------------------------------------------------------------------- |
|
||||
| `temDISABLED` | The PriceOracle amendment is not enabled. |
|
||||
| `temINVALID_FLAG` | Invalid flags specified. |
|
||||
| `terNO_ACCOUNT` | The sending account does not exist. |
|
||||
| `tecNO_ENTRY` | No Oracle object exists for the given account and `OracleDocumentID`. |
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
title: OracleSet
|
||||
description: >-
|
||||
An OracleSet transaction creates or updates a Price Oracle object on the
|
||||
ledger, publishing one or more asset price data points for a given account.
|
||||
---
|
||||
\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/xrpld/app/tx/detail/SetOracle.cpp)]
|
||||
|
||||
_(Added by the [PriceOracle amendment](/docs/features/amendments/#priceoracle).)_
|
||||
|
||||
### Create
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "OracleSet",
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"OracleDocumentID": 1,
|
||||
"Provider": "70726F7669646572",
|
||||
"AssetClass": "63757272656E6379",
|
||||
"LastUpdateTime": 1763033559,
|
||||
"PriceDataSeries": [
|
||||
{
|
||||
"PriceData": {
|
||||
"BaseAsset": "XAH",
|
||||
"QuoteAsset": "USD",
|
||||
"AssetPrice": 74560,
|
||||
"Scale": 4
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Update
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "OracleSet",
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"OracleDocumentID": 1,
|
||||
"LastUpdateTime": 1763033700,
|
||||
"PriceDataSeries": [
|
||||
{
|
||||
"PriceData": {
|
||||
"BaseAsset": "XAH",
|
||||
"QuoteAsset": "USD",
|
||||
"AssetPrice": 74800,
|
||||
"Scale": 4
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Fields
|
||||
|
||||
| Field | JSON Type | \[Internal Type]\[] | Description |
|
||||
| ------------------ | --------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `Account` | String | AccountID | The address of the account creating or updating the Oracle. Only this account can later update or delete the object. |
|
||||
| `OracleDocumentID` | Number | UInt32 | A unique identifier for this Oracle within the owner account. Multiple Oracles can exist per account using different IDs. |
|
||||
| `Provider` | String | Blob | _(Optional on update; required on create)_ Hex-encoded identifier of the Oracle provider (e.g. Chainlink, Band). Max 256 bytes. |
|
||||
| `URI` | String | Blob | _(Optional)_ Hex-encoded URI referencing supplementary off-chain data for this Oracle (e.g. IPFS CID). Max 256 bytes. |
|
||||
| `AssetClass` | String | Blob | _(Optional on update; required on create)_ Hex-encoded category describing the type of assets (e.g. `63757272656E6379` = "currency"). Max 16 bytes. |
|
||||
| `LastUpdateTime` | Number | UInt32 | Unix timestamp (seconds since January 1, 1970) of the last price update. Must be within ±300 seconds of the ledger close time and must be strictly greater than the current stored value on updates. |
|
||||
| `PriceDataSeries` | Array | Array | Array of `PriceData` objects. Must contain between 1 and 10 entries. On update, pairs without `AssetPrice` are deleted from the object. |
|
||||
|
||||
### PriceData Object
|
||||
|
||||
Each entry in `PriceDataSeries` is a `PriceData` object:
|
||||
|
||||
| Field | JSON Type | \[Internal Type]\[] | Description |
|
||||
| ------------ | --------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `BaseAsset` | String | Currency | The asset being priced (e.g. `"XAH"`, `"BTC"`). |
|
||||
| `QuoteAsset` | String | Currency | The denomination currency (e.g. `"USD"`, `"EUR"`). Must differ from `BaseAsset`. |
|
||||
| `AssetPrice` | Number | UInt64 | _(Optional)_ The price as a scaled integer. The effective price is `AssetPrice × 10^(-Scale)`. Omit this field to **delete** an existing pair during an update. |
|
||||
| `Scale` | Number | UInt8 | _(Optional)_ Decimal exponent used to derive the effective price. Valid values: 0–10. Default: 0. Example: `AssetPrice = 74560`, `Scale = 4` → effective price = 7.456. |
|
||||
|
||||
### Reserve
|
||||
|
||||
OracleSet transactions consume owner reserves depending on the number of `PriceData` pairs stored:
|
||||
|
||||
| Pairs | Owner reserves consumed |
|
||||
| ----- | ----------------------- |
|
||||
| 1–5 | 1 |
|
||||
| 6–10 | 2 |
|
||||
|
||||
If an update changes the number of pairs across the 5-pair threshold, the owner count is adjusted automatically (±1).
|
||||
|
||||
### Special Transaction Cost
|
||||
|
||||
OracleSet transactions have the standard transaction cost.
|
||||
|
||||
### Error Cases
|
||||
|
||||
| Error Code | Description |
|
||||
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `temDISABLED` | The PriceOracle amendment is not enabled. |
|
||||
| `temINVALID_FLAG` | Invalid flags specified. |
|
||||
| `temMALFORMED` | `Provider`, `URI`, or `AssetClass` is empty or exceeds max length; duplicate base/quote pairs in the same transaction; `BaseAsset` equals `QuoteAsset`; `Scale` > 10; `Provider` or `AssetClass` do not match stored values on update; `Provider` or `AssetClass` missing on create. |
|
||||
| `temARRAY_EMPTY` | `PriceDataSeries` is empty. |
|
||||
| `temARRAY_TOO_LARGE` | `PriceDataSeries` contains more than 10 entries in the transaction. |
|
||||
| `terNO_ACCOUNT` | The sending account does not exist. |
|
||||
| `tecINVALID_UPDATE_TIME` | `LastUpdateTime` is outside the ±300 second window from ledger close time, predates the UNIX timestamp (seconds since January 1, 1970), or is not strictly greater than the stored value on an update. |
|
||||
| `tecTOKEN_PAIR_NOT_FOUND` | A pair specified for deletion (no `AssetPrice`) does not exist in the current Oracle object. |
|
||||
| `tecARRAY_EMPTY` | The result after applying all updates and deletions would leave `PriceDataSeries` empty. |
|
||||
| `tecARRAY_TOO_LARGE` | The result after applying all updates and additions would exceed 10 entries. |
|
||||
| `tecINSUFFICIENT_RESERVE` | The account does not have enough XAH to meet the reserve requirement for creating the Oracle object. |
|
||||
@@ -98,11 +98,11 @@ _All_ of the following conditions are met:
|
||||
|
||||
* The Corresponding Hook does not exist _or_`FLAG_OVERRIDE` is specified.
|
||||
* `CreateCode` field is specified and is not blank and contains the valid web assembly bytecode for a valid Hook.
|
||||
* No instance of the same web assembly bytecode already exists on the XRPL. (If it does and all other requirements are met then interpret as an Install Operation — see below.)
|
||||
* No instance of the same web assembly bytecode already exists on Xahau. (If it does and all other requirements are met then interpret as an Install Operation — see below.)
|
||||
|
||||
**Behaviour**:
|
||||
|
||||
* A reference counted `HookDefinition` object is created on the XRPL containing the fields in the HookSet Object, with all specified fields (Namespace, Parameters, HookOn) becoming defaults (but not Grants.)
|
||||
* A reference counted `HookDefinition` object is created on Xahau containing the fields in the HookSet Object, with all specified fields (Namespace, Parameters, HookOn) becoming defaults (but not Grants.)
|
||||
* A `Hooks` array is created on the executing account, if it doesn't already exist. (This is the structure that contains the Corresponding Hooks.)
|
||||
* A `Hook` object is created at the Corresponding Hook position if one does not already exist.
|
||||
* The `Hook` object points at the `HookDefinition`.
|
||||
@@ -274,7 +274,7 @@ _All_ of the following conditions are met:
|
||||
* `HookNamespace` is specified.
|
||||
* `CreateCode` is absent.
|
||||
* `HookHash` is absent.
|
||||
* `HookGrants`, `HookParameters`, `HookOn` and `HookApiVersion` are absent.
|
||||
* `HookGrants`, `HookParameters`, `HookOn`, `HookOnIncoming`, `HookOnOutgoing` and `HookApiVersion` are absent.
|
||||
|
||||
**Behaviour**:
|
||||
|
||||
@@ -308,15 +308,18 @@ The following fields are used in the hook object:
|
||||
|
||||
| Field | JSON Type | Internal Type | Description |
|
||||
| ---------------- | --------- | ------------- | ------------------------------------------------- |
|
||||
| `HookHash` | String | Hash256 | The hash of the hook. |
|
||||
| `CreateCode` | String | Blob | The WebAssembly code for the hook. |
|
||||
| `HookGrants` | Array | Array | The grants associated with the hook. |
|
||||
| `HookNamespace` | String | Hash256 | The namespace of the hook. |
|
||||
| `HookParameters` | Array | Array | The parameters of the hook. |
|
||||
| `HookOn` | String | Hash256 | The transaction/s on which the hook is triggered. |
|
||||
| `HookCanEmit` | String | Hash256 | The transaction/s which the hook can emit. |
|
||||
| `HookApiVersion` | Number | UInt16 | The API version of the hook. |
|
||||
| `Flags` | Number | UInt32 | Additional flags for the hook. |
|
||||
| `HookHash` | String | Hash256 | The hash of the hook. |
|
||||
| `CreateCode` | String | Blob | The WebAssembly code for the hook. |
|
||||
| `HookGrants` | Array | Array | The grants associated with the hook. |
|
||||
| `HookNamespace` | String | Hash256 | The namespace of the hook. |
|
||||
| `HookParameters` | Array | Array | The parameters of the hook. |
|
||||
| `HookOn` | String | Hash256 | _(Optional, HookOnV2)_ The transaction/s on which the hook is triggered. Mutually exclusive with `HookOnIncoming`/`HookOnOutgoing`. |
|
||||
| `HookOnIncoming` | String | Hash256 | _(Optional, HookOnV2)_ Same syntax as `HookOn`. Triggers the hook on transactions originating from **another account**. Mutually exclusive with `HookOn`. |
|
||||
| `HookOnOutgoing` | String | Hash256 | _(Optional, HookOnV2)_ Same syntax as `HookOn`. Triggers the hook on transactions originating from **the Hook account itself**. Mutually exclusive with `HookOn`. |
|
||||
| `HookCanEmit` | String | Hash256 | _(Optional)_ Same syntax as `HookOn`. Controls which transaction types the hook is allowed to emit. If absent, the hook may emit any transaction type. |
|
||||
| `HookName` | String | Blob | _(Optional, NamedHooks)_ A UTF-8 string (4–16 bytes, hex-encoded) assigned to this hook installation. When set, the hook only executes if the incoming transaction carries a matching top-level `HookName` field. Set to an empty blob to remove a previously assigned name. |
|
||||
| `HookApiVersion` | Number | UInt16 | The API version of the hook. |
|
||||
| `Flags` | Number | UInt32 | Additional flags for the hook. |
|
||||
|
||||
### Flags
|
||||
|
||||
|
||||
@@ -120,6 +120,17 @@
|
||||
"This feature, inherited from XRPL's DEX, enables a dynamic and responsive trading environment where exchange of value happens peer-to-peer without intermediary exchanges. The ability to place and cancel trade orders is provided by dedicated transactions (OfferCreate and OfferCancel). Unlike many blockchains that require smart contracts or external platforms for trading, Xahau's DEX is a first-class feature of the ledger. This on-ledger exchange offers fast settlement and low fees, making asset trading seamless for users and applications."
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "oracles",
|
||||
"label": "Data Feeds",
|
||||
"type": "finance",
|
||||
"graphic": null,
|
||||
"heading": "Price Oracles: Native On-Ledger Price Feeds",
|
||||
"paragraphs": [
|
||||
"Xahau provides a built-in Price Oracle system that brings real-world asset prices directly onto the ledger. Authorized data providers can publish and update price data for any asset pair, and multiple oracle entries can be aggregated on-chain to derive a single trusted reference price — all without relying on external smart contracts or off-chain middleware.",
|
||||
"Applications such as DeFi protocols, automated market makers, or compliance tools can query the on-ledger aggregate price through a standardized interface. Because oracle data is validated and stored as first-class ledger objects, it inherits the same finality, auditability, and security guarantees as any other transaction on Xahau."
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "checks",
|
||||
"label": "Payments",
|
||||
|
||||
@@ -99,6 +99,14 @@ export const featuresTranslations = {
|
||||
checks_para2:
|
||||
"The ledger has dedicated transactions for creating a check, cashing it, or canceling it. Few other platforms have this kind of native deferred payment instrument; Xahau's check system provides an extra layer of payment control, all enforced by the network's rules without requiring custom smart contracts.",
|
||||
|
||||
// Price Oracles solo
|
||||
oracle_label: 'Data Feeds',
|
||||
oracle_h4: 'Price Oracles: Native On-Ledger Price Feeds',
|
||||
oracle_para1:
|
||||
'Xahau provides a built-in Price Oracle system that brings real-world asset prices directly onto the ledger. Data providers can publish and update price data for any asset pair, and multiple oracle entries can be aggregated on-chain to derive a single trusted reference price, all without relying on external smart contracts or off-chain middleware.',
|
||||
oracle_para2:
|
||||
'Applications such as DeFi protocols, automated market makers, or compliance tools can query the on-ledger aggregate price through a standardized interface. Because oracle data is validated and stored as first-class ledger objects, it inherits the same finality, auditability, and security guarantees as any other transaction on Xahau.',
|
||||
|
||||
// Act III — Governance & Identity
|
||||
act3_label: 'Governance & Identity',
|
||||
|
||||
|
||||
Reference in New Issue
Block a user