Core Concept

Wallet Derivation

Buff creates a deterministic wallet from the user's signature. Same wallet every time, no storage needed, fully exportable.

How It Works

  • User signs a fixed message: "Buff Portfolio Wallet v1"
  • The signature (unique per wallet) is SHA-256 hashed to get a 32-byte seed
  • The seed generates a Solana Keypair — this is the Buff wallet
  • Same main wallet → same signature → same Buff wallet, every time
  • No private keys are stored anywhere — the wallet is derived on-the-fly
derivation.ts
typescript
1import { sha256 } from "@noble/hashes/sha2.js"
2import { Keypair } from "@solana/web3.js"
3
4// 1. User signs a message
5const message = "Buff Portfolio Wallet v1"
6const signature = await wallet.signMessage(encode(message))
7
8// 2. Hash the signature to get 32 bytes
9const seed = sha256(signature)
10
11// 3. Create keypair from seed
12const buffWallet = Keypair.fromSeed(seed)
13// Same signature = same wallet, always

Exporting the Wallet

Users can export their Buff wallet's private key at any time and import it into Phantom, Solflare, or any Solana wallet. They have full control.

export.ts
typescript
1// Export the secret key
2const secretKey = buff.exportKey()
3// Uint8Array(64) — import this into Phantom
4
5// The wallet address
6const address = buff.getWalletAddress()
7// e.g. "E71R6Ph2sS4eYJVSNLacorUtSDNK1rUixVswgFD5hCY3"
Note
Buff never stores the private key. It's derived fresh each time from the user's signature. If the user signs with the same main wallet on a different device, they get the same Buff wallet.

Security

  • Private key only exists in memory during the session
  • Uses @noble/hashes — audited, pure JS, no native dependencies
  • The derivation message is versioned to prevent collisions
  • Buff platform never has access to user funds