SDK — Examples
Practical code samples for common operations using @yellow-org/contracts.
Setup (viem)
All examples below use this shared setup:
import { createPublicClient, createWalletClient, http, parseEther } from "viem";
import { mainnet } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import {
YellowTokenAbi,
NodeRegistryAbi,
AppRegistryAbi,
YellowGovernorAbi,
TreasuryAbi,
FaucetAbi,
addresses,
} from "@yellow-org/contracts";
const addr = addresses[1]; // or addresses[11155111] for Sepolia
const publicClient = createPublicClient({
chain: mainnet,
transport: http(),
});
const walletClient = createWalletClient({
chain: mainnet,
transport: http(),
account: privateKeyToAccount("0x..."),
});
Token
Check balance and approve
const balance = await publicClient.readContract({
address: addr.yellowToken!,
abi: YellowTokenAbi,
functionName: "balanceOf",
args: [walletClient.account.address],
});
// Approve NodeRegistry to spend tokens for collateral deposit
await walletClient.writeContract({
address: addr.yellowToken!,
abi: YellowTokenAbi,
functionName: "approve",
args: [addr.nodeRegistry!, parseEther("1000")],
});
Node Operator Collateral (NodeRegistry)
Post security deposit
// Post YELLOW as a mandatory functional security deposit to operate a clearnode
await walletClient.writeContract({
address: addr.nodeRegistry!,
abi: NodeRegistryAbi,
functionName: "lock",
args: [walletClient.account.address, parseEther("1000")],
});
Read lock state
const state = await publicClient.readContract({
address: addr.nodeRegistry!,
abi: NodeRegistryAbi,
functionName: "lockStateOf",
args: [userAddress],
});
// 0 = Idle, 1 = Locked, 2 = Unlocking
const locked = await publicClient.readContract({
address: addr.nodeRegistry!,
abi: NodeRegistryAbi,
functionName: "balanceOf",
args: [userAddress],
});
const unlockAt = await publicClient.readContract({
address: addr.nodeRegistry!,
abi: NodeRegistryAbi,
functionName: "unlockTimestampOf",
args: [userAddress],
});
Unlock, relock, withdraw
// Start unlock countdown
await walletClient.writeContract({
address: addr.nodeRegistry!,
abi: NodeRegistryAbi,
functionName: "unlock",
});
// Cancel unlock
await walletClient.writeContract({
address: addr.nodeRegistry!,
abi: NodeRegistryAbi,
functionName: "relock",
});
// Withdraw after period elapses
await walletClient.writeContract({
address: addr.nodeRegistry!,
abi: NodeRegistryAbi,
functionName: "withdraw",
args: [walletClient.account.address], // destination
});
Delegate collateral weight
// Delegate collateral weight for protocol parameter administration
await walletClient.writeContract({
address: addr.nodeRegistry!,
abi: NodeRegistryAbi,
functionName: "delegate",
args: [delegateeAddress],
});
// Check collateral weight
const weight = await publicClient.readContract({
address: addr.nodeRegistry!,
abi: NodeRegistryAbi,
functionName: "getVotes",
args: [userAddress],
});
Protocol Parameter Administration
Create a proposal
import { encodeFunctionData, keccak256, toBytes } from "viem";
// Example: transfer 1000 YELLOW from Treasury to a grants recipient
const calldata = encodeFunctionData({
abi: TreasuryAbi,
functionName: "transfer",
args: [addr.yellowToken!, recipientAddress, parseEther("1000")],
});
const description = "Transfer 1000 YELLOW to grants recipient";
await walletClient.writeContract({
address: addr.governor!,
abi: YellowGovernorAbi,
functionName: "propose",
args: [
[addr.treasury!], // targets
[0n], // values
[calldata], // calldatas
description,
],
});
Signal support on a proposal
// support: 0 = Against, 1 = For, 2 = Abstain
await walletClient.writeContract({
address: addr.governor!,
abi: YellowGovernorAbi,
functionName: "castVote",
args: [proposalId, 1], // For
});
// With reason
await walletClient.writeContract({
address: addr.governor!,
abi: YellowGovernorAbi,
functionName: "castVoteWithReason",
args: [proposalId, 1, "Necessary parameter update for network scaling"],
});
Queue and execute
const descriptionHash = keccak256(toBytes(description));
// Queue (after operator consensus is reached)
await walletClient.writeContract({
address: addr.governor!,
abi: YellowGovernorAbi,
functionName: "queue",
args: [[addr.treasury!], [0n], [calldata], descriptionHash],
});
// Execute (after timelock delay)
await walletClient.writeContract({
address: addr.governor!,
abi: YellowGovernorAbi,
functionName: "execute",
args: [[addr.treasury!], [0n], [calldata], descriptionHash],
});
Read proposal state
const state = await publicClient.readContract({
address: addr.governor!,
abi: YellowGovernorAbi,
functionName: "state",
args: [proposalId],
});
// 0=Pending, 1=Active, 2=Canceled, 3=Defeated,
// 4=Succeeded, 5=Queued, 6=Expired, 7=Executed
const [againstWeight, forWeight, abstainWeight] = await publicClient.readContract({
address: addr.governor!,
abi: YellowGovernorAbi,
functionName: "proposalVotes",
args: [proposalId],
});
Slashing (AppRegistry — adjudicator)
// Slash an app builder's service quality guarantee for protocol violation
await walletClient.writeContract({
address: addr.appRegistry!,
abi: AppRegistryAbi,
functionName: "slash",
args: [
userAddress,
parseEther("500"),
treasuryAddress, // recipient
"0x1234abcd", // decision reference
],
});
Listening to Events
// Watch for new collateral deposits on NodeRegistry
publicClient.watchContractEvent({
address: addr.nodeRegistry!,
abi: NodeRegistryAbi,
eventName: "Locked",
onLogs: (logs) => {
for (const log of logs) {
console.log(`${log.args.user} posted ${log.args.deposited} collateral`);
}
},
});
// Watch for new parameter proposals
publicClient.watchContractEvent({
address: addr.governor!,
abi: YellowGovernorAbi,
eventName: "ProposalCreated",
onLogs: (logs) => {
for (const log of logs) {
console.log(`Proposal ${log.args.proposalId} by ${log.args.proposer}`);
}
},
});
Faucet (Sepolia)
import { sepolia } from "viem/chains";
const sepoliaAddr = addresses[11155111];
await walletClient.writeContract({
address: sepoliaAddr.faucet!,
abi: FaucetAbi,
functionName: "drip",
});