wallet

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 9, 2026 License: MIT Imports: 15 Imported by: 0

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

View Source
const CurrencyUSDC = "USDC"

CurrencyUSDC is the ticker symbol for the USDC stablecoin used across the payment system.

View Source
const USDCDecimals = 6

USDCDecimals is the number of decimal places for USDC (6).

View Source
const WalletKeyName = "wallet.privatekey"

WalletKeyName is the secrets store key for the wallet private key.

Variables

View Source
var ErrWalletExists = errors.New("wallet already exists")

ErrWalletExists is returned when attempting to create a wallet that already exists.

Functions

func CreateWallet

func CreateWallet(ctx context.Context, secrets *security.SecretsStore) (string, error)

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

func FormatUSDC(amount *big.Int) string

FormatUSDC converts smallest USDC units back to a decimal string.

func NetworkName

func NetworkName(chainID int64) string

NetworkName returns a human-readable network name for common chain IDs.

func ParseUSDC

func ParseUSDC(amount string) (*big.Int, error)

ParseUSDC converts a decimal string (e.g. "1.50") to the smallest USDC unit.

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 ChainID

type ChainID int64

ChainID identifies a blockchain network.

const (
	ChainEthereumMainnet ChainID = 1
	ChainBase            ChainID = 8453
	ChainBaseSepolia     ChainID = 84532
	ChainSepolia         ChainID = 11155111
)

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) Balance

func (w *CompositeWallet) Balance(ctx context.Context) (*big.Int, error)

Balance returns the balance 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

func (w *CompositeWallet) SignMessage(ctx context.Context, message []byte) ([]byte, error)

SignMessage signs using the active provider.

func (*CompositeWallet) SignTransaction

func (w *CompositeWallet) SignTransaction(ctx context.Context, rawTx []byte) ([]byte, error)

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

func (l *EntSpendingLimiter) Check(ctx context.Context, amount *big.Int) error

Check verifies that the amount does not exceed per-tx or daily limits.

func (*EntSpendingLimiter) DailyRemaining

func (l *EntSpendingLimiter) DailyRemaining(ctx context.Context) (*big.Int, error)

DailyRemaining returns how much can still be spent today.

func (*EntSpendingLimiter) DailySpent

func (l *EntSpendingLimiter) DailySpent(ctx context.Context) (*big.Int, error)

DailySpent sums confirmed and submitted transaction amounts for today.

func (*EntSpendingLimiter) IsAutoApprovable

func (l *EntSpendingLimiter) IsAutoApprovable(ctx context.Context, amount *big.Int) (bool, error)

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.

func (*EntSpendingLimiter) Record

func (l *EntSpendingLimiter) Record(_ context.Context, _ *big.Int) error

Record is a no-op: spending is tracked via PaymentTx records created by PaymentService.

type LocalUserOpSigner added in v0.5.0

type LocalUserOpSigner struct {
	// contains filtered or unexported fields
}

LocalUserOpSigner signs UserOps using a local ECDSA private key.

func NewLocalUserOpSigner added in v0.5.0

func NewLocalUserOpSigner(key *ecdsa.PrivateKey) *LocalUserOpSigner

NewLocalUserOpSigner creates a signer from an ECDSA private key.

func (*LocalUserOpSigner) SignUserOp added in v0.5.0

func (s *LocalUserOpSigner) SignUserOp(
	_ context.Context,
	userOpHash []byte,
	entryPoint common.Address,
	chainID *big.Int,
) ([]byte, error)

SignUserOp computes the ERC-4337 UserOp signature. The hash is: keccak256(abi.encode(userOpHash, entryPoint, chainId)).

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) Balance

func (w *LocalWallet) Balance(ctx context.Context) (*big.Int, error)

Balance returns the native token (ETH) balance of the wallet.

func (*LocalWallet) PublicKey

func (w *LocalWallet) PublicKey(ctx context.Context) ([]byte, error)

PublicKey returns the compressed public key bytes.

func (*LocalWallet) SignMessage

func (w *LocalWallet) SignMessage(ctx context.Context, message []byte) ([]byte, error)

SignMessage signs an arbitrary message with the wallet's private key.

func (*LocalWallet) SignTransaction

func (w *LocalWallet) SignTransaction(ctx context.Context, rawTx []byte) ([]byte, error)

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) Address

func (w *RPCWallet) Address(ctx context.Context) (string, error)

Address requests the wallet address from the companion.

func (*RPCWallet) Balance

func (w *RPCWallet) Balance(_ context.Context) (*big.Int, error)

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) PublicKey

func (w *RPCWallet) PublicKey(_ context.Context) ([]byte, error)

PublicKey is not supported via RPC — returns an error.

func (*RPCWallet) SetSender

func (w *RPCWallet) SetSender(fn types.RPCSenderFunc)

SetSender configures the transport for sending requests to the companion.

func (*RPCWallet) SignMessage

func (w *RPCWallet) SignMessage(ctx context.Context, message []byte) ([]byte, error)

SignMessage sends a message signing request to the companion.

func (*RPCWallet) SignTransaction

func (w *RPCWallet) SignTransaction(ctx context.Context, rawTx []byte) ([]byte, error)

SignTransaction sends a signing request to the companion and waits for the response.

type SignMsgRequest

type SignMsgRequest struct {
	RequestID string `json:"requestId"`
	Message   []byte `json:"message"`
}

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

type SignTxRequest struct {
	RequestID string `json:"requestId"`
	RawTx     []byte `json:"rawTx"`
}

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 UserOpSigner added in v0.5.0

type UserOpSigner interface {
	// SignUserOp signs a UserOp hash for the given entry point and chain.
	SignUserOp(
		ctx context.Context,
		userOpHash []byte,
		entryPoint common.Address,
		chainID *big.Int,
	) ([]byte, error)
}

UserOpSigner signs ERC-4337 UserOperation hashes.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL