openapi: 3.1.0
info:
  title: Infrared API
  description: Token swap routing and execution API
  version: 1.0.0
  contact:
    name: Infrared Support
    url: https://github.com/branched-services/infrared
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://api.infraredtrading.com
    description: Production server

security:
  - ApiKeyAuth: []

tags:
  - name: Quote
    description: Quote operations for token swaps
  - name: Build
    description: Assemble a quoted swap into an executable transaction
  - name: Health
    description: Health check endpoints

paths:
  /v1/quote:
    post:
      operationId: createQuote
      summary: Create a quote for token swap
      description: |
        Computes optimal routing for a token swap and returns a quote with estimated outputs,
        costs, and routing details. The quote is stored server-side and a quote_id is returned
        for use with the Build endpoint.
      tags:
        - Quote
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QuoteRequest'
            examples:
              singleSwap:
                summary: Single token swap
                value:
                  inputs:
                    - chain_id: 1
                      address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
                      amount: "1000000000000000000"
                  outputs:
                    - chain_id: 1
                      address: "0x6B175474E89094C44Da98b954EedeBC836211103"
                      ratio_bps: 10000
                  taker: "0x742d35Cc6634C0532925a3b844Bc9e7595f8b3c4"
              multiOutput:
                summary: Split output to multiple tokens
                value:
                  inputs:
                    - chain_id: 1
                      address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
                      amount: "1000000000000000000"
                  outputs:
                    - chain_id: 1
                      address: "0x6B175474E89094C44Da98b954EedeBC836211103"
                      ratio_bps: 5000
                    - chain_id: 1
                      address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
                      ratio_bps: 5000
                  taker: "0x742d35Cc6634C0532925a3b844Bc9e7595f8b3c4"
                  slippage_tolerance_bps: 50
      responses:
        '200':
          description: Quote created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/QuoteResponseEnvelope'
        '400':
          description: Bad request - invalid JSON or request format
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: BAD_REQUEST
                  message: invalid JSON body
        '401':
          description: Unauthorized - missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: UNAUTHORIZED
                  message: missing API key
        '403':
          description: Forbidden - insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: FORBIDDEN
                  message: "insufficient permissions: requires quotes:read"
        '422':
          description: Unprocessable entity - validation error or routing failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                validationError:
                  summary: Validation error
                  value:
                    error:
                      code: VALIDATION_ERROR
                      message: output ratios must sum to 10000 BPS (100%)
                      details:
                        field: outputs
                noRoute:
                  summary: No route found
                  value:
                    error:
                      code: NO_ROUTE_FOUND
                      message: no route found between tokens
                insufficientLiquidity:
                  summary: Insufficient liquidity
                  value:
                    error:
                      code: INSUFFICIENT_LIQUIDITY
                      message: insufficient liquidity for swap
                simulationFailed:
                  summary: Simulation failed
                  value:
                    error:
                      code: SIMULATION_FAILED
                      message: simulated transaction reverted
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: INTERNAL_ERROR
                  message: an internal error occurred
        '503':
          description: Service unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: SERVICE_UNAVAILABLE
                  message: RPC provider unavailable

  /v1/build:
    post:
      operationId: buildTransaction
      summary: Assemble a quote into an executable transaction
      description: |
        Takes a quote_id from a previous /v1/quote response and assembles it into an unsigned
        transaction ready for wallet signing and on-chain submission. This is the second step
        in the swap flow: quote -> build -> execute (or submit directly).

        The response contains a complete transaction object (to, data, value, gas, chain_id)
        targeting the ExecutionProxy contract, plus estimated output metadata.

        Quotes can be built multiple times (no consumption on build).
        An optional permit2_signature can be attached for gasless approval flows.
      tags:
        - Build
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BuildRequest'
            examples:
              basicBuild:
                summary: Basic build from quote
                value:
                  quote_id: "550e8400-e29b-41d4-a716-446655440000"
              buildWithPermit2:
                summary: Build with Permit2 signature
                value:
                  quote_id: "550e8400-e29b-41d4-a716-446655440000"
                  permit2_signature: "0x1234567890abcdef..."
              buildWithSimulation:
                summary: Build with fork simulation
                value:
                  quote_id: "550e8400-e29b-41d4-a716-446655440000"
                  simulate: true
      responses:
        '200':
          description: Transaction assembled successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BuildResponseEnvelope'
              examples:
                basicResponse:
                  summary: Basic build response
                  value:
                    data:
                      transaction:
                        to: "0x1111111111111111111111111111111111111111"
                        data: "0x5ca02d52000000000000000000000000..."
                        value: "0"
                        gas: 250000
                        chain_id: 1
                      estimated_outputs:
                        - token: "0x6B175474E89094C44Da98b954EedeBC836211103"
                          chain_id: 1
                          expected_amount: "1850000000000000000000"
                          minimum_amount: "1831500000000000000000"
                withSimulation:
                  summary: Build response with simulation
                  value:
                    data:
                      transaction:
                        to: "0x1111111111111111111111111111111111111111"
                        data: "0x5ca02d52000000000000000000000000..."
                        value: "0"
                        gas: 250000
                        chain_id: 1
                      estimated_outputs:
                        - token: "0x6B175474E89094C44Da98b954EedeBC836211103"
                          chain_id: 1
                          expected_amount: "1850000000000000000000"
                          minimum_amount: "1831500000000000000000"
                      simulation:
                        success: true
                        gas_used: 185000
                        output_amounts:
                          "0x6B175474E89094C44Da98b954EedeBC836211103": "1848500000000000000000"
        '400':
          description: Bad request - missing quote_id or invalid JSON
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: VALIDATION_ERROR
                  message: quote_id is required
                  details:
                    field: quote_id
        '401':
          description: Unauthorized - missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: UNAUTHORIZED
                  message: missing API key
        '404':
          description: Quote not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: NOT_FOUND
                  message: quote not found
        '500':
          description: Internal server error - assembly failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: INTERNAL_ERROR
                  message: failed to build transaction

  /health:
    get:
      operationId: healthCheck
      summary: Health check
      description: Returns service health status
      tags:
        - Health
      security: []
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  version:
                    type: string
                    example: "1.0.0"
        '503':
          description: Service is unhealthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /ready:
    get:
      operationId: readinessCheck
      summary: Readiness check
      description: Returns whether service is ready to accept traffic
      tags:
        - Health
      security: []
      responses:
        '200':
          description: Service is ready
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ready
        '503':
          description: Service is not ready
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: |
        API key for authentication. Can also be provided via Authorization header
        with Bearer prefix: `Authorization: Bearer <api-key>`

  schemas:
    # Request schemas
    QuoteRequest:
      type: object
      required:
        - inputs
        - outputs
        - taker
      properties:
        inputs:
          type: array
          description: Input tokens and amounts to swap
          minItems: 1
          maxItems: 6
          items:
            $ref: '#/components/schemas/InputToken'
        outputs:
          type: array
          description: Desired output tokens and ratios. Ratios must sum to 10000 BPS (100%).
          minItems: 1
          maxItems: 6
          items:
            $ref: '#/components/schemas/OutputToken'
        taker:
          type: string
          pattern: "^0x[a-fA-F0-9]{40}$"
          description: Address holding input tokens with allowances set. This address will execute the transaction.
          example: "0x742d35Cc6634C0532925a3b844Bc9e7595f8b3c4"
        recipient:
          type: string
          pattern: "^0x[a-fA-F0-9]{40}$"
          description: Address to receive output tokens. Defaults to taker if not specified.
          example: "0x742d35Cc6634C0532925a3b844Bc9e7595f8b3c4"
        slippage_tolerance_bps:
          type: integer
          minimum: 0
          maximum: 5000
          default: 100
          description: Maximum acceptable slippage in basis points (0-5000). 100 = 1%.
          example: 100
        max_hops:
          type: integer
          minimum: 1
          maximum: 10
          default: 4
          description: Maximum number of intermediate swaps allowed.
          example: 4
        exclude_protocols:
          type: array
          items:
            type: string
          description: Protocol identifiers to exclude from routing.
          example: ["uniswap_v2", "sushiswap"]
        exclude_pools:
          type: array
          items:
            type: string
            pattern: "^0x[a-fA-F0-9]{40}$"
          description: Pool addresses to exclude from routing.
          example: ["0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8"]
        simulate:
          type: boolean
          default: true
          description: Whether to run full causal simulation. Disabling returns faster but less accurate quotes.
        gas_priority:
          type: string
          enum: ["slow", "standard", "fast", "urgent"]
          default: "fast"
          description: |
            Gas price tier for cost estimation. Affects EIP-1559 gas parameters.
            - slow: Lower priority, saves gas cost but may take longer to confirm
            - standard: Normal priority, balanced cost and speed
            - fast: Higher priority, recommended for most swaps (default)
            - urgent: Highest priority, for time-sensitive transactions
        include_usd_pricing:
          type: boolean
          default: false
          description: Whether to include USD pricing in the response. When true, costs will include gas_cost_usd, fee_cost_usd, max_slippage_usd, and total_cost_usd.
        check_allowances:
          type: boolean
          default: false
          description: Check on-chain allowances and only return approvals for tokens with insufficient allowance.
        include_permit2:
          type: boolean
          default: false
          description: Include Permit2 EIP-712 typed data for signature-based approval flow.

    InputToken:
      type: object
      required:
        - chain_id
        - address
        - amount
      properties:
        chain_id:
          type: integer
          description: Blockchain network ID (e.g., 1 for Ethereum mainnet)
          example: 1
        address:
          type: string
          pattern: "^0x[a-fA-F0-9]{40}$"
          description: Token contract address. Use 0x0000000000000000000000000000000000000000 for native ETH.
          example: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
        amount:
          type: string
          pattern: "^[0-9]+$"
          description: Amount in atomic units (wei) as decimal string to avoid precision loss.
          example: "1000000000000000000"

    OutputToken:
      type: object
      required:
        - chain_id
        - address
        - ratio_bps
      properties:
        chain_id:
          type: integer
          description: Blockchain network ID (must match input chain)
          example: 1
        address:
          type: string
          pattern: "^0x[a-fA-F0-9]{40}$"
          description: Token contract address
          example: "0x6B175474E89094C44Da98b954EedeBC836211103"
        ratio_bps:
          type: integer
          minimum: 1
          maximum: 10000
          description: Desired proportion of this output in basis points. All ratios must sum to 10000.
          example: 10000

    BuildRequest:
      type: object
      required:
        - quote_id
      properties:
        quote_id:
          type: string
          description: Quote identifier from a previous /v1/quote response
          example: "550e8400-e29b-41d4-a716-446655440000"
        permit2_signature:
          type: string
          pattern: "^0x[a-fA-F0-9]+$"
          description: |
            Hex-encoded Permit2 signature from signing the EIP-712 typed data returned in the quote's
            permit2 field. Only used if the original quote was requested with include_permit2=true.
            Silently ignored if the quote did not include permit2 data.
          example: "0x1234567890abcdef..."
        simulate:
          type: boolean
          default: false
          description: |
            Run fork simulation on the assembled transaction before returning. The simulation result
            is included in the response. Simulation failures do NOT block the response — the transaction
            is still returned with simulation.success=false.

    # Response schemas
    BuildResponseEnvelope:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/BuildResponse'

    BuildResponse:
      type: object
      properties:
        transaction:
          $ref: '#/components/schemas/TransactionObject'
        estimated_outputs:
          type: array
          items:
            $ref: '#/components/schemas/EstimatedOutput'
          description: Estimated output amounts from the quote
        simulation:
          $ref: '#/components/schemas/SimulationResult'
          description: Fork simulation result. Only present when simulate=true.

    TransactionObject:
      type: object
      description: Unsigned transaction ready for wallet signing
      properties:
        to:
          type: string
          pattern: "^0x[a-fA-F0-9]{40}$"
          description: ExecutionProxy contract address (EIP-55 checksummed)
          example: "0x1111111111111111111111111111111111111111"
        data:
          type: string
          pattern: "^0x[a-fA-F0-9]+$"
          description: ABI-encoded calldata for ExecutionProxy.execute() or ExecutionProxy.executeSingle()
          example: "0x5ca02d52000000000000000000000000..."
        value:
          type: string
          pattern: "^[0-9]+$"
          description: ETH value to send in wei (decimal string). "0" for ERC-20 only swaps.
          example: "0"
        gas:
          type: integer
          format: int64
          description: Recommended gas limit for the transaction
          example: 250000
        chain_id:
          type: integer
          description: Target blockchain network ID
          example: 1

    SimulationResult:
      type: object
      description: Result of fork simulation on the assembled transaction
      properties:
        success:
          type: boolean
          description: Whether the simulation succeeded
          example: true
        gas_used:
          type: integer
          format: int64
          description: Actual gas consumed in simulation (only on success)
          example: 185000
        output_amounts:
          type: object
          additionalProperties:
            type: string
          description: Map of token addresses to simulated output amounts (only on success)
          example:
            "0x6B175474E89094C44Da98b954EedeBC836211103": "1848500000000000000000"
        error:
          type: string
          description: Error message if simulation failed
          example: "execution reverted: INSUFFICIENT_OUTPUT_AMOUNT"

    QuoteResponseEnvelope:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/QuoteResponse'

    QuoteResponse:
      type: object
      properties:
        quote_id:
          type: string
          format: uuid
          description: Unique identifier for this quote. Use with Execute endpoint.
          example: "550e8400-e29b-41d4-a716-446655440000"
        inputs:
          type: array
          items:
            $ref: '#/components/schemas/InputTokenResponse'
          description: Echoed input tokens with normalized addresses
        outputs:
          type: array
          items:
            $ref: '#/components/schemas/OutputTokenResponse'
          description: Echoed output tokens with normalized addresses
        taker:
          type: string
          description: Checksummed taker address
          example: "0x742d35Cc6634C0532925a3b844Bc9e7595f8b3c4"
        estimated_outputs:
          type: array
          items:
            $ref: '#/components/schemas/EstimatedOutput'
          description: Estimated output amounts for each output token
        costs:
          $ref: '#/components/schemas/CostBreakdown'
        path:
          $ref: '#/components/schemas/Path'
        protocols_used:
          type: array
          items:
            type: string
          description: Protocols involved in the route
          example: ["uniswap_v3", "curve"]
        approvals:
          type: array
          items:
            $ref: '#/components/schemas/ApprovalRequirement'
          description: ERC-20 approval requirements for this swap. Empty if user has sufficient allowances (when check_allowances=true) or inputs are native tokens only.
        permit2:
          $ref: '#/components/schemas/Permit2Data'
          description: Permit2 EIP-712 typed data for signature-based approval. Only present when include_permit2=true.

    InputTokenResponse:
      type: object
      properties:
        chain_id:
          type: integer
          example: 1
        address:
          type: string
          description: EIP-55 checksummed address
          example: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
        amount:
          type: string
          example: "1000000000000000000"

    OutputTokenResponse:
      type: object
      properties:
        chain_id:
          type: integer
          example: 1
        address:
          type: string
          description: EIP-55 checksummed address
          example: "0x6B175474E89094C44Da98b954EedeBC836211103"
        ratio_bps:
          type: integer
          example: 10000

    EstimatedOutput:
      type: object
      properties:
        token:
          type: string
          description: EIP-55 checksummed token address
          example: "0x6B175474E89094C44Da98b954EedeBC836211103"
        chain_id:
          type: integer
          example: 1
        expected_amount:
          type: string
          description: Estimated output amount before slippage
          example: "1850000000000000000000"
        minimum_amount:
          type: string
          description: Guaranteed minimum after slippage tolerance
          example: "1831500000000000000000"

    CostBreakdown:
      type: object
      description: Breakdown of estimated execution costs with EIP-1559 gas parameters
      properties:
        gas_cost_wei:
          type: string
          description: Estimated gas cost in wei (based on max_fee_per_gas * total_gas_units)
          example: "5000000000000000"
        gas_cost_usd:
          type:
            - number
            - 'null'
          description: Gas cost in USD. Only populated when include_usd_pricing=true.
          example: 8.50
        fee_cost_usd:
          type:
            - number
            - 'null'
          description: Total DEX fees in USD. Only populated when include_usd_pricing=true.
          example: 5.55
        max_slippage_usd:
          type:
            - number
            - 'null'
          description: Maximum potential slippage loss in USD. Only populated when include_usd_pricing=true.
          example: 2.25
        total_cost_usd:
          type:
            - number
            - 'null'
          description: Sum of gas and fee costs in USD (excludes slippage). Only populated when include_usd_pricing=true.
          example: 14.05
        total_gas_units:
          type: integer
          description: Estimated gas units for execution
          example: 250000
        base_fee_wei:
          type: integer
          format: int64
          description: EIP-1559 base fee in wei at quote time
          example: 15000000000
        max_priority_fee_per_gas:
          type: integer
          format: int64
          description: EIP-1559 max priority fee (tip) in wei
          example: 2000000000
        max_fee_per_gas:
          type: integer
          format: int64
          description: EIP-1559 max total fee per gas in wei (base_fee + priority_fee buffer)
          example: 20000000000
        gas_priority:
          type: string
          enum: ["slow", "standard", "fast", "urgent"]
          description: Gas priority tier used for this quote
          example: "fast"

    Path:
      type: object
      description: Execution path with token metadata and steps. Supports multi-token operations like LP decompose/compose.
      properties:
        tokens:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/PathToken'
          description: Map of token addresses to their metadata. Keys are EIP-55 checksummed addresses.
          example:
            "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2":
              name: "Wrapped Ether"
              symbol: "WETH"
              decimals: 18
              token_type: "erc20"
            "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc":
              name: "Uniswap V2"
              symbol: "UNI-V2"
              decimals: 18
              token_type: "lp"
        steps:
          type: array
          items:
            $ref: '#/components/schemas/PathStep'
          description: Ordered list of execution steps

    PathToken:
      type: object
      description: Token metadata
      properties:
        name:
          type: string
          description: Token name
          example: "Wrapped Ether"
        symbol:
          type: string
          description: Token symbol
          example: "WETH"
        decimals:
          type: integer
          minimum: 0
          maximum: 18
          description: Token decimal precision
          example: 18
        token_type:
          type: string
          enum: ["erc20", "lp", "native", "wrapped"]
          description: Token type classification
          example: "erc20"

    PathStep:
      type: object
      description: A single step in the execution path. Supports multi-token inputs/outputs for decompose/compose operations.
      properties:
        type:
          type: string
          enum: ["swap", "decompose", "compose", "wrap", "unwrap"]
          description: Operation type
          example: "swap"
        protocol:
          type: string
          description: Protocol handling this step
          example: "uniswap_v3"
        pool:
          type: string
          description: EIP-55 checksummed pool/contract address
          example: "0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8"
        tokens_in:
          type: array
          items:
            type: string
          description: EIP-55 checksummed input token addresses. Multiple for compose operations.
          example: ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"]
        tokens_out:
          type: array
          items:
            type: string
          description: EIP-55 checksummed output token addresses. Multiple for decompose operations.
          example: ["0x6B175474E89094C44Da98b954EedeBC836211103"]
        amounts_in:
          type: array
          items:
            type: string
          description: Input amounts in atomic units. "0" if dynamic/unknown.
          example: ["1000000000000000000"]
        amounts_out:
          type: array
          items:
            type: string
          description: Output amounts in atomic units. "0" if dynamic/unknown.
          example: ["1850000000000000000000"]
        gas_estimate:
          type: string
          description: Estimated gas units for this step
          example: "60000"
        share_of_input_bps:
          type: integer
          minimum: 0
          maximum: 10000
          description: Percentage of total input value flowing through this step in basis points (0-10000)
          example: 10000

    # Error schemas
    ErrorResponse:
      type: object
      properties:
        error:
          $ref: '#/components/schemas/ErrorBody'

    ErrorBody:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          enum:
            - BAD_REQUEST
            - VALIDATION_ERROR
            - NOT_FOUND
            - SIMULATION_FAILED
            - INSUFFICIENT_LIQUIDITY
            - NO_ROUTE_FOUND
            - UNAUTHORIZED
            - FORBIDDEN
            - RATE_LIMITED
            - CONFLICT
            - INTERNAL_ERROR
            - TIMEOUT
            - SERVICE_UNAVAILABLE
          description: Machine-readable error code
          example: VALIDATION_ERROR
        message:
          type: string
          description: Human-readable error message
          example: output ratios must sum to 10000 BPS (100%)
        details:
          type: object
          additionalProperties: true
          description: Additional error context
          example:
            field: outputs

    # Approval schemas
    ApprovalRequirement:
      type: object
      required:
        - token
        - amount
        - spender
      description: ERC-20 token approval required for execution
      properties:
        token:
          type: string
          pattern: "^0x[a-fA-F0-9]{40}$"
          description: ERC-20 token contract address requiring approval
          example: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
        amount:
          type: string
          pattern: "^[0-9]+$"
          description: Amount to approve in atomic units (wei). This is the exact amount needed for this swap.
          example: "1000000000000000000"
        spender:
          type: string
          pattern: "^0x[a-fA-F0-9]{40}$"
          description: Address to approve as spender (ExecutionProxy contract)
          example: "0x1234567890123456789012345678901234567890"

    Permit2Data:
      type: object
      description: Complete EIP-712 typed data for Permit2 PermitTransferFrom signature
      properties:
        hash:
          type: string
          pattern: "^0x[a-fA-F0-9]{64}$"
          description: Keccak256 hash of the typed data for reference
          example: "0x6b35d87d974ef207889b10326321b83869cac1f3b637656901bbd075b68e7123"
        eip712:
          $ref: '#/components/schemas/EIP712TypedData'

    EIP712TypedData:
      type: object
      description: EIP-712 typed data structure ready for wallet.signTypedData()
      required:
        - types
        - domain
        - primaryType
        - message
      properties:
        types:
          type: object
          description: Type definitions for EIP-712
          properties:
            EIP712Domain:
              type: array
              items:
                $ref: '#/components/schemas/EIP712TypeField'
            TokenPermissions:
              type: array
              items:
                $ref: '#/components/schemas/EIP712TypeField'
            PermitTransferFrom:
              type: array
              items:
                $ref: '#/components/schemas/EIP712TypeField'
        domain:
          type: object
          description: EIP-712 domain separator
          properties:
            name:
              type: string
              description: Domain name
              example: "Permit2"
            chainId:
              type: integer
              description: Chain ID
              example: 1
            verifyingContract:
              type: string
              pattern: "^0x[a-fA-F0-9]{40}$"
              description: Permit2 contract address
              example: "0x000000000022d473030f116ddee9f6b43ac78ba3"
        primaryType:
          type: string
          description: Primary type being signed
          example: "PermitTransferFrom"
        message:
          type: object
          description: The permit message to sign
          properties:
            permitted:
              type: object
              properties:
                token:
                  type: string
                  pattern: "^0x[a-fA-F0-9]{40}$"
                  description: Token address
                amount:
                  type: string
                  pattern: "^[0-9]+$"
                  description: Amount in atomic units
            spender:
              type: string
              pattern: "^0x[a-fA-F0-9]{40}$"
              description: ExecutionProxy address that will call Permit2
            nonce:
              type: string
              pattern: "^[0-9]+$"
              description: Unique nonce from Permit2 contract
            deadline:
              type: string
              pattern: "^[0-9]+$"
              description: Unix timestamp when signature expires

    EIP712TypeField:
      type: object
      description: EIP-712 type field definition
      properties:
        name:
          type: string
          description: Field name
        type:
          type: string
          description: Field type
