Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/olive-pandas-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@mysten/sui': minor
---

Add `listTransactions` and `listEvents` core API methods for querying transactions and events with filters, pagination, and ordering. The methods behave identically across the gRPC, GraphQL, and JSON-RPC transports. The regenerated gRPC protos also add the new `SubscribeTransactions` and `SubscribeEvents` subscription APIs.
113 changes: 113 additions & 0 deletions packages/docs/content/sui/clients/core.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,114 @@ const finalResult = await client.core.waitForTransaction({
});
```

## Query methods

Query methods return pages of transactions or events. They behave identically on every transport,
and share a common set of options:

| Option | Type | Description |
| -------- | ---------------------------------- | ----------------------------------------------------- |
| `filter` | `TransactionFilter \| EventFilter` | Filter to apply (transactions and events) |
| `limit` | `number` | Maximum number of items to return (defaults to 50) |
| `after` | `string \| null` | Return items strictly after this cursor (ascending) |
| `before` | `string \| null` | Return items strictly before this cursor (descending) |
| `order` | `'ascending' \| 'descending'` | Order of results (defaults to `ascending`) |

A filter specifies exactly one predicate. MVR names in `function` and `eventType` predicates are
resolved automatically.

`after` and `before` are exclusive ledger-position bounds, and each page reports the positions of
its first and last items as `startCursor` and `endCursor`. You can provide at most one bound per
query, and the bound implies the traversal direction (`after` reads ascending, `before` reads
descending), so a feed of recent activity can page in both directions from any point:

```typescript
// Fetch the most recent transactions
const latest = await client.core.listTransactions({
filter: { sender: '0xabc...' },
order: 'descending',
limit: 10,
});

// Load older transactions
const older = await client.core.listTransactions({
filter: { sender: '0xabc...' },
before: latest.endCursor,
limit: 10,
});

// Poll for transactions executed since
const newer = await client.core.listTransactions({
filter: { sender: '0xabc...' },
after: latest.startCursor,
});
```

<Callout type="info">
Richer filtering (combined predicates, additional predicates like affected addresses and objects,
and checkpoint ranges on transaction and event queries) is available through the [raw gRPC ledger
service](/sui/clients/grpc#ledger-service) and [raw GraphQL queries](/sui/clients/graphql).
</Callout>

### `listTransactions`

Query transactions matching a filter. Results support the same `include` options as
[`getTransaction`](#gettransaction).

```typescript
const result = await client.core.listTransactions({
filter: { function: '0x2::coin::transfer' },
limit: 10,
include: { effects: true },
});

for (const tx of result.transactions) {
const transaction = tx.Transaction ?? tx.FailedTransaction;
console.log(transaction.digest, tx.$kind);
}

// Paginate
if (result.hasNextPage) {
const nextPage = await client.core.listTransactions({
filter: { function: '0x2::coin::transfer' },
after: result.endCursor,
});
}
```

Transaction filters support one of the following predicates:

| Predicate | Description |
| ---------- | --------------------------------------------------------------------------- |
| `sender` | Transactions sent by an address |
| `function` | Transactions calling a Move function (`pkg`, `pkg::mod`, or `pkg::mod::fn`) |

### `listEvents`

Query events matching a filter. Each event includes its position in the ledger (`transactionDigest`
and `eventIndex`, plus `checkpoint` on transports that can provide it; `checkpoint` is `null` on
JSON-RPC).

```typescript
const result = await client.core.listEvents({
filter: { eventType: '0x2::coin::CoinCreated' },
order: 'descending',
limit: 10,
});

for (const event of result.events) {
console.log(event.eventType, event.transactionDigest, event.json);
}
```

Event filters support one of the following predicates:

| Predicate | Description |
| ------------ | --------------------------------------------------------------------------------- |
| `sender` | Events from transactions sent by an address |
| `emitModule` | Events emitted by a module (`pkg::mod`) |
| `eventType` | Events with types defined in a module (`pkg::mod`) or a fully qualified type name |

## System methods

### `getReferenceGasPrice`
Expand Down Expand Up @@ -613,6 +721,9 @@ const options: SuiClientTypes.GetObjectOptions<{ content: true }> = {
| `TransactionResult` | Success or failure result from execution |
| `TransactionEffects` | Detailed effects from transaction execution |
| `Event` | Emitted event from a transaction |
| `EventEntry` | Queried event with its ledger position |
| `TransactionFilter` | Filter for transaction queries |
| `EventFilter` | Filter for event queries |
| `ObjectOwner` | Union of all owner types |
| `ExecutionStatus` | Success/failure status with error details |
| `DynamicFieldName` | Name identifier for dynamic fields |
Expand Down Expand Up @@ -643,3 +754,5 @@ const options: SuiClientTypes.GetObjectOptions<{ content: true }> = {
| `SignAndExecuteTransactionOptions` | Options for `signAndExecuteTransaction` |
| `GetTransactionOptions` | Options for `getTransaction` |
| `WaitForTransactionOptions` | Options for `waitForTransaction` |
| `ListTransactionsOptions` | Options for `listTransactions` |
| `ListEventsOptions` | Options for `listEvents` |
68 changes: 68 additions & 0 deletions packages/docs/content/sui/clients/grpc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,74 @@ const { response } = await grpcClient.ledgerService.getTransaction({
const { response: epochInfo } = await grpcClient.ledgerService.getEpoch({});
```

The ledger service also provides streaming `listCheckpoints`, `listTransactions`, and `listEvents`
RPCs. For most use cases, prefer the corresponding
[core API query methods](/sui/clients/core#query-methods), which handle pagination and filter
construction for you. The raw RPCs additionally support DNF filters (combined, negated, and
additional predicates like `affected_address` and `package_write`) and checkpoint range bounds that
the core API does not expose:

```typescript
// Transactions that affected an address but were not sent by it:
const stream = grpcClient.ledgerService.listTransactions({
filter: {
terms: [
{
literals: [
{
negated: false,
predicate: {
oneofKind: 'affectedAddress',
affectedAddress: { address: '0xabc...' },
},
},
{
negated: true,
predicate: { oneofKind: 'sender', sender: { address: '0xabc...' } },
},
],
},
],
},
readMask: { paths: ['digest'] },
});

for await (const frame of stream.responses) {
if (frame.transaction) {
console.log(frame.transaction.digest);
}
}
```

### Subscription service

Subscribe to filtered, real-time streams of checkpoints, transactions, or events. Streams begin at
the current tip of the chain:

```typescript
const stream = grpcClient.subscriptionService.subscribeTransactions({
filter: {
terms: [
{
literals: [
{
negated: false,
predicate: { oneofKind: 'sender', sender: { address: '0xabc...' } },
},
],
},
],
},
readMask: { paths: ['digest', 'effects.status'] },
});

for await (const frame of stream.responses) {
if (frame.transaction) {
console.log(frame.transaction.digest);
}
}
```

### State service

```typescript
Expand Down
Loading
Loading