mirror of
https://github.com/Xahau/xahau-web.git
synced 2026-08-19 01:01:42 +00:00
Merge branch 'main' into patch-1
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -45,6 +45,35 @@ const tr = (v: unknown): string => {
|
||||
return ''
|
||||
}
|
||||
|
||||
/**
|
||||
* Card tag text.
|
||||
*
|
||||
* Items carry vocabulary *keys* (`phase`, `note`) rather than per-locale
|
||||
* strings, so a wording change happens once in `labels.<locale>.tags` instead
|
||||
* of once per item per language. Renders "<phase> · <note>"; `note` is
|
||||
* optional. `tag` stays supported as a free-form escape hatch for one-offs.
|
||||
*
|
||||
* An unknown key is a build error, not a silently blank tag — the fallback
|
||||
* locale is checked too, so a key missing only from a translation still
|
||||
* renders (in the default locale) rather than breaking the page.
|
||||
*/
|
||||
const tagFor = (it: RoadmapItem): string => {
|
||||
if (!it.phase) return it.tag ? tr(it.tag) : ''
|
||||
|
||||
const pick = (kind: 'phases' | 'notes', key: string): string => {
|
||||
const here = data.labels[lang]?.tags?.[kind]?.[key]
|
||||
const base = data.labels[defaultLocale]?.tags?.[kind]?.[key]
|
||||
if (here ?? base) return (here ?? base) as string
|
||||
throw new Error(
|
||||
`roadmap.json: item "${it.id}" uses ${kind === 'phases' ? 'phase' : 'note'} ` +
|
||||
`"${key}", which is not defined in labels.${defaultLocale}.tags.${kind}.`,
|
||||
)
|
||||
}
|
||||
|
||||
const phase = pick('phases', it.phase)
|
||||
return it.note ? `${phase} · ${pick('notes', it.note)}` : phase
|
||||
}
|
||||
|
||||
const qToIdx = (q: string) => {
|
||||
const [y, qx] = q.split('-Q')
|
||||
return Number(y) * 4 + (Number(qx) - 1)
|
||||
@@ -209,7 +238,7 @@ const fmtItemPeriod = (item: RoadmapItem): string => {
|
||||
return (
|
||||
<article class={classes} style={`grid-column:${p.col} / span ${p.span};`}>
|
||||
<span class="xr-q-badge" aria-hidden="true">{fmtItemPeriod(it)}</span>
|
||||
{it.tag && <div class="k">{tr(it.tag)}</div>}
|
||||
{tagFor(it) && <div class="k">{tagFor(it)}</div>}
|
||||
<div class="n">{tr(it.title)}</div>
|
||||
{it.description && <div class="d">{tr(it.description)}</div>}
|
||||
<span class="peg" aria-hidden="true"></span>
|
||||
@@ -245,7 +274,7 @@ const fmtItemPeriod = (item: RoadmapItem): string => {
|
||||
<article class={classes} style={`grid-column:${p.col} / span ${p.span};`}>
|
||||
<span class="peg" aria-hidden="true"></span>
|
||||
<span class="xr-q-badge" aria-hidden="true">{fmtItemPeriod(it)}</span>
|
||||
{it.tag && <div class="k">{tr(it.tag)}</div>}
|
||||
{tagFor(it) && <div class="k">{tagFor(it)}</div>}
|
||||
<div class="n">{tr(it.title)}</div>
|
||||
{it.description && <div class="d">{tr(it.description)}</div>}
|
||||
</article>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -81,6 +81,30 @@ Enmienda principal que habilita la funcionalidad de contratos inteligentes Hook
|
||||
|
||||
Actualizaciones y mejoras al sistema de Hooks.
|
||||
|
||||
##### HookAPISerializedType240
|
||||
|
||||
Corrige el análisis incorrecto de los campos `STPathSet` (usados por `sfPaths` en transacciones Payment) dentro de todas las funciones de la API Hook `sto_` ([sto_subfield](/es/docs/hooks/functions/serialization/sto_subfield), [sto_subarray](/es/docs/hooks/functions/serialization/sto_subarray), [sto_emplace](/es/docs/hooks/functions/serialization/sto_emplace), [sto_erase](/es/docs/hooks/functions/serialization/sto_erase), [sto_validate](/es/docs/hooks/functions/serialization/sto_validate)). Antes de esta enmienda, los campos PathSet eran tratados incorrectamente como datos codificados en VL, lo que causaba que el analizador interno (`get_stobject_length`) leyera mal el límite del campo y corrompiera el análisis de todos los campos subsiguientes en el objeto. Los campos PathSet se auto-delimitan (usando bytes separadores de ruta `0xFF` y un byte de fin de conjunto `0x00`) y ahora se analizan correctamente. También eleva el tipo serializado máximo soportado de `STI_VECTOR256` (19) a `STI_CURRENCY` (26), añadiendo soporte correcto para `STI_ISSUE` (24), `STI_XCHAIN_BRIDGE` (25) y `STI_CURRENCY` (26) dentro de todas las funciones `sto_`. _(Introducida en 2026.6.21-release+3350)_
|
||||
|
||||
##### NamedHooks
|
||||
|
||||
Añade un campo opcional `HookName` (4–16 bytes, UTF-8) al slot Hook en una [transacción SetHook](/es/docs/protocol-reference/transactions/transaction-types/sethook). Cuando una instalación de hook incluye un `HookName`, ese hook **solo se ejecutará** si la transacción entrante también incluye un campo `HookName` de nivel superior coincidente. Las transacciones sin `HookName`, o con un valor diferente, omiten silenciosamente el hook nombrado. `HookName` también se añade como campo común opcional en todos los tipos de transacción para que los remitentes puedan apuntar a hooks nombrados específicos. Esto permite que múltiples hooks coexistan en una cuenta con diferentes puntos de entrada activados por diferentes llamantes. _(Introducida en 2026.6.21-release+3350)_
|
||||
|
||||
##### HooksUpdate2
|
||||
|
||||
Añade la función de la API Hook `prepare()`. `prepare(write_ptr, write_len, read_ptr, read_len)` acepta una transacción serializada parcial que contiene solo los campos específicos del tipo de transacción e inyecta automáticamente todos los campos requeridos para la emisión: `Account`, `Sequence`, `SigningPubKey`, `Fee`, `FirstLedgerSequence`, `LastLedgerSequence` y `EmitDetails`. La salida puede pasarse directamente a `emit()`, eliminando la necesidad de construir manualmente estos campos repetitivos en el código del hook. _(Introducida en 2026.6.21-release+3350)_
|
||||
|
||||
##### HookOnV2
|
||||
|
||||
Los Hooks pueden continuar especificando `HookOn` con el comportamiento existente, u opcionalmente reemplazarlo con dos campos separados: `HookOnIncoming` y `HookOnOutgoing`. Ambos usan la misma sintaxis de máscara de bits que `HookOn`, pero diferencian entre transacciones originadas desde la cuenta del Hook (`HookOnOutgoing`) y transacciones originadas desde otra cuenta (`HookOnIncoming`). _(Introducida en 2026.6.21-release+3350)_
|
||||
|
||||
##### PriceOracle
|
||||
|
||||
Un puerto del estándar XRPL PriceOracle (XLS-47d). Habilita feeds de precios on-chain permitiendo a las cuentas publicar datos de precios de activos como [objetos Oracle del ledger](/es/docs/protocol-reference/ledger-data/ledger-objects-types/oracle). Introduce dos nuevas transacciones: [OracleSet](/es/docs/protocol-reference/transactions/transaction-types/oracleset) (crear o actualizar un Oracle) y [OracleDelete](/es/docs/protocol-reference/transactions/transaction-types/oracledelete) (eliminar un Oracle). También añade el método RPC `get_aggregate_price` para consultar precios agregados de múltiples oracles. Cada objeto Oracle almacena entre 1 y 10 pares de precios activo/cotización (1–5 pares consumen 1 reserva de propietario; 6–10 consumen 2). El entero `AssetPrice`, junto con `Scale`, codifica el precio como `AssetPrice` × 10^(-`Scale`). _(Introducida en 2026.6.21-release+3350)_
|
||||
|
||||
##### IOURewardClaim
|
||||
|
||||
Amplía el tipo de transacción [ClaimReward](/es/docs/protocol-reference/transactions/transaction-types/claimreward) más allá de los ajustes de saldo génesis a otras monedas IOU. Los contadores de recompensa se mantienen dentro de la línea de confianza (objetos `LowReward`/`HighReward` en el objeto [RippleState](/es/docs/protocol-reference/ledger-data/ledger-objects-types/ripple-state)) y no afectan a los ajustes de saldo génesis. La transacción activa cualquier Hook instalado en la cuenta especificada por el campo `Issuer`, permitiendo que ese Hook procese y opcionalmente pague la recompensa. La cuenta que paga la recompensa no necesita ser el emisor de la moneda IOU. _(Introducida en 2026.6.21-release+3350)_
|
||||
|
||||
##### Remit
|
||||
|
||||
Implementa [XLS-55](https://github.com/XRPLF/XRPL-Standards/discussions/156). Un nuevo tipo de transacción de pago push simple pero potente de lo-que-ves-es-lo-que-obtienes. Habilita [transacciones Remit](/es/docs/protocol-reference/transactions/transaction-types/remit) que permiten pagar múltiples monedas y URITokens en la misma transacción al mismo destino. La transacción paga automáticamente para crear líneas de confianza faltantes, paga automáticamente las reservas en tokens transferidos y paga automáticamente para crear la cuenta de destino si no existe. Puede acuñar un recibo o URIToken de bonificación inline dentro de la transacción. Opcionalmente, informar a un Hook de terceros sobre la transacción. Sin pagos parciales ni rutas.
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
title: get_aggregate_price
|
||||
description: >-
|
||||
Obtiene estadísticas de precios agregados de múltiples objetos Price Oracle
|
||||
para un par de activos determinado.
|
||||
---
|
||||
_(Añadido por la [enmienda PriceOracle](/es/docs/features/amendments/#priceoracle).)_
|
||||
|
||||
El método `get_aggregate_price` consulta los datos de precio almacenados en uno o más [objetos Oracle del ledger](/es/docs/protocol-reference/ledger-data/ledger-objects-types/oracle) para un par de activos especificado y devuelve estadísticas agregadas (media, mediana, desviación estándar). Opcionalmente, se pueden eliminar valores atípicos y aplicar un filtro de ventana temporal.
|
||||
|
||||
### Formato de solicitud
|
||||
|
||||
```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
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Parámetros de solicitud
|
||||
|
||||
| Campo | Tipo JSON | ¿Requerido? | Descripción |
|
||||
| ---------------- | ---------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `base_asset` | String | Sí | El código de moneda del activo que se está cotizando (p. ej. `"XAH"`, `"BTC"`). |
|
||||
| `quote_asset` | String | Sí | El código de moneda de la denominación (p. ej. `"USD"`, `"EUR"`). |
|
||||
| `oracles` | Array | Sí | Array de hasta **200** referencias de oracle. Cada entrada debe contener `account` (String, AccountID) y `oracle_document_id` (Number, UInt32). |
|
||||
| `trim` | Number | No | Porcentaje (1–25) de valores atípicos a eliminar de ambos extremos de la distribución de precios antes de calcular las estadísticas de `trimmed_set`. |
|
||||
| `time_threshold` | Number | No | Antigüedad máxima en segundos para que un precio sea incluido. Los precios con `LastUpdateTime < (latestTime - time_threshold)` se excluyen. Si se omite, se incluyen todos los precios. |
|
||||
| `ledger_index` | String o Number | No | El ledger a consultar. Por defecto `"current"`. |
|
||||
|
||||
### Formato de respuesta
|
||||
|
||||
```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"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Campos de respuesta
|
||||
|
||||
| Campo | Tipo JSON | Descripción |
|
||||
| ------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| `entire_set.mean` | String | Precio medio de todos los puntos de datos recogidos (como cadena decimal). |
|
||||
| `entire_set.size` | Number | Número de puntos de datos de precio utilizados para calcular las estadísticas. |
|
||||
| `entire_set.standard_deviation` | String | Desviación estándar de los precios en el conjunto completo. |
|
||||
| `trimmed_set.mean` | String | Precio medio tras eliminar el `trim%` superior e inferior de valores atípicos. Solo presente si se especificó `trim`. |
|
||||
| `trimmed_set.size` | Number | Número de puntos de datos restantes tras el recorte. Solo presente si se especificó `trim`. |
|
||||
| `trimmed_set.standard_deviation`| String | Desviación estándar tras el recorte. Solo presente si se especificó `trim`. |
|
||||
| `median` | String | Precio mediano del conjunto completo. |
|
||||
| `time` | Number | El `LastUpdateTime` (epoch de Ripple) más reciente encontrado entre todos los objetos Oracle consultados. |
|
||||
|
||||
### Algoritmo
|
||||
|
||||
1. Itera a través de hasta **200** cuentas de oracle y recupera sus entradas del ledger `Oracle`.
|
||||
2. Para cada Oracle, busca en hasta **3** entradas de metadatos de transacciones históricas para encontrar un precio para el par `base_asset`/`quote_asset` solicitado.
|
||||
3. Aplica el filtro `time_threshold`: conserva solo los precios donde `LastUpdateTime ≥ (latestTime - time_threshold)`.
|
||||
4. Calcula la media, la desviación estándar y la mediana sobre el conjunto filtrado.
|
||||
5. Si `trim` > 0: elimina el `trim%` superior e inferior por valor de precio y recalcula las estadísticas para `trimmed_set`.
|
||||
|
||||
### Casos de error
|
||||
|
||||
| Código de error | Descripción |
|
||||
| --------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| `rpcORACLE_MALFORMED` | Una entrada en `oracles` tiene un `account` o `oracle_document_id` faltante o inválido. |
|
||||
| `rpcINVALID_PARAMS` | Tipo de parámetro inválido, cadena de activo vacía, o `trim` fuera del rango 1–25. |
|
||||
| `rpcOBJECT_NOT_FOUND` | No se encontraron datos de precio coincidentes para el par de activos solicitado en ninguno de los objetos Oracle consultados. |
|
||||
| `rpcINTERNAL` | Todos los puntos de datos fueron excluidos por el filtro `time_threshold`, dejando un conjunto de resultados vacío. |
|
||||
|
||||
### Límites
|
||||
|
||||
| Parámetro | Límite |
|
||||
| -------------- | ------------------------------------------------------------- |
|
||||
| `oracles` | Máximo 200 entradas por solicitud |
|
||||
| Profundidad histórica | Máximo 3 entradas de metadatos históricas buscadas por oracle |
|
||||
| `trim` | 1–50 (%) |
|
||||
@@ -68,6 +68,14 @@ Interactúe directamente con un servidor xahaud usando los métodos de API públ
|
||||
| server_state | Obtiene el estado del servidor en formato legible por máquina. |
|
||||
| manifest | Recupera detalles de clave pública para un validador. |
|
||||
|
||||
### Métodos de Oracle
|
||||
|
||||
_(Requiere la [enmienda PriceOracle](/es/docs/features/amendments/#priceoracle).)_
|
||||
|
||||
| Método | Descripción |
|
||||
| ----------------------- | ------------------------------------------------------------------------------------ |
|
||||
| [get_aggregate_price](/es/docs/features/http-websocket-apis/get-aggregate-price) | Obtiene estadísticas de precios agregados de múltiples objetos Oracle para un par de activos. |
|
||||
|
||||
### Métodos de Utilidad
|
||||
|
||||
| Método | Descripción |
|
||||
|
||||
@@ -18,3 +18,25 @@ Una transacción `ClaimReward` permite a una cuenta reclamar las recompensas que
|
||||
El tipo de transacción `GenesisMint` también está asociado con la característica de Recompensas de Balance. Esta es una transacción Emitida que se ejecuta a través del Hook de Recompensa cada vez que un usuario reclama sus recompensas de balance.
|
||||
|
||||
<LinkCard title="GenesisMint - (Txn Emitida)" href="/es/docs/protocol-reference/transactions/transaction-types/genesismint-emitted-txn" />
|
||||
|
||||
### IOU Reward Claim
|
||||
|
||||
_(Requiere la [enmienda IOURewardClaim](/es/docs/features/amendments/#iourewardclaim).)_
|
||||
|
||||
La enmienda `IOURewardClaim` extiende el mecanismo de recompensas a las monedas IOU emitidas por cualquier cuenta. El mismo cálculo de área bajo la curva (tiempo de tenencia × cantidad tenida) que rige las recompensas génesis de XAH se aplica a los tenedores de tokens IOU, con el Hook del emisor controlando la lógica de pago.
|
||||
|
||||
#### Cómo funciona
|
||||
|
||||
1. **Opt-in**: El tenedor de tokens envía una transacción `ClaimReward` con el campo `ClaimCurrency` especificando el IOU. Esto inicializa contadores de seguimiento de recompensas (`LowReward` o `HighReward`) directamente en la línea de confianza (objeto de ledger [RippleState](/es/docs/protocol-reference/ledger-data/ledger-objects-types/ripple-state)).
|
||||
2. **Acumulación**: Después de cada transacción que modifica el saldo de la línea de confianza, el ledger actualiza automáticamente el campo `TrustLineRewardAccumulator`. Esto rastrea el producto acumulado de saldo × ledgers transcurridos desde el último reinicio.
|
||||
3. **Reclamación**: Cuando el tenedor envía otra `ClaimReward` con `ClaimCurrency`, el ledger reinicia los contadores y activa el Hook del emisor (que debe estar instalado y debe ejecutarse en la transacción `ClaimReward`). El Hook lee el valor acumulado y emite un pago de recompensa en la forma que elija el emisor.
|
||||
|
||||
#### Diferencias clave respecto a las recompensas génesis de XAH
|
||||
|
||||
| | Recompensas Génesis XAH | Recompensas IOU |
|
||||
|---|---|---|
|
||||
| Enmienda | `BalanceRewards` | `IOURewardClaim` |
|
||||
| Contadores almacenados en | AccountRoot | RippleState (línea de confianza) |
|
||||
| Tipo de acumulador | UInt64 (drops / 1.000.000) | Amount (en las unidades del token) |
|
||||
| Pago gestionado por | Hook de la cuenta génesis | Hook de la cuenta del emisor |
|
||||
| Restricción de emisor | Debe ser la cuenta génesis | Cualquier cuenta con un Hook en la transacción `ClaimReward`, excepto cuentas AMM |
|
||||
|
||||
@@ -18,13 +18,13 @@ La solución: **Transacciones emitidas**. Permitimos que la Transacción Origina
|
||||
|
||||
Las Transacciones emitidas son transacciones _nuevas_ creadas por la ejecución de un Hook y que entran en consenso para ser procesadas en el siguiente ledger. La transacción puede ser de cualquier tipo, pero debe seguir reglas estrictas de emisión.
|
||||
|
||||
Para emitir una transacción, el Hook primero prepara la transacción serializada y luego llama a [emit](/es/docs/hooks/functions/emitted-transaction/emit-1).
|
||||
Para emitir una transacción, el Hook primero prepara la transacción serializada y luego llama a [emit](/es/docs/hooks/functions/emitted-transaction/emit). Con la [enmienda HooksUpdate2](/es/docs/features/amendments/#hooksupdate2), la API [prepare()](/es/docs/hooks/functions/emitted-transaction/prepare) puede construir automáticamente la transacción completa lista para emisión a partir de una entrada parcial, eliminando la necesidad de establecer manualmente `Account`, `Sequence`, `SigningPubKey`, `Fee`, `FirstLedgerSequence`, `LastLedgerSequence` y `EmitDetails`.
|
||||
|
||||
Dado que las transacciones emitidas pueden activar Hooks en el siguiente ledger, que a su vez pueden emitir más transacciones, todas las transacciones emitidas incluyen un campo `burden` y un campo `generation` dentro de su bloque `EmitDetails`. El bloque `EmitDetails` reemplaza el campo de firma en una transacción tradicional.
|
||||
|
||||
Los campos `burden` y `generation` previenen conjuntamente ataques de tipo [Fork bomb](https://en.wikipedia.org/wiki/Fork_bomb) en el ledger al aumentar exponencialmente el coste de las transacciones emitidas que crecen de forma exponencial.
|
||||
|
||||
Es importante destacar que la API de Hooks sigue la regla estricta de _no reescritura_. Debes presentar una transacción emitida completa, válida y canónicamente formada a xahaud para su emisión, o será rechazada. No es responsabilidad de xahaud construir tu transacción por ti. El Hook debe hacerlo por sí mismo.
|
||||
Es importante destacar que la API de Hooks sigue la regla estricta de _no reescritura_. Debes presentar una transacción emitida completa, válida y canónicamente formada a xahaud para su emisión, o será rechazada. Con la [enmienda HooksUpdate2](/es/docs/features/amendments/#hooksupdate2), la API [prepare()](/es/docs/hooks/functions/emitted-transaction/prepare) automatiza esto: el Hook proporciona solo los campos específicos del tipo de transacción y el runtime inyecta todo el código repetitivo de emisión requerido. Sin HooksUpdate2, el Hook debe construir la transacción completa por sí mismo.
|
||||
|
||||
### Callbacks
|
||||
|
||||
@@ -34,7 +34,7 @@ Si una transacción emitida expira antes de poder ser aceptada en un ledger (por
|
||||
|
||||
### Reglas de emisión
|
||||
|
||||
La API [emit](/es/docs/hooks/functions/emitted-transaction/emit-1) aplicará las siguientes reglas sobre una transacción propuesta (a emitir):
|
||||
La API [emit](/es/docs/hooks/functions/emitted-transaction/emit) aplicará las siguientes reglas sobre una transacción propuesta (a emitir):
|
||||
|
||||
| # | Regla de emisión | Explicación |
|
||||
| - | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|
||||
@@ -41,4 +41,28 @@ Ejemplos (asumiendo un entero sin signo de 256 bits):
|
||||
|
||||
### Calculadora HookOn
|
||||
|
||||
<LinkCard title="Calculadora HookOn" href="https://richardah.github.io/xrpl-hookon-calculator/" />
|
||||
<LinkCard title="Calculadora HookOn" href="https://richardah.github.io/xrpl-hookon-calculator/" />
|
||||
|
||||
### Campo HookCanEmit
|
||||
|
||||
_(Añadido por la [enmienda HookCanEmit](/es/docs/features/amendments/#hookcanemit).)_
|
||||
|
||||
`HookCanEmit` usa la misma sintaxis de máscara de bits de 256 bits que `HookOn`, pero controla qué tipos de transacción puede **emitir** un Hook, en lugar de qué tipos lo activan.
|
||||
|
||||
- Usa la misma semántica activo-bajo que `HookOn`, con el bit 22 (`ttHOOK_SET`) siendo activo-alto.
|
||||
- Si `HookCanEmit` está ausente, el Hook puede emitir cualquier tipo de transacción, incluyendo `SetHook`.
|
||||
|
||||
### Campos HookOnIncoming y HookOnOutgoing
|
||||
|
||||
_(Añadido por la [enmienda HookOnV2](/es/docs/features/amendments/#hookonv2).)_
|
||||
|
||||
En lugar de especificar un único campo `HookOn`, los Hooks pueden opcionalmente reemplazarlo con dos campos separados que diferencian la dirección de la transacción que los activa:
|
||||
|
||||
- **`HookOnIncoming`** — activa el Hook en transacciones **originadas desde otra cuenta** (la cuenta del Hook no es el iniciador).
|
||||
- **`HookOnOutgoing`** — activa el Hook en transacciones **originadas desde la propia cuenta del Hook**.
|
||||
|
||||
Ambos campos usan la misma sintaxis de campo de bits que `HookOn`. `HookOnIncoming` y `HookOnOutgoing` son mutuamente excluyentes con `HookOn` — debes usar `HookOn` solo o el par `HookOnIncoming`/`HookOnOutgoing`, no ambos. Si solo se especifica uno del par, el Hook no se activará en la dirección no especificada.
|
||||
|
||||
_Nota: Los campos `HookOnIncoming` y `HookOnOutgoing` no pueden configurarse con exactamente los mismos ajustes. Si necesitas que un Hook responda en ambas direcciones usando criterios idénticos, usa el campo `HookOn` en su lugar, ya que ofrece una forma más simple y apropiada de definir el comportamiento de activación compartida._
|
||||
|
||||
Usar `HookOn` solo continúa funcionando exactamente como antes.
|
||||
105
src/content/docs/es/docs/hooks/concepts/named-hooks.mdx
Normal file
105
src/content/docs/es/docs/hooks/concepts/named-hooks.mdx
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
title: Named Hooks
|
||||
description: Activa hooks específicos en una cuenta usando una puerta de ejecución basada en nombre.
|
||||
---
|
||||
|
||||
_(Añadido por la [enmienda NamedHooks](/es/docs/features/amendments/#namedhooks).)_
|
||||
|
||||
### Descripción general
|
||||
|
||||
Por defecto, cada hook instalado en una cuenta se ejecuta en cada tipo de transacción para el que ha sido configurado mediante `HookOn`. Los Named Hooks permiten que un hook instalado declare una **puerta de ejecución**: el hook solo se ejecuta si la transacción que lo activa lleva un valor `HookName` coincidente.
|
||||
|
||||
Esto permite que varios hooks coexistan en la misma cuenta, cada uno con un caso de uso diferente, donde los llamantes seleccionan qué hook activar incluyendo el `HookName` apropiado en su transacción.
|
||||
|
||||
### Cómo funciona
|
||||
|
||||
**1. Nombrar el hook en el momento de la instalación**
|
||||
|
||||
Establece el campo `HookName` dentro del slot `Hook` de una [transacción SetHook](/es/docs/protocol-reference/transactions/transaction-types/sethook):
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "SetHook",
|
||||
"Account": "rHookOwner...",
|
||||
"Hooks": [
|
||||
{
|
||||
"Hook": {
|
||||
"HookHash": "A5663784D04ED1B4408C6B97193464D27C9C3334AAF8BBB4FA5EB8E557FC4A2C",
|
||||
"HookOn": "0000000000000000",
|
||||
"HookNamespace": "...",
|
||||
"HookName": "6D795F68616E646C6572"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`HookName` es una cadena UTF-8 codificada en hexadecimal (p. ej. `6D795F68616E646C6572` = `"my_handler"`). Se almacena por instalación en el [objeto Hook del ledger](/es/docs/protocol-reference/ledger-data/ledger-objects-types/hook) de la cuenta y no se comparte con la [HookDefinition](/es/docs/protocol-reference/ledger-data/ledger-objects-types/hook-definition).
|
||||
|
||||
**2. Activar el hook por nombre en una transacción**
|
||||
|
||||
Cualquier tipo de transacción puede incluir el campo `HookName` de nivel superior para apuntar al hook nombrado:
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "Payment",
|
||||
"Account": "rSender...",
|
||||
"Destination": "rHookOwner...",
|
||||
"Amount": "1000000",
|
||||
"HookName": "6D795F68616E646C6572"
|
||||
}
|
||||
```
|
||||
|
||||
Cuando el ledger procesa esta transacción y llega a la cadena de hooks en `rHookOwner`:
|
||||
|
||||
- Los hooks **sin** un `HookName` establecido → se ejecutan normalmente (comportamiento sin cambios).
|
||||
- Los hooks **con** un `HookName` que coincide con el `HookName` de la transacción → se ejecutan.
|
||||
- Los hooks **con** un `HookName` que **no coincide** → se omiten silenciosamente (sin error).
|
||||
|
||||
Las transacciones que **no** llevan el campo `HookName` omitirán todos los hooks nombrados de la cuenta.
|
||||
|
||||
### Restricciones de HookName
|
||||
|
||||
| Restricción | Valor |
|
||||
| ----------------- | ------------------------------ |
|
||||
| Longitud mínima | 4 bytes (8 caracteres hex en JSON) |
|
||||
| Longitud máxima | 16 bytes (32 caracteres hex en JSON) |
|
||||
| Codificación | UTF-8 válido |
|
||||
| Eliminar nombre | Establecer en blob vacío (`""`) en una operación de actualización |
|
||||
|
||||
### Eliminar un nombre
|
||||
|
||||
Para eliminar un nombre previamente asignado a un slot de hook, envía una operación de actualización con `HookName` establecido en un blob vacío:
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "SetHook",
|
||||
"Account": "rHookOwner...",
|
||||
"Hooks": [
|
||||
{
|
||||
"Hook": {
|
||||
"HookName": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Tras la eliminación, el hook vuelve a la ejecución incondicional (gobernada únicamente por sus configuraciones de `HookOn` / `HookOnIncoming` / `HookOnOutgoing`).
|
||||
|
||||
### Cálculo de comisiones
|
||||
|
||||
El cálculo de comisiones de hook respeta la misma lógica de puerta: los hooks nombrados que serían omitidos por una transacción (nombre no coincidente o ausente) **no** se contabilizan al calcular la comisión de ejecución de hook para esa transacción.
|
||||
|
||||
### Casos de error
|
||||
|
||||
| Código de error | Condición |
|
||||
| --------------- | --------- |
|
||||
| `temDISABLED` | `HookName` está presente en un slot Hook pero la enmienda `NamedHooks` no está habilitada. |
|
||||
| `temMALFORMED` | `HookName` presente como campo de transacción de nivel superior pero `Hooks` o `NamedHooks` no está activo; o el valor no supera la validación de UTF-8 o longitud. |
|
||||
|
||||
### Casos de uso
|
||||
|
||||
- **Cuentas multipropósito**: instala varios hooks especializados (p. ej. procesador de pagos, manejador de gobernanza, gestor de escrow), cada uno controlado por un nombre diferente.
|
||||
- **Invocación selectiva**: contratos externos o usuarios pueden activar selectivamente solo el hook relevante para su interacción sin afectar a los demás.
|
||||
- **Migración gradual**: despliega una nueva versión de hook bajo un nombre diferente y migra los llamantes de forma incremental sin eliminar el hook anterior.
|
||||
@@ -2,6 +2,7 @@
|
||||
title: Objetos serializados
|
||||
description: ¡Manipula objetos serializados de xahaud directamente!
|
||||
---
|
||||
import { Aside } from '@astrojs/starlight/components';
|
||||
|
||||
### ¿Qué son los objetos serializados?
|
||||
|
||||
@@ -45,6 +46,34 @@ for (int i = 0; GUARD(3), i < 3; ++i)
|
||||
}
|
||||
````
|
||||
|
||||
### Soporte de PathSet y Tipos Serializados Soportados
|
||||
|
||||
<Aside type="caution" title="Error de análisis de PathSet (pre-HookAPISerializedType240)">
|
||||
Sin la [enmienda HookAPISerializedType240](/es/docs/features/amendments/#hookapiserializedtype240), todas las funciones `sto_` analizan incorrectamente los campos `sfPaths` (campos STPathSet, usados en transacciones Payment con enrutamiento entre monedas). El analizador interno lee mal el límite del PathSet, corrompiendo los resultados de cualquier campo que aparezca después de `sfPaths` en el objeto serializado. Los desarrolladores de Hooks que procesen transacciones Payment con rutas entre monedas deben asegurarse de que esta enmienda esté habilitada.
|
||||
</Aside>
|
||||
|
||||
Con la [enmienda HookAPISerializedType240](/es/docs/features/amendments/#hookapiserializedtype240), los siguientes tipos serializados son manejados correctamente por todas las funciones `sto_`:
|
||||
|
||||
| Tipo STI | Código | Ejemplos |
|
||||
|---|---|---|
|
||||
| `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`, objetos internos |
|
||||
| `STI_ARRAY` | 15 | `sfHooks`, `sfMemos`, `sfSigners` |
|
||||
| `STI_UINT8` | 16 | `sfCloseResolution` |
|
||||
| `STI_UINT160` | 17 | `sfTakerPaysCurrency` |
|
||||
| `STI_PATHSET` | 18 | `sfPaths` _(corregido por HookAPISerializedType240)_ |
|
||||
| `STI_VECTOR256` | 19 | `sfHookNamespaces` |
|
||||
| `STI_ISSUE` | 24 | _(añadido por HookAPISerializedType240)_ |
|
||||
| `STI_XCHAIN_BRIDGE` | 25 | _(añadido por HookAPISerializedType240)_ |
|
||||
| `STI_CURRENCY` | 26 | _(añadido por HookAPISerializedType240)_ |
|
||||
|
||||
### Solapamiento con slots
|
||||
|
||||
Puede que observes cierta superposición entre las APIs de slots y las APIs STO. La diferencia clave es quién *posee* los datos subyacentes:
|
||||
|
||||
@@ -1,45 +1,72 @@
|
||||
---
|
||||
title: prepare
|
||||
description: Prepara una transacción JSON para su emisión.
|
||||
title: emit
|
||||
description: Emite una nueva transacción desde el hook
|
||||
---
|
||||
import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components';
|
||||
|
||||
### Conceptos
|
||||
|
||||
<LinkButton href="/es/docs/protocol-reference/transactions">Transacciones</LinkButton>
|
||||
<LinkButton href="/es/docs/hooks/concepts/emitted-transactions">Transacciones Emitidas</LinkButton>
|
||||
<LinkButton href="/es/docs/hooks/functions/emitted-transaction/prepare">prepare()</LinkButton>
|
||||
|
||||
### Comportamiento
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
* Lee una transacción de `read_ptr`
|
||||
* Valida la transacción contra las reglas de emisión
|
||||
* Emite la transacción al consenso cuando es válida
|
||||
* Escribe el hash canónico de la transacción en `write_ptr`
|
||||
|
||||
Con la [enmienda HooksUpdate2](/es/docs/features/amendments/#hooksupdate2), usa [`prepare()`](/es/docs/hooks/functions/emitted-transaction/prepare) antes de `emit()` para inyectar automáticamente todos los campos de emisión requeridos (`Account`, `Sequence`, `SigningPubKey`, `Fee`, `EmitDetails`, etc.) a partir de una transacción parcial.
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
* Esta función toma un objeto JSON de transacción y lo prepara para su emisión.
|
||||
* La transacción debe estar completa excepto el campo Account, que siempre debe ser la cuenta del Hook.
|
||||
* Esta función emite el JSON de transacción proporcionado.
|
||||
* En caso de éxito, devuelve los hashes de la transacción emitida.
|
||||
* Si hay un error, devuelve un código de error.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Definición
|
||||
|
||||
<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>
|
||||
|
||||
### Ejemplo
|
||||
|
||||
<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>
|
||||
@@ -47,15 +74,23 @@ const prepared_txn = prepare({
|
||||
### Parámetros
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
<table><thead><tr><th>Nombre</th><th width="124">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td>write_ptr</td><td>uint32_t</td><td>Puntero a un buffer donde escribir el hash de la transacción</td></tr><tr><td>write_len</td><td>uint32_t</td><td>El tamaño del buffer para escribir el hash de la transacción (debe ser 32)</td></tr><tr><td>read_ptr</td><td>uint32_t</td><td>Puntero a la transacción a emitir</td></tr><tr><td>read_len</td><td>uint32_t</td><td>La longitud de la transacción</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
<table><thead><tr><th>Nombre</th><th width="124">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td>txJson</td><td>Record<string, any> | Transaction</td><td>El JSON de la transacción, debe estar completo excepto el campo Account (siempre la cuenta del Hook).</td></tr></tbody></table>
|
||||
<table><thead><tr><th>Nombre</th><th width="124">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td>txJson</td><td>Record<string, any> | Transaction</td><td>El JSON de la transacción a emitir.</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Código de retorno
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="JavaScript">
|
||||
<table><thead><tr><th width="231">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td>ErrorCode | Record<string, any> | Transaction</td><td>Devuelve un ErrorCode si hay un error, o el JSON de la transacción preparada o el objeto Transaction.</td></tr></tbody></table>
|
||||
<TabItem label="C">
|
||||
<table><thead><tr><th width="127">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td>int64_t</td><td>En caso de éxito, el número de bytes del hash de transacción escritos (32), o:<br /><br />Si es negativo, un error:<br /><code>OUT_OF_BOUNDS</code><br />- punteros/longitudes especificados fuera de la memoria del hook.<br /><br /><code>PREREQUISITE_NOT_MET</code><br />- se debe llamar primero a <code>etxn_reserve</code><br /><br /><code>TOO_MANY_EMITTED_TXN</code><br />- el número de transacciones emitidas es ahora mayor que la promesa hecha cuando se llamó a <code>etxn_reserve</code><br /><br /><code>EMISSION_FAILURE</code><br />- la transacción estaba malformada según las reglas de emisión.</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
<table><thead><tr><th width="231">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td>ErrorCode | ByteArray</td><td>Devuelve un ErrorCode si hay un error, o un array de hashes de la transacción emitida en caso de éxito.</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
---
|
||||
title: prepare
|
||||
description: Prepara una transacción para su emisión inyectando automáticamente todos los campos de emisión requeridos.
|
||||
---
|
||||
import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components';
|
||||
|
||||
### Conceptos
|
||||
|
||||
<LinkButton href="/es/docs/hooks/concepts/emitted-transactions">Transacciones Emitidas</LinkButton>
|
||||
|
||||
### Comportamiento
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
|
||||
_(Requiere la [enmienda HooksUpdate2](/es/docs/features/amendments/#hooksupdate2).)_
|
||||
|
||||
* Lee una transacción serializada parcial de `read_ptr`/`read_len`. La entrada debe contener como mínimo el `TransactionType` y todos los campos requeridos por ese tipo de transacción, pero los campos específicos de emisión incluidos serán **sobreescritos**.
|
||||
* Inyecta automáticamente todos los campos requeridos para la emisión: `Account` (la cuenta Hook), `Sequence` (0), `SigningPubKey` (todo ceros), `Fee` (calculada), `FirstLedgerSequence` (ledger actual + 1), `LastLedgerSequence` (ledger actual + 5) y `EmitDetails`.
|
||||
* Escribe el blob de transacción completo y listo para emisión en `write_ptr`.
|
||||
* La salida puede pasarse directamente a [`emit()`](/es/docs/hooks/functions/emitted-transaction/emit).
|
||||
* Se debe llamar a `etxn_reserve()` antes de `prepare()`.
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
* Esta función toma un objeto JSON de transacción y lo prepara para su emisión.
|
||||
* La transacción debe estar completa excepto por los campos Account, Sequence, SigningPubKey, Fee, FirstLedgerSequence, LastLedgerSequence y EmitDetails.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Definición
|
||||
|
||||
<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>
|
||||
|
||||
### Ejemplo
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
```c
|
||||
etxn_reserve(1);
|
||||
|
||||
// Construir una transacción de pago mínima (TransactionType + campos requeridos únicamente)
|
||||
uint8_t tx[256];
|
||||
// ... rellenar tx con TransactionType, Destination, Amount ...
|
||||
int64_t tx_len = /* tamaño de tx */;
|
||||
|
||||
// prepare() rellena 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() envía la transacción completamente formada
|
||||
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>
|
||||
|
||||
### Parámetros
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
|
||||
| Nombre | Tipo | Descripción |
|
||||
| ----------- | --------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `write_ptr` | uint32_t | Puntero a un buffer para recibir el blob de transacción preparado completo. |
|
||||
| `write_len` | uint32_t | Longitud del buffer de escritura. Debe ser suficientemente grande para contener la transacción preparada (tamaño de entrada + campos inyectados). |
|
||||
| `read_ptr` | uint32_t | Puntero a una transacción serializada parcial. Debe incluir `TransactionType` y todos los campos requeridos específicos del tipo. |
|
||||
| `read_len` | uint32_t | Longitud de la transacción de entrada. |
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
|
||||
<table><thead><tr><th>Nombre</th><th width="124">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td>txJson</td><td>Record<string, any> | Transaction</td><td>El JSON de la transacción; debe ser una transacción completa excepto por Account (siempre la cuenta Hook).</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Código de retorno
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="C">
|
||||
|
||||
| Tipo | Descripción |
|
||||
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| int64_t | En caso de éxito, el número de bytes escritos en `write_ptr` (el tamaño del blob de transacción preparado). El valor devuelto es la longitud de la transacción preparada. Pasa el buffer original como `read_ptr` y la longitud devuelta como `read_len` al llamar a `emit()`.<br /><br />Si es negativo, un error:<br />`OUT_OF_BOUNDS` — los punteros/longitudes quedan fuera de la memoria del hook.<br />`PREREQUISITE_NOT_MET` — se debe llamar a `etxn_reserve()` antes de `prepare()`.<br />`INVALID_ARGUMENT` — el blob de entrada no es una transacción serializada válida, o la transacción no puede prepararse (p. ej. falló el cálculo de la comisión).<br />`INTERNAL_ERROR` — fallo al generar `EmitDetails` o al re-serializar la transacción. |
|
||||
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="JavaScript">
|
||||
|
||||
<table><thead><tr><th width="231">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td>ErrorCode | Record<string, any> | Transaction</td><td>Devuelve un ErrorCode si hay un error, o el JSON de la transacción preparada o el objeto Transaction.</td></tr></tbody></table>
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
@@ -13,11 +13,12 @@ Un objeto `HookDefinition` describe un hook, que es un fragmento de código que
|
||||
{
|
||||
"HookHash": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0",
|
||||
"HookOn": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"HookCanEmit": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"HookNamespace": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"HookParameters": {
|
||||
"HookParameter": {
|
||||
"HookParameterName": "DEADBEEF",
|
||||
"HookParameterValue": "DEADBEEF",
|
||||
"HookParameterValue": "DEADBEEF"
|
||||
}
|
||||
},
|
||||
"HookApiVersion": 1,
|
||||
@@ -37,10 +38,12 @@ Un objeto `HookDefinition` tiene los siguientes campos:
|
||||
|
||||
| Campo | Tipo JSON | \[Tipo Interno]\[] | ¿Requerido? | Descripción |
|
||||
| ----------------- | --------- | ------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `HookHash` | String | Hash256 | Sí | El identificador único del hook. |
|
||||
| `HookOn` | String | Hash256 | Sí | La/s transacción/es en las que se activa el hook. |
|
||||
| `HookCanEmit` | String | Hash256 | No | La/s transacción/es que el hook puede emitir. |
|
||||
| `HookNamespace` | String | Hash256 | Sí | El espacio de nombres del hook. |
|
||||
| `HookHash` | String | Hash256 | Sí | El identificador único del hook. |
|
||||
| `HookOn` | String | Hash256 | No | La/s transacción/es en las que se activa el hook. Mutuamente exclusivo con `HookOnIncoming`/`HookOnOutgoing`. |
|
||||
| `HookOnIncoming` | String | Hash256 | No | _(HookOnV2)_ Misma sintaxis que `HookOn`. Activa el hook en transacciones originadas desde otra cuenta. Mutuamente exclusivo con `HookOn`. |
|
||||
| `HookOnOutgoing` | String | Hash256 | No | _(HookOnV2)_ Misma sintaxis que `HookOn`. Activa el hook en transacciones originadas desde la propia cuenta del Hook. Mutuamente exclusivo con `HookOn`. |
|
||||
| `HookCanEmit` | String | Hash256 | No | Misma sintaxis que `HookOn`. Controla qué tipos de transacción puede emitir el hook. Si está ausente, el hook puede emitir cualquier tipo de transacción. |
|
||||
| `HookNamespace` | String | Hash256 | Sí | El espacio de nombres del hook. |
|
||||
| `HookParameters` | String | Vector | Sí | Los parámetros que acepta el hook. |
|
||||
| `HookApiVersion` | Number | UInt16 | Sí | La versión de la API del hook que usa el hook. |
|
||||
| `CreateCode` | String | VL | Sí | El código que se ejecuta cuando se crea el hook. |
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Oracle
|
||||
---
|
||||
\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/xrpld/app/tx/detail/SetOracle.cpp)]
|
||||
|
||||
_(Añadido por la [enmienda PriceOracle](/es/docs/features/amendments/#priceoracle).)_
|
||||
|
||||
Un objeto `Oracle` del ledger representa un Price Oracle creado por una cuenta en el ledger de Xahau. Almacena uno o más puntos de datos de precio de activos y se identifica mediante la cuenta propietaria junto con un ID de documento. Los objetos Oracle se crean y actualizan mediante [transacciones OracleSet](/es/docs/protocol-reference/transactions/transaction-types/oracleset) y se eliminan mediante [transacciones OracleDelete](/es/docs/protocol-reference/transactions/transaction-types/oracledelete).
|
||||
|
||||
### Ejemplo 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"
|
||||
}
|
||||
```
|
||||
|
||||
### Campos
|
||||
|
||||
Un objeto `Oracle` tiene los siguientes campos:
|
||||
|
||||
| Campo | Tipo JSON | \[Internal Type]\[] | ¿Requerido? | Descripción |
|
||||
| ------------------- | --------- | ------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `Owner` | String | AccountID | Sí | La cuenta que creó y posee este Oracle. Solo esta cuenta puede actualizarlo o eliminarlo. |
|
||||
| `OracleDocumentID` | Number | UInt32 | Sí | El identificador único de este Oracle dentro de la cuenta propietaria. |
|
||||
| `Provider` | String | Blob | Sí | Identificador del proveedor de datos codificado en hexadecimal (p. ej. el nombre del servicio oracle). Máximo 256 bytes. |
|
||||
| `AssetClass` | String | Blob | Sí | Cadena codificada en hexadecimal que describe la categoría de activos (p. ej. `63757272656E6379` = "currency"). Máximo 16 bytes. |
|
||||
| `LastUpdateTime` | Number | UInt32 | Sí | Marca de tiempo epoch de Ripple (segundos desde el 1 de enero de 2000) de la última actualización de precio. |
|
||||
| `PriceDataSeries` | Array | Array | Sí | Array de objetos `PriceData` (1–10 entradas). Las entradas se almacenan en orden canónico por par `BaseAsset`/`QuoteAsset`. |
|
||||
| `URI` | String | Blob | No | URI codificado en hexadecimal que apunta a datos complementarios fuera de la cadena (p. ej. un CID de IPFS). Máximo 256 bytes. |
|
||||
| `OwnerNode` | String | UInt64 | Sí | Indicación de qué página del directorio del propietario enlaza con este objeto. |
|
||||
| `PreviousTxnID` | String | Hash256 | Sí | El hash identificador de la transacción que modificó este objeto más recientemente. |
|
||||
| `PreviousTxnLgrSeq` | Number | UInt32 | Sí | El índice del ledger que contiene la transacción que modificó este objeto más recientemente. |
|
||||
| `LedgerEntryType` | String | UInt16 | Sí | El valor `0x0080`, mapeado a la cadena `Oracle`, indica que este es un objeto Oracle. |
|
||||
|
||||
### Objeto PriceData
|
||||
|
||||
Cada entrada en `PriceDataSeries` contiene un objeto `PriceData`:
|
||||
|
||||
| Campo | Tipo JSON | \[Internal Type]\[] | ¿Requerido? | Descripción |
|
||||
| ------------ | --------- | ------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `BaseAsset` | String | Currency | Sí | El activo cuyo precio se publica (p. ej. `"XAH"`, `"BTC"`). |
|
||||
| `QuoteAsset` | String | Currency | Sí | La moneda de denominación (p. ej. `"USD"`, `"EUR"`). |
|
||||
| `AssetPrice` | Number | UInt64 | No | El precio como número entero escalado. El precio efectivo es `AssetPrice × 10^(-Scale)`. |
|
||||
| `Scale` | Number | UInt8 | No | Exponente decimal (0–10) usado para derivar el precio efectivo. Ejemplo: `AssetPrice = 74560`, `Scale = 4` → precio efectivo = 7,456. |
|
||||
|
||||
### Reserva
|
||||
|
||||
Un objeto Oracle consume reservas del propietario según el número de pares `PriceData` almacenados:
|
||||
|
||||
| Pares | Reservas del propietario consumidas |
|
||||
| ----- | ----------------------------------- |
|
||||
| 1–5 | 1 |
|
||||
| 6–10 | 2 |
|
||||
|
||||
### Formato del ID de Oracle
|
||||
|
||||
El ID de un objeto `Oracle` es el \[SHA-512Half]\[] de los siguientes valores, concatenados en orden:
|
||||
|
||||
* La clave de espacio Oracle (`0x0152`)
|
||||
* El AccountID del `Owner`
|
||||
* El `OracleDocumentID` como entero sin signo de 32 bits
|
||||
@@ -44,6 +44,16 @@ El "emisor" del saldo en una línea de confianza depende de si el saldo es posit
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"value": "10"
|
||||
},
|
||||
"LowReward": {
|
||||
"RewardLgrFirst": 1000000,
|
||||
"RewardLgrLast": 1001234,
|
||||
"RewardTime": 744000000,
|
||||
"TrustLineRewardAccumulator": {
|
||||
"currency": "USD",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"value": "500"
|
||||
}
|
||||
},
|
||||
"index": "9CA88CDEDFF9252B3DE183CE35B038F57282BC9503CDFA1923EF9A95DF0D6F7B"
|
||||
}
|
||||
```
|
||||
@@ -69,6 +79,21 @@ Un objeto `RippleState` tiene los siguientes campos:
|
||||
| `PreviousTxnLgrSeq` | Number | UInt32 | Sí | El \[índice del ledger]\[Ledger Index] que contiene la transacción que modificó más recientemente este objeto. |
|
||||
| `LockCount` | Number | UInt32 | No | El número total de saldos bloqueados en un objeto de ledger RippleState. |
|
||||
| `LockedBalance` | Object | Amount | No | El monto actual de tokens bloqueados para una línea de confianza específica. |
|
||||
| `LowReward` | Object | STObject | No | _(IOURewardClaim)_ Contadores de seguimiento de recompensas IOU para la cuenta baja. Presente solo después de que la cuenta baja opte mediante `ClaimReward` con `ClaimCurrency`. Contiene `RewardLgrFirst`, `RewardLgrLast`, `RewardTime` y `TrustLineRewardAccumulator`. |
|
||||
| `HighReward` | Object | STObject | No | _(IOURewardClaim)_ Contadores de seguimiento de recompensas IOU para la cuenta alta. Presente solo después de que la cuenta alta opte mediante `ClaimReward` con `ClaimCurrency`. Contiene `RewardLgrFirst`, `RewardLgrLast`, `RewardTime` y `TrustLineRewardAccumulator`. |
|
||||
|
||||
### Campos LowReward / HighReward
|
||||
|
||||
_(Añadido por la [enmienda IOURewardClaim](/es/docs/features/amendments/#iourewardclaim).)_
|
||||
|
||||
Tanto `LowReward` como `HighReward` son objetos internos con la misma estructura. `LowReward` está presente si la cuenta baja ha optado por las recompensas IOU para esta línea de confianza, y `HighReward` está presente si la cuenta alta ha optado. Ambos pueden estar presentes si ambas cuentas han optado. El ordenamiento canónico alto/bajo solo determina a qué lado se mapea una cuenta.
|
||||
|
||||
| Campo | Tipo JSON | Tipo Interno | Descripción |
|
||||
| ---------------------------- | --------- | ------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| `RewardLgrFirst` | Number | UInt32 | El número de secuencia del ledger cuando la cuenta optó por primera vez por las recompensas IOU para esta línea de confianza. Se actualiza cada vez que se ejecuta `ClaimReward`. El campo se eliminará si la cuenta opta por salir. |
|
||||
| `RewardLgrLast` | Number | UInt32 | El número de secuencia del ledger de la última vez que se actualizó el acumulador de recompensas. |
|
||||
| `RewardTime` | Number | UInt32 | El tiempo de cierre del ledger (segundos en epoch de Ripple) cuando los contadores fueron reiniciados por última vez por una transacción `ClaimReward`. |
|
||||
| `TrustLineRewardAccumulator` | Object | Amount | El total acumulado de `saldo × ledgers transcurridos` desde el último `ClaimReward`. Expresado en la moneda de la línea de confianza. Este es el valor que el Hook del emisor lee para calcular el pago de recompensa. |
|
||||
|
||||
### Indicadores RippleState
|
||||
|
||||
|
||||
@@ -4,13 +4,15 @@ description: >-
|
||||
Una transacción ClaimReward permite a una cuenta reclamar las recompensas
|
||||
acumuladas. Las recompensas pueden ser reclamadas por el propietario de la
|
||||
cuenta o por un emisor especificado. La cuenta también puede optar por
|
||||
no recibir recompensas.
|
||||
no recibir recompensas. Con la enmienda IOURewardClaim, esta transacción
|
||||
también soporta reclamar recompensas para monedas IOU con un Hook de
|
||||
recompensa instalado.
|
||||
---
|
||||
\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/ClaimReward.cpp)]
|
||||
|
||||
_(Añadido por la enmienda \[BalanceRewards]\[].)_
|
||||
|
||||
### Opt-in + Reclamación
|
||||
### Opt-in + Reclamación (recompensas génesis XAH)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -20,7 +22,7 @@ _(Añadido por la enmienda \[BalanceRewards]\[].)_
|
||||
}
|
||||
```
|
||||
|
||||
### Opt-out
|
||||
### Opt-out (recompensas génesis XAH)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -30,34 +32,68 @@ _(Añadido por la enmienda \[BalanceRewards]\[].)_
|
||||
}
|
||||
```
|
||||
|
||||
### Reclamación de Recompensa IOU
|
||||
|
||||
_(Requiere la enmienda \[IOURewardClaim]\[].)_
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "ClaimReward",
|
||||
"Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm",
|
||||
"Issuer": "rIssuerAccountXXXXXXXXXXXXXXXXXXX",
|
||||
"ClaimCurrency": {
|
||||
"currency": "USD",
|
||||
"issuer": "rIssuerAccountXXXXXXXXXXXXXXXXXXX"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Campos
|
||||
|
||||
| Campo | Tipo JSON | \[Tipo Interno]\[] | Descripción |
|
||||
| --------- | --------- | ------------------- | -------------------------------------------------------------------- |
|
||||
| `Account` | String | AccountID | La dirección de la cuenta que está reclamando la recompensa. |
|
||||
| `Flags` | Number | UInt32 | _(Opcional)_ Puede tener el indicador 1 activado para optar por no recibir recompensas. |
|
||||
| `Issuer` | String | AccountID | _(Opcional)_ La cuenta génesis. |
|
||||
| Campo | Tipo JSON | \[Tipo Interno]\[] | Descripción |
|
||||
| --------------- | --------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `Account` | String | AccountID | La dirección de la cuenta que está reclamando la recompensa. |
|
||||
| `Flags` | Number | UInt32 | _(Opcional)_ Puede tener el indicador 1 activado para optar por no recibir recompensas. |
|
||||
| `Issuer` | String | AccountID | _(Opcional)_ La cuenta génesis (recompensas XAH) o una cuenta IOU (recompensas IOU). |
|
||||
| `ClaimCurrency` | Object | Issue | _(Opcional, IOURewardClaim)_ La moneda IOU para reclamar recompensas, como `{"currency": "...", "issuer": "..."}`. No puede ser XAH. El emisor no debe ser la cuenta génesis y no debe ser igual a `Account`. Requiere que exista una línea de confianza entre `Account` y el emisor. |
|
||||
|
||||
### Indicadores ClaimReward
|
||||
|
||||
Las transacciones del tipo ClaimReward admiten valores adicionales en el campo `Flags`, de la siguiente manera:
|
||||
|
||||
| Nombre del Indicador | Valor Hex | Valor Decimal | Descripción |
|
||||
| -------------------- | ------------ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `tfOptOut` | `0x00000001` | 1 | El indicador `isOptOut` en el código ClaimReward se usa para optar una cuenta por no recibir recompensas eliminando los campos relacionados con recompensas del objeto de cuenta en el ledger si el campo `sfFlags` de la transacción se establece en 1. |
|
||||
| Nombre del Indicador | Valor Hex | Valor Decimal | Descripción |
|
||||
| -------------------- | ------------ | ------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| `tfOptOut` | `0x00000001` | 1 | Excluye a la cuenta de las recompensas eliminando los campos relacionados con recompensas del objeto de cuenta del ledger. |
|
||||
|
||||
### Costo de Transacción Especial
|
||||
|
||||
La transacción ClaimReward tiene un costo de transacción estándar, que es el costo mínimo de transacción requerido para todas las transacciones.
|
||||
|
||||
### Comportamiento de Recompensa IOU
|
||||
|
||||
_(Requiere la enmienda \[IOURewardClaim]\[].)_
|
||||
|
||||
Cuando se especifica `ClaimCurrency`, la transacción sigue el camino de recompensa IOU:
|
||||
|
||||
1. La cuenta `Issuer` debe tener un Hook instalado que se active en una transacción `ClaimReward`. El Hook es responsable de calcular y distribuir el pago de recompensa.
|
||||
2. En la primera reclamación, se inicializa un objeto de seguimiento de recompensas `LowReward` o `HighReward` en la línea de confianza (objeto de ledger [RippleState](/es/docs/protocol-reference/ledger-data/ledger-objects-types/ripple-state)) entre `Account` y el emisor. El lado utilizado depende del ordenamiento canónico alto/bajo de las dos cuentas.
|
||||
3. Después de cada transacción subsiguiente que cambia el saldo de la línea de confianza, el ledger actualiza automáticamente `TrustLineRewardAccumulator` dentro del objeto de seguimiento usando la misma fórmula de área bajo la curva que las recompensas génesis de XAH.
|
||||
4. Cuando se envía una `ClaimReward` con `ClaimCurrency`, el ledger reinicia los contadores de recompensa en la línea de confianza y activa el Hook del emisor, que lee el valor acumulado y emite un pago de recompensa.
|
||||
|
||||
Los contadores de recompensa IOU son completamente independientes de los campos de recompensa génesis de XAH en el objeto AccountRoot.
|
||||
|
||||
### Casos de Error
|
||||
|
||||
Además de los errores que pueden ocurrir para todas las transacciones, las transacciones ClaimReward pueden resultar en los siguientes códigos de resultado:
|
||||
|
||||
| Código de Error | Descripción |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| `temDISABLED` | Ocurre si la función no está habilitada. |
|
||||
| `temINVALID_FLAG` | Ocurre si el indicador se establece en un valor distinto de 1. |
|
||||
| `temMALFORMED` | Ocurre si el emisor es el mismo que la cuenta fuente o si el indicador y el emisor no están correctamente establecidos. |
|
||||
| `tecNO_ISSUER` | Ocurre si el emisor no existe. |
|
||||
| `terNO_ACCOUNT` | Ocurre si la cuenta emisora no existe. |
|
||||
| Código de Error | Descripción |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `temDISABLED` | Ocurre si la enmienda requerida (`BalanceRewards` o `IOURewardClaim`) no está habilitada. |
|
||||
| `temINVALID_FLAG` | Ocurre si el indicador se establece en un valor distinto de 1. _(Requiere la enmienda \[fixRewardClaimFlags]\[].)_ |
|
||||
| `temMALFORMED` | Ocurre si `ClaimCurrency` es un tipo no monetario o XAH, si el emisor es igual a `Account`, o si los campos de la transacción están incorrectamente establecidos. |
|
||||
| `temBAD_ISSUER` | Ocurre si se establece `ClaimCurrency` pero el emisor es la cuenta génesis, o si `Issuer` es la cuenta génesis pero también se establece `ClaimCurrency`. |
|
||||
| `terNO_ACCOUNT` | Ocurre si la cuenta emisora no existe. |
|
||||
| `tecNO_ISSUER` | Ocurre si la cuenta `Issuer` no existe. |
|
||||
| `tecNO_PERMISSION` | Ocurre si la cuenta del emisor es una cuenta AMM. Las cuentas AMM no pueden tener Hooks de recompensa. |
|
||||
| `tecNO_TARGET` | Ocurre si la cuenta del emisor no tiene Hooks, o ninguno de sus Hooks se activa en una transacción `ClaimReward`. |
|
||||
| `tecNO_LINE` | Ocurre si no existe ninguna línea de confianza entre `Account` y el emisor para el `ClaimCurrency` especificado. |
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: OracleDelete
|
||||
description: >-
|
||||
Una transacción OracleDelete elimina un objeto Price Oracle existente del
|
||||
ledger, liberando las reservas del propietario que mantenía.
|
||||
---
|
||||
\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/xrpld/app/tx/detail/DeleteOracle.cpp)]
|
||||
|
||||
_(Añadido por la [enmienda PriceOracle](/es/docs/features/amendments/#priceoracle).)_
|
||||
|
||||
### Ejemplo
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "OracleDelete",
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"OracleDocumentID": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Campos
|
||||
|
||||
| Campo | Tipo JSON | \[Internal Type]\[] | Descripción |
|
||||
| ------------------ | --------- | ------------------- | -------------------------------------------------------------------------------------------- |
|
||||
| `Account` | String | AccountID | La dirección de la cuenta propietaria del Oracle. Solo el propietario puede eliminar el objeto. |
|
||||
| `OracleDocumentID` | Number | UInt32 | El ID de documento del objeto Oracle a eliminar. |
|
||||
|
||||
### Coste especial de transacción
|
||||
|
||||
Las transacciones OracleDelete tienen el coste de transacción estándar.
|
||||
|
||||
### Casos de error
|
||||
|
||||
| Código de error | Descripción |
|
||||
| ----------------- | -------------------------------------------------------------------- |
|
||||
| `temDISABLED` | La enmienda PriceOracle no está habilitada. |
|
||||
| `temINVALID_FLAG` | Se especificaron flags inválidos. |
|
||||
| `terNO_ACCOUNT` | La cuenta emisora no existe. |
|
||||
| `tecNO_ENTRY` | No existe ningún objeto Oracle para la cuenta y `OracleDocumentID` indicados. |
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
title: OracleSet
|
||||
description: >-
|
||||
Una transacción OracleSet crea o actualiza un objeto Price Oracle en el
|
||||
ledger, publicando uno o más puntos de datos de precio de activos para una cuenta dada.
|
||||
---
|
||||
\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/xrpld/app/tx/detail/SetOracle.cpp)]
|
||||
|
||||
_(Añadido por la [enmienda PriceOracle](/es/docs/features/amendments/#priceoracle).)_
|
||||
|
||||
### Crear
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "OracleSet",
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"OracleDocumentID": 1,
|
||||
"Provider": "70726F7669646572",
|
||||
"AssetClass": "63757272656E6379",
|
||||
"LastUpdateTime": 1763033559,
|
||||
"PriceDataSeries": [
|
||||
{
|
||||
"PriceData": {
|
||||
"BaseAsset": "XAH",
|
||||
"QuoteAsset": "USD",
|
||||
"AssetPrice": 74560,
|
||||
"Scale": 4
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Actualizar
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "OracleSet",
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"OracleDocumentID": 1,
|
||||
"LastUpdateTime": 1763033700,
|
||||
"PriceDataSeries": [
|
||||
{
|
||||
"PriceData": {
|
||||
"BaseAsset": "XAH",
|
||||
"QuoteAsset": "USD",
|
||||
"AssetPrice": 74800,
|
||||
"Scale": 4
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Campos
|
||||
|
||||
| Campo | Tipo JSON | \[Internal Type]\[] | Descripción |
|
||||
| ------------------ | --------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `Account` | String | AccountID | La dirección de la cuenta que crea o actualiza el Oracle. Solo esta cuenta puede actualizarlo o eliminarlo posteriormente. |
|
||||
| `OracleDocumentID` | Number | UInt32 | Un identificador único para este Oracle dentro de la cuenta propietaria. Pueden existir múltiples Oracles por cuenta usando diferentes IDs. |
|
||||
| `Provider` | String | Blob | _(Opcional en actualización; requerido en creación)_ Identificador codificado en hexadecimal del proveedor de Oracle (p. ej. Chainlink, Band). Máximo 256 bytes. |
|
||||
| `URI` | String | Blob | _(Opcional)_ URI codificado en hexadecimal que hace referencia a datos complementarios fuera de la cadena para este Oracle (p. ej. CID de IPFS). Máximo 256 bytes. |
|
||||
| `AssetClass` | String | Blob | _(Opcional en actualización; requerido en creación)_ Categoría codificada en hexadecimal que describe el tipo de activos (p. ej. `63757272656E6379` = "currency"). Máximo 16 bytes. |
|
||||
| `LastUpdateTime` | Number | UInt32 | Marca de tiempo Unix (segundos desde el 1 de enero de 1970) de la última actualización de precio. Debe estar dentro de ±300 segundos del tiempo de cierre del ledger y debe ser estrictamente mayor que el valor almacenado actualmente en actualizaciones. |
|
||||
| `PriceDataSeries` | Array | Array | Array de objetos `PriceData`. Debe contener entre 1 y 10 entradas. En una actualización, los pares sin `AssetPrice` se eliminan del objeto. |
|
||||
|
||||
### Objeto PriceData
|
||||
|
||||
Cada entrada en `PriceDataSeries` es un objeto `PriceData`:
|
||||
|
||||
| Campo | Tipo JSON | \[Internal Type]\[] | Descripción |
|
||||
| ------------ | --------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `BaseAsset` | String | Currency | El activo cuyo precio se publica (p. ej. `"XAH"`, `"BTC"`). |
|
||||
| `QuoteAsset` | String | Currency | La moneda de denominación (p. ej. `"USD"`, `"EUR"`). Debe diferir de `BaseAsset`. |
|
||||
| `AssetPrice` | Number | UInt64 | _(Opcional)_ El precio como número entero escalado. El precio efectivo es `AssetPrice × 10^(-Scale)`. Omitir este campo **elimina** un par existente durante una actualización. |
|
||||
| `Scale` | Number | UInt8 | _(Opcional)_ Exponente decimal usado para derivar el precio efectivo. Valores válidos: 0–10. Por defecto: 0. Ejemplo: `AssetPrice = 74560`, `Scale = 4` → precio efectivo = 7,456. |
|
||||
|
||||
### Reserva
|
||||
|
||||
Las transacciones OracleSet consumen reservas del propietario según el número de pares `PriceData` almacenados:
|
||||
|
||||
| Pares | Reservas del propietario consumidas |
|
||||
| ----- | ----------------------------------- |
|
||||
| 1–5 | 1 |
|
||||
| 6–10 | 2 |
|
||||
|
||||
Si una actualización cambia el número de pares por encima o por debajo del umbral de 5 pares, el recuento del propietario se ajusta automáticamente (±1).
|
||||
|
||||
### Coste especial de transacción
|
||||
|
||||
Las transacciones OracleSet tienen el coste de transacción estándar.
|
||||
|
||||
### Casos de error
|
||||
|
||||
| Código de error | Descripción |
|
||||
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `temDISABLED` | La enmienda PriceOracle no está habilitada. |
|
||||
| `temINVALID_FLAG` | Se especificaron flags inválidos. |
|
||||
| `temMALFORMED` | `Provider`, `URI` o `AssetClass` está vacío o supera la longitud máxima; pares base/quote duplicados en la misma transacción; `BaseAsset` igual a `QuoteAsset`; `Scale` > 10; `Provider` o `AssetClass` no coinciden con los valores almacenados en una actualización; `Provider` o `AssetClass` ausentes en una creación. |
|
||||
| `temARRAY_EMPTY` | `PriceDataSeries` está vacío. |
|
||||
| `temARRAY_TOO_LARGE` | `PriceDataSeries` contiene más de 10 entradas en la transacción. |
|
||||
| `terNO_ACCOUNT` | La cuenta emisora no existe. |
|
||||
| `tecINVALID_UPDATE_TIME` | `LastUpdateTime` está fuera de la ventana de ±300 segundos desde el tiempo de cierre del ledger, es anterior a la marca de tiempo UNIX (segundos desde el 1 de enero de 1970), o no es estrictamente mayor que el valor almacenado en una actualización. |
|
||||
| `tecTOKEN_PAIR_NOT_FOUND` | Un par especificado para eliminación (sin `AssetPrice`) no existe en el objeto Oracle actual. |
|
||||
| `tecARRAY_EMPTY` | El resultado tras aplicar todas las actualizaciones y eliminaciones dejaría `PriceDataSeries` vacío. |
|
||||
| `tecARRAY_TOO_LARGE` | El resultado tras aplicar todas las actualizaciones y adiciones superaría las 10 entradas. |
|
||||
| `tecINSUFFICIENT_RESERVE` | La cuenta no tiene suficiente XAH para cumplir el requisito de reserva para crear el objeto Oracle. |
|
||||
@@ -92,11 +92,11 @@ Cada operación se especifica por la inclusión u omisión de ciertos campos del
|
||||
|
||||
* El Hook Correspondiente no existe _o_ se especifica `FLAG_OVERRIDE`.
|
||||
* El campo `CreateCode` está especificado y no está en blanco y contiene el bytecode WebAssembly válido para un Hook válido.
|
||||
* No existe ninguna instancia del mismo bytecode WebAssembly en el XRPL. (Si existe y todos los demás requisitos se cumplen, se interpreta como una Operación Instalar.)
|
||||
* No existe ninguna instancia del mismo bytecode WebAssembly en Xahau. (Si existe y todos los demás requisitos se cumplen, se interpreta como una Operación Instalar.)
|
||||
|
||||
**Comportamiento**:
|
||||
|
||||
* Se crea un objeto `HookDefinition` con conteo de referencias en el XRPL.
|
||||
* Se crea un objeto `HookDefinition` con conteo de referencias en Xahau.
|
||||
* Se crea un array `Hooks` en la cuenta ejecutante, si no existe ya.
|
||||
* Se crea un objeto `Hook` en la posición del Hook Correspondiente si no existe ya.
|
||||
* El objeto `Hook` apunta a la `HookDefinition`.
|
||||
@@ -156,7 +156,7 @@ Cada operación se especifica por la inclusión u omisión de ciertos campos del
|
||||
* El Hook Correspondiente existe.
|
||||
* `HookHash` está ausente.
|
||||
* `CreateCode` está ausente.
|
||||
* Uno o más de `HookNamespace`, `HookParameters` o `HookGrants` está presente.
|
||||
* Uno o más de `HookNamespace`, `HookParameters`, `HookGrants`, `HookOn`, `HookOnIncoming`, `HookOnOutgoing`, `HookCanEmit` o `HookName` está presente.
|
||||
|
||||
**Ejemplo**:
|
||||
|
||||
@@ -235,17 +235,20 @@ Cada operación se especifica por la inclusión u omisión de ciertos campos del
|
||||
|
||||
### Campos del Hook
|
||||
|
||||
| Campo | Tipo JSON | Tipo Interno | Descripción |
|
||||
| ---------------- | --------- | ------------ | ------------------------------------------------- |
|
||||
| `HookHash` | String | Hash256 | El hash del hook. |
|
||||
| `CreateCode` | String | Blob | El código WebAssembly del hook. |
|
||||
| `HookGrants` | Array | Array | Las concesiones asociadas con el hook. |
|
||||
| `HookNamespace` | String | Hash256 | El espacio de nombres del hook. |
|
||||
| `HookParameters` | Array | Array | Los parámetros del hook. |
|
||||
| `HookOn` | String | Hash256 | Las transacciones en las que se activa el hook. |
|
||||
| `HookCanEmit` | String | Hash256 | Las transacciones que el hook puede emitir. |
|
||||
| `HookApiVersion` | Number | UInt16 | La versión de API del hook. |
|
||||
| `Flags` | Number | UInt32 | Indicadores adicionales para el hook. |
|
||||
| Campo | Tipo JSON | Tipo Interno | Descripción |
|
||||
| ------------------ | --------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `HookHash` | String | Hash256 | El hash del hook. |
|
||||
| `CreateCode` | String | Blob | El código WebAssembly del hook. |
|
||||
| `HookGrants` | Array | Array | Las concesiones asociadas con el hook. |
|
||||
| `HookNamespace` | String | Hash256 | El espacio de nombres del hook. |
|
||||
| `HookParameters` | Array | Array | Los parámetros del hook. |
|
||||
| `HookOn` | String | Hash256 | Las transacciones en las que se activa el hook. Mutuamente exclusivo con `HookOnIncoming`/`HookOnOutgoing`. |
|
||||
| `HookOnIncoming` | String | Hash256 | _(HookOnV2)_ Misma sintaxis que `HookOn`. Activa el hook en transacciones originadas desde otra cuenta. Mutuamente exclusivo con `HookOn`. |
|
||||
| `HookOnOutgoing` | String | Hash256 | _(HookOnV2)_ Misma sintaxis que `HookOn`. Activa el hook en transacciones originadas desde la propia cuenta del Hook. Mutuamente exclusivo con `HookOn`. |
|
||||
| `HookCanEmit` | String | Hash256 | Misma sintaxis que `HookOn`. Controla qué tipos de transacción puede emitir el hook. Si está ausente, el hook puede emitir cualquier tipo. |
|
||||
| `HookName` | String | Blob | _(NamedHooks)_ Un nombre UTF-8 de 4–16 bytes para el hook. Cuando se establece, el hook solo se ejecutará si la transacción entrante incluye un campo `HookName` coincidente. |
|
||||
| `HookApiVersion` | Number | UInt16 | La versión de API del hook. |
|
||||
| `Flags` | Number | UInt32 | Indicadores adicionales para el hook. |
|
||||
|
||||
### Indicadores
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"$comment": "Xahau roadmap source of truth. Edit this file to add/update/remove items. Committed JSON is rendered at build time by src/components/XahauRoadmap.astro — no runtime JS required.",
|
||||
|
||||
"$comment": "Xahau roadmap source of truth. Edit this file to add/update/remove items. Committed JSON is rendered at build time by src/components/XahauRoadmap.astro — no runtime JS required. Card tags come from `labels.<locale>.tags`: set `phase` (and optionally `note`) on an item instead of writing the tag text per locale.",
|
||||
"meta": {
|
||||
"updated": "2026-04-19",
|
||||
"window": {
|
||||
@@ -14,7 +13,6 @@
|
||||
"locales": ["en", "es", "pt-BR"]
|
||||
}
|
||||
},
|
||||
|
||||
"labels": {
|
||||
"en": {
|
||||
"title": "Xahau Roadmap",
|
||||
@@ -54,6 +52,33 @@
|
||||
"partnership": "Partnership",
|
||||
"launch": "Launch / public good"
|
||||
},
|
||||
"tags": {
|
||||
"$comment": "Card tag vocabulary. Items reference these by key via `phase` / `note`; the card renders \"<phase> · <note>\". Edit a word here and it changes everywhere it is used. A `note` is written to agree with the `phase` it follows (gender/number), so check before reusing one under a new phase.",
|
||||
"phases": {
|
||||
"feature": "Feature",
|
||||
"ongoing": "Ongoing",
|
||||
"live": "Live",
|
||||
"ga": "GA",
|
||||
"pilot": "Pilot",
|
||||
"launch": "Launch",
|
||||
"partnerships": "Partnerships",
|
||||
"enterprise": "Enterprise",
|
||||
"event": "Event"
|
||||
},
|
||||
"notes": {
|
||||
"activated": "Activated",
|
||||
"ready-for-amendment": "ready for amendment",
|
||||
"in-development": "in development",
|
||||
"alpha": "in alpha development",
|
||||
"beta": "in beta development",
|
||||
"audits-optimisations": "audits + optimisations",
|
||||
"remittance": "remittance",
|
||||
"payments": "payments",
|
||||
"public-good": "public good",
|
||||
"quarterly": "quarterly",
|
||||
"enterprise-devs": "enterprise + devs"
|
||||
}
|
||||
},
|
||||
"foot": "Directional - subject to change - xahau.network"
|
||||
},
|
||||
"es": {
|
||||
@@ -94,6 +119,33 @@
|
||||
"partnership": "Alianza",
|
||||
"launch": "Lanzamiento / bien público"
|
||||
},
|
||||
"tags": {
|
||||
"$comment": "Card tag vocabulary. Items reference these by key via `phase` / `note`; the card renders \"<phase> · <note>\". Edit a word here and it changes everywhere it is used. A `note` is written to agree with the `phase` it follows (gender/number), so check before reusing one under a new phase.",
|
||||
"phases": {
|
||||
"feature": "Función",
|
||||
"ongoing": "Continuo",
|
||||
"live": "En vivo",
|
||||
"ga": "GA",
|
||||
"pilot": "Piloto",
|
||||
"launch": "Lanzamiento",
|
||||
"partnerships": "Alianzas",
|
||||
"enterprise": "Empresarial",
|
||||
"event": "Evento"
|
||||
},
|
||||
"notes": {
|
||||
"activated": "activada",
|
||||
"ready-for-amendment": "lista para enmienda",
|
||||
"in-development": "en desarrollo",
|
||||
"alpha": "en desarrollo alfa",
|
||||
"beta": "en desarrollo beta",
|
||||
"audits-optimisations": "auditorías y optimizaciones",
|
||||
"remittance": "remesas",
|
||||
"payments": "pagos",
|
||||
"public-good": "bien público",
|
||||
"quarterly": "trimestral",
|
||||
"enterprise-devs": "empresas y desarrolladores"
|
||||
}
|
||||
},
|
||||
"foot": "Orientativo - sujeto a cambios - xahau.network"
|
||||
},
|
||||
"pt-BR": {
|
||||
@@ -134,22 +186,83 @@
|
||||
"partnership": "Parceria",
|
||||
"launch": "Lançamento / bem público"
|
||||
},
|
||||
"tags": {
|
||||
"$comment": "Card tag vocabulary. Items reference these by key via `phase` / `note`; the card renders \"<phase> · <note>\". Edit a word here and it changes everywhere it is used. A `note` is written to agree with the `phase` it follows (gender/number), so check before reusing one under a new phase.",
|
||||
"phases": {
|
||||
"feature": "Funcionalidade",
|
||||
"ongoing": "Contínuo",
|
||||
"live": "Ao vivo",
|
||||
"ga": "GA",
|
||||
"pilot": "Piloto",
|
||||
"launch": "Lançamento",
|
||||
"partnerships": "Parcerias",
|
||||
"enterprise": "Empresarial",
|
||||
"event": "Evento"
|
||||
},
|
||||
"notes": {
|
||||
"activated": "ativada",
|
||||
"ready-for-amendment": "pronta para emenda",
|
||||
"in-development": "em desenvolvimento",
|
||||
"alpha": "em desenvolvimento alfa",
|
||||
"beta": "em desenvolvimento beta",
|
||||
"audits-optimisations": "auditorias e otimizações",
|
||||
"remittance": "remessas",
|
||||
"payments": "pagamentos",
|
||||
"public-good": "bem público",
|
||||
"quarterly": "trimestral",
|
||||
"enterprise-devs": "empresas e desenvolvedores"
|
||||
}
|
||||
},
|
||||
"foot": "Direcional - sujeito a alterações - xahau.network"
|
||||
}
|
||||
},
|
||||
|
||||
"items": [
|
||||
{
|
||||
"id": "price-oracle",
|
||||
"lane": "tech",
|
||||
"status": "feature",
|
||||
"quarter": "2026-Q2",
|
||||
"span": 2,
|
||||
"phase": "feature",
|
||||
"note": "activated",
|
||||
"title": {
|
||||
"en": "PriceOracle",
|
||||
"es": "PriceOracle",
|
||||
"pt-BR": "PriceOracle"
|
||||
},
|
||||
"description": {
|
||||
"en": "Native on-ledger price feed primitive — tamper-resistant asset prices for DeFi, AMM and Hooks.",
|
||||
"es": "Primitiva nativa de precios en el ledger — precios de activos resistentes a manipulación para DeFi, AMM y Hooks.",
|
||||
"pt-BR": "Primitiva nativa de feed de preços no ledger — preços de ativos resistentes a adulterações para DeFi, AMM e Hooks."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "iou-reward-claim",
|
||||
"lane": "tech",
|
||||
"status": "feature",
|
||||
"quarter": "2026-Q2",
|
||||
"endQuarter": "2026-Q3",
|
||||
"phase": "feature",
|
||||
"note": "activated",
|
||||
"title": {
|
||||
"en": "IOURewardClaim",
|
||||
"es": "IOURewardClaim",
|
||||
"pt-BR": "IOURewardClaim"
|
||||
},
|
||||
"description": {
|
||||
"en": "Extends the current RewardClaim for XAH to make it available for IOU tokens as well — letting projects use Hooks to distribute rewards based on a user's token holdings.",
|
||||
"es": "Extiende el RewardClaim actual de XAH para ofrecerlo también a tokens IOU — permitiendo a los proyectos usar Hooks para distribuir recompensas según las tenencias de tokens de un usuario.",
|
||||
"pt-BR": "Estende o RewardClaim atual do XAH para torná-lo disponível também para tokens IOU — permitindo que projetos usem Hooks para distribuir recompensas com base nas posições de tokens de um usuário."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "rng",
|
||||
"lane": "tech",
|
||||
"status": "feature",
|
||||
"quarter": "2026-Q2",
|
||||
"endQuarter": "2026-Q2",
|
||||
"tag": {
|
||||
"en": "Feature · in beta development",
|
||||
"es": "Función · en desarrollo beta",
|
||||
"pt-BR": "Funcionalidade · em desenvolvimento beta"
|
||||
},
|
||||
"endQuarter": "2026-Q3",
|
||||
"phase": "feature",
|
||||
"note": "beta",
|
||||
"title": {
|
||||
"en": "Random Number Generator",
|
||||
"es": "Generador de números aleatorios",
|
||||
@@ -167,11 +280,8 @@
|
||||
"status": "feature",
|
||||
"quarter": "2026-Q2",
|
||||
"endQuarter": "2026-Q3",
|
||||
"tag": {
|
||||
"en": "Feature · in development",
|
||||
"es": "Función · en desarrollo",
|
||||
"pt-BR": "Funcionalidade · em desenvolvimento"
|
||||
},
|
||||
"phase": "feature",
|
||||
"note": "in-development",
|
||||
"title": {
|
||||
"en": "FeatureExport",
|
||||
"es": "FeatureExport",
|
||||
@@ -189,74 +299,32 @@
|
||||
"status": "feature",
|
||||
"quarter": "2026-Q2",
|
||||
"span": 2,
|
||||
"tag": {
|
||||
"en": "Feature · ready for amendment",
|
||||
"es": "Función · lista para enmienda",
|
||||
"pt-BR": "Funcionalidade · pronta para emenda"
|
||||
"phase": "feature",
|
||||
"note": "ready-for-amendment",
|
||||
"title": {
|
||||
"en": "AMM",
|
||||
"es": "AMM",
|
||||
"pt-BR": "AMM"
|
||||
},
|
||||
"title": { "en": "AMM", "es": "AMM", "pt-BR": "AMM" },
|
||||
"description": {
|
||||
"en": "Automated Market Maker primitive for deep native liquidity on the Xahau DEX. Merged into the xahaud dev branch, awaiting amendment vote.",
|
||||
"es": "Primitiva Automated Market Maker para liquidez nativa profunda en el DEX de Xahau. Integrada en la rama dev de xahaud, a la espera de la votación de enmienda.",
|
||||
"pt-BR": "Primitiva de Automated Market Maker para liquidez nativa profunda no DEX da Xahau. Integrada ao branch dev do xahaud, aguardando votação de emenda."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "price-oracle",
|
||||
"lane": "tech",
|
||||
"status": "feature",
|
||||
"quarter": "2026-Q2",
|
||||
"span": 2,
|
||||
"tag": {
|
||||
"en": "Feature · ready for amendment",
|
||||
"es": "Función · lista para enmienda",
|
||||
"pt-BR": "Funcionalidade · pronta para emenda"
|
||||
},
|
||||
"title": {
|
||||
"en": "PriceOracle",
|
||||
"es": "PriceOracle",
|
||||
"pt-BR": "PriceOracle"
|
||||
},
|
||||
"description": {
|
||||
"en": "Native on-ledger price feed primitive — tamper-resistant asset prices for DeFi, AMM and Hooks. Merged into the xahaud dev branch, awaiting amendment vote.",
|
||||
"es": "Primitiva nativa de precios en el ledger — precios de activos resistentes a manipulación para DeFi, AMM y Hooks. Integrada en la rama dev de xahaud, a la espera de la votación de enmienda.",
|
||||
"pt-BR": "Primitiva nativa de feed de preços no ledger — preços de ativos resistentes a adulterações para DeFi, AMM e Hooks. Integrada ao branch dev do xahaud, aguardando votação de emenda."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "iou-reward-claim",
|
||||
"lane": "tech",
|
||||
"status": "feature",
|
||||
"quarter": "2026-Q2",
|
||||
"endQuarter": "2026-Q3",
|
||||
"tag": {
|
||||
"en": "Feature · in development",
|
||||
"es": "Función · en desarrollo",
|
||||
"pt-BR": "Funcionalidade · em desenvolvimento"
|
||||
},
|
||||
"title": {
|
||||
"en": "IOURewardClaim",
|
||||
"es": "IOURewardClaim",
|
||||
"pt-BR": "IOURewardClaim"
|
||||
},
|
||||
"description": {
|
||||
"en": "Extends the current RewardClaim for XAH to make it available for IOU tokens as well — letting projects use Hooks to distribute rewards based on a user's token holdings.",
|
||||
"es": "Extiende el RewardClaim actual de XAH para ofrecerlo también a tokens IOU — permitiendo a los proyectos usar Hooks para distribuir recompensas según las tenencias de tokens de un usuario.",
|
||||
"pt-BR": "Estende o RewardClaim atual do XAH para torná-lo disponível também para tokens IOU — permitindo que projetos usem Hooks para distribuir recompensas com base nas posições de tokens de um usuário."
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "named-hook",
|
||||
"lane": "tech",
|
||||
"status": "feature",
|
||||
"quarter": "2026-Q3",
|
||||
"endQuarter": "2026-Q4",
|
||||
"tag": {
|
||||
"en": "Feature · in development",
|
||||
"es": "Función · en desarrollo",
|
||||
"pt-BR": "Funcionalidade · em desenvolvimento"
|
||||
"phase": "feature",
|
||||
"note": "ready-for-amendment",
|
||||
"title": {
|
||||
"en": "NamedHook",
|
||||
"es": "NamedHook",
|
||||
"pt-BR": "NamedHook"
|
||||
},
|
||||
"title": { "en": "NamedHook", "es": "NamedHook", "pt-BR": "NamedHook" },
|
||||
"description": {
|
||||
"en": "Allows names to be set to identify Hooks, so different Hooks can be invoked even within the same transaction type.",
|
||||
"es": "Permite asignar nombres para identificar Hooks, de modo que se puedan invocar diferentes Hooks incluso dentro del mismo tipo de transacción.",
|
||||
@@ -269,12 +337,13 @@
|
||||
"status": "feature",
|
||||
"quarter": "2026-Q2",
|
||||
"span": 3,
|
||||
"tag": {
|
||||
"en": "Feature · in alpha development",
|
||||
"es": "Función · en desarrollo alfa",
|
||||
"pt-BR": "Funcionalidade · em desenvolvimento alfa"
|
||||
"phase": "feature",
|
||||
"note": "alpha",
|
||||
"title": {
|
||||
"en": "JSHooks",
|
||||
"es": "JSHooks",
|
||||
"pt-BR": "JSHooks"
|
||||
},
|
||||
"title": { "en": "JSHooks", "es": "JSHooks", "pt-BR": "JSHooks" },
|
||||
"description": {
|
||||
"en": "JavaScript runtime for Hooks — write Xahau smart-contract logic in JavaScript alongside the existing WebAssembly runtime, broadening the developer surface.",
|
||||
"es": "Entorno de ejecución JavaScript para Hooks — escribir la lógica de smart contracts en JavaScript junto al entorno WebAssembly existente, ampliando la superficie para desarrolladores.",
|
||||
@@ -287,11 +356,8 @@
|
||||
"status": "feature",
|
||||
"quarter": "2026-Q2",
|
||||
"openEnded": true,
|
||||
"tag": {
|
||||
"en": "Ongoing · audits + optimisations",
|
||||
"es": "Continuo · auditorías y optimizaciones",
|
||||
"pt-BR": "Contínuo · auditorias e otimizações"
|
||||
},
|
||||
"phase": "ongoing",
|
||||
"note": "audits-optimisations",
|
||||
"title": {
|
||||
"en": "Audit & optimisations",
|
||||
"es": "Auditorías y optimizaciones",
|
||||
@@ -303,19 +369,15 @@
|
||||
"pt-BR": "Auditorias de segurança e melhorias de desempenho contínuas no protocolo, Hooks e ferramentas."
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"id": "coopbank-eur",
|
||||
"lane": "rollout",
|
||||
"status": "live",
|
||||
"quarter": "2026-Q2",
|
||||
"openEnded": false,
|
||||
"span": 2,
|
||||
"tag": {
|
||||
"en": "Live · remittance",
|
||||
"es": "En vivo · remesas",
|
||||
"pt-BR": "Ao vivo · remessas"
|
||||
},
|
||||
"openEnded": false,
|
||||
"phase": "live",
|
||||
"note": "remittance",
|
||||
"title": {
|
||||
"en": "COOP Bank EUR corridor scale-up to entire country.",
|
||||
"es": "Escalado del corredor EUR de COOP Bank a todo el país.",
|
||||
@@ -333,7 +395,7 @@
|
||||
"status": "partnership",
|
||||
"quarter": "2026-Q2",
|
||||
"endQuarter": "2026-Q3",
|
||||
"tag": { "en": "Launch", "es": "Lanzamiento", "pt-BR": "Lançamento" },
|
||||
"phase": "launch",
|
||||
"title": {
|
||||
"en": "USD stablecoin on Xahau",
|
||||
"es": "Stablecoin USD en Xahau",
|
||||
@@ -351,7 +413,7 @@
|
||||
"status": "partnership",
|
||||
"quarter": "2026-Q4",
|
||||
"openEnded": true,
|
||||
"tag": { "en": "Launch", "es": "Lanzamiento", "pt-BR": "Lançamento" },
|
||||
"phase": "launch",
|
||||
"title": {
|
||||
"en": "Currencies from multiple countries on Xahau",
|
||||
"es": "Divisas de múltiples países en Xahau",
|
||||
@@ -369,7 +431,7 @@
|
||||
"status": "partnership",
|
||||
"quarter": "2026-Q3",
|
||||
"endQuarter": "2026-Q4",
|
||||
"tag": { "en": "Launch", "es": "Lanzamiento", "pt-BR": "Lançamento" },
|
||||
"phase": "launch",
|
||||
"title": {
|
||||
"en": "GBP stablecoin on Xahau",
|
||||
"es": "Stablecoin GBP en Xahau",
|
||||
@@ -387,7 +449,7 @@
|
||||
"status": "pilot",
|
||||
"quarter": "2026-Q3",
|
||||
"endQuarter": "2026-Q4",
|
||||
"tag": { "en": "Pilot", "es": "Piloto", "pt-BR": "Piloto" },
|
||||
"phase": "pilot",
|
||||
"title": {
|
||||
"en": "USD corridor pilot",
|
||||
"es": "Piloto del corredor USD",
|
||||
@@ -405,7 +467,7 @@
|
||||
"status": "partnership",
|
||||
"quarter": "2026-Q4",
|
||||
"openEnded": true,
|
||||
"tag": { "en": "Partnerships", "es": "Alianzas", "pt-BR": "Parcerias" },
|
||||
"phase": "partnerships",
|
||||
"title": {
|
||||
"en": "Additional bank & remittance partners",
|
||||
"es": "Bancos y socios de remesas adicionales",
|
||||
@@ -423,11 +485,8 @@
|
||||
"status": "live",
|
||||
"quarter": "2027-Q1",
|
||||
"span": 1,
|
||||
"tag": {
|
||||
"en": "GA · remittance",
|
||||
"es": "GA · remesas",
|
||||
"pt-BR": "GA · remessas"
|
||||
},
|
||||
"phase": "ga",
|
||||
"note": "remittance",
|
||||
"title": {
|
||||
"en": "Corridor expansion · GA",
|
||||
"es": "Expansión de corredores · GA",
|
||||
@@ -445,11 +504,8 @@
|
||||
"status": "pilot",
|
||||
"quarter": "2027-Q2",
|
||||
"endQuarter": "2027-Q3",
|
||||
"tag": {
|
||||
"en": "Pilot · payments",
|
||||
"es": "Piloto · pagos",
|
||||
"pt-BR": "Piloto · pagamentos"
|
||||
},
|
||||
"phase": "pilot",
|
||||
"note": "payments",
|
||||
"title": {
|
||||
"en": "Merchant settlement pilot",
|
||||
"es": "Piloto de liquidación para comercios",
|
||||
@@ -461,18 +517,13 @@
|
||||
"pt-BR": "Liquidação com stablecoins e conformidade baseada em Hooks para comerciantes."
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"id": "enterprise-ga",
|
||||
"lane": "rollout",
|
||||
"status": "partnership",
|
||||
"quarter": "2027-Q3",
|
||||
"openEnded": true,
|
||||
"tag": {
|
||||
"en": "Enterprise",
|
||||
"es": "Empresarial",
|
||||
"pt-BR": "Empresarial"
|
||||
},
|
||||
"phase": "enterprise",
|
||||
"title": {
|
||||
"en": "Enterprise settlement GA",
|
||||
"es": "GA de liquidación empresarial",
|
||||
@@ -484,18 +535,14 @@
|
||||
"pt-BR": "Oferta de produção para parceiros regulamentados, construída sobre componentes Hooks auditados."
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"id": "ngo-donations",
|
||||
"lane": "rollout",
|
||||
"status": "launch",
|
||||
"quarter": "2026-Q4",
|
||||
"openEnded": true,
|
||||
"tag": {
|
||||
"en": "Launch · public good",
|
||||
"es": "Lanzamiento · bien público",
|
||||
"pt-BR": "Lançamento · bem público"
|
||||
},
|
||||
"phase": "launch",
|
||||
"note": "public-good",
|
||||
"title": {
|
||||
"en": "NGO donation platform",
|
||||
"es": "Plataforma de donaciones para ONG",
|
||||
@@ -535,11 +582,8 @@
|
||||
"status": "launch",
|
||||
"quarter": "2026-Q2",
|
||||
"openEnded": true,
|
||||
"tag": {
|
||||
"en": "Event · quarterly",
|
||||
"es": "Evento · trimestral",
|
||||
"pt-BR": "Evento · trimestral"
|
||||
},
|
||||
"phase": "event",
|
||||
"note": "quarterly",
|
||||
"title": {
|
||||
"en": "Xahau Connect",
|
||||
"es": "Xahau Connect",
|
||||
@@ -556,11 +600,8 @@
|
||||
"lane": "rollout",
|
||||
"status": "launch",
|
||||
"quarter": "2026-Q4",
|
||||
"tag": {
|
||||
"en": "Event · enterprise + devs",
|
||||
"es": "Evento · empresas y desarrolladores",
|
||||
"pt-BR": "Evento · empresas e desenvolvedores"
|
||||
},
|
||||
"phase": "event",
|
||||
"note": "enterprise-devs",
|
||||
"title": {
|
||||
"en": "InFTF event",
|
||||
"es": "Evento InFTF",
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -221,6 +229,14 @@ export const featuresTranslations = {
|
||||
checks_para2:
|
||||
'Pocas plataformas tienen un instrumento de pago diferido nativo. Sin contratos inteligentes personalizados. Solo una primitiva limpia y simple.',
|
||||
|
||||
// Price Oracles solo
|
||||
oracle_label: 'Feeds de Datos',
|
||||
oracle_h4: 'Price Oracles: Feeds de Precio Nativos en el Ledger',
|
||||
oracle_para1:
|
||||
'Xahau dispone de un sistema de Price Oracle integrado que lleva los precios de activos del mundo real directamente al ledger. Los proveedores de datos autorizados pueden publicar y actualizar precios para cualquier par de activos, y múltiples entradas de oracle pueden agregarse on-chain para derivar un precio de referencia único y fiable — sin depender de contratos inteligentes externos ni middleware fuera de la cadena.',
|
||||
oracle_para2:
|
||||
'Aplicaciones como protocolos DeFi, creadores de mercado automatizados o herramientas de cumplimiento pueden consultar el precio agregado on-ledger a través de una interfaz estandarizada. Dado que los datos del oracle se validan y almacenan como objetos de primera clase del ledger, heredan las mismas garantías de finalidad, auditabilidad y seguridad que cualquier otra transacción en Xahau.',
|
||||
|
||||
// Act III — Governance & Identity
|
||||
act3_label: 'Gobernanza e Identidad',
|
||||
|
||||
|
||||
@@ -29,6 +29,14 @@ export const roadmapItem = z.object({
|
||||
// Ongoing activity with no firm end date. Stretches to the end of the visible
|
||||
// window and renders a "continues" indicator. Overrides `span`/`endQuarter`.
|
||||
openEnded: z.boolean().optional().default(false),
|
||||
// Card tag, built from the shared vocabulary in `labels.<locale>.tags`.
|
||||
// `phase` is the base word ('feature' -> "Feature"), `note` the optional
|
||||
// qualifier ('activated' -> "Activated"); the card renders "phase · note".
|
||||
// Both are keys, not text — translations live in `labels`, not on the item.
|
||||
phase: z.string().min(1).optional(),
|
||||
note: z.string().min(1).optional(),
|
||||
// Escape hatch for one-off tags that aren't part of the vocabulary.
|
||||
// Ignored when `phase` is set. Prefer `phase`/`note` for anything reusable.
|
||||
tag: localized.optional(),
|
||||
title: localized,
|
||||
description: localized.optional(),
|
||||
@@ -59,6 +67,13 @@ export const roadmapLabels = z.object({
|
||||
partnership: z.string(),
|
||||
launch: z.string(),
|
||||
}),
|
||||
// Tag vocabulary — see `phase`/`note` on roadmapItem. Open records so a new
|
||||
// key only has to be added to the JSON, not here; XahauRoadmap.astro fails
|
||||
// the build if an item points at a key that doesn't exist.
|
||||
tags: z.object({
|
||||
phases: z.record(z.string(), z.string()),
|
||||
notes: z.record(z.string(), z.string()),
|
||||
}),
|
||||
foot: z.string(),
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user