UNPKG

viem

Version:

TypeScript Interface for Ethereum

1,789 lines (1,673 loc) • 65.1 kB
import type { Address } from 'abitype' import * as Hash from 'ox/Hash' import * as Hex from 'ox/Hex' import { parseAccount } from '../../accounts/utils/parseAccount.js' import { type ReadContractReturnType, readContract, } from '../../actions/public/readContract.js' import { type WatchContractEventParameters, watchContractEvent, } from '../../actions/public/watchContractEvent.js' import { type WriteContractReturnType, writeContract, } from '../../actions/wallet/writeContract.js' import { writeContractSync } from '../../actions/wallet/writeContractSync.js' import type { Client } from '../../clients/createClient.js' import type { Transport } from '../../clients/transports/createTransport.js' import type { BaseErrorType } from '../../errors/base.js' import type { Account } from '../../types/account.js' import type { Chain } from '../../types/chain.js' import type { ExtractAbiItem, GetEventArgs } from '../../types/contract.js' import type { Log as viem_Log } from '../../types/log.js' import type { Compute, UnionOmit } from '../../types/utils.js' import { parseEventLogs } from '../../utils/abi/parseEventLogs.js' import * as Abis from '../Abis.js' import * as Addresses from '../Addresses.js' import type { GetAccountParameter, ReadParameters, WriteParameters, } from '../internal/types.js' import { defineCall } from '../internal/utils.js' import type { TransactionReceipt } from '../Transaction.js' /** * Order type for limit orders. */ type OrderType = 'buy' | 'sell' /** * Buys a specific amount of tokens. * * @example * ```ts * import { createClient, http, parseUnits } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const hash = await Actions.dex.buy(client, { * tokenIn: '0x20c...11', * tokenOut: '0x20c...20', * amountOut: parseUnits('100', 6), * maxAmountIn: parseUnits('105', 6), * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction hash. */ export async function buy< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: buy.Parameters<chain, account>, ): Promise<buy.ReturnValue> { return buy.inner(writeContract, client, parameters) } export namespace buy { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = WriteParameters<chain, account> & Args export type Args = { /** Amount of tokenOut to buy. */ amountOut: bigint /** Maximum amount of tokenIn to spend. */ maxAmountIn: bigint /** Address of the token to spend. */ tokenIn: Address /** Address of the token to buy. */ tokenOut: Address } export type ReturnValue = WriteContractReturnType // TODO: exhaustive error type export type ErrorType = BaseErrorType /** @internal */ export async function inner< action extends typeof writeContract | typeof writeContractSync, chain extends Chain | undefined, account extends Account | undefined, >( action: action, client: Client<Transport, chain, account>, parameters: buy.Parameters<chain, account>, ): Promise<ReturnType<action>> { const { tokenIn, tokenOut, amountOut, maxAmountIn, ...rest } = parameters const call = buy.call({ tokenIn, tokenOut, amountOut, maxAmountIn }) return (await action(client, { ...rest, ...call, } as never)) as never } /** * Defines a call to the `swapExactAmountOut` function. * * Can be passed as a parameter to: * - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call * - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call * - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls * * @example * ```ts * import { createClient, http, parseUnits, walletActions } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }).extend(walletActions) * * const { result } = await client.sendCalls({ * calls: [ * Actions.dex.buy.call({ * tokenIn: '0x20c0...beef', * tokenOut: '0x20c0...babe', * amountOut: parseUnits('100', 6), * maxAmountIn: parseUnits('105', 6), * }), * ] * }) * ``` * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { tokenIn, tokenOut, amountOut, maxAmountIn } = args return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, functionName: 'swapExactAmountOut', args: [tokenIn, tokenOut, amountOut, maxAmountIn], }) } } /** * Buys a specific amount of tokens. * * @example * ```ts * import { createClient, http, parseUnits } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const result = await Actions.dex.buySync(client, { * tokenIn: '0x20c...11', * tokenOut: '0x20c...20', * amountOut: parseUnits('100', 6), * maxAmountIn: parseUnits('105', 6), * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction receipt. */ export async function buySync< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: buySync.Parameters<chain, account>, ): Promise<buySync.ReturnValue> { const { throwOnReceiptRevert = true, ...rest } = parameters const receipt = await buy.inner(writeContractSync, client, { ...rest, throwOnReceiptRevert, } as never) return { receipt } } export namespace buySync { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = buy.Parameters<chain, account> export type Args = buy.Args export type ReturnValue = Compute<{ /** Transaction receipt. */ receipt: TransactionReceipt }> // TODO: exhaustive error type export type ErrorType = BaseErrorType } /** * Cancels an order from the orderbook. * * @example * ```ts * import { createClient, http } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const hash = await Actions.dex.cancel(client, { * orderId: 123n, * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction hash. */ export async function cancel< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: cancel.Parameters<chain, account>, ): Promise<cancel.ReturnValue> { return cancel.inner(writeContract, client, parameters) } export namespace cancel { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = WriteParameters<chain, account> & Args export type Args = { /** Order ID to cancel. */ orderId: bigint } export type ReturnValue = WriteContractReturnType // TODO: exhaustive error type export type ErrorType = BaseErrorType /** @internal */ export async function inner< action extends typeof writeContract | typeof writeContractSync, chain extends Chain | undefined, account extends Account | undefined, >( action: action, client: Client<Transport, chain, account>, parameters: cancel.Parameters<chain, account>, ): Promise<ReturnType<action>> { const { orderId, ...rest } = parameters const call = cancel.call({ orderId }) return (await action(client, { ...rest, ...call, } as never)) as never } /** * Defines a call to the `cancel` function. * * Can be passed as a parameter to: * - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call * - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call * - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls * * @example * ```ts * import { createClient, http, walletActions } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }).extend(walletActions) * * const { result } = await client.sendCalls({ * calls: [ * Actions.dex.cancel.call({ * orderId: 123n, * }), * ] * }) * ``` * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { orderId } = args return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, functionName: 'cancel', args: [orderId], }) } /** * Extracts the `OrderCancelled` event from logs. * * @param logs - The logs. * @returns The `OrderCancelled` event. */ export function extractEvent(logs: viem_Log[]) { const [log] = parseEventLogs({ abi: Abis.stablecoinDex, logs, eventName: 'OrderCancelled', strict: true, }) if (!log) throw new Error('`OrderCancelled` event not found.') return log } } /** * Cancels an order from the orderbook. * * @example * ```ts * import { createClient, http } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const result = await Actions.dex.cancelSync(client, { * orderId: 123n, * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction receipt and event data. */ export async function cancelSync< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: cancelSync.Parameters<chain, account>, ): Promise<cancelSync.ReturnValue> { const { throwOnReceiptRevert = true, ...rest } = parameters const receipt = await cancel.inner(writeContractSync, client, { ...rest, throwOnReceiptRevert, } as never) const { args } = cancel.extractEvent(receipt.logs) return { ...args, receipt, } as never } export namespace cancelSync { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = cancel.Parameters<chain, account> export type Args = cancel.Args export type ReturnValue = Compute< GetEventArgs< typeof Abis.stablecoinDex, 'OrderCancelled', { IndexedOnly: false; Required: true } > & { /** Transaction receipt. */ receipt: TransactionReceipt } > // TODO: exhaustive error type export type ErrorType = BaseErrorType } /** * Cancels a stale order from the orderbook. * * A stale order is one where the owner's balance or allowance has dropped * below the order amount. * * @example * ```ts * import { createClient, http } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const hash = await Actions.dex.cancelStale(client, { * orderId: 123n, * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction hash. */ export async function cancelStale< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: cancelStale.Parameters<chain, account>, ): Promise<cancelStale.ReturnValue> { return cancelStale.inner(writeContract, client, parameters) } export namespace cancelStale { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = WriteParameters<chain, account> & Args export type Args = { /** Order ID to cancel. */ orderId: bigint } export type ReturnValue = WriteContractReturnType // TODO: exhaustive error type export type ErrorType = BaseErrorType /** @internal */ export async function inner< action extends typeof writeContract | typeof writeContractSync, chain extends Chain | undefined, account extends Account | undefined, >( action: action, client: Client<Transport, chain, account>, parameters: cancelStale.Parameters<chain, account>, ): Promise<ReturnType<action>> { const { orderId, ...rest } = parameters const call = cancelStale.call({ orderId }) return (await action(client, { ...rest, ...call, } as never)) as never } /** * Defines a call to the `cancelStaleOrder` function. * * Can be passed as a parameter to: * - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call * - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call * - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls * * @example * ```ts * import { createClient, http, walletActions } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }).extend(walletActions) * * const { result } = await client.sendCalls({ * calls: [ * Actions.dex.cancelStale.call({ * orderId: 123n, * }), * ] * }) * ``` * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { orderId } = args return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, functionName: 'cancelStaleOrder', args: [orderId], }) } /** * Extracts the `OrderCancelled` event from logs. * * @param logs - The logs. * @returns The `OrderCancelled` event. */ export function extractEvent(logs: viem_Log[]) { const [log] = parseEventLogs({ abi: Abis.stablecoinDex, logs, eventName: 'OrderCancelled', strict: true, }) if (!log) throw new Error('`OrderCancelled` event not found.') return log } } /** * Cancels a stale order from the orderbook and waits for confirmation. * * A stale order is one where the owner's balance or allowance has dropped * below the order amount. * * @example * ```ts * import { createClient, http } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const result = await Actions.dex.cancelStaleSync(client, { * orderId: 123n, * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction receipt and event data. */ export async function cancelStaleSync< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: cancelStaleSync.Parameters<chain, account>, ): Promise<cancelStaleSync.ReturnValue> { const { throwOnReceiptRevert = true, ...rest } = parameters const receipt = await cancelStale.inner(writeContractSync, client, { ...rest, throwOnReceiptRevert, } as never) const { args } = cancelStale.extractEvent(receipt.logs) return { ...args, receipt, } as never } export namespace cancelStaleSync { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = cancelStale.Parameters<chain, account> export type Args = cancelStale.Args export type ReturnValue = Compute< GetEventArgs< typeof Abis.stablecoinDex, 'OrderCancelled', { IndexedOnly: false; Required: true } > & { /** Transaction receipt. */ receipt: TransactionReceipt } > // TODO: exhaustive error type export type ErrorType = BaseErrorType } /** * Creates a new trading pair on the DEX. * * @example * ```ts * import { createClient, http } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const hash = await Actions.dex.createPair(client, { * base: '0x20c...11', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction hash. */ export async function createPair< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: createPair.Parameters<chain, account>, ): Promise<createPair.ReturnValue> { return createPair.inner(writeContract, client, parameters) } export namespace createPair { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = WriteParameters<chain, account> & Args export type Args = { /** Address of the base token for the pair. */ base: Address } export type ReturnValue = WriteContractReturnType // TODO: exhaustive error type export type ErrorType = BaseErrorType /** @internal */ export async function inner< action extends typeof writeContract | typeof writeContractSync, chain extends Chain | undefined, account extends Account | undefined, >( action: action, client: Client<Transport, chain, account>, parameters: createPair.Parameters<chain, account>, ): Promise<ReturnType<action>> { const { base, ...rest } = parameters const call = createPair.call({ base }) return (await action(client, { ...rest, ...call, } as never)) as never } /** * Defines a call to the `createPair` function. * * Can be passed as a parameter to: * - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call * - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call * - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls * * @example * ```ts * import { createClient, http, walletActions } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }).extend(walletActions) * * const { result } = await client.sendCalls({ * calls: [ * Actions.dex.createPair.call({ * base: '0x20c0...beef', * }), * ] * }) * ``` * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { base } = args return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, functionName: 'createPair', args: [base], }) } /** * Extracts the `PairCreated` event from logs. * * @param logs - The logs. * @returns The `PairCreated` event. */ export function extractEvent(logs: viem_Log[]) { const [log] = parseEventLogs({ abi: Abis.stablecoinDex, logs, eventName: 'PairCreated', strict: true, }) if (!log) throw new Error('`PairCreated` event not found.') return log } } /** * Creates a new trading pair on the DEX. * * @example * ```ts * import { createClient, http } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const result = await Actions.dex.createPairSync(client, { * base: '0x20c...11', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction receipt and event data. */ export async function createPairSync< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: createPairSync.Parameters<chain, account>, ): Promise<createPairSync.ReturnValue> { const { throwOnReceiptRevert = true, ...rest } = parameters const receipt = await createPair.inner(writeContractSync, client, { ...rest, throwOnReceiptRevert, } as never) const { args } = createPair.extractEvent(receipt.logs) return { ...args, receipt, } as never } export namespace createPairSync { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = createPair.Parameters<chain, account> export type Args = createPair.Args export type ReturnValue = Compute< GetEventArgs< typeof Abis.stablecoinDex, 'PairCreated', { IndexedOnly: false; Required: true } > & { /** Transaction receipt. */ receipt: TransactionReceipt } > // TODO: exhaustive error type export type ErrorType = BaseErrorType } /** * Gets a user's token balance on the DEX. * * @example * ```ts * import { createClient, http } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const balance = await Actions.dex.getBalance(client, { * account: '0x...', * token: '0x20c...11', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The user's token balance on the DEX. */ export async function getBalance< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: getBalance.Parameters<account>, ): Promise<getBalance.ReturnValue> { const { account: acc = client.account, token, ...rest } = parameters const address = acc ? parseAccount(acc).address : undefined if (!address) throw new Error('account is required.') return readContract(client, { ...rest, ...getBalance.call({ account: address, token }), }) } export namespace getBalance { export type Parameters< account extends Account | undefined = Account | undefined, > = ReadParameters & GetAccountParameter<account> & Args export type Args = { /** Address of the account. */ account: Address /** Address of the token. */ token: Address } export type ReturnValue = ReadContractReturnType< typeof Abis.stablecoinDex, 'balanceOf', never > /** * Defines a call to the `balanceOf` function. * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { account, token } = args return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, args: [account, token], functionName: 'balanceOf', }) } } /** * Gets the quote for buying a specific amount of tokens. * * @example * ```ts * import { createClient, http, parseUnits } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const amountIn = await Actions.dex.getBuyQuote(client, { * amountOut: parseUnits('100', 6), * tokenIn: '0x20c...11', * tokenOut: '0x20c...20', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The amount of tokenIn needed to buy the specified amountOut. */ export async function getBuyQuote<chain extends Chain | undefined>( client: Client<Transport, chain>, parameters: getBuyQuote.Parameters, ): Promise<getBuyQuote.ReturnValue> { const { tokenIn, tokenOut, amountOut, ...rest } = parameters return readContract(client, { ...rest, ...getBuyQuote.call({ tokenIn, tokenOut, amountOut }), }) } export namespace getBuyQuote { export type Parameters = ReadParameters & Args export type Args = { /** Amount of tokenOut to buy. */ amountOut: bigint /** Address of the token to spend. */ tokenIn: Address /** Address of the token to buy. */ tokenOut: Address } export type ReturnValue = ReadContractReturnType< typeof Abis.stablecoinDex, 'quoteSwapExactAmountOut', never > /** * Defines a call to the `quoteSwapExactAmountOut` function. * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { tokenIn, tokenOut, amountOut } = args return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, args: [tokenIn, tokenOut, amountOut], functionName: 'quoteSwapExactAmountOut', }) } } /** * Gets an order's details from the orderbook. * * @example * ```ts * import { createClient, http } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const order = await Actions.dex.getOrder(client, { * orderId: 123n, * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The order details. */ export async function getOrder<chain extends Chain | undefined>( client: Client<Transport, chain>, parameters: getOrder.Parameters, ): Promise<getOrder.ReturnValue> { const { orderId, ...rest } = parameters return readContract(client, { ...rest, ...getOrder.call({ orderId }), }) } export namespace getOrder { export type Parameters = ReadParameters & Args export type Args = { /** Order ID to query. */ orderId: bigint } export type ReturnValue = ReadContractReturnType< typeof Abis.stablecoinDex, 'getOrder', never > /** * Defines a call to the `getOrder` function. * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { orderId } = args return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, args: [orderId], functionName: 'getOrder', }) } } /** * Gets orderbook information for a trading pair. * * @example * ```ts * import { createClient, http } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const book = await Actions.dex.getOrderbook(client, { * base: '0x20c...11', * quote: '0x20c...20', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The orderbook information. */ export async function getOrderbook<chain extends Chain | undefined>( client: Client<Transport, chain>, parameters: getOrderbook.Parameters, ): Promise<getOrderbook.ReturnValue> { const { base, quote, ...rest } = parameters return readContract(client, { ...rest, ...getOrderbook.call({ base, quote }), }) } export namespace getOrderbook { export type Parameters = ReadParameters & Args export type Args = { /** Address of the base token. */ base: Address /** Address of the quote token. */ quote: Address } export type ReturnValue = ReadContractReturnType< typeof Abis.stablecoinDex, 'books', never > /** * Defines a call to the `books` function. * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { base, quote } = args const pairKey = getPairKey(base, quote) return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, args: [pairKey], functionName: 'books', }) } } /** * Gets the price level information at a specific tick. * * @example * ```ts * import { createClient, http } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions, Tick } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const level = await Actions.dex.getTickLevel(client, { * base: '0x20c...11', * tick: Tick.fromPrice('1.001'), * isBid: true, * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The price level information. */ export async function getTickLevel<chain extends Chain | undefined>( client: Client<Transport, chain>, parameters: getTickLevel.Parameters, ): Promise<getTickLevel.ReturnValue> { const { base, tick, isBid, ...rest } = parameters const [head, tail, totalLiquidity] = await readContract(client, { ...rest, ...getTickLevel.call({ base, tick, isBid }), }) return { head, tail, totalLiquidity } } export namespace getTickLevel { export type Parameters = ReadParameters & Args export type Args = { /** Address of the base token. */ base: Address /** Whether to query the bid side (true) or ask side (false). */ isBid: boolean /** Price tick to query. */ tick: number } export type ReturnValue = { /** Order ID of the first order at this tick (0 if empty) */ head: bigint /** Order ID of the last order at this tick (0 if empty) */ tail: bigint /** Total liquidity available at this tick level */ totalLiquidity: bigint } /** * Defines a call to the `getTickLevel` function. * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { base, tick, isBid } = args return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, args: [base, tick, isBid], functionName: 'getTickLevel', }) } } /** * Gets the quote for selling a specific amount of tokens. * * @example * ```ts * import { createClient, http, parseUnits } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const amountOut = await Actions.dex.getSellQuote(client, { * amountIn: parseUnits('100', 6), * tokenIn: '0x20c...11', * tokenOut: '0x20c...20', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The amount of tokenOut received for selling the specified amountIn. */ export async function getSellQuote<chain extends Chain | undefined>( client: Client<Transport, chain>, parameters: getSellQuote.Parameters, ): Promise<getSellQuote.ReturnValue> { const { tokenIn, tokenOut, amountIn, ...rest } = parameters return readContract(client, { ...rest, ...getSellQuote.call({ tokenIn, tokenOut, amountIn }), }) } export namespace getSellQuote { export type Parameters = ReadParameters & Args export type Args = { /** Amount of tokenIn to sell. */ amountIn: bigint /** Address of the token to sell. */ tokenIn: Address /** Address of the token to receive. */ tokenOut: Address } export type ReturnValue = ReadContractReturnType< typeof Abis.stablecoinDex, 'quoteSwapExactAmountIn', never > /** * Defines a call to the `quoteSwapExactAmountIn` function. * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { tokenIn, tokenOut, amountIn } = args return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, args: [tokenIn, tokenOut, amountIn], functionName: 'quoteSwapExactAmountIn', }) } } /** * Places a limit order on the orderbook. * * @example * ```ts * import { createClient, http, parseUnits } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions, Tick } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const hash = await Actions.dex.place(client, { * amount: parseUnits('100', 6), * tick: Tick.fromPrice('0.99'), * token: '0x20c...11', * type: 'buy', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction hash. */ export async function place< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: place.Parameters<chain, account>, ): Promise<place.ReturnValue> { return place.inner(writeContract, client, parameters) } export namespace place { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = WriteParameters<chain, account> & Args export type Args = { /** Amount of tokens to place in the order. */ amount: bigint /** Price tick for the order. */ tick: number /** Address of the base token. */ token: Address /** Order type - 'buy' to buy the token, 'sell' to sell it. */ type: OrderType } export type ReturnValue = WriteContractReturnType // TODO: exhaustive error type export type ErrorType = BaseErrorType /** @internal */ export async function inner< action extends typeof writeContract | typeof writeContractSync, chain extends Chain | undefined, account extends Account | undefined, >( action: action, client: Client<Transport, chain, account>, parameters: place.Parameters<chain, account>, ): Promise<ReturnType<action>> { const { amount, token, type, tick, ...rest } = parameters const call = place.call({ amount, token, type, tick }) return (await action(client, { ...rest, ...call, } as never)) as never } /** * Defines a call to the `place` function. * * Can be passed as a parameter to: * - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call * - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call * - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls * * @example * ```ts * import { createClient, http, parseUnits, walletActions } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions, Tick } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }).extend(walletActions) * * const { result } = await client.sendCalls({ * calls: [ * Actions.dex.place.call({ * amount: parseUnits('100', 6), * tick: Tick.fromPrice('0.99'), * token: '0x20c0...beef', * type: 'buy', * }), * ] * }) * ``` * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { token, amount, type, tick } = args const isBid = type === 'buy' return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, functionName: 'place', args: [token, amount, isBid, tick], }) } /** * Extracts the `OrderPlaced` event from logs. * * @param logs - The logs. * @returns The `OrderPlaced` event. */ export function extractEvent(logs: viem_Log[]) { const [log] = parseEventLogs({ abi: Abis.stablecoinDex, logs, eventName: 'OrderPlaced', strict: true, }) if (!log) throw new Error('`OrderPlaced` event not found.') return log } } /** * Places a flip order that automatically flips when filled. * * @example * ```ts * import { createClient, http, parseUnits } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions, Tick } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const hash = await Actions.dex.placeFlip(client, { * amount: parseUnits('100', 6), * flipTick: Tick.fromPrice('1.01'), * tick: Tick.fromPrice('0.99'), * token: '0x20c...11', * type: 'buy', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction hash. */ export async function placeFlip< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: placeFlip.Parameters<chain, account>, ): Promise<placeFlip.ReturnValue> { return placeFlip.inner(writeContract, client, parameters) } export namespace placeFlip { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = WriteParameters<chain, account> & Args export type Args = { /** Amount of tokens to place in the order. */ amount: bigint /** Target tick to flip to when order is filled. */ flipTick: number /** Price tick for the order. */ tick: number /** Address of the base token. */ token: Address /** Order type - 'buy' to buy the token, 'sell' to sell it. */ type: OrderType } export type ReturnValue = WriteContractReturnType // TODO: exhaustive error type export type ErrorType = BaseErrorType /** @internal */ export async function inner< action extends typeof writeContract | typeof writeContractSync, chain extends Chain | undefined, account extends Account | undefined, >( action: action, client: Client<Transport, chain, account>, parameters: placeFlip.Parameters<chain, account>, ): Promise<ReturnType<action>> { const { amount, flipTick, tick, token, type, ...rest } = parameters const call = placeFlip.call({ amount, flipTick, tick, token, type }) return (await action(client, { ...rest, ...call, } as never)) as never } /** * Defines a call to the `placeFlip` function. * * Can be passed as a parameter to: * - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call * - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call * - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls * * @example * ```ts * import { createClient, http, parseUnits, walletActions } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions, Tick } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }).extend(walletActions) * * const { result } = await client.sendCalls({ * calls: [ * Actions.dex.placeFlip.call({ * amount: parseUnits('100', 6), * flipTick: Tick.fromPrice('1.01'), * tick: Tick.fromPrice('0.99'), * token: '0x20c0...beef', * type: 'buy', * }), * ] * }) * ``` * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { token, amount, type, tick, flipTick } = args const isBid = type === 'buy' return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, functionName: 'placeFlip', args: [token, amount, isBid, tick, flipTick], }) } /** * Extracts the `OrderPlaced` event (with `isFlipOrder: true`) from logs. * * @param logs - The logs. * @returns The `OrderPlaced` event for a flip order. */ export function extractEvent(logs: viem_Log[]) { const parsedLogs = parseEventLogs({ abi: Abis.stablecoinDex, logs, eventName: 'OrderPlaced', strict: true, }) const log = parsedLogs.find((l) => l.args.isFlipOrder) if (!log) throw new Error('`OrderPlaced` event (flip order) not found.') return log } } /** * Places a flip order that automatically flips when filled. * * @example * ```ts * import { createClient, http, parseUnits } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions, Tick } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const result = await Actions.dex.placeFlipSync(client, { * amount: parseUnits('100', 6), * flipTick: Tick.fromPrice('1.01'), * tick: Tick.fromPrice('0.99'), * token: '0x20c...11', * type: 'buy', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction receipt and event data. */ export async function placeFlipSync< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: placeFlipSync.Parameters<chain, account>, ): Promise<placeFlipSync.ReturnValue> { const { throwOnReceiptRevert = true, ...rest } = parameters const receipt = await placeFlip.inner(writeContractSync, client, { ...rest, throwOnReceiptRevert, } as never) const { args } = placeFlip.extractEvent(receipt.logs) return { ...args, receipt, } as never } export namespace placeFlipSync { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = placeFlip.Parameters<chain, account> export type Args = placeFlip.Args export type ReturnValue = Compute< GetEventArgs< typeof Abis.stablecoinDex, 'OrderPlaced', { IndexedOnly: false; Required: true } > & { /** Transaction receipt. */ receipt: TransactionReceipt } > // TODO: exhaustive error type export type ErrorType = BaseErrorType } /** * Places a limit order on the orderbook. * * @example * ```ts * import { createClient, http, parseUnits } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions, Tick } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const result = await Actions.dex.placeSync(client, { * amount: parseUnits('100', 6), * tick: Tick.fromPrice('0.99'), * token: '0x20c...11', * type: 'buy', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction receipt and event data. */ export async function placeSync< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: placeSync.Parameters<chain, account>, ): Promise<placeSync.ReturnValue> { const { throwOnReceiptRevert = true, ...rest } = parameters const receipt = await place.inner(writeContractSync, client, { ...rest, throwOnReceiptRevert, } as never) const { args } = place.extractEvent(receipt.logs) return { ...args, receipt, } as never } export namespace placeSync { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = place.Parameters<chain, account> export type Args = place.Args export type ReturnValue = Compute< GetEventArgs< typeof Abis.stablecoinDex, 'OrderPlaced', { IndexedOnly: false; Required: true } > & { /** Transaction receipt. */ receipt: TransactionReceipt } > // TODO: exhaustive error type export type ErrorType = BaseErrorType } /** * Sells a specific amount of tokens. * * @example * ```ts * import { createClient, http, parseUnits } from 'viem' * import { privateKeyToAccount } from 'viem/accounts' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * account: privateKeyToAccount('0x...'), * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }) * * const hash = await Actions.dex.sell(client, { * amountIn: parseUnits('100', 6), * minAmountOut: parseUnits('95', 6), * tokenIn: '0x20c...11', * tokenOut: '0x20c...20', * }) * ``` * * @param client - Client. * @param parameters - Parameters. * @returns The transaction hash. */ export async function sell< chain extends Chain | undefined, account extends Account | undefined, >( client: Client<Transport, chain, account>, parameters: sell.Parameters<chain, account>, ): Promise<sell.ReturnValue> { return sell.inner(writeContract, client, parameters) } export namespace sell { export type Parameters< chain extends Chain | undefined = Chain | undefined, account extends Account | undefined = Account | undefined, > = WriteParameters<chain, account> & Args export type Args = { /** Amount of tokenIn to sell. */ amountIn: bigint /** Minimum amount of tokenOut to receive. */ minAmountOut: bigint /** Address of the token to sell. */ tokenIn: Address /** Address of the token to receive. */ tokenOut: Address } export type ReturnValue = WriteContractReturnType // TODO: exhaustive error type export type ErrorType = BaseErrorType /** @internal */ export async function inner< action extends typeof writeContract | typeof writeContractSync, chain extends Chain | undefined, account extends Account | undefined, >( action: action, client: Client<Transport, chain, account>, parameters: sell.Parameters<chain, account>, ): Promise<ReturnType<action>> { const { tokenIn, tokenOut, amountIn, minAmountOut, ...rest } = parameters const call = sell.call({ tokenIn, tokenOut, amountIn, minAmountOut }) return (await action(client, { ...rest, ...call, } as never)) as never } /** * Defines a call to the `swapExactAmountIn` function. * * Can be passed as a parameter to: * - [`estimateContractGas`](https://viem.sh/docs/contract/estimateContractGas): estimate the gas cost of the call * - [`simulateContract`](https://viem.sh/docs/contract/simulateContract): simulate the call * - [`sendCalls`](https://viem.sh/docs/actions/wallet/sendCalls): send multiple calls * * @example * ```ts * import { createClient, http, parseUnits, walletActions } from 'viem' * import { tempo } from 'tempo.ts/chains' * import { Actions } from 'tempo.ts/viem' * * const client = createClient({ * chain: tempo({ feeToken: '0x20c0000000000000000000000000000000000001' }) * transport: http(), * }).extend(walletActions) * * const { result } = await client.sendCalls({ * calls: [ * Actions.dex.sell.call({ * amountIn: parseUnits('100', 6), * minAmountOut: parseUnits('95', 6), * tokenIn: '0x20c0...beef', * tokenOut: '0x20c0...babe', * }), * ] * }) * ``` * * @param args - Arguments. * @returns The call. */ export function call(args: Args) { const { tokenIn, tokenOut, amountIn, minAmountOut } = args return defineCall({ address: Addresses.stablecoinDex, abi: Abis.stablecoinDex, functionName: 'swapExactAmountIn', args: [tokenIn, tokenOut, amountIn, minAmountOut],