# `Cartouche.Solana.Keys`
[🔗](https://github.com/zenhive/cartouche/blob/main/lib/cartouche/solana/keys.ex#L1)

Ed25519 keypair generation and management for Solana.

Solana uses Ed25519 public keys as addresses directly (no hashing).
A keypair consists of a 32-byte seed (private key material) and a
32-byte public key. Solana stores these as a 64-byte concatenation
(seed ++ pubkey) in keypair files.

## Examples

    iex> {pub, seed} = Cartouche.Solana.Keys.generate_keypair()
    iex> {byte_size(pub), byte_size(seed)}
    {32, 32}

    iex> {pub, _seed} = Cartouche.Solana.Keys.from_seed(<<0::256>>)
    iex> Cartouche.Solana.Keys.to_address(pub)
    "4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS"

# `keypair`

```elixir
@type keypair() :: {pub_key :: &lt;&lt;_::256&gt;&gt;, seed :: &lt;&lt;_::256&gt;&gt;}
```

# `from_json`

```elixir
@spec from_json(String.t()) :: {:ok, keypair()} | {:error, term()}
```

Import a keypair from a Solana JSON keypair file.

Solana keypair files (e.g. `~/.config/solana/id.json`) contain a JSON
array of 64 decimal byte values: the first 32 bytes are the seed and
the last 32 bytes are the public key.

## Examples

    iex> json = "[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,59,106,39,188,206,182,164,45,98,163,168,208,42,111,13,115,101,50,21,119,29,226,67,166,58,192,72,161,139,89,218,41]"
    iex> {:ok, {pub, _seed}} = Cartouche.Solana.Keys.from_json(json)
    iex> Cartouche.Solana.Keys.to_address(pub)
    "4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS"

# `from_keypair_bytes`

```elixir
@spec from_keypair_bytes(&lt;&lt;_::512&gt;&gt;) :: {:ok, keypair()} | {:error, :pubkey_mismatch}
```

Import a keypair from the 64-byte Solana format (seed ++ pubkey).

Validates that the public key matches the seed by re-deriving it.

## Examples

    iex> seed = Base.decode16!("9D61B19DEFFD5A60BA844AF492EC2CC44449C5697B326919703BAC031CAE7F60")
    iex> pub = Base.decode16!("D75A980182B10AB7D54BFED3C964073A0EE172F3DAA62325AF021A68F707511A")
    iex> {:ok, {^pub, ^seed}} = Cartouche.Solana.Keys.from_keypair_bytes(seed <> pub)
    iex> byte_size(pub)
    32

# `from_seed`

```elixir
@spec from_seed(&lt;&lt;_::256&gt;&gt;) :: keypair()
```

Derive a keypair from a 32-byte Ed25519 seed.

Deterministic: the same seed always produces the same public key.

## Examples

    iex> seed = Base.decode16!("9D61B19DEFFD5A60BA844AF492EC2CC44449C5697B326919703BAC031CAE7F60")
    iex> {pub, ^seed} = Cartouche.Solana.Keys.from_seed(seed)
    iex> Base.encode16(pub, case: :lower)
    "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"

# `generate_keypair`

```elixir
@spec generate_keypair() :: keypair()
```

Generate a new random Ed25519 keypair.

Returns `{pub_key, seed}` where both are 32-byte binaries.

## Examples

    iex> {pub, seed} = Cartouche.Solana.Keys.generate_keypair()
    iex> byte_size(pub) == 32 and byte_size(seed) == 32
    true

# `to_address`

```elixir
@spec to_address(&lt;&lt;_::256&gt;&gt;) :: String.t()
```

Get the Base58-encoded Solana address from a 32-byte public key.

In Solana, the public key IS the address (no hashing step).

## Examples

    iex> pub = Base.decode16!("D75A980182B10AB7D54BFED3C964073A0EE172F3DAA62325AF021A68F707511A")
    iex> Cartouche.Solana.Keys.to_address(pub)
    "FVen3X669xLzsi6N2V91DoiyzHzg1uAgqiT8jZ9nS96Z"

---

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