Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .changeset/tricky-pianos-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
"@cartesi/rpc": major
"@cartesi/client": major
"@cartesi/react": major
---

Track the JSON-RPC API changes of rollups-node.

New methods:

- `cartesi_getEpochByVirtualIndex` — fetch an epoch by its dense insertion rank, exposed as `getEpochByVirtualIndex` / `useEpochByVirtualIndex`.
- `cartesi_getExecutedOutputCount` and `cartesi_getPendingExecutableOutputCount`, exposed as `getExecutedOutputCount` / `useExecutedOutputCount` and `getPendingExecutableOutputCount` / `usePendingExecutableOutputCount`. The executed count is monotone and meant to be polled for change detection; the pending count is a gauge and is not.
- `cartesi_getNodeInfo` — chain ID, node version and the node's default block tag in one call, exposed as `getNodeInfo` / `useNodeInfo`. It replaces `getChainId` and `getNodeVersion`, which the node deprecated and which are now marked `@deprecated`.

New filters on the listing methods:

- `from` and `to`, an inclusive index range, on `listEpochs`, `listInputs`, `listOutputs` and `listReports`.
- `listEpochs` takes a list of statuses (`status?: EpochStatus | NonEmptyArray<EpochStatus>`), so unsettled epochs can be watched by filtering on the non-terminal ones.
- `listOutputs` takes a list of output types (`outputType?: OutputType | NonEmptyArray<OutputType>`) and a new `executed?: boolean` filter. Because executions happen out of index order, `executed` must not be used to build a resume cursor keyed on the output index — poll `getExecutedOutputCount` instead.

The node rejects an empty filter list with invalid params, so both list-valued filters use the new `NonEmptyArray` type exported by `@cartesi/rpc` (and re-exported by `@cartesi/client`): `status: []` and `outputType: []` are compile errors rather than failed requests.

Input completion changes:

- `InputStatus` lost its resource-limit members. The node collapsed `OUTPUTS_LIMIT_EXCEEDED`, `REPORTS_LIMIT_EXCEEDED`, `CYCLE_LIMIT_EXCEEDED`, `TIME_LIMIT_EXCEEDED` and `PAYLOAD_LENGTH_LIMIT_EXCEEDED` into the remaining outcomes, so the union is now `NONE | ACCEPTED | REJECTED | EXCEPTION | MACHINE_HALTED`. Code that switches on the removed members no longer compiles; `waitForInput` with `rejectErrors` now aborts on `EXCEPTION`, `MACHINE_HALTED` and `REJECTED`, which is every terminal status other than `ACCEPTED`.
- `Input` gained `exceptionData: Hex | null` (`exception_data` on the wire), the raw guest-provided CMIO exception payload. It is non-null only when `status` is `EXCEPTION`, and an empty payload is `0x`. The bytes are passed through undecoded.

Breaking changes:

- `cartesi_getMatchAdvanced` was renamed to `cartesi_getMatchAdvance`, following the node. The `getMatchAdvanced` action is now `getMatchAdvance`, the `useMatchAdvanced` hook is now `useMatchAdvance` (with `matchAdvanceOptions` / `matchAdvanceQueryKey`), and `GetMatchAdvancedParams` / `GetMatchAdvancedReturnType` are now `GetMatchAdvanceParams` / `GetMatchAdvanceReturnType`.
- The node's application-level error codes moved out of the JSON-RPC reserved range: application not found is now `-31002` (was `-32002`) and resource not found is now `-31001` (was `-32001`). `@cartesi/rpc` exports them as `errorCodes`, along with the new batch (`-32040`), timeout (`-32070`), response-size-limit (`-31003`) and batch-list-work (`-31004`) codes, plus the `maxBatchSize`, `maxBatchListWork` and `defaultListLimit` constants that bound a batch.
39 changes: 39 additions & 0 deletions apps/docs/pages/client/getEpochByVirtualIndex.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# getEpochByVirtualIndex

Fetches a single epoch by its virtual index, which is the epoch's dense
insertion rank — 0, 1, 2, … with no gaps by construction. Use it to walk the
epochs of an application contiguously, where the epoch index itself can skip
values.

## Usage

```ts twoslash
import { http } from "viem";
import { createCartesiPublicClient } from "@cartesi/client";

const publicClientL2 = createCartesiPublicClient({
transport: http("http://127.0.0.1:6751/rpc"),
});

const epoch = await publicClientL2.getEpochByVirtualIndex({
application: "0x...",
virtualIndex: 42n,
});
```

## Parameters

```ts twoslash
import type { GetEpochByVirtualIndexParams } from "@cartesi/client";
// {
// application: Address | string;
// virtualIndex: bigint;
// }
```

## Return Type

```ts twoslash
import type { GetEpochByVirtualIndexReturnType, Epoch } from "@cartesi/client";
// GetEpochByVirtualIndexReturnType = Epoch;
```
46 changes: 46 additions & 0 deletions apps/docs/pages/client/getExecutedOutputCount.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# getExecutedOutputCount

Number of outputs of an application that were already executed.

The count is monotone, so an unchanged value means no new executions have been
observed and it is a sound change signal to poll. When it changes, re-query the
bounded executable-output working set with
[`listOutputs`](/client/listOutputs) using `executed: false` and
`outputType: ["Voucher", "DelegateCallVoucher"]`, then diff that pending set
against the previous result to identify the executions.

Neither this count, nor an output index, nor a pagination offset is a valid
resume cursor: executions are observed out of output-index order, so a late
execution can land behind one. The node documents a race-free execution cursor
as expected in a future ingestion API.

## Usage

```ts twoslash
import { http } from "viem";
import { createCartesiPublicClient } from "@cartesi/client";

const publicClientL2 = createCartesiPublicClient({
transport: http("http://127.0.0.1:6751/rpc"),
});

const executedOutputCount = await publicClientL2.getExecutedOutputCount({
application: "0x...",
});
```

## Parameters

```ts twoslash
import type { GetExecutedOutputCountParams } from "@cartesi/client";
// {
// application: Address | string;
// }
```

## Return Type

```ts twoslash
import type { GetExecutedOutputCountReturnType } from "@cartesi/client";
// GetExecutedOutputCountReturnType = bigint;
```
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# getMatchAdvanced
# getMatchAdvance

## Usage

Expand All @@ -10,7 +10,7 @@ const publicClientL2 = createCartesiPublicClient({
transport: http("http://127.0.0.1:6751/rpc"),
});

const matchAdvanced = await publicClientL2.getMatchAdvanced({
const matchAdvance = await publicClientL2.getMatchAdvance({
application: "0x...",
epochIndex: 1n,
tournamentAddress: "0x...",
Expand All @@ -22,7 +22,7 @@ const matchAdvanced = await publicClientL2.getMatchAdvanced({
## Parameters

```ts twoslash
import type { GetMatchAdvancedParams } from "@cartesi/client";
import type { GetMatchAdvanceParams } from "@cartesi/client";
// {
// application: Address | string;
// epochIndex: bigint;
Expand All @@ -35,6 +35,6 @@ import type { GetMatchAdvancedParams } from "@cartesi/client";
## Return Type

```ts twoslash
import type { GetMatchAdvancedReturnType, MatchAdvanced } from "@cartesi/client";
// GetMatchAdvancedReturnType = MatchAdvanced;
import type { GetMatchAdvanceReturnType, MatchAdvanced } from "@cartesi/client";
// GetMatchAdvanceReturnType = MatchAdvanced;
```
30 changes: 30 additions & 0 deletions apps/docs/pages/client/getNodeInfo.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# getNodeInfo

Fetches the chain ID, the semantic node version and the blockchain block tag the
node reads the base layer at, in a single call.

It replaces `getChainId` and `getNodeVersion`, which are both deprecated.

## Usage

```ts twoslash
import { http } from "viem";
import { createCartesiPublicClient } from "@cartesi/client";

const publicClientL2 = createCartesiPublicClient({
transport: http("http://127.0.0.1:6751/rpc"),
});

const { chainId, version, defaultBlock } = await publicClientL2.getNodeInfo();
```

## Return Type

```ts twoslash
import type { GetNodeInfoReturnType, NodeInfo } from "@cartesi/client";
// NodeInfo = {
// chainId: number;
// version: string;
// defaultBlock: DefaultBlock; // FINALIZED | SAFE | LATEST | PENDING
// }
```
40 changes: 40 additions & 0 deletions apps/docs/pages/client/getPendingExecutableOutputCount.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# getPendingExecutableOutputCount

Number of executable outputs of an application that are still pending execution.

This is a gauge, not a change signal or a resume cursor: it grows with new
executable outputs and shrinks with executions, so it can return to a previous
value while work happened in between. Poll
[`getExecutedOutputCount`](/client/getExecutedOutputCount) instead and diff the
pending set on change.

## Usage

```ts twoslash
import { http } from "viem";
import { createCartesiPublicClient } from "@cartesi/client";

const publicClientL2 = createCartesiPublicClient({
transport: http("http://127.0.0.1:6751/rpc"),
});

const pending = await publicClientL2.getPendingExecutableOutputCount({
application: "0x...",
});
```

## Parameters

```ts twoslash
import type { GetPendingExecutableOutputCountParams } from "@cartesi/client";
// {
// application: Address | string;
// }
```

## Return Type

```ts twoslash
import type { GetPendingExecutableOutputCountReturnType } from "@cartesi/client";
// GetPendingExecutableOutputCountReturnType = bigint;
```
10 changes: 8 additions & 2 deletions apps/docs/pages/client/listEpochs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const { data, pagination } = await publicClientL2.listEpochs({
application: "0x...",
limit: 10,
offset: 0,
// status (optional)
// status, from, to (optional)
});
```

Expand All @@ -24,7 +24,9 @@ const { data, pagination } = await publicClientL2.listEpochs({
import type { ListEpochsParams } from "@cartesi/client";
// {
// application: Address | string;
// status?: EpochStatus;
// status?: EpochStatus | NonEmptyArray<EpochStatus>;
// from?: bigint;
// to?: bigint;
// limit?: number;
// offset?: number;
// descending?: boolean;
Expand All @@ -40,3 +42,7 @@ import type { ListEpochsReturnType, Epoch, Pagination } from "@cartesi/client";
// pagination: Pagination;
// }
```

The node rejects an empty status list with invalid params, so `status` is typed
as a non-empty array — `status: []` is a compile error rather than a failed
request.
4 changes: 3 additions & 1 deletion apps/docs/pages/client/listInputs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const { data, pagination } = await publicClientL2.listInputs({
application: "0x...",
limit: 10,
offset: 0,
// epochIndex, sender (optional)
// epochIndex, sender, from, to (optional)
});
```

Expand All @@ -27,6 +27,8 @@ import type { ListInputsParams } from "@cartesi/client";
// epochIndex?: bigint;
// sender?: Address;
// transactionHash?: Hash;
// from?: bigint;
// to?: bigint;
// limit?: number;
// offset?: number;
// descending?: boolean;
Expand Down
35 changes: 33 additions & 2 deletions apps/docs/pages/client/listOutputs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const { data, pagination } = await publicClientL2.listOutputs({
application: "0x...",
limit: 10,
offset: 0,
// epochIndex, inputIndex, outputType, voucherAddress (optional)
// epochIndex, inputIndex, outputType, voucherAddress, from, to, executed (optional)
});
```

Expand All @@ -26,14 +26,45 @@ import type { ListOutputsParams } from "@cartesi/client";
// application: Address | string;
// epochIndex?: bigint;
// inputIndex?: bigint;
// outputType?: OutputType;
// outputType?: OutputType | NonEmptyArray<OutputType>;
// voucherAddress?: Address;
// from?: bigint;
// to?: bigint;
// executed?: boolean;
// limit?: number;
// offset?: number;
// descending?: boolean;
// }
```

`outputType` accepts a list, and `executed` filters by execution status, so the
outputs still waiting to be executed can be fetched in one call. The node
rejects an empty list with invalid params, so the list is typed as a non-empty
array — `outputType: []` is a compile error rather than a failed request:

```ts twoslash
import { http } from "viem";
import { createCartesiPublicClient } from "@cartesi/client";

const publicClientL2 = createCartesiPublicClient({
transport: http("http://127.0.0.1:6751/rpc"),
});
// ---cut---
const { data: pending } = await publicClientL2.listOutputs({
application: "0x...",
outputType: ["Voucher", "DelegateCallVoucher"],
executed: false,
});
```

::::warning
Executions happen out of index order — an old voucher can be executed long after
newer ones — so a resume cursor keyed on the output index over this filter
silently skips those late executions. Poll
[`getExecutedOutputCount`](/client/getExecutedOutputCount) for change detection
instead.
::::

## Return Type

```ts twoslash
Expand Down
4 changes: 3 additions & 1 deletion apps/docs/pages/client/listReports.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const { data, pagination } = await publicClientL2.listReports({
application: "0x...",
limit: 10,
offset: 0,
// epochIndex, inputIndex (optional)
// epochIndex, inputIndex, from, to (optional)
});
```

Expand All @@ -26,6 +26,8 @@ import type { ListReportsParams } from "@cartesi/client";
// application: Address | string;
// epochIndex?: bigint;
// inputIndex?: bigint;
// from?: bigint;
// to?: bigint;
// limit?: number;
// offset?: number;
// descending?: boolean;
Expand Down
29 changes: 29 additions & 0 deletions apps/docs/pages/react/useEpochByVirtualIndex.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# useEpochByVirtualIndex

Fetches a single epoch by its virtual index, which is the epoch's dense
insertion rank — 0, 1, 2, … with no gaps by construction.

## Usage

```tsx twoslash
import { useEpochByVirtualIndex } from "@cartesi/react";

function Example() {
const { data, isLoading } = useEpochByVirtualIndex({
application: "0x...",
virtualIndex: 42n,
});
// render logic
}
```

## Return Type

The `data` is an `Epoch`:

```ts twoslash
import type {
Epoch,
GetEpochByVirtualIndexReturnType,
} from "@cartesi/client";
```
5 changes: 4 additions & 1 deletion apps/docs/pages/react/useEpochs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ function Example() {
The hook can filter results by:

- `application: Address | string`
- `status?: EpochStatus`
- `status?: EpochStatus | NonEmptyArray<EpochStatus>` — an empty list is not a
valid filter, and does not compile
- `from?: bigint` — inclusive lower bound on the epoch index
- `to?: bigint` — inclusive upper bound on the epoch index

```ts twoslash
import type {
Expand Down
Loading
Loading