Working with Atoms
Conceptual overview: Atoms Fundamentals
Atoms are unique identifiers for any entityβpeople, concepts, smart contracts, or data. This guide covers all ways to create and query atoms using the SDK.
SDK read helpers use the mainnet GraphQL API by default. The write examples on this page use Intuition Testnet, so configure reads once before calling a read helper:
import { configureSdk } from '@0xintuition/sdk';
import { API_URL_DEV } from '@0xintuition/graphql';
configureSdk({ apiUrl: API_URL_DEV });
Atom creation helpers dynamically fetch and forward the required atom base cost. Their optional amount is an additional TRUST/tTRUST deposit (signal), not the required base cost.
Table of Contentsβ
- Creating from Strings
- Creating from Thing (JSON-LD)
- Creating from Ethereum Accounts
- Creating from Smart Contracts
- Creating from IPFS
- Batch Creation
- Querying Atoms
Creating from Stringsβ
The simplest way to create an atom is from a plain string.
Function Signatureβ
function createAtomFromString(
config: WriteConfig,
data: string,
depositAmount?: bigint,
): Promise<AtomCreationResult>;
Parametersβ
| Parameter | Type | Description | Required |
|---|---|---|---|
config | WriteConfig | Client configuration with wallet, public client, and contract address | Yes |
data | string | The text string to create an atom from | Yes |
depositAmount | bigint | Optional additional deposit/signal amount in wei | No |
Basic Exampleβ
import {
createAtomFromString,
getMultiVaultAddressFromChainId,
intuitionTestnet,
} from '@0xintuition/sdk';
import { createPublicClient, createWalletClient, http, parseEther } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
// Setup clients
const account = privateKeyToAccount('0x...');
const publicClient = createPublicClient({
chain: intuitionTestnet,
transport: http(),
});
const walletClient = createWalletClient({
chain: intuitionTestnet,
transport: http(),
account,
});
const address = getMultiVaultAddressFromChainId(intuitionTestnet.id);
// Create atom
const atom = await createAtomFromString(
{ walletClient, publicClient, address },
'developer',
parseEther('0.01'), // Optional: additional 0.01 tTRUST signal
);
console.log('Atom ID:', atom.state.termId);
console.log('Transaction:', atom.transactionHash);
Common Use Casesβ
Creating Tags or Labelsβ
const tag = await createAtomFromString(
{ walletClient, publicClient, address },
'blockchain',
);
Creating Simple Identifiersβ
const identifier = await createAtomFromString(
{ walletClient, publicClient, address },
'user-role-admin',
);
Creating Predicates for Triplesβ
// Create predicate atoms for relationships
const hasSkill = await createAtomFromString(
{ walletClient, publicClient, address },
'hasSkill',
);
const worksOn = await createAtomFromString(
{ walletClient, publicClient, address },
'worksOn',
);
Best Practicesβ
1. Use Descriptive Stringsβ
// Good - clear and descriptive
await createAtomFromString(config, 'JavaScript Developer');
// Avoid - too vague
await createAtomFromString(config, 'dev');
2. Check for Existing Atomsβ
Before creating an atom, check if it already exists:
import {
calculateAtomId,
configureSdk,
createAtomFromString,
getAtomDetails,
type WriteConfig,
} from '@0xintuition/sdk';
import { API_URL_DEV } from '@0xintuition/graphql';
import { toHex } from 'viem';
configureSdk({ apiUrl: API_URL_DEV });
async function createDeveloperAtom(config: WriteConfig) {
const atomId = calculateAtomId(toHex('developer'));
const existing = await getAtomDetails(atomId);
if (existing !== null) {
console.log('Atom already exists:', atomId);
return existing;
}
return createAtomFromString(config, 'developer');
}
Creating from Thingβ
Create atoms from structured JSON-LD objects for rich metadata.
Function Signatureβ
function createAtomFromThing(
config: WriteConfig,
data: PinThingMutationVariables,
options?: CreateAtomFromThingOptions | bigint,
): Promise<AtomCreationResult>;
Thing Object Structureβ
type Thing = {
name: string; // Display name
description: string; // Detailed description
image: string; // Image URL
url: string; // Primary URL/website
};
Basic Exampleβ
import {
configureSdk,
createAtomFromThing,
type WriteConfig,
} from '@0xintuition/sdk';
import { parseEther } from 'viem';
configureSdk({
pinApiKey: process.env.INTUITION_PIN_API_KEY,
});
async function createProjectAtom(config: WriteConfig) {
const atom = await createAtomFromThing(
config,
{
url: 'https://www.example.com',
name: 'Example Project',
description: 'A great Web3 project',
image: 'https://example.com/logo.png',
},
{ depositAmount: parseEther('0.05') },
);
console.log('Atom ID:', atom.state.termId);
console.log('IPFS URI:', atom.uri); // ipfs://bafkrei...
return atom;
}
Common Use Casesβ
Creating Organization Atomsβ
const organization = await createAtomFromThing(
{ walletClient, publicClient, address },
{
name: 'Acme Corporation',
description: 'Leading blockchain solutions provider',
url: 'https://acme.com',
image: 'https://acme.com/brand.png',
},
);
Creating Person Atomsβ
const person = await createAtomFromThing(
{ walletClient, publicClient, address },
{
name: 'Alice Johnson',
description: 'Blockchain developer and researcher',
image: 'https://example.com/alice.jpg',
url: 'https://example.com/alice',
},
);
How It Worksβ
- Pin to IPFS: The Thing object is automatically pinned to IPFS via the Intuition pinning service using your configured
pinApiKey - Generate URI: An IPFS URI is generated (e.g.,
ipfs://bafkrei...) - Create Atom: The atom is created with the IPFS URI as its data
- Return: Returns the atom details with the IPFS URI
Creating from Ethereum Accountsβ
Create atoms representing Ethereum wallet addresses.
Function Signatureβ
function createAtomFromEthereumAccount(
config: WriteConfig,
address: Address,
deposit?: bigint,
): Promise<AtomCreationResult>;
Basic Exampleβ
import {
createAtomFromEthereumAccount,
type WriteConfig,
} from '@0xintuition/sdk';
import { parseEther } from 'viem';
async function createIdentityAtom(config: WriteConfig) {
const atom = await createAtomFromEthereumAccount(
config,
'0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
parseEther('0.01'),
);
console.log('Identity Atom ID:', atom.state.termId);
console.log('Address:', atom.uri);
return atom;
}
Common Use Casesβ
Creating User Identity Atomsβ
// Create atom for user's wallet
const userAtom = await createAtomFromEthereumAccount(
{ walletClient, publicClient, address },
walletClient.account.address,
);
Building Social Graphsβ
// Create atoms for follower relationships
const alice = await createAtomFromEthereumAccount(config, '0xAlice...');
const bob = await createAtomFromEthereumAccount(config, '0xBob...');
// Then create a "follows" triple
const follows = await createAtomFromString(config, 'follows');
const triple = await createTripleStatement(config, {
args: [
[alice.state.termId],
[follows.state.termId],
[bob.state.termId],
[parseEther('0.1')],
],
value: parseEther('0.1'),
});
Creating from Smart Contractsβ
Create atoms representing smart contract addresses.
Function Signatureβ
function createAtomFromSmartContract(
config: WriteConfig,
contract: { address: Address; chainId: number },
deposit?: bigint,
): Promise<AtomCreationResult>;
Basic Exampleβ
import {
createAtomFromSmartContract,
type WriteConfig,
} from '@0xintuition/sdk';
import { parseEther } from 'viem';
async function createUniswapAtom(config: WriteConfig) {
const uniswap = await createAtomFromSmartContract(
config,
{
address: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984', // UNI token
chainId: 1,
},
parseEther('0.01'),
);
console.log('Contract Atom ID:', uniswap.state.termId);
console.log('Contract URI:', uniswap.uri); // caip10:eip155:1:0x...
return uniswap;
}
Common Use Casesβ
Creating Protocol Atomsβ
// Create atoms for DeFi protocols
const aave = await createAtomFromSmartContract(
config,
{
address: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9', // AAVE token
chainId: 1,
},
);
const compound = await createAtomFromSmartContract(
config,
{
address: '0xc00e94Cb662C3520282E6f5717214004A7f26888', // COMP token
chainId: 1,
},
);
Creating from IPFSβ
Create atoms from IPFS content, either by referencing existing IPFS URIs or uploading new content to Pinata.
createAtomFromIpfsUriβ
Create an atom from an existing IPFS URI.
Function Signatureβ
function createAtomFromIpfsUri(
config: WriteConfig,
ipfsUri: `ipfs://${string}`,
deposit?: bigint,
): Promise<AtomCreationResult>;
Basic Exampleβ
import {
createAtomFromIpfsUri,
type WriteConfig,
} from '@0xintuition/sdk';
import { parseEther } from 'viem';
async function createIpfsAtom(config: WriteConfig) {
const atom = await createAtomFromIpfsUri(
config,
'ipfs://bafkreib7534cszxn2c6qwoviv43sqh244yfrxomjbealjdwntd6a7atq6u',
parseEther('0.01'),
);
console.log('IPFS Atom ID:', atom.state.termId);
return atom;
}
createAtomFromIpfsUploadβ
Upload JSON data to Pinata and create an atom with the resulting IPFS URI.
Function Signatureβ
function createAtomFromIpfsUpload(
config: WriteConfig & { pinataApiJWT: string },
data: object,
deposit?: bigint,
): Promise<AtomCreationResult>;
Basic Exampleβ
import {
createAtomFromIpfsUpload,
type CreateAtomConfigWithIpfs,
} from '@0xintuition/sdk';
import { parseEther } from 'viem';
async function uploadProjectAtom(config: CreateAtomConfigWithIpfs) {
const atom = await createAtomFromIpfsUpload(
config,
{
name: 'My Project',
description: 'A blockchain project',
url: 'https://myproject.com',
},
parseEther('0.05'),
);
console.log('Atom ID:', atom.state.termId);
console.log('IPFS URI:', atom.uri); // ipfs://bafkrei...
return atom;
}
Batch Creationβ
Create multiple atoms in a single transaction for improved efficiency and reduced gas costs.
Available Batch Functionsβ
batchCreateAtomsFromEthereumAccounts- Batch create account atomsbatchCreateAtomsFromSmartContracts- Batch create contract atomsbatchCreateAtomsFromIpfsUris- Batch create IPFS atomsbatchCreateAtomsFromThings- Batch create Thing atoms
batchCreateAtomsFromEthereumAccountsβ
import {
batchCreateAtomsFromEthereumAccounts,
type WriteConfig,
} from '@0xintuition/sdk';
import { parseEther, type Address } from 'viem';
const addresses: Address[] = [
'0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
'0x1234567890123456789012345678901234567890',
];
async function createAccountAtoms(config: WriteConfig) {
const result = await batchCreateAtomsFromEthereumAccounts(
config,
addresses,
parseEther('0.01'), // Additional 0.01 tTRUST signal per atom
);
console.log('Created', result.state.length, 'atoms');
console.log(
'Atom IDs:',
result.state.map((state) => state.termId),
);
console.log('Single transaction:', result.transactionHash);
return result;
}
Gas Savingsβ
Batch creation saves significant gas compared to individual transactions:
| Atoms | Individual Txs | Batch Tx | Savings |
|---|---|---|---|
| 1 | ~150k gas | ~150k gas | 0% |
| 5 | ~750k gas | ~300k gas | 60% |
| 10 | ~1.5M gas | ~450k gas | 70% |
| 50 | ~7.5M gas | ~1.5M gas | 80% |
Querying Atomsβ
Query atom information and calculate atom IDs for existing or potential atoms.
getAtomDetailsβ
Fetch comprehensive atom details from the Intuition API.
Function Signatureβ
function getAtomDetails(atomId: string): Promise<AtomDetails | null>;
Basic Exampleβ
import { getAtomDetails } from '@0xintuition/sdk';
const atomId = '0x1234567890abcdef...';
const details = await getAtomDetails(atomId);
if (!details) throw new Error('Atom not found');
const vault = details.term?.vaults[0];
console.log('Atom Label:', details.label);
console.log('Creator:', details.creator?.label ?? details.creator_id);
console.log('Vault Shares:', vault?.total_shares);
console.log('Share Price:', vault?.current_share_price);
calculateAtomIdβ
Calculate the atom ID from hex-encoded atom data without querying the blockchain. Encode text exactly as the creation helpers do before calculating its ID.
Function Signatureβ
function calculateAtomId(atomData: Hex): Hex;
Basic Exampleβ
import { calculateAtomId } from '@0xintuition/sdk';
import { toHex } from 'viem';
// Calculate ID for a string atom
const atomId = calculateAtomId(toHex('developer'));
console.log('Atom ID:', atomId);
// Calculate ID for an Ethereum address
const addressAtomId = calculateAtomId(
toHex('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'),
);
console.log('Address Atom ID:', addressAtomId);
// Calculate ID for IPFS URI
const ipfsAtomId = calculateAtomId(toHex('ipfs://bafkreib...'));
console.log('IPFS Atom ID:', ipfsAtomId);
Use Casesβ
Check if Atom Exists Before Creatingβ
import {
calculateAtomId,
configureSdk,
getAtomDetails,
createAtomFromString,
type WriteConfig,
} from '@0xintuition/sdk';
import { API_URL_DEV } from '@0xintuition/graphql';
import { toHex } from 'viem';
configureSdk({ apiUrl: API_URL_DEV });
async function createAtomIfNotExists(config: WriteConfig, data: string) {
// Calculate ID
const atomId = calculateAtomId(toHex(data));
// Check if exists
const existing = await getAtomDetails(atomId);
if (existing !== null) {
console.log('Atom already exists:', atomId);
return existing;
}
// Doesn't exist, create it
console.log('Creating new atom');
const atom = await createAtomFromString(config, data);
return atom;
}
Batch Query Multiple Atomsβ
import { getAtomDetails } from '@0xintuition/sdk';
async function getMultipleAtoms(atomIds: string[]) {
const atoms = await Promise.all(atomIds.map((id) => getAtomDetails(id)));
atoms.forEach((atom) => {
if (atom === null) return;
const vault = atom.term?.vaults[0];
if (!vault) {
console.log(`${atom.label}: no vault data`);
return;
}
console.log(`${atom.label}: ${vault.total_shares} shares`);
});
return atoms;
}
Response Data Structureβ
After successfully creating an atom, the SDK returns a data object with transaction details and state:
type AtomCreationResult = {
uri: string; // The atom's data URI (IPFS or raw data)
transactionHash: `0x${string}`; // Transaction hash on chain
state: {
creator: Address; // Address that created the atom
termId: Hex; // Unique atom identifier
atomData: Hex; // Encoded atom data
atomWallet: Address; // Associated vault wallet address
};
};
Example Usageβ
const result = await createAtomFromString(config, 'developer');
console.log('Transaction:', result.transactionHash);
console.log('Atom ID:', result.state.termId);
console.log('Creator:', result.state.creator);
console.log('Vault Wallet:', result.state.atomWallet);
Complete Examplesβ
See working examples in the SDK Examples section