Emit/Prepare update

This commit is contained in:
Ekiserrepé
2026-06-23 16:32:35 +02:00
parent c87deb89a5
commit 4eea0bf01c
5 changed files with 162 additions and 163 deletions

View File

@@ -197,7 +197,7 @@ A port of the XRPL PriceOracle (XLS-47d) standard. Enables on-chain price feeds
##### IOURewardClaim
Expands the [ClaimReward](/docs/protocol-reference/transactions/transaction-types/claimreward) transaction type beyond genesis balance adjustments to issuers of other IOU currencies. The same reward logic (area under the curve of hold time vs. hold amount) is optionally applied to issuer currencies using the `ClaimCurrency` field. 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 actual reward payout is handled by a Hook installed on the issuer account that fires on `ttCLAIM_REWARD`. _(Introduced in 2026.6.21-release+3350)_
Expands the [ClaimReward](/docs/protocol-reference/transactions/transaction-types/claimreward) transaction type beyond genesis balance adjustments to issuers of 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)_
##### fixCronStacking

View File

@@ -39,5 +39,4 @@ The `IOURewardClaim` amendment extends the reward mechanic to IOU currencies iss
| 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 |
| Opt-out flag | `tfOptOut` (flag 1) | Not applicable |
| Issuer restriction | Must be genesis account | Any account with a Hook on `ttCLAIM_REWARD`, except AMM accounts |

View File

@@ -1,114 +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>
<LinkButton href="/docs/hooks/functions/emitted-transaction/emit">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/emit) 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 emits the provided transaction JSON.
* On success, it returns the number of emitted transaction hashes.&#x20;
* 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&#x3C;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>

View File

@@ -1,30 +1,30 @@
---
title: prepare
description: Prepares a transaction for emission by automatically injecting all required emission fields.
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>
<LinkButton href="/docs/hooks/functions/emitted-transaction/emit">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`
_(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 **must not** include emission-specific fields.
* 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-1).
* `etxn_reserve()` must be called before `prepare()`.
With the [HooksUpdate2 amendment](/docs/features/amendments/#hooksupdate2), use [`prepare()`](/docs/hooks/functions/emitted-transaction/emit) 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 number of emitted transaction hashes.&#x20;
* If there is an error, it returns an error code.
</TabItem>
</Tabs>
@@ -33,93 +33,82 @@ _(Requires the [HooksUpdate2 amendment](/docs/features/amendments/#hooksupdate2)
<Tabs>
<TabItem label="C">
```c
int64_t prepare (
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>
### 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);
if (emit(tx, tx_len) < 0)
rollback("Failed to emit!", 15, 1);
```
</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>
### 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>
| 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&#x3C;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&#x3C;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>
| Type | Description |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| int64_t | On success, the number of bytes written to `write_ptr` (the size of the prepared transaction blob). The result can be passed directly as `read_ptr`/`read_len` to `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&#x3C;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>

View File

@@ -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-1).
* `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 field, which should always be the Hook account.
</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&#x3C;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 result can be passed directly as `read_ptr`/`read_len` to `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&#x3C;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>