import type { SignatureEnvelope } from 'ox/tempo'
import * as z from 'zod/mini'

import * as Schema from '../internal/schema.js'
import * as u from './utils.js'

export const log = z.object({
  address: u.address(),
  blockHash: u.hex(),
  blockNumber: u.bigint(),
  data: u.hex(),
  logIndex: u.number(),
  removed: z.boolean(),
  topics: z.readonly(z.array(u.hex())),
  transactionHash: u.hex(),
  transactionIndex: u.number(),
})

export const receipt = z.object({
  blobGasPrice: z.optional(u.bigint()),
  blobGasUsed: z.optional(u.bigint()),
  blockHash: u.hex(),
  blockNumber: u.bigint(),
  contractAddress: z.nullable(u.address()),
  cumulativeGasUsed: u.bigint(),
  effectiveGasPrice: u.bigint(),
  feePayer: z.optional(u.address()),
  feeToken: z.optional(u.address()),
  from: u.address(),
  gasUsed: u.bigint(),
  logs: z.array(log),
  logsBloom: u.hex(),
  root: z.optional(u.hex()),
  status: z.codec(u.hex(), z.enum(['success', 'reverted']), {
    decode: (value) => (value === '0x1' ? 'success' : 'reverted'),
    encode: (value) => (value === 'success' ? '0x1' : '0x0'),
  }),
  to: z.nullable(u.address()),
  transactionHash: u.hex(),
  transactionIndex: u.number(),
  type: u.hex(),
})

export const signatureEnvelope = z.custom<SignatureEnvelope.SignatureEnvelopeRpc>()

export const keyType = z.union([z.literal('secp256k1'), z.literal('p256'), z.literal('webAuthn')])

export const keyAuthorization = z.object({
  address: z.optional(u.address()),
  chainId: u.bigint(),
  expiry: z.union([u.number(), z.null(), z.undefined()]),
  keyId: u.address(),
  keyType,
  limits: z.optional(
    z.readonly(
      z.array(z.object({ token: u.address(), limit: u.bigint(), period: z.optional(u.number()) })),
    ),
  ),
  signature: signatureEnvelope,
})

export const call = z.object({
  data: z.optional(u.hex()),
  to: z.optional(u.address()),
  value: z.optional(u.bigint()),
})

export const transactionRequest = z.object({
  accessList: z.optional(
    z.array(z.object({ address: u.address(), storageKeys: z.array(u.hex()) })),
  ),
  calls: z.optional(z.readonly(z.array(call))),
  chainId: z.optional(u.number()),
  data: z.optional(u.hex()),
  feePayer: z.optional(z.union([z.boolean(), z.string()])),
  feePayerSignature: z.optional(z.record(z.string(), z.unknown())),
  feeToken: z.optional(u.address()),
  from: z.optional(u.address()),
  gas: z.optional(u.bigint()),
  keyAuthorization: z.optional(keyAuthorization),
  keyData: z.optional(u.hex()),
  keyId: z.optional(u.address()),
  keyType: z.optional(keyType),
  maxFeePerGas: z.optional(u.bigint()),
  maxPriorityFeePerGas: z.optional(u.bigint()),
  nonce: z.optional(u.number()),
  nonceKey: z.optional(u.bigint()),
  to: z.optional(u.address()),
  validAfter: z.optional(u.number()),
  validBefore: z.optional(u.number()),
  value: z.optional(u.bigint()),
})

export namespace eth_accounts {
  export const schema = Schema.defineItem({
    method: z.literal('eth_accounts'),
    params: undefined,
    returns: z.readonly(z.array(u.address())),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace eth_chainId {
  export const schema = Schema.defineItem({
    method: z.literal('eth_chainId'),
    params: undefined,
    returns: u.hex(),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace eth_requestAccounts {
  export const schema = Schema.defineItem({
    method: z.literal('eth_requestAccounts'),
    params: undefined,
    returns: z.readonly(z.array(u.address())),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace eth_sendTransaction {
  export const schema = Schema.defineItem({
    method: z.literal('eth_sendTransaction'),
    params: z.readonly(z.tuple([transactionRequest])),
    returns: u.hex(),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace eth_fillTransaction {
  const balanceDiff = z.object({
    address: u.address(),
    decimals: z.number(),
    direction: z.enum(['incoming', 'outgoing']),
    formatted: z.string(),
    name: z.string(),
    recipients: z.readonly(z.array(u.address())),
    symbol: z.string(),
    value: u.hex(),
  })

  const swapAmount = z.object({
    decimals: z.number(),
    formatted: z.string(),
    name: z.string(),
    symbol: z.string(),
    token: u.address(),
    value: u.hex(),
  })

  export const schema = Schema.defineItem({
    method: z.literal('eth_fillTransaction'),
    params: z.readonly(z.tuple([transactionRequest])),
    returns: z.object({
      capabilities: z.object({
        balanceDiffs: z.optional(z.record(u.address(), z.readonly(z.array(balanceDiff)))),
        error: z.optional(
          z.object({
            abiItem: z.optional(z.record(z.string(), z.unknown())),
            data: z.optional(u.hex()),
            errorName: z.string(),
            message: z.string(),
          }),
        ),
        fee: z.optional(
          z.object({
            amount: u.hex(),
            decimals: z.number(),
            formatted: z.string(),
            symbol: z.string(),
          }),
        ),
        requireFunds: z.optional(
          z.object({
            amount: u.hex(),
            decimals: z.number(),
            formatted: z.string(),
            token: u.address(),
            symbol: z.string(),
          }),
        ),
        autoSwap: z.optional(
          z.object({
            maxIn: swapAmount,
            minOut: swapAmount,
            slippage: z.number(),
          }),
        ),
        sponsor: z.optional(
          z.object({
            address: u.address(),
            name: z.optional(z.string()),
            url: z.optional(z.string()),
          }),
        ),
        sponsored: z.boolean(),
      }),
      tx: z.record(z.string(), z.unknown()),
    }),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace eth_signTransaction {
  export const schema = Schema.defineItem({
    method: z.literal('eth_signTransaction'),
    params: z.readonly(z.tuple([transactionRequest])),
    returns: u.hex(),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace eth_sendTransactionSync {
  export const schema = Schema.defineItem({
    method: z.literal('eth_sendTransactionSync'),
    params: z.readonly(z.tuple([transactionRequest])),
    returns: receipt,
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace eth_signTypedData_v4 {
  export const schema = Schema.defineItem({
    method: z.literal('eth_signTypedData_v4'),
    params: z.readonly(z.tuple([u.address(), z.string()])),
    returns: u.hex(),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace personal_sign {
  export const schema = Schema.defineItem({
    method: z.literal('personal_sign'),
    params: z.readonly(z.tuple([u.hex(), u.address()])),
    returns: u.hex(),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

const sendCallsCapabilities = z.optional(
  z.object({
    feePayer: z.optional(z.union([z.boolean(), z.string()])),
    sync: z.optional(z.boolean()),
  }),
)

export namespace wallet_sendCalls {
  export const schema = Schema.defineItem({
    method: z.literal('wallet_sendCalls'),
    params: z.optional(
      z.readonly(
        z.tuple([
          z.object({
            atomicRequired: z.optional(z.boolean()),
            calls: z.readonly(z.array(call)),
            capabilities: sendCallsCapabilities,
            chainId: z.optional(u.number()),
            from: z.optional(u.address()),
            version: z.optional(z.string()),
          }),
        ]),
      ),
    ),
    returns: z.object({
      atomic: z.optional(z.boolean()),
      capabilities: sendCallsCapabilities,
      chainId: z.optional(u.number()),
      id: z.string(),
      receipts: z.optional(z.array(receipt)),
      status: z.optional(z.number()),
      version: z.optional(z.string()),
    }),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace wallet_getBalances {
  export const schema = Schema.defineItem({
    method: z.literal('wallet_getBalances'),
    params: z.optional(
      z.readonly(
        z.tuple([
          z.object({
            account: z.optional(u.address()),
            chainId: z.optional(u.number()),
            tokens: z.optional(z.readonly(z.array(u.address()))),
          }),
        ]),
      ),
    ),
    returns: z.readonly(
      z.array(
        z.object({
          address: u.address(),
          balance: u.bigint(),
          decimals: z.number(),
          display: z.string(),
          name: z.string(),
          symbol: z.string(),
        }),
      ),
    ),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace wallet_getCapabilities {
  export const schema = Schema.defineItem({
    method: z.literal('wallet_getCapabilities'),
    params: z.optional(
      z.readonly(
        z.union([z.tuple([u.address()]), z.tuple([u.address(), z.readonly(z.array(u.hex()))])]),
      ),
    ),
    returns: z.record(
      u.hex(),
      z.object({
        accessKeys: z.optional(
          z.object({
            status: z.union([z.literal('supported'), z.literal('unsupported')]),
          }),
        ),
        atomic: z.object({
          status: z.union([z.literal('supported'), z.literal('ready'), z.literal('unsupported')]),
        }),
        feePayer: z.optional(
          z.object({
            status: z.union([z.literal('supported'), z.literal('unsupported')]),
          }),
        ),
      }),
    ),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace wallet_authorizeAccessKey {
  export const parameters = z.object({
    address: z.optional(u.address()),
    chainId: z.optional(u.bigint()),
    expiry: z.number(),
    keyType: z.optional(keyType),
    limits: z.optional(
      z.readonly(
        z.array(
          z.object({ token: u.address(), limit: u.bigint(), period: z.optional(z.number()) }),
        ),
      ),
    ),
    publicKey: z.optional(u.hex()),
    scopes: z.optional(
      z.readonly(
        z.array(
          z.object({
            address: u.address(),
            selector: z.optional(z.union([u.hex(), z.string()])),
            recipients: z.optional(z.readonly(z.array(u.address()))),
          }),
        ),
      ),
    ),
  })

  export const returns = z.object({
    keyAuthorization,
    rootAddress: u.address(),
  })

  export const schema = Schema.defineItem({
    method: z.literal('wallet_authorizeAccessKey'),
    params: z.readonly(z.tuple([parameters])),
    returns,
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace wallet_authorizeAccessKey_strict {
  export const parameters = z.object({
    address: z.optional(u.address()),
    expiry: z.number(),
    keyType: z.optional(keyType),
    limits: z.readonly(
      z
        .array(z.object({ token: u.address(), limit: u.bigint(), period: z.optional(z.number()) }))
        .check(z.minLength(1)),
    ),
    publicKey: z.optional(u.hex()),
    scopes: z.readonly(
      z
        .array(
          z.object({
            address: u.address(),
            selector: z.optional(z.union([u.hex(), z.string()])),
            recipients: z.optional(z.readonly(z.array(u.address()))),
          }),
        )
        .check(z.minLength(1)),
    ),
  })
}

export namespace wallet_revokeAccessKey {
  export const schema = Schema.defineItem({
    method: z.literal('wallet_revokeAccessKey'),
    params: z.readonly(
      z.tuple([z.object({ address: u.address(), accessKeyAddress: u.address() })]),
    ),
    returns: undefined,
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace wallet_connect {
  export const authorizeAccessKey = z.optional(wallet_authorizeAccessKey.parameters)

  /**
   * SIWE round-trip configuration. Bare string is shorthand for `{ url }`.
   *
   * - `auth: '/api/auth'` derives `${url}/challenge`, `${url}` (verify), `${url}/logout`.
   * - Object form lets callers override individual endpoints, opt into a
   *   `{ token }` body via `returnToken`, etc.
   *
   * Cross-field validation (must include `url` or both `challenge` + `verify`)
   * is enforced inside `prepareSiwe`, not in zod, so the error message can be
   * specific.
   */
  export const auth = z.optional(
    z.union([
      z.string(),
      z.object({
        /** Base URL. SDK derives `${url}/challenge` and `${url}/logout`; `${url}` itself is verify. */
        url: z.optional(z.string()),
        /** Override individual endpoints. Either `url` or both `challenge` + `verify` must be set. */
        challenge: z.optional(z.string()),
        verify: z.optional(z.string()),
        logout: z.optional(z.string()),
        /**
         * Ask the verify endpoint to also return `{ token }` in the JSON body.
         * Default `false` — cookie mode relies on `Set-Cookie` only.
         * Set this for non-browser clients (RN, CLI) that can't store cookies, or
         * to surface the JWT alongside a cookie in dual-transport setups.
         */
        returnToken: z.optional(z.boolean()),
      }),
    ]),
  )

  /**
   * Request a `personal_sign` (EIP-191) over the supplied message during
   * `wallet_connect`. The wallet computes `hashMessage(message)` and signs
   * the resulting 32-byte digest in the same passkey ceremony that loads
   * or creates the account, so this costs no extra prompt over a plain
   * `wallet_connect`. The signature is returned via the top-level
   * `capabilities.signature` field on the connected account.
   */
  export const personalSign = z.optional(
    z.object({
      /** Message to sign. The wallet applies the EIP-191 prehash. */
      message: z.string(),
    }),
  )

  export const capabilities = {
    request: z.optional(
      z.union([
        z.object({
          digest: z.optional(u.hex()),
          authorizeAccessKey,
          auth,
          method: z.literal('register'),
          name: z.optional(z.string()),
          personalSign,
          userId: z.optional(z.string()),
        }),
        z.object({
          digest: z.optional(u.hex()),
          credentialId: z.optional(z.string()),
          authorizeAccessKey,
          auth,
          method: z.optional(z.literal('login')),
          personalSign,
          selectAccount: z.optional(z.boolean()),
        }),
      ]),
    ),
    result: z.object({
      email: z.optional(z.nullable(z.string())),
      keyAuthorization: z.optional(keyAuthorization),
      /**
       * Echo of the `personalSign` request, present iff the caller set
       * `capabilities.personalSign` (or `capabilities.auth` folded a SIWE
       * message into the same slot). The signature itself lives on the
       * top-level `capabilities.signature` field.
       */
      personalSign: z.optional(
        z.object({
          message: z.string(),
        }),
      ),
      signature: z.optional(u.hex()),
      username: z.optional(z.nullable(z.string())),
      /**
       * SIWE round-trip output, populated when the request `auth` capability was set.
       * `token` is present in JWT mode or when the request set `returnToken: true`.
       * Cookie-mode default = `{}` (the session arrived via `Set-Cookie`).
       */
      auth: z.optional(
        z.object({
          token: z.optional(z.string()),
        }),
      ),
    }),
  }

  export const schema = Schema.defineItem({
    method: z.literal('wallet_connect'),
    params: z.optional(
      z.readonly(
        z.tuple([
          z.object({
            capabilities: capabilities.request,
            chainId: z.optional(u.number()),
            version: z.optional(z.string()),
          }),
        ]),
      ),
    ),
    returns: z.object({
      accounts: z.readonly(
        z.array(
          z.object({
            address: u.address(),
            capabilities: capabilities.result,
          }),
        ),
      ),
    }),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace wallet_connect_strict {
  const authorizeAccessKey = z.optional(wallet_authorizeAccessKey_strict.parameters)
  const auth = wallet_connect.auth
  const personalSign = wallet_connect.personalSign

  export const parameters = z.object({
    capabilities: z.optional(
      z.union([
        z.object({
          digest: z.optional(u.hex()),
          authorizeAccessKey,
          auth,
          method: z.literal('register'),
          name: z.optional(z.string()),
          personalSign,
          userId: z.optional(z.string()),
        }),
        z.object({
          digest: z.optional(u.hex()),
          credentialId: z.optional(z.string()),
          authorizeAccessKey,
          auth,
          method: z.optional(z.literal('login')),
          personalSign,
          selectAccount: z.optional(z.boolean()),
        }),
      ]),
    ),
    chainId: z.optional(u.number()),
    version: z.optional(z.string()),
  })
}

export namespace wallet_disconnect {
  export const schema = Schema.defineItem({
    method: z.literal('wallet_disconnect'),
    params: undefined,
    returns: undefined,
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace wallet_getCallsStatus {
  export const schema = Schema.defineItem({
    method: z.literal('wallet_getCallsStatus'),
    params: z.optional(z.readonly(z.tuple([z.string()]))),
    returns: z.object({
      atomic: z.boolean(),
      chainId: u.number(),
      id: z.string(),
      receipts: z.optional(z.array(receipt)),
      status: z.number(),
      version: z.string(),
    }),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace wallet_transfer {
  /**
   * Parameters for `wallet_transfer`.
   *
   * Discriminated on `editable`:
   *
   * - omitted or `false` (default): Read-only. `amount` is a
   *   human-readable string (e.g. `"1.5"`), `to` and `token` are
   *   required, no editable UI is shown. Uses an access key when one
   *   matches (signs without UI), otherwise falls back to a confirm
   *   dialog the user has to approve.
   * - `true`: Editable. Wallet shows a UI with optional fields
   *   pre-filled; the user confirms or edits before signing.
   */
  export const parameters = z.discriminatedUnion('editable', [
    z.object({
      /** Human-readable amount to transfer (e.g. `"1.5"`). */
      amount: z.string(),
      /** Chain id. Defaults to the active chain. */
      chainId: z.optional(u.number()),
      /** Skip the editable wallet UI (Read-only mode). @default false */
      editable: z.optional(z.literal(false)),
      /**
       * Fee payer override. `false` to disable the wallet's default fee
       * payer, a URL string to use a custom fee payer service.
       */
      feePayer: z.optional(z.union([z.boolean(), z.string()])),
      /**
       * Address to transfer tokens from. Defaults to the active account.
       * When set to a different address, the call uses `transferFrom` and
       * requires the active account to have an allowance from `from`.
       */
      from: z.optional(u.address()),
      /**
       * UTF-8 memo to attach to the transfer (max 32 bytes when encoded
       * as UTF-8). Sent via `transferWithMemo` / `transferFromWithMemo`.
       */
      memo: z.optional(z.string()),
      /** Recipient address. */
      to: u.address(),
      /**
       * Token to transfer, accepted as either a contract address or a
       * curated tokenlist symbol (case-insensitive, e.g. `"pathUsd"`).
       * Symbols are resolved against the curated tokenlist on the active
       * chain.
       */
      token: z.union([u.address(), z.string()]),
    }),
    z.object({
      /** Human-readable amount to pre-fill (e.g. `"1.5"`). */
      amount: z.optional(z.string()),
      /** Chain id. Defaults to the active chain. */
      chainId: z.optional(u.number()),
      /** Show the wallet UI for the user to confirm or edit. */
      editable: z.literal(true),
      /**
       * Fee payer override. `false` to disable the wallet's default fee
       * payer, a URL string to use a custom fee payer service.
       */
      feePayer: z.optional(z.union([z.boolean(), z.string()])),
      /**
       * UTF-8 memo (max 32 bytes) to attach to the transfer. Wallet
       * rejects the request if the selected token does not support
       * memos (non-TIP-20).
       */
      memo: z.optional(z.string()),
      /** Recipient address to pre-fill. */
      to: z.optional(u.address()),
      /**
       * Token to pre-fill, accepted as either a contract address or a
       * curated tokenlist symbol (case-insensitive, e.g. `"pathUsd"`).
       * Symbols are resolved against the curated tokenlist on the active
       * chain. Omit to let the user choose.
       */
      token: z.optional(z.union([u.address(), z.string()])),
    }),
  ])

  export const schema = Schema.defineItem({
    method: z.literal('wallet_transfer'),
    params: z.optional(z.readonly(z.tuple([parameters]))),
    returns: z.object({
      /** Chain id the send is to. */
      chainId: u.number(),
      /** Receipt of the submitted send. */
      receipt,
    }),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

const swapParameters = z.object({
  /** Human-readable amount to pre-fill (e.g. "1.5"). */
  amount: z.optional(z.string()),
  /** Other side of the swap pair. For buys, this is the token to sell. For sells, this is the token to buy. */
  pairToken: z.optional(u.address()),
  /** Maximum allowed slippage as a decimal fraction (for example `0.05` for 5%). */
  slippage: z.optional(z.number().check(z.minimum(0), z.maximum(1))),
  /** Token to buy or sell. Omit to let the user choose. */
  token: z.optional(u.address()),
  /** Whether the amount is an exact buy amount (`swapExactAmountOut`) or sell amount (`swapExactAmountIn`). */
  type: z.optional(z.union([z.literal('buy'), z.literal('sell')])),
})

/** Opens the wallet swap flow with optional pre-filled swap intent fields. */
export namespace wallet_swap {
  export const schema = Schema.defineItem({
    method: z.literal('wallet_swap'),
    params: z.optional(z.readonly(z.tuple([swapParameters]))),
    returns: z.object({
      /** Receipt of the submitted swap. */
      receipt,
    }),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace wallet_switchEthereumChain {
  export const schema = Schema.defineItem({
    method: z.literal('wallet_switchEthereumChain'),
    params: z.readonly(z.tuple([z.object({ chainId: u.number() })])),
    returns: undefined,
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

export namespace wallet_deposit {
  export const schema = Schema.defineItem({
    method: z.literal('wallet_deposit'),
    params: z.readonly(
      z.tuple([
        z.object({
          address: z.optional(u.address()),
          chainId: z.optional(u.number()),
          displayName: z.optional(z.string()),
          token: z.optional(u.address()),
          value: z.optional(z.string()),
        }),
      ]),
    ),
    returns: z.optional(
      z.object({
        /**
         * Receipts of any onchain operations performed during the
         * deposit (e.g. testnet faucet drops). Absent for offchain
         * paths like Apple Pay where funds arrive asynchronously.
         */
        receipts: z.optional(z.readonly(z.array(receipt))),
      }),
    ),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

/** Opens the wallet zone-deposit flow with optional pre-filled fields. */
export namespace wallet_depositZone {
  /** Parameters object for `wallet_depositZone`. */
  export const parameters = z.object({
    /** Human-readable amount to pre-fill (e.g. "1.5"). */
    amount: z.optional(z.string()),
    /**
     * Fee payer override. `false` to disable the wallet's default fee
     * payer, a URL string to use a custom fee payer service.
     */
    feePayer: z.optional(z.union([z.boolean(), z.string()])),
    /** Token contract address to pre-fill. Omit to let the user choose. */
    token: z.optional(u.address()),
    /** Zone id to deposit into. */
    zoneId: z.optional(u.number()),
  })

  export const schema = Schema.defineItem({
    method: z.literal('wallet_depositZone'),
    params: z.optional(z.readonly(z.tuple([parameters]))),
    returns: z.object({
      /** Receipt of the submitted deposit. */
      receipt,
    }),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

/** Opens the wallet zone-withdraw flow with optional pre-filled fields. */
export namespace wallet_withdrawZone {
  /** Parameters object for `wallet_withdrawZone`. */
  export const parameters = z.object({
    /** Human-readable amount to pre-fill (e.g. "1.5"). */
    amount: z.optional(z.string()),
    /** Token contract address to pre-fill. Omit to let the user choose. */
    token: z.optional(u.address()),
    /** Zone id to withdraw from. */
    zoneId: z.optional(u.number()),
  })

  export const schema = Schema.defineItem({
    method: z.literal('wallet_withdrawZone'),
    params: z.optional(z.readonly(z.tuple([parameters]))),
    returns: z.object({
      /** Receipt of the submitted withdrawal. */
      receipt,
    }),
  })
  export type Encoded = Schema.Encoded<typeof schema>
  export type Decoded = Schema.Decoded<typeof schema>
}

/** Strict parameter schemas keyed by method name. */
export const strictParameters = {
  wallet_authorizeAccessKey: wallet_authorizeAccessKey_strict.parameters,
  wallet_connect: wallet_connect_strict.parameters,
} satisfies Partial<Record<string, z.ZodMiniType>>
