Raxol.Payments.Wallet behaviour (Raxol Payments v0.2.0)

Copy Markdown View Source

Behaviour for wallet implementations providing signing and identity.

Wallets handle private key storage and signing operations. Two implementations are provided:

Implementing a Custom Wallet

defmodule MyWallet do
  @behaviour Raxol.Payments.Wallet

  @impl true
  def address, do: "0x..."

  @impl true
  def chain_id, do: 8453

  @impl true
  def sign_message(message) do
    # Sign raw message bytes
    {:ok, signature_bytes}
  end

  @impl true
  def sign_typed_data(domain, types, message) do
    # Sign EIP-712 structured data
    {:ok, signature_bytes}
  end

  @impl true
  def sign_hash(digest) do
    # Sign a precomputed 32-byte digest (e.g. EIP-1559 tx hash)
    {:ok, signature_bytes}
  end
end

Summary

Callbacks

Return the wallet's hex-encoded address (0x-prefixed).

Return the chain ID this wallet is configured for.

Sign a precomputed 32-byte digest with secp256k1.

Sign a raw message (keccak256 hash + secp256k1 signature).

Sign EIP-712 typed structured data.

Types

signature()

@type signature() :: binary()

Callbacks

address()

@callback address() :: String.t()

Return the wallet's hex-encoded address (0x-prefixed).

chain_id()

@callback chain_id() :: pos_integer()

Return the chain ID this wallet is configured for.

sign_hash(digest)

@callback sign_hash(digest :: <<_::256>>) :: {:ok, signature()} | {:error, term()}

Sign a precomputed 32-byte digest with secp256k1.

Unlike sign_message/1, this does NOT hash the input. The caller is responsible for producing the canonical 32-byte hash for whatever scheme they are signing for. EIP-1559 transaction signing uses this callback: keccak256(0x02 || rlp(unsigned_fields)) is the digest; the wallet returns the 65-byte r || s || y_parity signature.

This is intentionally separate from sign_message/1 to avoid ambiguity: callers that already have a digest must not pay for a second keccak round, and accidentally double-hashing produces a silently-wrong signature.

sign_message(message)

@callback sign_message(message :: binary()) :: {:ok, signature()} | {:error, term()}

Sign a raw message (keccak256 hash + secp256k1 signature).

sign_typed_data(domain, types, message)

@callback sign_typed_data(
  domain :: map(),
  types :: map(),
  message :: map()
) :: {:ok, signature()} | {:error, term()}

Sign EIP-712 typed structured data.

Used by x402 (ERC-3009 transferWithAuthorization) and other protocols that require typed data signatures.