> ## Documentation Index
> Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Address.fromPublicKey

> Derive address from secp256k1 public key

<Card title="Try it Live" icon="play" href="https://playground.tevm.sh?example=primitives/address.ts">
  Run Address examples in the interactive playground
</Card>

<Tip>
  View the complete executable example at [`playground/src/examples/primitives/address/from-public-key.ts`](https://github.com/evmts/voltaire/blob/main/playground/src/examples/primitives/address/from-public-key.ts).
</Tip>

<Tabs>
  <Tab title="Factory API">
    ## `FromPublicKey({ keccak256 })`

    Create Address from secp256k1 public key coordinates using factory pattern. Enables tree-shakeable imports without bundling unnecessary crypto.

    **Parameters:**

    * `deps.keccak256: (data: Uint8Array) => Uint8Array` - Keccak256 hash function

    **Returns:** `(x: bigint, y: bigint) => AddressType` - Function that creates Address from public key

    **Example:**

    ```typescript theme={null}
    import { FromPublicKey } from 'tevm/Address/AddressType'
    import { hash as keccak256 } from 'tevm/crypto/Keccak256'

    // Create factory with injected crypto
    const fromPublicKey = FromPublicKey({ keccak256 })

    // Use it to derive addresses
    const x = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n
    const y = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n
    const addr = fromPublicKey(x, y)
    console.log(addr.length) // 20
    ```

    **Bundle Size:** Tree-shakeable. Only includes keccak256 if used.

    **Use Case:** Optimal for libraries that need to avoid bundling crypto dependencies by default.
  </Tab>

  <Tab title="Namespace API">
    ## `Address.fromPublicKey(x, y)`

    Create Address from secp256k1 public key coordinates (auto-injected keccak256).

    **Parameters:**

    * `x: bigint` - Public key x coordinate
    * `y: bigint` - Public key y coordinate

    **Returns:** `AddressType` - Address derived from keccak256(pubkey)\[12:32]

    **Example:**

    ```typescript theme={null}
    import { Address } from 'tevm'

    const x = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n
    const y = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n
    const addr = Address.fromPublicKey(x, y)
    console.log(addr.length) // 20
    ```

    **Bundle Size:** Includes keccak256 in bundle (\~5-10 KB).

    **Use Case:** Convenient for applications where bundle size is not a primary concern.
  </Tab>

  <Tab title="C">
    ## `primitives_keccak256(data, data_len, out_hash)`

    Derive address from secp256k1 public key using C API. Requires manual concatenation of coordinates and keccak256 hashing.

    **Parameters:**

    * `x_bytes: uint8_t[32]` - X coordinate (32 bytes, big-endian)
    * `y_bytes: uint8_t[32]` - Y coordinate (32 bytes, big-endian)
    * `out_address: PrimitivesAddress*` - Output address

    **Returns:** `int` - PRIMITIVES\_SUCCESS or error code

    **Example:**

    ```c theme={null}
    #include "primitives.h"
    #include <string.h>

    // Public key coordinates (32 bytes each, big-endian)
    uint8_t x[32] = { /* x coordinate bytes */ };
    uint8_t y[32] = { /* y coordinate bytes */ };

    // Concatenate coordinates
    uint8_t pubkey[64];
    memcpy(pubkey, x, 32);
    memcpy(pubkey + 32, y, 32);

    // Hash with keccak256
    PrimitivesHash hash;
    int result = primitives_keccak256(pubkey, 64, &hash);
    if (result != PRIMITIVES_SUCCESS) {
        // Handle error
    }

    // Extract last 20 bytes as address
    PrimitivesAddress addr;
    memcpy(addr.bytes, hash.bytes + 12, 20);
    ```

    **Note:** C API does not provide a dedicated `fromPublicKey` function. Derive manually using `primitives_keccak256` and extract last 20 bytes.

    **Defined in:** [primitives.h:139](https://github.com/evmts/voltaire/blob/main/src/primitives.h#L139)
  </Tab>
</Tabs>

## Algorithm

The address derivation follows Ethereum's standard process:

1. **Concatenate coordinates** - Combine x and y into 64-byte uncompressed public key
2. **Hash with keccak256** - Compute keccak256 hash (32 bytes output)
3. **Extract address** - Take last 20 bytes of hash

**Pseudocode:**

```
pubkey = x (32 bytes) || y (32 bytes)  // 64 bytes total
hash = keccak256(pubkey)               // 32 bytes
address = hash[12:32]                  // Last 20 bytes
```

## Public Key Format

Ethereum uses uncompressed secp256k1 public keys:

* **Curve:** secp256k1 (same as Bitcoin)
* **Coordinates:** x and y, each 256 bits (32 bytes)
* **Total size:** 64 bytes (no 0x04 prefix in Ethereum)

The x and y coordinates must be valid points on the secp256k1 curve.

## Complete Example

```typescript theme={null}
import { Address } from 'tevm'
import * as Secp256k1 from 'tevm/crypto/Secp256k1'

// Start with private key
const privateKey = Bytes32()
// ... fill with secure random bytes

// Derive public key from private key
const publicKey = Secp256k1.derivePublicKey(privateKey) // 64 bytes

// Extract coordinates (big-endian)
let x = 0n
let y = 0n
for (let i = 0; i < 32; i++) {
  x = (x << 8n) | BigInt(publicKey[i])
  y = (y << 8n) | BigInt(publicKey[i + 32])
}

// Derive address
const addr = Address.fromPublicKey(x, y)
console.log(addr.toHex())
```

## Use Cases

### Verifying Signatures

After recovering a public key from an ECDSA signature:

```typescript theme={null}
import { Address } from 'tevm'
import * as Secp256k1 from 'tevm/crypto/Secp256k1'

const signature = // ... ECDSA signature
const message = // ... signed message

// Recover public key from signature
const recovered = Secp256k1.recoverPublicKey(signature, message)

// Extract coordinates
const x = // ... extract from recovered
const y = // ... extract from recovered

// Derive address
const signer = Address.fromPublicKey(x, y)
```

### Deterministic Address Generation

Generate addresses from known public keys:

```typescript theme={null}
const knownPublicKeys = [
  { x: 0x123n, y: 0x456n },
  { x: 0x789n, y: 0xabcn },
]

const addresses = knownPublicKeys.map(pk =>
  Address.fromPublicKey(pk.x, pk.y)
)
```

## Performance

**Cryptographic dependency:** Uses keccak256 hash function internally.

**Bundle size impact:**

* Factory API (`FromPublicKey`): Tree-shakeable, only includes keccak256 if used
* Namespace API (`Address.fromPublicKey`): Always includes keccak256 (\~5-10 KB)

**Recommendation:** Use Factory API for libraries, Namespace API for applications.

**Alternative:** For performance-critical code, consider using `fromPrivateKey()` directly if you have the private key, as it combines key derivation and address generation.

## See Also

* [fromPrivateKey](/primitives/address/from-private-key) - Derive from private key
* [from](/primitives/address/from) - Universal constructor
* [Secp256k1](/crypto/secp256k1) - secp256k1 cryptography
* [Keccak256](/crypto/keccak256) - Keccak256 hash function
* [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) - Section 4.2 (Address derivation)
