# `X402.Extensions.SIWX.Message`
[🔗](https://github.com/cardotrejos/x402/blob/v0.9.0/lib/x402/extensions/siwx/message.ex#L1)

CAIP-122 message text for Sign-In-With-X challenges.

Builds the exact text a wallet signs for a SIWX proof, routed by the
CAIP-2 namespace of `chainId`:

* `eip155:*` — [EIP-4361 (Sign-In With Ethereum)](https://eips.ethereum.org/EIPS/eip-4361),
  whose `Chain ID` line carries the numeric chain reference. When no
  statement is present the address is followed by two blank lines, as the
  EIP-4361 ABNF (and the reference `siwe` library) produce.
* `solana:*` — [Sign-In With Solana](https://github.com/phantom/sign-in-with-solana),
  identical apart from the `Solana account` header and the genesis-hash
  chain reference. Without a statement the address is followed by a single
  blank line, matching the reference x402 implementation.

Field values are read from the wire (camelCase string) keys or their
snake_case atom equivalents, so both a decoded `SIGN-IN-WITH-X` payload
and a locally built map work.

# `build_error`

```elixir
@type build_error() :: :invalid_fields | :invalid_chain_id | :unsupported_chain
```

Errors returned by `build/1`.

# `family`

```elixir
@type family() :: :eip155 | :solana
```

Chain family derived from a CAIP-2 chain id.

# `build`
*since 0.9.0* 

```elixir
@spec build(map()) :: {:ok, String.t()} | {:error, build_error()}
```

Builds the CAIP-122 message text for a fields map.

Requires `domain`, `address`, `uri`, `version`, `chainId`, `nonce`, and
`issuedAt`; `statement`, `expirationTime`, `notBefore`, `requestId`, and
`resources` are optional and omitted from the text when absent (an empty
`resources` list is treated as absent).

## Examples

    iex> {:ok, text} = X402.Extensions.SIWX.Message.build(%{
    ...>   "domain" => "api.example.com",
    ...>   "address" => "0x857b06519E91e3A54538791bDbb0E22373e36b66",
    ...>   "statement" => "Sign in to access premium data",
    ...>   "uri" => "https://api.example.com/premium-data",
    ...>   "version" => "1",
    ...>   "chainId" => "eip155:8453",
    ...>   "nonce" => "a1b2c3d4e5f67890a1b2c3d4e5f67890",
    ...>   "issuedAt" => "2024-01-15T10:30:00.000Z",
    ...>   "expirationTime" => "2024-01-15T10:35:00.000Z",
    ...>   "resources" => ["https://api.example.com/premium-data"]
    ...> })
    iex> String.split(text, "\n")
    [
      "api.example.com wants you to sign in with your Ethereum account:",
      "0x857b06519E91e3A54538791bDbb0E22373e36b66",
      "",
      "Sign in to access premium data",
      "",
      "URI: https://api.example.com/premium-data",
      "Version: 1",
      "Chain ID: 8453",
      "Nonce: a1b2c3d4e5f67890a1b2c3d4e5f67890",
      "Issued At: 2024-01-15T10:30:00.000Z",
      "Expiration Time: 2024-01-15T10:35:00.000Z",
      "Resources:",
      "- https://api.example.com/premium-data"
    ]

    iex> X402.Extensions.SIWX.Message.build(%{"domain" => "api.example.com"})
    {:error, :invalid_fields}

# `chain_reference`
*since 0.9.0* 

```elixir
@spec chain_reference(String.t()) :: String.t()
```

Returns the chain reference rendered on the `Chain ID` line.

## Examples

    iex> X402.Extensions.SIWX.Message.chain_reference("eip155:8453")
    "8453"

    iex> X402.Extensions.SIWX.Message.chain_reference("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")
    "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"

# `family`
*since 0.9.0* 

```elixir
@spec family(term()) ::
  {:ok, family()} | {:error, :invalid_chain_id | :unsupported_chain}
```

Returns the chain family of a CAIP-2 chain id.

## Examples

    iex> X402.Extensions.SIWX.Message.family("eip155:8453")
    {:ok, :eip155}

    iex> X402.Extensions.SIWX.Message.family("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")
    {:ok, :solana}

    iex> X402.Extensions.SIWX.Message.family("eip155:base")
    {:error, :invalid_chain_id}

    iex> X402.Extensions.SIWX.Message.family("cosmos:hub")
    {:error, :unsupported_chain}

# `signature_type`
*since 0.9.0* 

```elixir
@spec signature_type(family()) :: String.t()
```

Returns the signature `type` a chain family authenticates with.

## Examples

    iex> X402.Extensions.SIWX.Message.signature_type(:eip155)
    "eip191"

    iex> X402.Extensions.SIWX.Message.signature_type(:solana)
    "ed25519"

---

*Consult [api-reference.md](api-reference.md) for complete listing*
