Skip to main content

Code Examples — viem

Complete TypeScript examples using viem for interacting with Emerald Vault contracts.

Setup

import {
createPublicClient,
createWalletClient,
http,
parseUnits,
erc20Abi,
} from "viem";
import { mainnet } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import vaultAbi from "./abi/EmeraldVault.json";

const publicClient = createPublicClient({
chain: mainnet,
transport: http("https://eth.llamarpc.com"),
});

const account = privateKeyToAccount("0x...");
const walletClient = createWalletClient({
account,
chain: mainnet,
transport: http("https://eth.llamarpc.com"),
});

const VAULT = "0x..." as const; // Vault address
const TOKEN = "0x..." as const; // Underlying token address

Read Vault State

const [totalAssets, paused, shareBalance] = await Promise.all([
publicClient.readContract({
address: VAULT, abi: vaultAbi, functionName: "totalAssets",
}),
publicClient.readContract({
address: VAULT, abi: vaultAbi, functionName: "paused",
}),
publicClient.readContract({
address: VAULT, abi: vaultAbi, functionName: "balanceOf",
args: [account.address],
}),
]);

console.log({ totalAssets, paused, shareBalance });

Deposit

const amount = parseUnits("1000", 6); // 1000 USDC

// 1. Check allowance
const allowance = await publicClient.readContract({
address: TOKEN,
abi: erc20Abi,
functionName: "allowance",
args: [account.address, VAULT],
});

// 2. Approve if needed
if (allowance < amount) {
const approveTx = await walletClient.writeContract({
address: TOKEN,
abi: erc20Abi,
functionName: "approve",
args: [VAULT, amount],
});
await publicClient.waitForTransactionReceipt({ hash: approveTx });
}

// 3. Deposit
const depositTx = await walletClient.writeContract({
address: VAULT,
abi: vaultAbi,
functionName: "deposit",
args: [amount, account.address, PARTNER_ID], // (assets, receiver, partnerId) — use 0 for no attribution
});
const receipt = await publicClient.waitForTransactionReceipt({ hash: depositTx });
console.log("Deposit tx:", receipt.transactionHash);

Request Withdrawal

// Shares follow the asset's decimals (this USDC vault → 6).
// Use requestWithdrawal(shares, partnerId) to attribute to a partner.
const shares = parseUnits("500", 6);

const requestTx = await walletClient.writeContract({
address: VAULT,
abi: vaultAbi,
functionName: "requestWithdrawal",
args: [shares],
});
const receipt = await publicClient.waitForTransactionReceipt({ hash: requestTx });
console.log("Withdrawal requested:", receipt.transactionHash);

Claim Withdrawal

// claimWithdrawal() takes NO argument — it settles your request when it is at
// the head of the FIFO queue and the vault is liquid (else reverts
// NotAtQueueHead / InsufficientLiquidity).
const claimTx = await walletClient.writeContract({
address: VAULT,
abi: vaultAbi,
functionName: "claimWithdrawal",
args: [],
});
await publicClient.waitForTransactionReceipt({ hash: claimTx });
console.log("Withdrawal claimed");

Cancel Withdrawal

const requestIndex = 0n;

const cancelTx = await walletClient.writeContract({
address: VAULT,
abi: vaultAbi,
functionName: "cancelWithdrawal",
args: [requestIndex],
});
await publicClient.waitForTransactionReceipt({ hash: cancelTx });
console.log("Withdrawal cancelled");

Check Withdrawal Status

const [user, shares, assetsOwed, timestamp, claimed, cancelled] =
await publicClient.readContract({
address: VAULT,
abi: vaultAbi,
functionName: "getWithdrawalRequest",
args: [0n],
});

// assetsOwed is computed live (0 once resolved). Status is queued/claimed/
// cancelled — there is no time-based claimable/expired state.
let status: string;
if (cancelled) status = "cancelled";
else if (claimed) status = "claimed";
else status = "queued";

console.log({ user, shares, assetsOwed, status });

Get All User Requests

const indices = await publicClient.readContract({
address: VAULT,
abi: vaultAbi,
functionName: "getUserRequests",
args: [account.address],
});

const requests = await Promise.all(
indices.map((index) =>
publicClient.readContract({
address: VAULT,
abi: vaultAbi,
functionName: "getWithdrawalRequest",
args: [index],
})
)
);

console.log(`${requests.length} withdrawal requests`);

Watch Events

// Watch for new deposits in real-time
const unwatch = publicClient.watchContractEvent({
address: VAULT,
abi: vaultAbi,
eventName: "Deposit",
onLogs: (logs) => {
for (const log of logs) {
console.log("Deposit:", log.args.sender, log.args.assets);
}
},
});