ERCs

ERC-1155 — Multi-Token Standard

eips.ethereum.org/EIPS/eip-1155

One contract, many token IDs. Each ID can be fungible (supply > 1) or non-fungible (supply = 1). The interesting primitives are the batch operations — atomic transfers and balance reads across many IDs in one call.

import {
  balanceOf,
  balanceOfBatch,
  safeTransferFrom,
  safeBatchTransferFrom,
  setApprovalForAll,
  isApprovedForAll,
} from "@ethernauta/erc/1155";

void balanceOf;
void balanceOfBatch;
void safeTransferFrom;
void safeBatchTransferFrom;
void setApprovalForAll;
void isApprovedForAll;

Core methods

MethodShapePurpose
balanceOf({ owner, id })Callable<Uint256>Balance for one ID.
balanceOfBatch({ owners, ids })Callable<Uint256[]>Batched balance read.
safeTransferFrom({ from, to, id, amount, data? })Signable<Hash32>Single-ID transfer.
safeBatchTransferFrom({ from, to, ids, amounts, data? })Signable<Hash32>Atomic multi-ID transfer.
setApprovalForAll({ operator, approved })Signable<Hash32>Operator approval.
isApprovedForAll({ owner, operator })Callable<boolean>Read operator approval.

Extensions

SubpathMethods
@ethernauta/erc/1155/metadata_uriuri({ id })

Batch reads

import { parse } from "valibot";
import type { Bytes } from "@ethernauta/core";
import { AddressSchema, Uint256Schema } from "@ethernauta/core";
import { balanceOfBatch } from "@ethernauta/erc/1155";
import { eth_call } from "@ethernauta/eth";
import { contract, create_reader, encode_chain_id, http } from "@ethernauta/transport";
import { eip155_1 } from "@ethernauta/chain/eip155-1";

const CHAIN_ID = encode_chain_id({ namespace: "eip155", reference: eip155_1.chainId });
const reader = create_reader([
  { chainId: CHAIN_ID, transports: [http("https://ethereum-rpc.publicnode.com")] },
]);

const collection = parse(AddressSchema, "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D");
const me = parse(AddressSchema, "0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
const id1 = parse(Uint256Schema, "0x1");
const id2 = parse(Uint256Schema, "0x2");
const id3 = parse(Uint256Schema, "0x3");

const callable = balanceOfBatch({
  accounts: [me, me, me],
  ids: [id1, id2, id3],
})(contract({ chain_id: CHAIN_ID, to: collection }));

const result_bytes: Bytes = await eth_call([{ to: callable.to, input: callable.data }])(
  reader({ chain_id: CHAIN_ID }),
);
const balances = callable.decode(result_bytes);
// → [Uint256, Uint256, Uint256]
void balances;

One eth_call, one decoded array. No need for client-side multicall.

See also

  • ERC-721 — single-token NFT alternative.
  • ERC-165 — interface detection.