@lifi/types
Version:
Types for the LI.FI stack
253 lines (219 loc) • 7.28 kB
text/typescript
import type {
TypedData,
TransactionRequest,
SignedTypedData,
ExecutionType,
} from './api.js'
import type { Token } from './tokens/index.js'
/**
* How a fee was calculated / the role of the recipient in the split.
*
* - `FIXED` — a fixed LI.FI cut applied alongside the integrator's own fee.
* - `SHARED` — a single shared pool divided between LI.FI and the integrator.
* - `DYNAMIC` — fee resolved at quote time from configured rules (e.g. dynamic
* stablecoin pricing).
* - `INTERMEDIARY` — a third-party recipient that carves a configured share
* from the integrator pool (e.g. a widget or aggregator).
* - `DISTRIBUTION` — a partner-specified extra recipient added in parallel to
* the integrator/intermediary split via the `distributionFees` request param.
*
* The union is expected to grow over time. When pattern-matching with a
* `switch`, always include a `default` branch so adding a new value remains
* a non-breaking minor for consumers.
*/
export type FeeSplitType =
| 'FIXED'
| 'SHARED'
| 'DYNAMIC'
| 'INTERMEDIARY'
| 'DISTRIBUTION'
export interface FeeRecipient {
/** Recipient identifier. Polymorphic — interpret in conjunction with `type`:
* - `'lifi'` for the LI.FI platform recipient,
* - the integrator id (e.g. `'jumper'`) for the integrator recipient,
* - the intermediary id (e.g. `'mesh'`) when `type === 'INTERMEDIARY'`,
* - the recipient wallet address when `type === 'DISTRIBUTION'`.
*
* Do not display this value directly in user-facing UI without
* `type`-aware formatting — for `DISTRIBUTION` rows the value is a
* raw hex address. */
name: string
/** Absolute fee amount, a big number in source token base units (string-encoded). */
fee: string
/** Fee calculation type. Absent when not statically determinable (e.g.
* an integrator entry whose `feeType` could not be resolved from the
* matching planned fee cost). Consumers should null-check before reading. */
type?: FeeSplitType
/** Recipient wallet address on the source chain. */
walletAddress?: string
}
export interface FeeSplit {
/** LI.FI's slice of THIS `FeeCost.amount`. */
lifiFee: string
/** The integrator's slice of THIS `FeeCost.amount` — the integrator's
* portion only, NOT including any intermediary or distribution amounts. */
integratorFee: string
/** The intermediary's slice of THIS `FeeCost.amount` when an intermediary
* participates in the split. Absent otherwise. */
intermediaryFee?: string
/** Per-recipient breakdown of THIS `FeeCost.amount`. Source of truth for
* new consumers — the aggregate fields above are disjoint slices kept
* for backward compatibility with 2-recipient consumers.
*
* Note: partner-specified distribution recipients are emitted as
* separate `FeeCost` entries (one per receiver, `name: "Fee Forward"`)
* at quote/route estimation time. At status-response time the same
* recipients may appear merged on the integrator's `FeeCost` for
* compactness. Iterate `estimate.feeCosts[]` to discover all
* recipients across both shapes. */
recipients?: FeeRecipient[]
}
export interface FeeCost {
name: string
description: string
percentage: string
token: Token
amount: string
amountUSD: string
included: boolean
feeSplit?: FeeSplit
}
export interface GasCost {
type: 'SUM' | 'APPROVE' | 'SEND' | 'FEE'
price: string // suggested current standard price for chain
estimate: string // estimate how much gas will be needed
limit: string // suggested gas limit (estimate +25%)
amount: string // estimate * price = amount of tokens that will be needed
amountUSD: string // usd value of token amount
token: Token // the used gas token
}
// ACTION
export interface Action {
fromChainId: number
fromAmount: string
fromToken: Token
fromAddress?: string
toChainId: number
toToken: Token
toAddress?: string
slippage?: number
}
// ESTIMATE
export interface Estimate {
tool: string
fromAmount: string
fromAmountUSD?: string
toAmount: string
toAmountMin: string
toAmountUSD?: string
approvalAddress: string
feeCosts?: FeeCost[]
/** This is a list to account for approval gas costs and transaction gas costs. However, approval gas costs are not integrated yet. */
gasCosts?: GasCost[]
/** Estimated duration in seconds */
executionDuration: number
/** Optional flag to indicate approval reset requirement for legacy ERC-20 tokens */
approvalReset?: boolean
/** Optional flag to skip approval in the cases where we only need to sign the message (e.g. Hyperliquid)*/
skipApproval?: boolean
/** Optional flag to skip permit usage when the tx doesn't include diamond interaction (some HyperEVM txs) */
skipPermit?: boolean
}
// STEP
export const _StepType = [
'lifi',
'swap',
'cross',
'protocol',
'custom',
] as const
export type StepType = (typeof _StepType)[number]
export type StepTool = string
export type StepToolDetails = {
key: string
name: string
logoURI: string
}
type StepInformationBase = {
tool: string
type: string
action: Action
estimate: Estimate
}
export type StepInformation = StepInformationBase & {
createdAt: Date
gasLimit: string
stepId: string
transactionId: string
intermediateActions: StepInformationBase[]
integrator?: string
relatedLifiSteps?: string[]
}
export interface StepBase {
id: string
type: StepType
tool: StepTool
toolDetails: StepToolDetails
integrator?: string
/** Intermediary identifier set when the route was generated with a multi-party fee split.
* Threaded through to /stepTransaction so the same split can be reproduced at tx-generation time. */
intermediary?: string
referrer?: string
action: Action
estimate?: Estimate
executionType?: ExecutionType
transactionRequest?: TransactionRequest
transactionId?: string
/**
* EIP-712 Typed Data
* @link https://eips.ethereum.org/EIPS/eip-712
*/
typedData?: TypedData[]
}
export interface DestinationCallInfo {
toContractAddress: string
toContractCallData: string
toFallbackAddress: string
callDataGasLimit: string
}
export type CallAction = Action & DestinationCallInfo
export interface SwapStep extends StepBase {
type: 'swap'
action: Action
estimate: Estimate
}
export interface CrossStep extends StepBase {
type: 'cross'
action: Action
estimate: Estimate
}
export interface ProtocolStep extends StepBase {
type: 'protocol'
action: Action
estimate: Estimate
}
export interface CustomStep extends StepBase {
type: 'custom'
action: CallAction
estimate: Estimate
}
export type Step = SwapStep | CrossStep | CustomStep | ProtocolStep
export interface LiFiStep extends Omit<Step, 'type'> {
type: 'lifi'
includedSteps: Step[]
}
export interface SignedLiFiStep extends LiFiStep {
typedData: SignedTypedData[]
}
export function isSwapStep(step: Step): step is SwapStep {
return step.type === 'swap'
}
export function isCrossStep(step: Step): step is CrossStep {
return step.type === 'cross'
}
export function isProtocolStep(step: Step): step is ProtocolStep {
return step.type === 'protocol'
}
export function isCustomStep(step: Step): step is CustomStep {
return step.type === 'custom'
}