# Signers

> Load the operator key that receives funds, co-signs x402 challenges, and optionally fee-pays settlement — local keys or a KMS-ready interface.

The operator identity lives on `Config.Operator`: the `Recipient` address that receives funds, the `Signer` that co-signs x402 challenges and (optionally) fee-pays settlement, and the `FeePayer` flag. With no signer set, the kit boots on the registered demo signer on non-mainnet networks.

## Local key material

The `paycore/signer` package builds a `paykit.Signer` from common key formats:

```go
import "github.com/solana-foundation/pay-kit/go/paycore/signer"

s, err := signer.FromFile("operator.json") // Solana CLI JSON keypair
s, err := signer.FromEnv("OPERATOR_KEY")   // JSON / hex / base58, auto-detected
s, err := signer.FromBytes(secretKeyBytes) // 64-byte keypair
```

## Wire it into the operator

```go
client, err := paykit.New(paykit.Config{
    Network: paykit.SolanaMainnet,
    Operator: paykit.Operator{
        Signer:   s,
        FeePayer: true, // operator sponsors the customer's network fee on settlement
    },
    MPP: paykit.MPPConfig{ChallengeBindingSecret: secret},
})
```

`Recipient` defaults to the signer's public key when left empty. Set `FeePayer: true` to have the operator pay Solana network fees on settlement transactions instead of the client.

## The demo signer

Blank-importing `paycore/signer` registers an in-memory demo signer that the kit falls back to when no `Operator.Signer` is set — convenient for local development against the Surfpool sandbox. It is refused on mainnet: `paykit.New` returns [`ErrDemoSignerOnMainnet`](/docs/sdk/go/errors) so real funds never route to a publicly known key.
