Documentation
¶
Overview ¶
Package wallet provides blockchain wallet management for the payment system. Private keys never leave the wallet layer — the agent only sees addresses and receipts.
Index ¶
- Constants
- Variables
- func CreateWallet(ctx context.Context, secrets *security.SecretsStore) (string, error)
- func FormatUSDC(amount *big.Int) string
- func NetworkName(chainID int64) string
- func ParseUSDC(amount string) (*big.Int, error)
- type AddressRequest
- type AddressResponse
- type ChainID
- type CompositeWallet
- func (w *CompositeWallet) Address(ctx context.Context) (string, error)
- func (w *CompositeWallet) Balance(ctx context.Context) (*big.Int, error)
- func (w *CompositeWallet) PublicKey(ctx context.Context) ([]byte, error)
- func (w *CompositeWallet) SignMessage(ctx context.Context, message []byte) ([]byte, error)
- func (w *CompositeWallet) SignTransaction(ctx context.Context, rawTx []byte) ([]byte, error)
- func (w *CompositeWallet) UsedLocal() bool
- type ConnectionChecker
- type EntSpendingLimiter
- func (l *EntSpendingLimiter) Check(ctx context.Context, amount *big.Int) error
- func (l *EntSpendingLimiter) DailyRemaining(ctx context.Context) (*big.Int, error)
- func (l *EntSpendingLimiter) DailySpent(ctx context.Context) (*big.Int, error)
- func (l *EntSpendingLimiter) IsAutoApprovable(ctx context.Context, amount *big.Int) (bool, error)
- func (l *EntSpendingLimiter) MaxDaily() *big.Int
- func (l *EntSpendingLimiter) MaxPerTx() *big.Int
- func (l *EntSpendingLimiter) Record(_ context.Context, _ *big.Int) error
- type LocalWallet
- func (w *LocalWallet) Address(ctx context.Context) (string, error)
- func (w *LocalWallet) Balance(ctx context.Context) (*big.Int, error)
- func (w *LocalWallet) PublicKey(ctx context.Context) ([]byte, error)
- func (w *LocalWallet) SignMessage(ctx context.Context, message []byte) ([]byte, error)
- func (w *LocalWallet) SignTransaction(ctx context.Context, rawTx []byte) ([]byte, error)
- type RPCWallet
- func (w *RPCWallet) Address(ctx context.Context) (string, error)
- func (w *RPCWallet) Balance(_ context.Context) (*big.Int, error)
- func (w *RPCWallet) HandleAddressResponse(resp AddressResponse)
- func (w *RPCWallet) HandleSignMsgResponse(resp SignMsgResponse)
- func (w *RPCWallet) HandleSignTxResponse(resp SignTxResponse)
- func (w *RPCWallet) PublicKey(_ context.Context) ([]byte, error)
- func (w *RPCWallet) SetSender(fn types.RPCSenderFunc)
- func (w *RPCWallet) SignMessage(ctx context.Context, message []byte) ([]byte, error)
- func (w *RPCWallet) SignTransaction(ctx context.Context, rawTx []byte) ([]byte, error)
- type SignMsgRequest
- type SignMsgResponse
- type SignTxRequest
- type SignTxResponse
- type SpendingLimiter
- type WalletInfo
- type WalletProvider
Constants ¶
const CurrencyUSDC = "USDC"
CurrencyUSDC is the ticker symbol for the USDC stablecoin used across the payment system.
const USDCDecimals = 6
USDCDecimals is the number of decimal places for USDC (6).
const WalletKeyName = "wallet.privatekey"
WalletKeyName is the secrets store key for the wallet private key.
Variables ¶
var ErrWalletExists = errors.New("wallet already exists")
ErrWalletExists is returned when attempting to create a wallet that already exists.
Functions ¶
func CreateWallet ¶
CreateWallet generates a new ECDSA private key, stores it encrypted in SecretsStore, and returns the derived public address. If a wallet already exists, it returns ErrWalletExists along with the existing address.
func FormatUSDC ¶
FormatUSDC converts smallest USDC units back to a decimal string.
func NetworkName ¶
NetworkName returns a human-readable network name for common chain IDs.
Types ¶
type AddressRequest ¶
type AddressRequest struct {
RequestID string `json:"requestId"`
}
AddressRequest is sent to the companion to retrieve the wallet address.
type AddressResponse ¶
type AddressResponse struct {
RequestID string `json:"requestId"`
Address string `json:"address,omitempty"`
Error string `json:"error,omitempty"`
}
AddressResponse is received from the companion with the wallet address.
type CompositeWallet ¶
type CompositeWallet struct {
// contains filtered or unexported fields
}
CompositeWallet implements WalletProvider with primary/fallback logic. When the companion app is connected (checked via ConnectionChecker), the primary (RPC) wallet is used. Otherwise, falls back to local.
func NewCompositeWallet ¶
func NewCompositeWallet(primary, fallback WalletProvider, checker ConnectionChecker) *CompositeWallet
NewCompositeWallet creates a composite wallet with primary/fallback providers.
func (*CompositeWallet) Address ¶
func (w *CompositeWallet) Address(ctx context.Context) (string, error)
Address returns the wallet address from the active provider.
func (*CompositeWallet) PublicKey ¶
func (w *CompositeWallet) PublicKey(ctx context.Context) ([]byte, error)
PublicKey returns the compressed public key from the active provider.
func (*CompositeWallet) SignMessage ¶
SignMessage signs using the active provider.
func (*CompositeWallet) SignTransaction ¶
SignTransaction signs using the active provider.
func (*CompositeWallet) UsedLocal ¶
func (w *CompositeWallet) UsedLocal() bool
UsedLocal returns true if the fallback (local) wallet was used at any point.
type ConnectionChecker ¶
type ConnectionChecker interface {
IsConnected() bool
}
ConnectionChecker determines whether a remote companion is connected.
type EntSpendingLimiter ¶
type EntSpendingLimiter struct {
// contains filtered or unexported fields
}
EntSpendingLimiter uses Ent PaymentTx records to enforce spending limits.
func NewEntSpendingLimiter ¶
func NewEntSpendingLimiter(client *ent.Client, maxPerTx, maxDaily, autoApproveBelow string) (*EntSpendingLimiter, error)
NewEntSpendingLimiter creates a spending limiter backed by Ent PaymentTx records. autoApproveBelow is the USDC amount threshold below which transactions can be auto-approved without explicit user confirmation. Pass "" or "0" to disable.
func (*EntSpendingLimiter) Check ¶
Check verifies that the amount does not exceed per-tx or daily limits.
func (*EntSpendingLimiter) DailyRemaining ¶
DailyRemaining returns how much can still be spent today.
func (*EntSpendingLimiter) DailySpent ¶
DailySpent sums confirmed and submitted transaction amounts for today.
func (*EntSpendingLimiter) IsAutoApprovable ¶
IsAutoApprovable checks whether amount can be auto-approved without user confirmation. Returns false when auto-approve is disabled (threshold is 0), when amount exceeds the threshold, or when spending limits would be exceeded.
func (*EntSpendingLimiter) MaxDaily ¶
func (l *EntSpendingLimiter) MaxDaily() *big.Int
MaxDaily returns the daily spending limit.
func (*EntSpendingLimiter) MaxPerTx ¶
func (l *EntSpendingLimiter) MaxPerTx() *big.Int
MaxPerTx returns the per-transaction limit.
type LocalWallet ¶
type LocalWallet struct {
// contains filtered or unexported fields
}
LocalWallet implements WalletProvider using a locally-stored encrypted private key. The key is loaded from SecretsStore, used for signing, then immediately zeroed.
func NewLocalWallet ¶
func NewLocalWallet(secrets *security.SecretsStore, rpcURL string, chainID int64) *LocalWallet
NewLocalWallet creates a wallet that loads its private key from the secrets store.
func (*LocalWallet) Address ¶
func (w *LocalWallet) Address(ctx context.Context) (string, error)
Address derives the wallet address from the stored private key.
func (*LocalWallet) PublicKey ¶
func (w *LocalWallet) PublicKey(ctx context.Context) ([]byte, error)
PublicKey returns the compressed public key bytes.
func (*LocalWallet) SignMessage ¶
SignMessage signs an arbitrary message with the wallet's private key.
func (*LocalWallet) SignTransaction ¶
SignTransaction signs a raw transaction hash with the wallet's private key.
type RPCWallet ¶
type RPCWallet struct {
// contains filtered or unexported fields
}
RPCWallet delegates wallet operations to a companion app via WebSocket RPC. Mirrors the security.RPCProvider pattern: correlation IDs + channel-based response.
func NewRPCWallet ¶
func NewRPCWallet() *RPCWallet
NewRPCWallet creates an RPC-based wallet provider.
func (*RPCWallet) Balance ¶
Balance is not supported via RPC — returns an error directing to local wallet.
func (*RPCWallet) HandleAddressResponse ¶
func (w *RPCWallet) HandleAddressResponse(resp AddressResponse)
HandleAddressResponse dispatches an address response from the companion.
func (*RPCWallet) HandleSignMsgResponse ¶
func (w *RPCWallet) HandleSignMsgResponse(resp SignMsgResponse)
HandleSignMsgResponse dispatches a message signing response from the companion.
func (*RPCWallet) HandleSignTxResponse ¶
func (w *RPCWallet) HandleSignTxResponse(resp SignTxResponse)
HandleSignTxResponse dispatches a signing response from the companion.
func (*RPCWallet) SetSender ¶
func (w *RPCWallet) SetSender(fn types.RPCSenderFunc)
SetSender configures the transport for sending requests to the companion.
func (*RPCWallet) SignMessage ¶
SignMessage sends a message signing request to the companion.
type SignMsgRequest ¶
SignMsgRequest is sent to the companion for message signing.
type SignMsgResponse ¶
type SignMsgResponse struct {
RequestID string `json:"requestId"`
Signature []byte `json:"signature,omitempty"`
Error string `json:"error,omitempty"`
}
SignMsgResponse is received from the companion after message signing.
type SignTxRequest ¶
SignTxRequest is sent to the companion for transaction signing.
type SignTxResponse ¶
type SignTxResponse struct {
RequestID string `json:"requestId"`
Signature []byte `json:"signature,omitempty"`
Error string `json:"error,omitempty"`
}
SignTxResponse is received from the companion after signing.
type SpendingLimiter ¶
type SpendingLimiter interface {
// Check verifies that spending amount is within limits without recording it.
Check(ctx context.Context, amount *big.Int) error
// Record records a spent amount for daily tracking.
Record(ctx context.Context, amount *big.Int) error
// DailySpent returns the total amount spent today.
DailySpent(ctx context.Context) (*big.Int, error)
// DailyRemaining returns the remaining daily budget.
DailyRemaining(ctx context.Context) (*big.Int, error)
// IsAutoApprovable checks whether the given amount can be auto-approved
// without explicit user confirmation, based on the autoApproveBelow threshold
// and spending limits.
IsAutoApprovable(ctx context.Context, amount *big.Int) (bool, error)
}
SpendingLimiter enforces per-transaction and daily spending limits.
type WalletInfo ¶
type WalletInfo struct {
Address string `json:"address"`
ChainID int64 `json:"chainId"`
Network string `json:"network"`
}
WalletInfo holds public wallet metadata.
type WalletProvider ¶
type WalletProvider interface {
// Address returns the wallet's public address.
Address(ctx context.Context) (string, error)
// Balance returns the native token balance in wei.
Balance(ctx context.Context) (*big.Int, error)
// SignTransaction signs a raw transaction and returns the signed bytes.
SignTransaction(ctx context.Context, rawTx []byte) ([]byte, error)
// SignMessage signs an arbitrary message and returns the signature.
SignMessage(ctx context.Context, message []byte) ([]byte, error)
// PublicKey returns the compressed public key bytes.
// Used for P2P identity derivation (DID). Private key is never exposed.
PublicKey(ctx context.Context) ([]byte, error)
}
WalletProvider abstracts blockchain wallet operations. Implementations must ensure private keys are never exposed to callers.