Skip to content

WASM JavaScript API

The WASM JavaScript API provides a modern, async/await interface to dojo.c functionality compiled to WebAssembly. This API is designed for web applications, Node.js backends, rapid prototyping, and developers who prefer JavaScript/TypeScript.

Getting Started

Installation

# Clone & enter the repository
git clone https://github.com/dojoengine/dojo.c && cd dojo.c
 
# Build WASM module for web clients
wasm-pack build --release --target web
 
# Build for Node.js backends
wasm-pack build --release --target nodejs

Basic Integration

Browser Integration:
<script type="module">
  import init, { ToriiClient } from './pkg/dojo_c.js';
 
  async function setup() {
    await init(); // Initialize WASM module
 
    const client = await new ToriiClient({
      toriiUrl: "http://localhost:8080",
      worldAddress: "0x064613f376f05242dfcc9fe360fa2ce1fdd6b00b1ce73dae2ea649ea118fd9be"
    });
  }
</script>
Node.js Integration:
const { ToriiClient } = require('./pkg/dojo_c');
 
// Node.js polyfills
global.WebSocket = require('ws');
global.WorkerGlobalScope = global;
 
async function main() {
  const client = await new ToriiClient({
    toriiUrl: 'http://127.0.0.1:8080',
    worldAddress: '0x064613f376f05242dfcc9fe360fa2ce1fdd6b00b1ce73dae2ea649ea118fd9be'
  });
 
  const entities = await client.getAllEntities(10);
  console.log(entities);
}

Client Management

Client Configuration

Client functions connect your application to the Dojo world state via Torii (the indexer). Use these to fetch current game state, query historical data, and receive real-time updates as the world changes. This is your read interface to the blockchain.

new ToriiClient(config) Creates a new client instance.

const client = await new ToriiClient({
  toriiUrl: "http://localhost:8080",
  worldAddress: "0x..."
});

Entity Operations

getEntities(query) Queries entities with advanced filtering and pagination.

const query = {
  pagination: {
    limit: 100,
    cursor: undefined,
    direction: "Forward"
  },
  clause: {
    Keys: {
      keys: [playerAddress],
      pattern_matching: "FixedLen",
      models: ["Position", "Health"]
    }
  },
  no_hashed_keys: false,
  historical: false
};
 
const entities = await client.getEntities(query);

getAllEntities(limit?) Fetches all entities with optional limit.

const allEntities = await client.getAllEntities(1000);

onEntityUpdated(clause, callback) Subscribes to real-time entity updates.

const subscription = await client.onEntityUpdated(
  {
    Keys: {
      keys: [undefined], // All entities
      pattern_matching: "VariableLen",
      models: []
    }
  },
  (entityId, models) => {
    console.log('Entity updated:', entityId, models);
  }
);
 
// Cancel subscription when done
subscription.cancel();

updateEntitySubscription(subscription, clauses) Updates an existing entity subscription with new filters.

Event Operations

getEventMessages(query) Queries historical event messages.

const events = await client.getEventMessages({
  pagination: { limit: 50 },
  clause: {
    Keys: {
      keys: [eventSelector],
      pattern_matching: "FixedLen",
      models: []
    }
  },
  historical: true
});

onEventMessageUpdated(clause, callback) Subscribes to real-time event updates.

const eventSub = await client.onEventMessageUpdated(
  {
    Keys: {
      keys: [undefined],
      pattern_matching: "VariableLen",
      models: []
    }
  },
  (entityId, models) => {
    console.log('New event:', entityId, models);
  }
);

onStarknetEvent(clauses, callback) Subscribes to raw Starknet events.

const starknetSub = await client.onStarknetEvent(
  [{
    keys: [eventSelector],
    pattern_matching: "FixedLen",
    models: []
  }],
  (event) => {
    console.log('Starknet event:', event);
  }
);

Token & Asset Operations

getTokens(query) Queries token information.

const tokens = await client.getTokens({
  contract_addresses: ["0x..."], // Optional filter
  token_ids: [],                 // Optional filter
  pagination: { limit: 100 }
});

getTokenBalances(query) Queries token balances.

const balances = await client.getTokenBalances({
  contract_addresses: ["0x..."],
  account_addresses: [playerAddress],
  token_ids: [],
  pagination: { limit: 100 }
});

getTokenCollections(query) Queries token collections (NFT collections).

const collections = await client.getTokenCollections({
  contract_addresses: [],
  pagination: { limit: 50 }
});

onTokenUpdated(contract_addresses, token_ids, callback) Subscribes to token metadata updates.

const tokenSub = await client.onTokenUpdated(
  ["0x..."], // Contract addresses
  [],        // Token IDs (empty for all)
  (token) => {
    console.log('Token updated:', token);
  }
);

onTokenBalanceUpdated(contract_addresses, account_addresses, token_ids, callback) Subscribes to token balance changes.

const balanceSub = await client.onTokenBalanceUpdated(
  ["0x..."],         // Contract addresses
  [playerAddress],   // Account addresses
  [],               // Token IDs
  (balance) => {
    console.log('Balance changed:', balance);
  }
);

Transaction Operations

getTransactions(query) Queries transaction history.

const transactions = await client.getTransactions({
  filter: {
    transaction_hashes: [],
    caller_addresses: [playerAddress],
    contract_addresses: [],
    entrypoints: ["move", "attack"],
    from_block: undefined,
    to_block: undefined
  },
  pagination: { limit: 100 }
});

onTransaction(filter, callback) Subscribes to new transactions.

const txSub = await client.onTransaction(
  {
    caller_addresses: [playerAddress],
    entrypoints: ["move"]
  },
  (transaction) => {
    console.log('New transaction:', transaction);
  }
);

Controller Operations

getControllers(query) Queries controller information.

const controllers = await client.getControllers({
  contract_addresses: [],
  pagination: { limit: 100 }
});

Messaging Operations

publishMessage(message, signature) Publishes a single message.

await client.publishMessage(
  {
    message: "Hello, Dojo!",
    signature: await signMessage(message)
  }
);

publishMessageBatch(messages) Publishes multiple messages in a batch.

await client.publishMessageBatch([
  { message: "Message 1", signature: sig1 },
  { message: "Message 2", signature: sig2 }
]);

Indexer Updates

onIndexerUpdated(callback) Subscribes to indexer synchronization updates.

const indexerSub = await client.onIndexerUpdated((update) => {
  console.log('Indexer update:', update);
});

Subscription Management

updateEntitySubscription(subscription, clause) Updates an existing entity subscription with new filtering criteria.

updateEventMessageSubscription(subscription, clause) Updates an existing event message subscription with new filtering criteria.

updateTokenBalanceSubscription(subscription, contract_addresses, account_addresses, token_ids) Updates an existing token balance subscription with new addresses and token IDs.

Account Operations

Account functions handle the write side of blockchain interaction. Use these to execute game transactions, manage player accounts, and handle cryptographic operations like signing and verification.

Signing Key Operations

SigningKey.fromRandom() Generates a new random signing key.

import { SigningKey } from './pkg/dojo_c.js';
 
const signingKey = SigningKey.fromRandom();
const secretScalar = signingKey.secretScalar();
const verifyingKey = signingKey.verifyingKey();

Provider & Account Operations

new Provider(rpc_url) Creates a new JSON-RPC provider.

import { Provider } from './pkg/dojo_c.js';
 
const provider = await new Provider("http://localhost:5050");
const chainId = await provider.chainId();
Account Operations:
import { Account, SigningKey } from './pkg/dojo_c.js';
 
// Create account with private key string
const signingKey = SigningKey.fromRandom();
const privateKeyHex = signingKey.secretScalar();
const account = await new Account(provider, privateKeyHex, address);
 
// Execute transactions
const txHash = await account.executeRaw([{
  to: "0x...",
  selector: "move",
  calldata: ["0x1", "0x2"]
}]);
 
// Deploy burner account with private key string
const burnerKey = SigningKey.fromRandom();
const burnerPrivateKey = burnerKey.secretScalar();
const burner = await account.deployBurner(burnerPrivateKey);

Data Utilities

ByteArray class - For handling Cairo byte arrays:

import { ByteArray } from './pkg/dojo_c.js';
 
const byteArray = new ByteArray("Hello, Dojo!");
const raw = byteArray.toRaw(); // Convert to field elements
const restored = ByteArray.fromRaw(raw); // Restore from field elements

TypedData class - For encoding typed data:

import { TypedData } from './pkg/dojo_c.js';
 
const typedData = new TypedData(JSON.stringify(typedDataObject));
const encoded = typedData.encode(accountAddress);
Provider utilities:
const result = await provider.call(call, blockId);
const chainId = await provider.chainId();

Utility Functions

Cryptographic Functions

poseidonHash(inputs) Computes Poseidon hash of field elements.

import { poseidonHash } from './pkg/dojo_c.js';
 
const hash = poseidonHash([
  "0x123...",
  "0x456..."
]);

starknetKeccak(data) Computes Starknet-compatible Keccak hash.

import { starknetKeccak } from './pkg/dojo_c.js';
 
const data = new Uint8Array(Buffer.from("move", "utf8"));
const hash = starknetKeccak(data);

getSelectorFromName(name) Gets contract function selector from name.

import { getSelectorFromName } from './pkg/dojo_c.js';
 
const selector = getSelectorFromName("move");

getSelectorFromTag(tag) Gets selector from Dojo tag.

import { getSelectorFromTag } from './pkg/dojo_c.js';
 
const selector = getSelectorFromTag("dojo_starter-Position");

Address & Encoding Functions

getContractAddress(class_hash, salt, constructor_calldata, deployer_address) Computes contract address for deployment.

import { getContractAddress } from './pkg/dojo_c.js';
 
const address = getContractAddress(
  classHash,
  salt,
  constructorCalldata,
  deployerAddress
);

cairoShortStringToFelt(str) Converts Cairo short string to felt.

parseCairoShortString(felt) Parses felt as Cairo short string.

Common Issues

WASM Initialization:
// Always await init() before using any functions
await init();
Node.js Compatibility:
// Required polyfills for Node.js
global.WebSocket = require('ws');
global.WorkerGlobalScope = global;
Subscription Management:
// Cancel subscriptions to prevent memory leaks
subscription.cancel();

Type Safety: Consider using TypeScript for better development experience:

import { ToriiClient, ClientConfig } from './pkg/dojo_c';
 
const config: ClientConfig = {
  toriiUrl: "http://localhost:8080",
  worldAddress: "0x..."
};
 
const client = await new ToriiClient(config);