Canonical handles
Section titled “Canonical handles”A Boon recipient is identified by a canonical social handle:
github:alicex:bob
Every surface must normalize before hashing. The shared TypeScript package is @boon/normalize, and the contract enforces that keccak256(bytes(displayHandle)) == handleHash.
| Provider | Input examples | Canonical output |
|---|---|---|
| GitHub | Github:Alice, github: alice | github:alice |
| X | X:@Bob, x:bob | x:bob |
GitHub usernames are lowercased, max 39 characters, alphanumeric with single hyphens and no leading/trailing hyphen.
X usernames are lowercased, max 15 characters, alphanumeric or underscore. A leading @ is stripped.
Unsupported schemes such as twitter:, fc:, or a bare alice are rejected in v1.
Hashing
Section titled “Hashing”canonicalHandle = "github:alice"handleHash = keccak256(utf8(canonicalHandle))providerHash = keccak256(utf8("github"))handleHash is the contract escrow key. providerHash is part of the EIP-712 Link voucher so a proof for one provider cannot be replayed as another.
Why this matters
Section titled “Why this matters”If a client hashes a non-canonical string, funds can land in escrow under a handle no recipient can prove. Always call the shared normalization package or a repo implementation that follows the same test vectors.