Documentation
¶
Overview ¶
Package auth provides Polymarket authentication primitives — L0 / L1 / L2 auth, EIP-712 signing, deposit-wallet CREATE2 derivation, and builder attribution.
Used by every signed request to the CLOB and relayer. The default mode for polygolem is read-only and never enters this package; mutating commands acquire signers here behind explicit gates. Start with the Signer types and DeriveDepositWallet for orientation.
This package is internal and not part of the polygolem public SDK.
Index ¶
- func AssertL1(level AccessLevel) error
- func AssertL2(level AccessLevel) error
- func BuildBuilderHeaders(bc *BuilderConfig, timestamp int64, method, path string, body *string) (map[string]string, error)
- func BuildClobAuthTypedData(address string, chainID uint64, timestamp string, nonce uint64) (EIP712Domain, ClobAuthMessage)
- func BuildL1HeadersForAddress(privateKeyHex string, chainID int64, timestamp int64, nonce int64, ...) (map[string]string, error)
- func BuildL1HeadersForDepositWallet(privateKeyHex string, chainID int64, timestamp int64, nonce int64, ...) (map[string]string, error)
- func BuildL1HeadersFromPrivateKey(privateKeyHex string, chainID int64, timestamp int64, nonce int64) (map[string]string, error)
- func BuildL2Headers(apiKey *APIKey, timestamp int64, method, path string, body *string) (map[string]string, error)
- func BuildSIWEBearerToken(msg SIWEMessage, signature []byte) (string, error)
- func CompactJSON(s string) string
- func EIP712ChainID(chainID int64) *gethmath.HexOrDecimal256
- func GeneratePrivateKey() (string, error)
- func HashTypedData(domain EIP712Domain, message ClobAuthMessage) ([32]byte, error)
- func L1HeaderMap(address string, signature [32]byte, timestamp string, nonce uint64) map[string]string
- func MakerAddressForSignatureType(signerAddress string, chainID int64, signatureType int) (string, error)
- func PrivateKeyToAddress(privateKeyHex string) (string, error)
- func Redact(v string) string
- func SignClobAuth(signer Signer, chainID uint64, timestamp string, nonce uint64) ([32]byte, error)
- func SignHMAC(secret string, timestamp int64, method, path string, body *string) string
- func WrapERC7739Signature(signer *PrivateKeySigner, depositWalletAddress string, chainID int64, ...) (string, error)
- type APIKey
- type AccessLevel
- type BuilderConfig
- type ClobAuthMessage
- type EIP712Domain
- type PrivateKeySigner
- func (s *PrivateKeySigner) Address() string
- func (s *PrivateKeySigner) ChainID() int64
- func (s *PrivateKeySigner) SignEIP712(typed apitypes.TypedData) ([]byte, error)
- func (s *PrivateKeySigner) SignHash(hash [32]byte) ([]byte, error)
- func (s *PrivateKeySigner) SignPersonalMessage(msg []byte) ([]byte, error)
- func (s *PrivateKeySigner) SignRaw(hash [32]byte) ([]byte, error)
- func (s *PrivateKeySigner) SignTypedData(hash [32]byte, _ [32]byte) ([32]byte, error)
- type SIWEMessage
- type SIWESession
- type SIWESessionOption
- type Signer
- type Status
- type TypedData
- type TypedDataField
- type TypedDataTypes
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AssertL1 ¶
func AssertL1(level AccessLevel) error
AssertL1 returns an error if the access level is below L1.
func AssertL2 ¶
func AssertL2(level AccessLevel) error
AssertL2 returns an error if the access level is below L2.
func BuildBuilderHeaders ¶
func BuildBuilderHeaders(bc *BuilderConfig, timestamp int64, method, path string, body *string) (map[string]string, error)
BuildBuilderHeaders builds builder attribution headers. Separate from L2 user credentials per PRD R3.
func BuildClobAuthTypedData ¶
func BuildClobAuthTypedData(address string, chainID uint64, timestamp string, nonce uint64) (EIP712Domain, ClobAuthMessage)
BuildClobAuthTypedData builds the EIP-712 typed data for Polymarket ClobAuth. Used for L1 API key creation/derivation.
func BuildL1HeadersForAddress ¶ added in v0.1.1
func BuildL1HeadersForAddress(privateKeyHex string, chainID int64, timestamp int64, nonce int64, ownerAddress string) (map[string]string, error)
BuildL1HeadersForAddress builds raw EOA-signed ClobAuth headers. When ownerAddress is non-empty it overrides both POLY_ADDRESS and the typed-data value.address, but the signature remains a raw EOA signature.
Do not use this helper for deposit-wallet-owned API-key minting; use BuildL1HeadersForDepositWallet so POLY_SIGNATURE is the ERC-7739 wrapped form validated through the deployed wallet's ERC-1271 hook.
func BuildL1HeadersForDepositWallet ¶ added in v0.1.1
func BuildL1HeadersForDepositWallet(privateKeyHex string, chainID int64, timestamp int64, nonce int64, depositWalletAddress string) (map[string]string, error)
BuildL1HeadersForDepositWallet builds CLOB L1 auth headers wrapped with the ERC-7739 nested EIP-712 envelope for use against a Polymarket deposit wallet's `isValidSignature`. The EOA holding privateKey produces the inner ECDSA, but POLY_ADDRESS is the smart wallet and POLY_SIGNATURE is the wrapped form Solady's ERC1271 mixin expects.
Required when minting an L2 API key bound to a deposit wallet (so the L2 key's address matches `Order.signer == Order.maker == depositWallet` for sigtype 3 — both the CLOB HTTP gate and the on-chain `_verifyPoly1271Signature` use this equality).
The deposit wallet must be deployed at depositWalletAddress before this call (the contract's `isValidSignature` runs on-chain).
func BuildL1HeadersFromPrivateKey ¶
func BuildL1HeadersFromPrivateKey(privateKeyHex string, chainID int64, timestamp int64, nonce int64) (map[string]string, error)
BuildL1HeadersFromPrivateKey builds Polymarket CLOB L1 auth headers for API-key creation and derivation. It signs the canonical ClobAuth EIP-712 message with a local EOA private key. POLY_ADDRESS is the EOA address.
func BuildL2Headers ¶
func BuildL2Headers(apiKey *APIKey, timestamp int64, method, path string, body *string) (map[string]string, error)
BuildL2Headers builds the L2 HMAC authentication headers. Signature = base64url(HMAC-SHA256(decoded_secret, timestamp + method + path + body)) Body must be compact JSON (no spaces).
func BuildSIWEBearerToken ¶
func BuildSIWEBearerToken(msg SIWEMessage, signature []byte) (string, error)
BuildSIWEBearerToken assembles the Polymarket /login bearer token: base64( JSON(message fields) + ":::" + 0x-prefixed signature hex ).
func CompactJSON ¶
CompactJSON removes all whitespace from a JSON string for HMAC body signing.
func EIP712ChainID ¶
func EIP712ChainID(chainID int64) *gethmath.HexOrDecimal256
func GeneratePrivateKey ¶
GeneratePrivateKey creates a new random secp256k1 key.
func HashTypedData ¶
func HashTypedData(domain EIP712Domain, message ClobAuthMessage) ([32]byte, error)
HashTypedData computes the EIP-712 typed data hash. Implements the algorithm from EIP-712:
encode(domainSeparator, message) = 0x19 0x01 ‖ domainSeparator ‖ hashStruct(message)
where:
domainSeparator = hashStruct(eip712Domain)
hashStruct(s) = keccak256(typeHash ‖ encodeData(s))
typeHash = keccak256(typeName ‖ "(" ‖ memberTypes ‖ ")")
func L1HeaderMap ¶
func L1HeaderMap(address string, signature [32]byte, timestamp string, nonce uint64) map[string]string
L1HeaderMap builds the L1 authentication headers for API key operations.
func MakerAddressForSignatureType ¶
func MakerAddressForSignatureType(signerAddress string, chainID int64, signatureType int) (string, error)
MakerAddressForSignatureType returns the CLOB maker/funder address for the configured signature type. EOA orders use the signer directly; proxy and Safe modes use Polymarket's deterministic CREATE2 wallet addresses on Polygon.
func PrivateKeyToAddress ¶
PrivateKeyToAddress derives the Ethereum address from a hex private key.
func SignClobAuth ¶
SignClobAuth performs the full L1 signing flow: 1. Builds EIP-712 domain and message 2. Computes typed data hash 3. Signs with provided signer
func WrapERC7739Signature ¶ added in v0.1.1
func WrapERC7739Signature(signer *PrivateKeySigner, depositWalletAddress string, chainID int64, appDomainSep [32]byte, contents [32]byte, contentsType string) (string, error)
WrapERC7739Signature produces a Solady-compatible ERC-7739 nested EIP-712 wrapped signature suitable for a Polymarket deposit wallet's `isValidSignature` check. The deposit wallet's `_erc1271IsValidSignatureViaNestedEIP712` recomputes:
finalHash = keccak256(0x1901 || appDomainSep ||
hashStruct(TypedDataSign{contents, DepositWallet inline domain}))
recovers the EOA from innerSig, and returns ERC1271_MAGIC if the recovered address matches the wallet's owner.
Layout: innerSig(65) || appDomainSep(32) || contents(32) || contentsType || uint16BE(len(contentsType)).
Caller responsibilities:
- appDomainSep is the OUTER domain separator the dapp/contract uses (e.g. CTF Exchange V2 for orders, ClobAuthDomain for L1 mints).
- contents is the EIP-712 hashStruct of the original typed-data.
- contentsType is the canonical type string (must start with the primary type name, e.g. "Order(...)" or "ClobAuth(...)").
- depositWalletAddress is the smart wallet that will validate the signature; it must be deployed.
Types ¶
type APIKey ¶
type APIKey struct {
Key string `json:"key"`
Secret string `json:"secret"`
Passphrase string `json:"passphrase"`
}
APIKey holds L2 credentials for HMAC-authenticated requests.
type AccessLevel ¶
type AccessLevel int
AccessLevel defines the authentication tier.
const ( L0 AccessLevel = iota // public, no credentials L1 // wallet signer for key creation/derivation L2 // API key + HMAC for authenticated operations )
func (AccessLevel) String ¶
func (l AccessLevel) String() string
type BuilderConfig ¶
BuilderConfig holds credentials for builder attribution headers. Builder credentials must be kept separate from user L2 credentials (per PRD R3).
func (*BuilderConfig) Valid ¶
func (bc *BuilderConfig) Valid() bool
type ClobAuthMessage ¶
type ClobAuthMessage struct {
Address string `json:"address"`
Timestamp string `json:"timestamp"`
Nonce uint64 `json:"nonce"`
Message string `json:"message"`
}
ClobAuthMessage is the EIP-712 typed data payload for ClobAuth.
type EIP712Domain ¶
type EIP712Domain struct {
Name string `json:"name"`
Version string `json:"version"`
ChainID uint64 `json:"chainId"`
VerifyingContract string `json:"verifyingContract,omitempty"`
Salt string `json:"salt,omitempty"`
}
EIP712Domain represents the EIP-712 domain separator.
type PrivateKeySigner ¶
type PrivateKeySigner struct {
// contains filtered or unexported fields
}
PrivateKeySigner implements Signer using go-ethereum/secp256k1.
func NewPrivateKeySigner ¶
func NewPrivateKeySigner(privateKeyHex string, chainID int64) (*PrivateKeySigner, error)
NewPrivateKeySigner creates a signer from a 0x-prefixed hex private key.
func (*PrivateKeySigner) Address ¶
func (s *PrivateKeySigner) Address() string
func (*PrivateKeySigner) ChainID ¶
func (s *PrivateKeySigner) ChainID() int64
func (*PrivateKeySigner) SignEIP712 ¶
func (s *PrivateKeySigner) SignEIP712(typed apitypes.TypedData) ([]byte, error)
SignEIP712 signs canonical EIP-712 typed data and returns the full 65-byte Ethereum signature with a 27/28 recovery byte.
func (*PrivateKeySigner) SignHash ¶
func (s *PrivateKeySigner) SignHash(hash [32]byte) ([]byte, error)
SignHash signs a 32-byte hash using personal_sign prefix.
func (*PrivateKeySigner) SignPersonalMessage ¶
func (s *PrivateKeySigner) SignPersonalMessage(msg []byte) ([]byte, error)
SignPersonalMessage signs an arbitrary-length byte slice using the EIP-191 personal_sign scheme: keccak256("\x19Ethereum Signed Message:\n" + len(msg) + msg). Returns the 65-byte signature with the recovery byte canonicalized to 27/28. Used by SIWE / EIP-4361 login flows.
func (*PrivateKeySigner) SignRaw ¶
func (s *PrivateKeySigner) SignRaw(hash [32]byte) ([]byte, error)
SignRaw signs an arbitrary 32-byte hash with the EOA private key. Required by wrapPOLY1271Signature for the ERC-7739 envelope.
func (*PrivateKeySigner) SignTypedData ¶
func (s *PrivateKeySigner) SignTypedData(hash [32]byte, _ [32]byte) ([32]byte, error)
type SIWEMessage ¶
type SIWEMessage struct {
Domain string `json:"domain"`
Address string `json:"address"`
Statement string `json:"statement"`
URI string `json:"uri"`
Version string `json:"version"`
ChainID int64 `json:"chainId"`
Nonce string `json:"nonce"`
IssuedAt string `json:"issuedAt"`
ExpirationTime string `json:"expirationTime"`
}
SIWEMessage holds the structured EIP-4361 fields. Field names match the viem JSON representation that ships to /login as the bearer payload.
func NewPolymarketSIWE ¶
func NewPolymarketSIWE(address, nonce string, chainID int64, now time.Time) SIWEMessage
NewPolymarketSIWE builds a SIWEMessage with the Polymarket-specific domain, statement, and URI defaults. The address is checksummed; the nonce comes from `GET gamma-api.polymarket.com/nonce`. Issued-at and expiration are populated automatically with a 7-day window unless overridden.
func (SIWEMessage) String ¶
func (m SIWEMessage) String() string
String renders the SIWEMessage in EIP-4361 plaintext form. This is the blob that gets personal_sign-hashed.
type SIWESession ¶
type SIWESession struct {
// contains filtered or unexported fields
}
SIWESession orchestrates the gamma-api SIWE login flow and holds the resulting session cookie in an in-memory jar. Mirrors the Polymarket frontend's `useSignIn` mutation.
Wire flow:
- GET {gammaURL}/nonce → { nonce: "..." }
- Build SIWEMessage, personal_sign with PrivateKeySigner
- GET {gammaURL}/login → Authorization: Bearer <token>, withCredentials → Set-Cookie
- Cookies persist in the jar — pass [HTTPClient] to downstream callers (relayer auth mint) so the cookies ride along.
func NewSIWESession ¶
func NewSIWESession(signer *PrivateKeySigner, gammaURL string, opts ...SIWESessionOption) (*SIWESession, error)
NewSIWESession builds a session with a fresh in-memory cookie jar. gammaURL is typically https://gamma-api.polymarket.com (no trailing slash).
func (*SIWESession) CookiesFor ¶
func (s *SIWESession) CookiesFor(rawURL string) []*http.Cookie
CookiesFor returns the cookies the jar would attach to a request to rawURL. Useful for diagnostics and for callers that need to forward cookies to a different transport.
func (*SIWESession) HTTPClient ¶
func (s *SIWESession) HTTPClient() *http.Client
HTTPClient returns the underlying http.Client (with the populated jar). Pass this to downstream calls — e.g. the relayer auth mint — so cookies captured by [Login] ride along automatically.
type SIWESessionOption ¶
type SIWESessionOption func(*SIWESession)
SIWESessionOption configures a SIWESession at construction time.
func WithSIWEClock ¶
func WithSIWEClock(now func() time.Time) SIWESessionOption
WithSIWEClock sets the clock used for `issuedAt` / `expirationTime`. Tests pass a fixed time so the SIWE message is deterministic.
func WithSIWEHTTPClient ¶
func WithSIWEHTTPClient(client *http.Client) SIWESessionOption
WithSIWEHTTPClient lets the caller supply a pre-configured *http.Client (with custom Timeout, Transport, etc). The cookie jar is preserved.
type Signer ¶
type Signer interface {
// Address returns the checksummed Ethereum address.
Address() string
// ChainID returns the configured chain identifier.
ChainID() int64
// SignHash signs a 32-byte hash (personal_sign style).
SignHash(hash [32]byte) ([]byte, error)
// SignTypedData signs an EIP-712 typed data hash.
SignTypedData(domainHash, structHash [32]byte) ([32]byte, error)
}
Signer is the abstraction for signing operations. Supports local private key and leaves room for KMS/Turnkey/HSM implementations.
type Status ¶
type Status struct {
AccessLevel AccessLevel `json:"access_level"`
HasSigner bool `json:"has_signer"`
HasAPIKey bool `json:"has_api_key"`
HasBuilder bool `json:"has_builder"`
SignerAddress string `json:"signer_address,omitempty"`
ChainID int64 `json:"chain_id"`
SignatureType string `json:"signature_type"`
}
Status reports the current auth readiness without exposing secrets.
type TypedData ¶
type TypedData struct {
Types TypedDataTypes `json:"types"`
PrimaryType string `json:"primaryType"`
Domain EIP712Domain `json:"domain"`
Message map[string]interface{} `json:"message"`
}
TypedData is the top-level EIP-712 structure.
func TypedDataFromClobAuth ¶
func TypedDataFromClobAuth(domain EIP712Domain, msg ClobAuthMessage) TypedData
TypedDataFromClobAuth builds the full EIP-712 TypedData from a ClobAuth.
func (TypedData) MarshalJSON ¶
MarshalJSON serializes the full typed data for signing via personal_sign.
type TypedDataField ¶
type TypedDataTypes ¶
type TypedDataTypes map[string][]TypedDataField