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);
}
},
});