UNPKG

@lifi/compose-spec

Version:

Public wire-format types and schemas for Compose flows

90 lines (75 loc) 2.36 kB
import { EVM_NATIVE_SENTINEL } from './chainCapabilities.js'; export type Availability = 'now' | 'future'; export interface OutputAmount { readonly expected: bigint; readonly min?: bigint; } export type Resource = | { readonly kind: 'native'; readonly chainId: number } | { readonly kind: 'erc20'; readonly token: string; readonly chainId: number; }; export type SimulatedAmounts = { readonly amountOut: bigint; readonly amountOutMin?: bigint; }; export type ProducedResource = Resource & { readonly availability: Availability; readonly simulated?: SimulatedAmounts; readonly owner: string; }; export const erc20Resource = (token: string, chainId: number): Resource => ({ kind: 'erc20', token, chainId, }); export const nativeResource = (chainId: number): Resource => ({ kind: 'native', chainId, }); export const isERC20Resource = ( r: Resource, ): r is Extract<Resource, { kind: 'erc20' }> => r.kind === 'erc20'; export const isNativeResource = ( r: Resource, ): r is Extract<Resource, { kind: 'native' }> => r.kind === 'native'; export const resourcesEqual = (a: Resource, b: Resource): boolean => { if (isNativeResource(a) && isNativeResource(b)) { return a.chainId === b.chainId; } if (isERC20Resource(a) && isERC20Resource(b)) { return ( a.chainId === b.chainId && a.token.toLowerCase() === b.token.toLowerCase() ); } return false; }; export const foldResource = <R>( r: Resource, cases: { readonly native: (chainId: number) => R; readonly erc20: (token: string, chainId: number) => R; }, ): R => r.kind === 'native' ? cases.native(r.chainId) : cases.erc20(r.token, r.chainId); // Canonical address representation of a resource for consumers whose wire // contract uses the EVM-native sentinel rather than the Resource union. export const resourceToken = (r: Resource): string => foldResource(r, { native: () => EVM_NATIVE_SENTINEL, erc20: (token) => token, }); export const resourceKey = (r: Resource): string => foldResource(r, { native: (chainId) => `native:${chainId}`, erc20: (token, chainId) => `erc20:${token.toLowerCase()}:${chainId}`, }); export const erc20Token = (r: Resource): string => { if (r.kind !== 'erc20') throw new Error(`Expected erc20 resource, got ${r.kind}`); return r.token; };