import { maxUint256, type Address } from "viem"; import type { LucidlyClient } from "./client.js"; import type { TxResult } from "./types.js"; import { TellerWithMultiAssetSupport, BoringVault } from "./artifacts.js"; const ERC20_APPROVE_ABI = [ { type: "function", name: "approve", stateMutability: "nonpayable", inputs: [ { name: "spender", type: "address" }, { name: "amount", type: "uint256" }, ], outputs: [{ type: "bool" }], }, ] as const; export class TellerModule { constructor(private readonly c: LucidlyClient) {} /** Enable an asset for deposits/withdrawals (OWNER role). */ async addAsset(asset: Address | string, teller?: Address): Promise { const t = this.c.requireTeller("teller.addAsset", teller); const a = this.c.resolveToken(asset); const hash = await this.c.send({ address: t, abi: TellerWithMultiAssetSupport.abi, functionName: "updateAssetData", args: [a, true, true, 0], }); return this.c.wrapTx(hash); } /** * Public deposit: pulls `amount` of `asset` and mints shares. The depositor must approve the * VAULT (BoringVault.enter does the safeTransferFrom). Pass autoApprove=false to skip approval. */ async deposit( asset: Address | string, amount: bigint, opts: { minMint?: bigint; teller?: Address; vault?: Address; autoApprove?: boolean } = {}, ): Promise { const t = this.c.requireTeller("teller.deposit", opts.teller); const v = this.c.requireVault("teller.deposit", opts.vault); const a = this.c.resolveToken(asset); if (opts.autoApprove !== false) { await this.c.sendAndWait({ address: a, abi: ERC20_APPROVE_ABI, functionName: "approve", args: [v, maxUint256] }); } const hash = await this.c.send({ address: t, abi: TellerWithMultiAssetSupport.abi, functionName: "deposit", args: [a, amount, opts.minMint ?? 0n], }); return this.c.wrapTx(hash); } /** Instant redemption via the solver path (caller needs SOLVER role). */ async withdraw( asset: Address | string, shares: bigint, opts: { minAssets?: bigint; to?: Address; teller?: Address } = {}, ): Promise { const t = this.c.requireTeller("teller.withdraw", opts.teller); const a = this.c.resolveToken(asset); const to = opts.to ?? this.c.requireSigner("teller.withdraw").account.address; const hash = await this.c.send({ address: t, abi: TellerWithMultiAssetSupport.abi, functionName: "bulkWithdraw", args: [a, shares, opts.minAssets ?? 0n, to], }); return this.c.wrapTx(hash); } /** Read: is this asset enabled for deposits? */ async isAssetSupported(asset: Address | string, teller?: Address): Promise { const t = this.c.requireTeller("teller.isAssetSupported", teller); const a = this.c.resolveToken(asset); const data = await this.c.read({ address: t, abi: TellerWithMultiAssetSupport.abi, functionName: "assetData", args: [a], }); return data[0]; } }