import type { Address } from 'abitype' import type { KeyAuthorization } from 'ox/tempo' import * as Selectors from './Selectors.js' export type Selector = NonNullable export type Options = { /** Recipient allowlist for selectors that support recipient restrictions. */ recipients?: readonly Address[] | undefined } export type Scope< address extends Address = Address, selector extends Selector | undefined = Selector | undefined, > = Omit & { address: address recipients?: readonly Address[] | undefined selector?: selector | undefined } export type Target
= { /** Allows any selector on the target. */ any: () => Scope /** Allows calls matching the selector on the target. */ selector: ( selector: selector, options?: Options | undefined, ) => Scope } export type SelectorMap = Record> export type Contract< address extends Address = Address, selectors extends SelectorMap = SelectorMap, > = Target
& { readonly [name in keyof selectors]: selectors[name] extends Selector ? (options?: Options | undefined) => Scope : selectors[name] extends Record ? OverloadedSelector : never } export type OverloadedSelector< address extends Address = Address, selectors extends Record = Record, > = { readonly [signature in keyof selectors]: ( options?: Options | undefined, ) => Scope } & { selector: ( signature: signature, options?: Options | undefined, ) => Scope } export type Tip20
= Contract< address, typeof Selectors.tip20 > /** * Creates a call scope builder for an arbitrary target. * * @experimental */ export function target
( address: address, ): Target
{ return { any: () => ({ address }), selector: (selector, options) => ({ address, ...(options && 'recipients' in options ? { recipients: options.recipients } : {}), selector, }), } } /** * Creates a typed call scope builder from a selector map. * * @experimental */ export function contract< address extends Address, selectors extends SelectorMap, >(address: address, selectors: selectors): Contract { const target_ = target(address) const result: Record = { ...target_ } for (const [name, selector] of Object.entries(selectors)) { if (typeof selector === 'string') { result[name] = (options?: Options | undefined) => target_.selector(selector, options) continue } const overloads: Record = {} for (const [signature, overloadSelector] of Object.entries(selector)) { overloads[signature] = (options?: Options | undefined) => target_.selector(overloadSelector, options) } overloads.selector = (signature: string, options?: Options | undefined) => target_.selector(selector[signature]!, options) result[name] = overloads } return result as Contract } /** * Creates a call scope builder for a TIP-20 token. * * @experimental */ export function tip20
( address: address, ): Tip20
{ return contract(address, Selectors.tip20) }