Skip to main content

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.

Match SDK reads to your network

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​

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​

ParameterTypeDescriptionRequired
configWriteConfigClient configuration with wallet, public client, and contract addressYes
datastringThe text string to create an atom fromYes
depositAmountbigintOptional additional deposit/signal amount in weiNo

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​

  1. Pin to IPFS: The Thing object is automatically pinned to IPFS via the Intuition pinning service using your configured pinApiKey
  2. Generate URI: An IPFS URI is generated (e.g., ipfs://bafkrei...)
  3. Create Atom: The atom is created with the IPFS URI as its data
  4. 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 atoms
  • batchCreateAtomsFromSmartContracts - Batch create contract atoms
  • batchCreateAtomsFromIpfsUris - Batch create IPFS atoms
  • batchCreateAtomsFromThings - 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:

AtomsIndividual TxsBatch TxSavings
1~150k gas~150k gas0%
5~750k gas~300k gas60%
10~1.5M gas~450k gas70%
50~7.5M gas~1.5M gas80%

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

Next Steps​