import type { RouteAmountAll, RouteAmountExact } from '@lifi/compose-spec';

// Constructors for the `amount` member of a `ComposeRouteRequest`. The wire
// union is discriminated by `type` and — deliberately, because the two variants
// mean different things — names its payload field differently in each variant:
// `amount` is the sum actually moved, `simAmount` is only a quoting stand-in for
// a balance resolved on-chain. These helpers keep call sites from having to
// remember which name goes with which discriminant.

/**
 * Spend an exact amount of the route's `fromToken`.
 *
 * @param amount - Amount in the token's smallest unit. `bigint` is serialised
 *   to a decimal string when the request is sent.
 * @returns The `EXACT` member of the route amount union.
 *
 * @example
 * ```ts
 * const result = await sdk.route({
 *   chainId: 1,
 *   fromToken: NATIVE_ETH,
 *   toToken: WETH,
 *   amount: routeAmount.exact(10n ** 17n), // 0.1 ETH, wrapped
 *   signer: OWNER,
 * });
 * ```
 */
export const exact = (amount: bigint | string): RouteAmountExact => ({
  type: 'EXACT',
  amount,
});

/**
 * Spend the signer's entire `fromToken` balance, resolved on-chain at execution
 * time.
 *
 * Not supported when `fromToken` is the chain's native sentinel — the server
 * rejects it. A gas coin is sent via `msg.value`, so there is no on-chain
 * balance to sweep; use {@link exact} for native inputs.
 *
 * @param simAmount - A realistic estimate of that balance, in the token's
 *   smallest unit. The server quotes and simulates against this value, so it
 *   shapes the returned quote and preconditions — but the amount actually moved
 *   is whatever the balance turns out to be.
 * @returns The `ALL` member of the route amount union.
 *
 * @example
 * ```ts
 * const result = await sdk.route({
 *   chainId: 1,
 *   fromToken: USDC,
 *   toToken: A_ETH_USDC,
 *   amount: routeAmount.all(1_000_000n), // estimate: ~1 USDC on hand
 *   signer: OWNER,
 * });
 * ```
 */
export const all = (simAmount: bigint | string): RouteAmountAll => ({
  type: 'ALL',
  simAmount,
});
