Use high-level package facades for Aftermath data. Use AftermathApi helpers
for general Sui objects, dynamic fields, events, and transaction history.
This guide assumes that you installed aftermath-ts-sdk and its
@mysten/sui 2.x peer dependency. Replace the example object IDs and wallet
address with values that exist on the selected network.
The setup below includes the optional JSON-RPC client because the event and
transaction-history examples need it. Omit jsonRpcClient and the third
AftermathApi argument when you only use gRPC helpers.
import { Aftermath, AftermathApi } from "aftermath-ts-sdk";
import { SuiGrpcClient } from "@mysten/sui/grpc";
import { SuiJsonRpcClient } from "@mysten/sui/jsonRpc";
const bootstrap = await Aftermath.create({ network: "MAINNET" });
const addresses = await bootstrap.getAddresses();
const fullnodeUrl = "https://fullnode.mainnet.sui.io:443";
const grpcClient = new SuiGrpcClient({
network: "mainnet",
baseUrl: fullnodeUrl,
});
const jsonRpcClient = new SuiJsonRpcClient({
network: "mainnet",
url: fullnodeUrl,
});
const api = new AftermathApi(grpcClient, addresses, jsonRpcClient);
AftermathApi construction performs no network I/O. The helper methods do.
The address configuration and both clients must target the same network.
Call fetchObject with an existing object ID:
const objectId = "0x2";
const object = await api.Objects().fetchObject({ objectId });
console.log(object.objectId, object.json);
The return value is a gRPC object view. It is not the JSON-RPC
SuiObjectResponse envelope, so read object.json instead of
object.data.content.fields. fetchObject requests the JSON view by default.
Set withDisplay: true when a caster or caller needs Display output:
const object = await api.Objects().fetchObject({
objectId,
withDisplay: true,
});
fetchObject throws a regular Error when the gRPC fullnode cannot return the
object. It does not return undefined for a missing object.
Use fetchCastObject when the returned object must become an application type:
const castObject = await api.Objects().fetchCastObject({
objectId,
objectFromSuiObjectResponse: (object) => ({
objectId: object.objectId,
objectType: object.type,
}),
});
The caster runs after the gRPC request. The caster receives the gRPC object view,
not a JSON-RPC response. Request withDisplay: true when the caster reads
Display fields.
Pass the owner address and an optional exact Move object type:
const walletAddress = "0x1";
const coinObjectType = "0x2::coin::Coin<0x2::sui::SUI>";
const coinObjects = await api.Objects().fetchOwnedObjects({
walletAddress,
objectType: coinObjectType,
});
fetchOwnedObjects follows gRPC pagination with a maximum request size of 50
objects and returns the accumulated object views. It does not return a cursor.
Use fetchObjectsOfTypeOwnedByAddress when you want the same exact-type query
with that method's name, or use a package facade when the SDK already provides
a typed caster.
Use DynamicFields() when no package facade owns the parent object's field:
const parentObjectId = "0x5";
const fieldPage = await api.DynamicFields().fetchDynamicFieldsOfTypeWithCursor({
parentObjectId,
limit: 50,
});
console.log(fieldPage.dynamicFields, fieldPage.nextCursor);
limit counts fields. nextCursor is a field object ID or null. Pass a
non-null cursor to the next request. Set dynamicFieldType to an exact Move
type string or to a predicate when you need a type filter.
To load a dynamic object field, convert the returned base64 BCS name to the
Uint8Array expected by gRPC:
import { fromBase64 } from "@mysten/sui/utils";
const field = fieldPage.dynamicFields[0];
if (field) {
const fieldObject = await api.DynamicFields().fetchDynamicFieldObject({
parentId: parentObjectId,
name: {
type: field.name.type,
bcs: fromBase64(field.bcsName),
},
});
console.log(fieldObject.objectId);
}
fetchDynamicFieldObject expects name: { type, bcs }. Do not pass the
JSON-RPC form name: { type, value }. Dynamic-field listing and object loading
use gRPC and can throw errors from the configured SuiGrpcClient.
fetchCastEventsWithCursor uses the optional SuiJsonRpcClient because gRPC
does not provide an equivalent to suix_queryEvents:
const eventPage = await api.Events().fetchCastEventsWithCursor<
{ type: string },
{ type: string }
>({
query: { MoveEventType: "0x2::module::Event" },
eventFromEventOnChain: (event) => ({ type: event.type }),
limit: 50,
});
console.log(eventPage.events, eventPage.nextCursor);
Replace the example event type with the fully qualified Move event type that
you want to query. nextCursor is an EventId or null. Pass it to the next
request until it is null. The helper converts the cursor's eventSeq to the
string form required by JSON-RPC.
fetchTransactionsWithCursor queries transactions with the Sui JSON-RPC
filter type:
const transactionPage = await api.Transactions().fetchTransactionsWithCursor({
query: {
filter: { FromAddress: walletAddress },
},
limit: 50,
});
console.log(transactionPage.transactions, transactionPage.nextCursor);
The method requests input, effects, events, balance changes, and object changes
for each returned transaction. Its nextCursor is a transaction digest or
null. Pass that digest to the next request while it is not null.
The low-level api.Wallet().fetchPastTransactions method delegates to this
transaction helper. It also requires the optional JSON-RPC client. The
high-level sdk.Wallet().getPastTransactions method uses the Aftermath HTTP
API instead.
Object and dynamic-field helpers in this guide use SuiGrpcClient. The two
history helpers use the optional SuiJsonRpcClient. If the optional client is
missing, the history helpers throw a configuration Error before making a
request. Low-level faucet and SuiFrens event wrappers use the same optional
client. These low-level helpers do not normalize failures to
AftermathTransportError and do not accept an AbortSignal.
For Aftermath HTTP endpoints and their normalized transport errors, see Handle cancellation and transport errors.