Documentation
¶
Overview ¶
adapters.go provides adapter implementations that wrap jarvis types to implement the minimal interfaces defined in deps.go.
deps.go defines minimal interfaces for external dependencies. This allows for easy mocking in tests and decouples the library from specific implementations.
Package walletarmy provides persistence interfaces for crash-resilient transaction management. Implement these interfaces to persist nonce state and in-flight transactions across restarts.
Index ¶
- Constants
- Variables
- func DefaultNetworkResolver(chainID uint64) (networks.Network, error)
- func IsGasLimitIsTooLow(err error) bool
- func IsInsufficientFund(err error) bool
- func IsNonceIsLow(err error) bool
- func IsReplacementUnderpriced(err error) bool
- func IsTxIsKnown(err error) bool
- type BroadcastError
- type BroadcasterFactory
- type DecodedErrordeprecated
- type ErrorDecoder
- type EthBroadcaster
- type EthReader
- type GasBounds
- type GasEstimationError
- type GasEstimationFailedHook
- type GasInfo
- type Hook
- type LoopAction
- type Manager
- type ManagerDefaults
- type NetworkBroadcasterFactory
- type NetworkReaderFactory
- type NetworkResolver
- type NetworkTxMonitorFactory
- type NonceState
- type NonceStore
- type PendingTx
- type PendingTxStatus
- type ReaderFactory
- type RecoveryHandler
- type RecoveryOptions
- type RecoveryResult
- type ResumeTransactionOptions
- type RetryConfig
- type SimulationFailedHook
- type SimulationRevertError
- type TxExecutionContext
- func (ctx *TxExecutionContext) AdjustGasPricesForSlowTx(tx *types.Transaction) bool
- func (ctx *TxExecutionContext) BumpGasForSlowTx(tx *types.Transaction) bool
- func (ctx *TxExecutionContext) IncrementRetryAndCheck(errorMsg string) *TxExecutionResult
- func (ctx *TxExecutionContext) IncrementRetryCountAndCheck(errorMsg string) *TxExecutionResult
- type TxExecutionResult
- type TxHooks
- type TxInfo
- type TxInfoStatus
- type TxMinedHook
- type TxMonitor
- type TxMonitorFactory
- type TxMonitorStatus
- type TxParams
- type TxRequest
- func (r *TxRequest) Execute() (*types.Transaction, *types.Receipt, error)
- func (r *TxRequest) ExecuteContext(ctx context.Context) (*types.Transaction, *types.Receipt, error)
- func (r *TxRequest) SetAbis(abis ...abi.ABI) *TxRequest
- func (r *TxRequest) SetAfterSignAndBroadcastHook(hook Hook) *TxRequest
- func (r *TxRequest) SetBeforeSignAndBroadcastHook(hook Hook) *TxRequest
- func (r *TxRequest) SetData(data []byte) *TxRequest
- func (r *TxRequest) SetExtraGasLimit(extraGasLimit uint64) *TxRequest
- func (r *TxRequest) SetExtraGasPrice(extraGasPrice float64) *TxRequest
- func (r *TxRequest) SetExtraTipCapGwei(extraTipCapGwei float64) *TxRequest
- func (r *TxRequest) SetFrom(from common.Address) *TxRequest
- func (r *TxRequest) SetGasEstimationFailedHook(hook GasEstimationFailedHook) *TxRequest
- func (r *TxRequest) SetGasLimit(gasLimit uint64) *TxRequest
- func (r *TxRequest) SetGasPrice(gasPrice float64) *TxRequest
- func (r *TxRequest) SetIdempotencyKey(key string) *TxRequest
- func (r *TxRequest) SetMaxGasPrice(maxGasPrice float64) *TxRequest
- func (r *TxRequest) SetMaxTipCap(maxTipCap float64) *TxRequest
- func (r *TxRequest) SetNetwork(network networks.Network) *TxRequest
- func (r *TxRequest) SetNumRetries(numRetries int) *TxRequest
- func (r *TxRequest) SetSimulationFailedHook(hook SimulationFailedHook) *TxRequest
- func (r *TxRequest) SetSkipSimulation(skip bool) *TxRequest
- func (r *TxRequest) SetSleepDuration(sleepDuration time.Duration) *TxRequest
- func (r *TxRequest) SetTipCapGwei(tipCapGwei float64) *TxRequest
- func (r *TxRequest) SetTo(to common.Address) *TxRequest
- func (r *TxRequest) SetTxCheckInterval(txCheckInterval time.Duration) *TxRequest
- func (r *TxRequest) SetTxMinedHook(hook TxMinedHook) *TxRequest
- func (r *TxRequest) SetTxType(txType uint8) *TxRequest
- func (r *TxRequest) SetValue(value *big.Int) *TxRequest
- type TxRetryState
- type TxStore
- type WalletManager
- func (wm *WalletManager) Account(wallet common.Address) *account.Account
- func (wm *WalletManager) Analyzer(network networks.Network) (*txanalyzer.TxAnalyzer, error)
- func (wm *WalletManager) BroadcastTx(tx *types.Transaction) (hash string, broadcasted bool, err BroadcastError)
- func (wm *WalletManager) BroadcastTxSync(tx *types.Transaction) (receipt *types.Receipt, err error)
- func (wm *WalletManager) Broadcaster(network networks.Network) (EthBroadcaster, error)
- func (wm *WalletManager) BuildTx(txType uint8, from, to common.Address, nonce *big.Int, value *big.Int, ...) (tx *types.Transaction, err error)
- func (wm *WalletManager) Defaults() ManagerDefaults
- func (wm *WalletManager) EnsureTx(txType uint8, from, to common.Address, value *big.Int, gasLimit uint64, ...) (tx *types.Transaction, receipt *types.Receipt, err error)
- func (wm *WalletManager) EnsureTxWithHooks(numRetries int, sleepDuration time.Duration, txCheckInterval time.Duration, ...) (tx *types.Transaction, receipt *types.Receipt, err error)
- func (wm *WalletManager) EnsureTxWithHooksContext(ctx context.Context, numRetries int, sleepDuration time.Duration, ...) (tx *types.Transaction, receipt *types.Receipt, err error)
- func (wm *WalletManager) GasSetting(network networks.Network) (*GasInfo, error)
- func (wm *WalletManager) GetCircuitBreakerStats(network networks.Network) circuitbreaker.Stats
- func (wm *WalletManager) IdempotencyStore() idempotency.Store
- func (wm *WalletManager) MonitorTx(tx *types.Transaction, network networks.Network, txCheckInterval time.Duration) <-chan TxInfodeprecated
- func (wm *WalletManager) MonitorTxContext(ctx context.Context, tx *types.Transaction, network networks.Network, ...) <-chan TxInfo
- func (wm *WalletManager) NonceStore() NonceStore
- func (wm *WalletManager) R() *TxRequest
- func (wm *WalletManager) Reader(network networks.Network) (EthReader, error)
- func (wm *WalletManager) RecordNetworkFailure(network networks.Network)
- func (wm *WalletManager) RecordNetworkSuccess(network networks.Network)
- func (wm *WalletManager) Recover(ctx context.Context) (*RecoveryResult, error)
- func (wm *WalletManager) RecoverWithOptions(ctx context.Context, opts RecoveryOptions) (*RecoveryResult, error)
- func (wm *WalletManager) ReleaseNonce(wallet common.Address, network networks.Network, nonce uint64)
- func (wm *WalletManager) ResetCircuitBreaker(network networks.Network)
- func (wm *WalletManager) ResumePendingTransaction(ctx context.Context, pendingTx *PendingTx, opts ResumeTransactionOptions) (*types.Transaction, *types.Receipt, error)
- func (wm *WalletManager) SetAccount(acc *account.Account)
- func (wm *WalletManager) SetDefaults(defaults ManagerDefaults)
- func (wm *WalletManager) SignTx(wallet common.Address, tx *types.Transaction, network networks.Network) (signedAddr common.Address, signedTx *types.Transaction, err error)
- func (wm *WalletManager) TxStore() TxStore
- func (wm *WalletManager) UnlockAccount(addr common.Address) (*account.Account, error)
- type WalletManagerOption
- func WithBroadcasterFactory(factory NetworkBroadcasterFactory) WalletManagerOption
- func WithDefaultExtraGasLimit(extraGasLimit uint64) WalletManagerOption
- func WithDefaultExtraGasPrice(extraGasPrice float64) WalletManagerOption
- func WithDefaultExtraTipCap(extraTipCap float64) WalletManagerOption
- func WithDefaultGasPriceBumpFactor(factor float64) WalletManagerOption
- func WithDefaultGasPriceIncreasePercent(percent float64) WalletManagerOptiondeprecated
- func WithDefaultIdempotencyStore(ttl time.Duration) WalletManagerOption
- func WithDefaultMaxGasPrice(maxGasPrice float64) WalletManagerOption
- func WithDefaultMaxTipCap(maxTipCap float64) WalletManagerOption
- func WithDefaultNetwork(network networks.Network) WalletManagerOption
- func WithDefaultNumRetries(numRetries int) WalletManagerOption
- func WithDefaultSleepDuration(duration time.Duration) WalletManagerOption
- func WithDefaultSlowTxTimeout(timeout time.Duration) WalletManagerOption
- func WithDefaultTipCapBumpFactor(factor float64) WalletManagerOption
- func WithDefaultTipCapIncreasePercent(percent float64) WalletManagerOptiondeprecated
- func WithDefaultTxCheckInterval(interval time.Duration) WalletManagerOption
- func WithDefaultTxType(txType uint8) WalletManagerOption
- func WithDefaults(defaults ManagerDefaults) WalletManagerOption
- func WithIdempotencyStore(store idempotency.Store) WalletManagerOption
- func WithNetworkResolver(resolver NetworkResolver) WalletManagerOption
- func WithNonceStore(store NonceStore) WalletManagerOption
- func WithReaderFactory(factory NetworkReaderFactory) WalletManagerOption
- func WithTxMonitorFactory(factory NetworkTxMonitorFactory) WalletManagerOption
- func WithTxStore(store TxStore) WalletManagerOption
Constants ¶
const ( DefaultNumRetries = 9 DefaultSleepDuration = 5 * time.Second DefaultTxCheckInterval = 5 * time.Second DefaultSlowTxTimeout = 5 * time.Second // Time before considering a tx "slow" // Default gas adjustment values (can be overridden via ManagerDefaults) DefaultGasPriceBumpFactor = 1.2 // 20% increase when tx is slow DefaultTipCapBumpFactor = 1.1 // 10% increase when tx is slow MaxCapMultiplier = 5.0 // Multiplier for default max gas price/tip cap when not set // Deprecated: Use DefaultGasPriceBumpFactor instead. DefaultGasPriceIncreasePercent = DefaultGasPriceBumpFactor // Deprecated: Use DefaultTipCapBumpFactor instead. DefaultTipCapIncreasePercent = DefaultTipCapBumpFactor )
Constants for transaction execution
Variables ¶
var ( ErrInsufficientFund = BroadcastError(fmt.Errorf("insufficient fund")) ErrNonceIsLow = BroadcastError(fmt.Errorf("nonce is low")) ErrReplacementUnderpriced = BroadcastError(fmt.Errorf("replacement transaction underpriced")) ErrGasLimitIsTooLow = BroadcastError(fmt.Errorf("gas limit is too low")) ErrTxIsKnown = BroadcastError(fmt.Errorf("tx is known")) )
var ( ErrEstimateGasFailed = fmt.Errorf("estimate gas failed") ErrAcquireNonceFailed = fmt.Errorf("acquire nonce failed") ErrGetGasSettingFailed = fmt.Errorf("get gas setting failed") ErrEnsureTxOutOfRetries = fmt.Errorf("ensure tx out of retries") ErrGasPriceLimitReached = fmt.Errorf("gas price protection limit reached") ErrFromAddressZero = fmt.Errorf("from address cannot be zero") ErrNetworkNil = fmt.Errorf("network cannot be nil") ErrSimulatedTxReverted = fmt.Errorf("tx will be reverted") ErrSimulatedTxFailed = fmt.Errorf("couldn't simulate tx at pending state") ErrCircuitBreakerOpen = fmt.Errorf("circuit breaker is open: network temporarily unavailable") ErrSyncBroadcastTimeout = fmt.Errorf("sync broadcast timed out, falling back to async monitoring") ErrTxReverted = fmt.Errorf("transaction was mined but reverted") )
Transaction execution errors
var GAS_INFO_TTL = 60 * time.Second
var SyncBroadcastTimeout = 5 * time.Second
SyncBroadcastTimeout is the maximum time to wait for BroadcastTxSync before falling back to async monitoring. This is a variable (not const) to allow tests to override it for faster testing.
Functions ¶
func DefaultNetworkResolver ¶
DefaultNetworkResolver is the default resolver that uses jarvis networks.GetNetworkByID. This supports standard EVM networks (Ethereum, Polygon, Arbitrum, Optimism, etc.). For custom networks, use WithNetworkResolver to provide a custom resolver.
func IsGasLimitIsTooLow ¶
func IsInsufficientFund ¶
func IsNonceIsLow ¶
func IsTxIsKnown ¶
Types ¶
type BroadcastError ¶
type BroadcastError error
func NewBroadcastError ¶
func NewBroadcastError(err error) BroadcastError
type BroadcasterFactory ¶
type BroadcasterFactory func(chainID uint64, networkName string) (EthBroadcaster, error)
BroadcasterFactory creates an EthBroadcaster for a given network. This allows injecting mock broadcasters for testing.
type DecodedError
deprecated
added in
v1.2.0
type DecodedError struct {
// AbiError is the matched ABI error definition, or nil if decoding failed.
AbiError *abi.Error
// RevertParams contains the decoded parameters of the revert, or nil.
RevertParams any
// RevertData is the raw revert bytes from the node.
RevertData []byte
// Err is the underlying error being wrapped.
Err error
}
Deprecated: Use GasEstimationError or SimulationRevertError instead. These dedicated types carry richer context (the built transaction, raw revert bytes, etc.) and are returned consistently on every error exit path.
DecodedError wraps a contract error with its decoded ABI information.
func (*DecodedError) Error ¶ added in v1.2.0
func (e *DecodedError) Error() string
func (*DecodedError) Unwrap ¶ added in v1.2.0
func (e *DecodedError) Unwrap() error
type ErrorDecoder ¶
type ErrorDecoder struct {
// contains filtered or unexported fields
}
func NewErrorDecoder ¶
func NewErrorDecoder(abis ...abi.ABI) (*ErrorDecoder, error)
func (*ErrorDecoder) Decode ¶
Decode decodes the error from a contract call. It should always wrap the original error (using %w). It can only decode Solidity custom errors https://soliditylang.org/blog/2021/04/21/custom-errors/
type EthBroadcaster ¶
type EthBroadcaster interface {
// BroadcastTx broadcasts a signed transaction to the network
// Returns the tx hash, whether it was broadcast successfully, and any errors
BroadcastTx(tx *types.Transaction) (hash string, broadcasted bool, err error)
// BroadcastTxSync broadcasts and waits for the transaction to be mined (for L2s that support it)
BroadcastTxSync(tx *types.Transaction) (receipt *types.Receipt, err error)
}
EthBroadcaster defines the minimal interface for broadcasting transactions.
func DefaultBroadcasterFactory ¶
func DefaultBroadcasterFactory(network networks.Network) (EthBroadcaster, error)
DefaultBroadcasterFactory is the default factory that creates jarvis broadcasters
func NewBroadcasterAdapter ¶
func NewBroadcasterAdapter(b *broadcaster.Broadcaster) EthBroadcaster
NewBroadcasterAdapter creates an EthBroadcaster from a jarvis broadcaster
type EthReader ¶
type EthReader interface {
// GetMinedNonce returns the nonce of the last mined transaction for the address
GetMinedNonce(addr string) (uint64, error)
// GetPendingNonce returns the nonce of the next pending transaction for the address
GetPendingNonce(addr string) (uint64, error)
// EstimateExactGas estimates the gas required for a transaction
EstimateExactGas(from, to string, gasPrice float64, value *big.Int, data []byte) (uint64, error)
// SuggestedGasSettings returns suggested gas price and tip cap in gwei
SuggestedGasSettings() (gasPrice float64, tipCapGwei float64, err error)
// EthCall simulates a transaction execution without sending it
// The overrides parameter allows for state overrides during the call simulation
EthCall(from, to string, data []byte, overrides *map[common.Address]gethclient.OverrideAccount) ([]byte, error)
// TxInfoFromHash returns transaction info for a given hash
TxInfoFromHash(hash string) (TxInfo, error)
}
EthReader defines the minimal interface for reading blockchain state. This abstracts away the concrete jarvis reader implementation.
func DefaultReaderFactory ¶
DefaultReaderFactory is the default factory that creates jarvis readers
func NewReaderAdapter ¶
NewReaderAdapter creates an EthReader from a jarvis reader
type GasBounds ¶
type GasBounds struct {
ExtraGasLimit uint64 // Extra gas limit added to estimates
ExtraGasPrice float64 // Extra gas price added to suggestions (gwei)
ExtraTipCap float64 // Extra tip cap added to suggestions (gwei)
MaxGasPrice float64 // Maximum gas price protection limit (gwei)
MaxTipCap float64 // Maximum tip cap protection limit (gwei)
GasPriceBumpFactor float64 // Multiplier for gas price when tx is slow (e.g., 1.2 = 20% increase)
TipCapBumpFactor float64 // Multiplier for tip cap when tx is slow (e.g., 1.1 = 10% increase)
}
GasBounds holds immutable gas configuration and protection limits.
type GasEstimationError ¶ added in v1.1.9
type GasEstimationError struct {
AbiError *abi.Error // decoded ABI error, nil if unavailable
RevertParams any // decoded parameters, nil if AbiError is nil
Err error // underlying error chain (preserves ErrEstimateGasFailed, ErrEnsureTxOutOfRetries, etc.)
}
GasEstimationError is a structured error returned when gas estimation fails. Callers can extract it with errors.As to access ABI-decoded error details.
AbiError and RevertParams are populated only when ABIs are provided via SetAbis() and the RPC error contains decodable Solidity custom error data.
func (*GasEstimationError) Error ¶ added in v1.1.9
func (e *GasEstimationError) Error() string
func (*GasEstimationError) Unwrap ¶ added in v1.1.9
func (e *GasEstimationError) Unwrap() error
type GasEstimationFailedHook ¶
type GasEstimationFailedHook func(tx *types.Transaction, abiError *abi.Error, revertParams any, revertMsgError, gasEstimationError error) (gasLimit *big.Int, err error)
GasEstimationFailedHook is called when gas estimation fails during transaction building. This typically means the transaction would revert or there is a network error.
This hook is always called when set, regardless of whether ABIs were provided.
Parameters:
- tx: always nil (the transaction could not be built due to gas estimation failure).
- abiError: the decoded ABI error if ABIs were provided via SetAbis() and the error could be decoded, nil otherwise (including when no ABIs are set).
- revertParams: the decoded revert parameters, nil when abiError is nil.
- revertMsgError: the error from ABI decoding itself, nil when no ABIs are set or decoding was not attempted.
- gasEstimationError: the original gas estimation error, always non-nil (wraps ErrEstimateGasFailed).
Return values:
- gasLimit non-nil: the returned gas limit overrides the estimate for the next retry attempt, allowing the caller to force a specific gas limit.
- gasLimit nil: the next retry will attempt gas estimation again.
- err non-nil: the execution stops immediately with this error.
type Hook ¶
type Hook func(tx *types.Transaction, err error) error
Hook is called before signing/broadcasting and after signing/broadcasting.
Before sign and broadcast (BeforeSignAndBroadcast):
- tx: the built (unsigned) transaction, always non-nil.
- err: always nil (reserved for future use).
- Return a non-nil error to abort the entire EnsureTx flow immediately.
After sign and broadcast (AfterSignAndBroadcast):
- tx: the signed transaction that was successfully broadcast, always non-nil.
- err: the broadcast error if any nodes rejected the tx, or nil on full success.
- Return a non-nil error to abort the entire EnsureTx flow immediately. The transaction was already broadcast, so returning an error here does NOT prevent it from being mined.
type LoopAction ¶
type LoopAction int
LoopAction represents what the transaction execution loop should do next.
const ( // ActionContinueToMonitor proceeds to the monitoring phase of the loop. ActionContinueToMonitor LoopAction = iota // ActionRetry goes back to the top of the loop for a new attempt. ActionRetry // ActionReturn exits the loop entirely, returning the result to the caller. ActionReturn )
type Manager ¶
type Manager interface {
// Account Management
SetAccount(acc *account.Account)
UnlockAccount(addr common.Address) (*account.Account, error)
Account(wallet common.Address) *account.Account
// Network Infrastructure
Reader(network networks.Network) (EthReader, error)
Broadcaster(network networks.Network) (EthBroadcaster, error)
Analyzer(network networks.Network) (*txanalyzer.TxAnalyzer, error)
// Gas Settings
GasSetting(network networks.Network) (*GasInfo, error)
// Nonce Management
// ReleaseNonce releases a previously acquired nonce that was not used.
ReleaseNonce(wallet common.Address, network networks.Network, nonce uint64)
// Circuit Breaker
GetCircuitBreakerStats(network networks.Network) circuitbreaker.Stats
ResetCircuitBreaker(network networks.Network)
RecordNetworkSuccess(network networks.Network)
RecordNetworkFailure(network networks.Network)
// Idempotency
IdempotencyStore() idempotency.Store
// Default Configuration
Defaults() ManagerDefaults
SetDefaults(defaults ManagerDefaults)
// Transaction Building
BuildTx(
txType uint8,
from, to common.Address,
nonce *big.Int,
value *big.Int,
gasLimit uint64,
extraGasLimit uint64,
gasPrice float64,
extraGasPrice float64,
tipCapGwei float64,
extraTipCapGwei float64,
data []byte,
network networks.Network,
) (*types.Transaction, error)
// Transaction Signing
SignTx(
wallet common.Address,
tx *types.Transaction,
network networks.Network,
) (signedAddr common.Address, signedTx *types.Transaction, err error)
// Transaction Broadcasting
BroadcastTx(tx *types.Transaction) (hash string, broadcasted bool, err BroadcastError)
BroadcastTxSync(tx *types.Transaction) (receipt *types.Receipt, err error)
// Transaction Monitoring
// MonitorTx is deprecated, use MonitorTxContext instead for better cancellation support.
MonitorTx(tx *types.Transaction, network networks.Network, txCheckInterval time.Duration) <-chan TxInfo
// MonitorTxContext is a context-aware version of MonitorTx that supports cancellation.
MonitorTxContext(ctx context.Context, tx *types.Transaction, network networks.Network, txCheckInterval time.Duration) <-chan TxInfo
// High-Level Transaction Execution
EnsureTx(
txType uint8,
from, to common.Address,
value *big.Int,
gasLimit uint64,
extraGasLimit uint64,
gasPrice float64,
extraGasPrice float64,
tipCapGwei float64,
extraTipCapGwei float64,
data []byte,
network networks.Network,
) (*types.Transaction, *types.Receipt, error)
EnsureTxWithHooks(
numRetries int,
sleepDuration time.Duration,
txCheckInterval time.Duration,
txType uint8,
from, to common.Address,
value *big.Int,
gasLimit uint64, extraGasLimit uint64,
gasPrice float64, extraGasPrice float64,
tipCapGwei float64, extraTipCapGwei float64,
maxGasPrice float64, maxTipCap float64,
data []byte,
network networks.Network,
beforeSignAndBroadcastHook Hook,
afterSignAndBroadcastHook Hook,
abis []abi.ABI,
gasEstimationFailedHook GasEstimationFailedHook,
) (*types.Transaction, *types.Receipt, error)
EnsureTxWithHooksContext(
ctx context.Context,
numRetries int,
sleepDuration time.Duration,
txCheckInterval time.Duration,
txType uint8,
from, to common.Address,
value *big.Int,
gasLimit uint64, extraGasLimit uint64,
gasPrice float64, extraGasPrice float64,
tipCapGwei float64, extraTipCapGwei float64,
maxGasPrice float64, maxTipCap float64,
data []byte,
network networks.Network,
beforeSignAndBroadcastHook Hook,
afterSignAndBroadcastHook Hook,
abis []abi.ABI,
gasEstimationFailedHook GasEstimationFailedHook,
simulationFailedHook SimulationFailedHook,
txMinedHook TxMinedHook,
) (*types.Transaction, *types.Receipt, error)
// Builder Pattern Entry Point
R() *TxRequest
}
Manager defines the interface for wallet management operations. This interface allows for easy mocking in tests and provides a stable API contract.
type ManagerDefaults ¶
type ManagerDefaults struct {
// Retry configuration
NumRetries int
SleepDuration time.Duration
TxCheckInterval time.Duration
SlowTxTimeout time.Duration // Time before considering a tx "slow" during monitoring
// Gas configuration
ExtraGasLimit uint64
ExtraGasPrice float64
ExtraTipCap float64
MaxGasPrice float64
MaxTipCap float64
// Gas bumping configuration (for slow tx retry)
GasPriceBumpFactor float64 // Multiplier for gas price when tx is slow (e.g., 1.2 = 20% increase)
TipCapBumpFactor float64 // Multiplier for tip cap when tx is slow (e.g., 1.1 = 10% increase)
// Default network (if not specified in request)
Network networks.Network
// Default transaction type
TxType uint8
}
ManagerDefaults holds default configuration values that are inherited by TxRequest
type NetworkBroadcasterFactory ¶
type NetworkBroadcasterFactory func(network networks.Network) (EthBroadcaster, error)
NetworkBroadcasterFactory creates an EthBroadcaster for a given network. This allows injecting mock broadcasters for testing.
type NetworkReaderFactory ¶
NetworkReaderFactory creates an EthReader for a given network. This allows injecting mock readers for testing.
type NetworkResolver ¶
NetworkResolver resolves a network by chain ID. This is used by recovery and broadcast methods that need to look up a network from a chain ID. The default implementation uses jarvis networks.GetNetworkByID.
type NetworkTxMonitorFactory ¶
NetworkTxMonitorFactory creates a TxMonitor for a given reader. This allows injecting mock monitors for testing.
type NonceState ¶
type NonceState struct {
// Wallet is the wallet address
Wallet common.Address
// ChainID is the network chain ID
ChainID uint64
// LocalPendingNonce is the highest nonce we've used locally (exclusive - next nonce to use is this value)
// If nil, no local state is tracked
LocalPendingNonce *uint64
// ReservedNonces are nonces that have been acquired but not yet confirmed
// This is used to prevent reuse after crash
ReservedNonces []uint64
// UpdatedAt is when this state was last updated
UpdatedAt time.Time
}
NonceState represents the persisted nonce state for a wallet on a network
type NonceStore ¶
type NonceStore interface {
// Get retrieves the nonce state for a wallet on a network.
// Returns nil, nil if no state exists (not an error).
Get(ctx context.Context, wallet common.Address, chainID uint64) (*NonceState, error)
// Save persists the nonce state. Creates or updates as needed.
Save(ctx context.Context, state *NonceState) error
// SavePendingNonce is a convenience method to update just the pending nonce.
// Implementations should use atomic updates if possible.
SavePendingNonce(ctx context.Context, wallet common.Address, chainID uint64, nonce uint64) error
// AddReservedNonce adds a nonce to the reserved set.
// This should be called when a nonce is acquired for a transaction.
AddReservedNonce(ctx context.Context, wallet common.Address, chainID uint64, nonce uint64) error
// RemoveReservedNonce removes a nonce from the reserved set.
// This should be called when a transaction is confirmed or abandoned.
RemoveReservedNonce(ctx context.Context, wallet common.Address, chainID uint64, nonce uint64) error
// ListAll returns all stored nonce states.
// Used during recovery to reconcile state.
ListAll(ctx context.Context) ([]*NonceState, error)
}
NonceStore provides persistence for nonce tracking state. Implement this interface to persist nonce state across process restarts.
Thread Safety: Implementations MUST be safe for concurrent use. The WalletManager will call these methods from multiple goroutines.
type PendingTx ¶
type PendingTx struct {
// Hash is the transaction hash
Hash common.Hash
// Wallet is the sender address
Wallet common.Address
// ChainID is the network chain ID
ChainID uint64
// Nonce is the transaction nonce
Nonce uint64
// Status is the current status of the transaction
Status PendingTxStatus
// Transaction is the full transaction object (optional, for re-monitoring)
Transaction *types.Transaction
// Receipt is the transaction receipt (set when mined/reverted)
Receipt *types.Receipt
// CreatedAt is when the transaction was first tracked
CreatedAt time.Time
// UpdatedAt is when the transaction was last updated
UpdatedAt time.Time
// Metadata allows storing arbitrary application-specific data
Metadata map[string]string
}
PendingTx represents a transaction that is being tracked for recovery
type PendingTxStatus ¶
type PendingTxStatus string
PendingTxStatus represents the status of a pending transaction
const ( // PendingTxStatusPending means the transaction is waiting to be mined PendingTxStatusPending PendingTxStatus = "pending" // PendingTxStatusBroadcasted means the transaction has been broadcast but status is unknown PendingTxStatusBroadcasted PendingTxStatus = "broadcasted" // PendingTxStatusMined means the transaction has been mined successfully PendingTxStatusMined PendingTxStatus = "mined" // PendingTxStatusReverted means the transaction was mined but reverted PendingTxStatusReverted PendingTxStatus = "reverted" // PendingTxStatusDropped means the transaction was dropped from the mempool PendingTxStatusDropped PendingTxStatus = "dropped" // PendingTxStatusReplaced means the transaction was replaced by another with same nonce PendingTxStatusReplaced PendingTxStatus = "replaced" )
type ReaderFactory ¶
ReaderFactory creates an EthReader for a given network. This allows injecting mock readers for testing.
type RecoveryHandler ¶
type RecoveryHandler struct {
// contains filtered or unexported fields
}
RecoveryHandler manages the recovery process for a WalletManager
func (*RecoveryHandler) Recover ¶
func (rh *RecoveryHandler) Recover(ctx context.Context, opts RecoveryOptions) (*RecoveryResult, error)
Recover performs recovery after a crash or restart. It reconciles nonce state with the chain and resumes monitoring pending transactions.
This method should be called once during application startup, before processing new transactions.
type RecoveryOptions ¶
type RecoveryOptions struct {
// ResumeMonitoring determines whether to start monitoring recovered pending transactions.
// If false, transactions are just marked with their current status.
// Default: true
ResumeMonitoring bool
// TxCheckInterval is the interval for checking transaction status during monitoring.
// Default: 5 seconds
TxCheckInterval time.Duration
// MaxConcurrentMonitors is the maximum number of transactions to monitor concurrently.
// Default: 10
MaxConcurrentMonitors int
// OnTxRecovered is called for each recovered transaction.
// Can be used to resume application-specific logic.
OnTxRecovered func(tx *PendingTx)
// OnTxMined is called when a recovered transaction is mined.
OnTxMined func(tx *PendingTx, receipt *types.Receipt)
// OnTxDropped is called when a recovered transaction is determined to be dropped.
OnTxDropped func(tx *PendingTx)
}
RecoveryOptions configures the recovery process
func DefaultRecoveryOptions ¶
func DefaultRecoveryOptions() RecoveryOptions
DefaultRecoveryOptions returns the default recovery options
type RecoveryResult ¶
type RecoveryResult struct {
// RecoveredTxs is the number of transactions that were recovered and re-monitored
RecoveredTxs int
// MinedTxs is the number of transactions that were found to be already mined
MinedTxs int
// DroppedTxs is the number of transactions that were found to be dropped
DroppedTxs int
// ReconciledNonces is the number of wallet/network pairs whose nonce state was reconciled
ReconciledNonces int
// Errors contains any non-fatal errors encountered during recovery
Errors []error
}
RecoveryResult contains the results of a recovery operation
type ResumeTransactionOptions ¶
type ResumeTransactionOptions struct {
// NumRetries is the maximum number of retries for gas bumping
// Default: 9
NumRetries int
// SleepDuration is the duration to sleep between retries
// Default: 5 seconds
SleepDuration time.Duration
// TxCheckInterval is the interval for checking transaction status
// Default: 5 seconds
TxCheckInterval time.Duration
// MaxGasPrice is the maximum gas price (in gwei) to use when bumping gas
// Default: 5x the original tx's gas price
MaxGasPrice float64
// MaxTipCap is the maximum tip cap (in gwei) to use when bumping gas
// Default: 5x the original tx's tip cap
MaxTipCap float64
// TxMinedHook is called when the transaction is mined
TxMinedHook TxMinedHook
}
ResumeTransactionOptions configures how a pending transaction should be resumed
func DefaultResumeTransactionOptions ¶
func DefaultResumeTransactionOptions() ResumeTransactionOptions
DefaultResumeTransactionOptions returns the default resume options
type RetryConfig ¶
type RetryConfig struct {
MaxAttempts int // Maximum number of retry attempts (renamed from NumRetries)
SleepDuration time.Duration // Sleep between retry attempts
TxCheckInterval time.Duration // Interval for checking tx status
SlowTxTimeout time.Duration // Time before considering a tx "slow" during monitoring
}
RetryConfig holds immutable retry/timing configuration.
type SimulationFailedHook ¶
type SimulationFailedHook func(tx *types.Transaction, revertData []byte, abiError *abi.Error, revertParams any, err error) (shouldRetry bool, retErr error)
SimulationFailedHook is called when eth_call simulation detects that the transaction would revert. This is called AFTER the transaction is built but BEFORE it is signed or broadcast.
This hook is distinct from GasEstimationFailedHook: gas estimation failure means the node could not estimate gas at all, while simulation failure means the tx was estimated successfully but eth_call showed it would revert at the current state.
Parameters:
- tx: the built (unsigned) transaction that would revert, always non-nil.
- revertData: raw revert bytes from the node, always non-nil (may be empty).
- abiError: the decoded ABI error if ABIs were provided and decoding succeeded, nil otherwise.
- revertParams: the decoded revert parameters if ABIs were provided and decoding succeeded, nil otherwise.
- err: the wrapped simulation error (always non-nil, wraps ErrSimulatedTxReverted).
Return values:
- shouldRetry=true: the execution will retry (counts against MaxAttempts).
- shouldRetry=false: the execution stops and returns the simulation error.
- retErr non-nil: the execution stops immediately with retErr, regardless of shouldRetry.
Note: each retry still counts against MaxAttempts even when shouldRetry is true. The nonce acquired for this attempt is preserved for the retry.
type SimulationRevertError ¶ added in v1.1.9
type SimulationRevertError struct {
Tx *types.Transaction // the built tx that would revert
RevertData []byte // raw revert bytes from the node
AbiError *abi.Error // decoded ABI error, nil if unavailable
RevertParams any // decoded parameters, nil if AbiError is nil
Err error // underlying error chain (preserves ErrSimulatedTxReverted, ErrEnsureTxOutOfRetries, etc.)
}
SimulationRevertError is a structured error returned when eth_call simulation detects that a transaction would revert. Callers can extract it with errors.As to access the built transaction, raw revert data, and ABI-decoded error details.
AbiError and RevertParams are populated only when ABIs are provided via SetAbis() and the revert data contains a decodable Solidity custom error.
func (*SimulationRevertError) Error ¶ added in v1.1.9
func (e *SimulationRevertError) Error() string
func (*SimulationRevertError) Unwrap ¶ added in v1.1.9
func (e *SimulationRevertError) Unwrap() error
type TxExecutionContext ¶
type TxExecutionContext struct {
Params TxParams
Retry RetryConfig
Gas GasBounds
Hooks TxHooks
State TxRetryState // The only mutable part
}
TxExecutionContext holds the state and parameters for transaction execution. It composes immutable configuration (Params, Retry, Gas, Hooks) with mutable retry state (State). Only State fields should be mutated during execution.
func NewTxExecutionContext ¶
func NewTxExecutionContext( params TxParams, retry RetryConfig, gas GasBounds, hooks TxHooks, initialGasPrice float64, initialTipCap float64, ) (*TxExecutionContext, error)
NewTxExecutionContext creates a new transaction execution context from structured sub-types. initialGasPrice and initialTipCap are the starting gas prices (gwei) for the first attempt.
func (*TxExecutionContext) AdjustGasPricesForSlowTx ¶
func (ctx *TxExecutionContext) AdjustGasPricesForSlowTx(tx *types.Transaction) bool
AdjustGasPricesForSlowTx is a deprecated alias for BumpGasForSlowTx.
func (*TxExecutionContext) BumpGasForSlowTx ¶
func (ctx *TxExecutionContext) BumpGasForSlowTx(tx *types.Transaction) bool
BumpGasForSlowTx adjusts gas prices when a transaction is slow. It reads from Gas (immutable bounds) and writes to State (mutable). Returns true if adjustment was applied, false if limits were reached.
func (*TxExecutionContext) IncrementRetryAndCheck ¶
func (ctx *TxExecutionContext) IncrementRetryAndCheck(errorMsg string) *TxExecutionResult
IncrementRetryAndCheck increments retry count and checks if we've exceeded max attempts. Returns a TxExecutionResult with ActionReturn if retries are exhausted, nil otherwise.
func (*TxExecutionContext) IncrementRetryCountAndCheck ¶
func (ctx *TxExecutionContext) IncrementRetryCountAndCheck(errorMsg string) *TxExecutionResult
IncrementRetryCountAndCheck is a deprecated alias for IncrementRetryAndCheck.
type TxExecutionResult ¶
type TxExecutionResult struct {
Transaction *types.Transaction
Receipt *types.Receipt
Action LoopAction
Error error
}
TxExecutionResult represents the outcome of a transaction execution step.
type TxHooks ¶
type TxHooks struct {
BeforeSignAndBroadcast Hook
AfterSignAndBroadcast Hook
GasEstimationFailed GasEstimationFailedHook
SimulationFailed SimulationFailedHook
TxMined TxMinedHook
ABIs []abi.ABI
}
TxHooks holds all callback hooks (set once at construction).
type TxInfo ¶
type TxInfo struct {
Status TxInfoStatus
Receipt *types.Receipt
}
TxInfo represents transaction information returned by the reader. This mirrors the essential fields from jarviscommon.TxInfo.
type TxInfoStatus ¶
type TxInfoStatus string
TxInfoStatus represents the status of a transaction in the monitoring/execution flow.
Statuses are categorized by origin:
From the external TxMonitor (node/mempool state):
- TxStatusMined, TxStatusReverted, TxStatusLost, TxStatusPending, TxStatusDone
Generated internally by walletarmy (NOT from the monitor):
- TxStatusSlow: fired when a broadcasted tx is not mined within SlowTxTimeout. This is a walletarmy-level timeout, not a status reported by any node or monitor.
- TxStatusCancelled: fired when the caller's context is cancelled.
const ( // TxStatusMined indicates the transaction was mined successfully. // Origin: mapped from TxMonitor "done" status. TxStatusMined TxInfoStatus = "mined" // TxStatusReverted indicates the transaction was mined but execution reverted. // Origin: mapped from TxMonitor "reverted" status. TxStatusReverted TxInfoStatus = "reverted" // TxStatusLost indicates the transaction was dropped from the mempool. // Origin: mapped from TxMonitor "lost" status. TxStatusLost TxInfoStatus = "lost" // TxStatusSlow indicates the transaction has not been mined within SlowTxTimeout // after the monitor has checked the node at least once. // Origin: generated internally by MonitorTxContext. The slow timer is deferred // until the first non-terminal monitor event, then fires after SlowTxTimeout. // This is NOT a status from the TxMonitor — it is a walletarmy-level timeout signal. TxStatusSlow TxInfoStatus = "slow" // TxStatusCancelled indicates the monitoring was cancelled via context. // Origin: generated internally by MonitorTxContext when ctx.Done() fires. TxStatusCancelled TxInfoStatus = "cancelled" // TxStatusPending indicates the transaction is still pending TxStatusPending TxInfoStatus = "pending" // TxStatusDone is the raw status from jarvis monitor indicating success TxStatusDone TxInfoStatus = "done" )
type TxMinedHook ¶
type TxMinedHook func(tx *types.Transaction, receipt *types.Receipt) error
TxMinedHook is called when a transaction is mined (either successfully or reverted).
Parameters:
- tx: the mined transaction, always non-nil.
- receipt: the transaction receipt, always non-nil. Check receipt.Status (types.ReceiptStatusSuccessful or types.ReceiptStatusFailed) to determine whether the transaction succeeded or reverted.
Return a non-nil error to propagate it to the EnsureTx caller. The transaction and receipt are still returned alongside the error.
type TxMonitor ¶
type TxMonitor interface {
// MakeWaitChannelWithInterval creates a channel that receives status updates
MakeWaitChannelWithInterval(txHash string, interval time.Duration) <-chan TxMonitorStatus
}
TxMonitor defines the minimal interface for monitoring transaction status.
func DefaultTxMonitorFactory ¶
DefaultTxMonitorFactory is the default factory that creates jarvis tx monitors. If the reader is a readerAdapter (wrapping a jarvis reader), it uses the underlying reader. Otherwise, it returns nil (custom implementations should provide their own monitor factory).
func NewTxMonitorAdapter ¶
NewTxMonitorAdapter creates a TxMonitor from a jarvis monitor
type TxMonitorFactory ¶
TxMonitorFactory creates a TxMonitor for a given network. This allows injecting mock monitors for testing.
type TxMonitorStatus ¶
TxMonitorStatus represents the status of a monitored transaction.
type TxParams ¶
type TxParams struct {
TxType uint8
From common.Address
To common.Address
Value *big.Int
Data []byte
Network networks.Network
// SkipSimulation, when true, skips the eth_call simulation that normally runs
// after BuildTx succeeds but before signing and broadcasting. This allows
// forcing a transaction through even when the simulation indicates it would
// revert. The caller should typically also provide a manual gas limit
// (via TxRequest.SetGasLimit or the GasLimit field in TxRetryState), since
// gas estimation may fail for the same reason the simulation would revert.
SkipSimulation bool
}
TxParams holds immutable transaction parameters (set once, never mutated).
type TxRequest ¶
type TxRequest struct {
// contains filtered or unexported fields
}
TxRequest represents a transaction request with builder pattern
func (*TxRequest) Execute ¶
Execute executes the transaction request using a background context. For production use, prefer ExecuteContext to allow cancellation.
func (*TxRequest) ExecuteContext ¶
ExecuteContext executes the transaction request with context support. The context allows the caller to cancel long-running retry loops.
func (*TxRequest) SetAfterSignAndBroadcastHook ¶
SetAfterSignAndBroadcastHook sets the hook to be called after signing and broadcasting
func (*TxRequest) SetBeforeSignAndBroadcastHook ¶
SetBeforeSignAndBroadcastHook sets the hook to be called before signing and broadcasting
func (*TxRequest) SetExtraGasLimit ¶
SetExtraGasLimit sets the extra gas limit
func (*TxRequest) SetExtraGasPrice ¶
SetExtraGasPrice sets the extra gas price
func (*TxRequest) SetExtraTipCapGwei ¶
SetExtraTipCapGwei sets the extra tip cap in gwei
func (*TxRequest) SetGasEstimationFailedHook ¶
func (r *TxRequest) SetGasEstimationFailedHook(hook GasEstimationFailedHook) *TxRequest
SetGasEstimationFailedHook sets the hook to be called when gas estimation fails
func (*TxRequest) SetGasLimit ¶
SetGasLimit sets the gas limit
func (*TxRequest) SetGasPrice ¶
SetGasPrice sets the gas price
func (*TxRequest) SetIdempotencyKey ¶
SetIdempotencyKey sets a unique key to prevent duplicate transaction submissions. If the same key is used again, the previous transaction result will be returned instead of submitting a new transaction. Requires an IdempotencyStore to be configured on the WalletManager.
func (*TxRequest) SetMaxGasPrice ¶
SetMaxGasPrice sets the maximum gas price limit
func (*TxRequest) SetMaxTipCap ¶
SetMaxTipCap sets the maximum tip cap limit
func (*TxRequest) SetNetwork ¶
SetNetwork sets the network
func (*TxRequest) SetNumRetries ¶
SetNumRetries sets the number of retries
func (*TxRequest) SetSimulationFailedHook ¶
func (r *TxRequest) SetSimulationFailedHook(hook SimulationFailedHook) *TxRequest
SetSimulationFailedHook sets the hook to be called when eth_call simulation fails. This hook is called when the transaction would revert, allowing the caller to decide whether to retry or handle the error.
func (*TxRequest) SetSkipSimulation ¶
SetSkipSimulation skips the eth_call simulation that runs before signing and broadcasting. When set to true, the transaction will be signed and broadcast even if it would revert. This is useful when you know the simulation will fail but want to force the transaction through. Note: you likely also need to set a manual gas limit via SetGasLimit, since gas estimation may fail for the same reason the simulation would revert.
func (*TxRequest) SetSleepDuration ¶
SetSleepDuration sets the sleep duration
func (*TxRequest) SetTipCapGwei ¶
SetTipCapGwei sets the tip cap in gwei
func (*TxRequest) SetTxCheckInterval ¶
SetTxCheckInterval sets the transaction check interval
func (*TxRequest) SetTxMinedHook ¶
func (r *TxRequest) SetTxMinedHook(hook TxMinedHook) *TxRequest
SetTxMinedHook sets the hook to be called when a transaction is mined. This hook is called for both successful and reverted transactions.
type TxRetryState ¶
type TxRetryState struct {
AttemptCount int // Number of retry attempts so far
GasPrice float64 // Current gas price for next attempt (gwei)
TipCap float64 // Current tip cap for next attempt (gwei)
GasLimit uint64 // May be overridden by hooks
Nonce *big.Int // nil = acquire new, non-nil = reuse this nonce
OldTxs map[string]*types.Transaction
ResumeWith *types.Transaction // If non-nil, skip build/broadcast and go straight to monitoring
}
TxRetryState holds all mutable state that changes during the retry loop. This is the ONLY part of TxExecutionContext that should be mutated during execution.
type TxStore ¶
type TxStore interface {
// Save persists a pending transaction. Creates or updates based on hash.
Save(ctx context.Context, tx *PendingTx) error
// Get retrieves a pending transaction by hash.
// Returns nil, nil if not found (not an error).
Get(ctx context.Context, hash common.Hash) (*PendingTx, error)
// GetByNonce retrieves pending transactions by wallet, chainID, and nonce.
// There may be multiple if a nonce was reused (replacement tx).
GetByNonce(ctx context.Context, wallet common.Address, chainID uint64, nonce uint64) ([]*PendingTx, error)
// ListPending returns all transactions with pending/broadcasted status for a wallet on a network.
ListPending(ctx context.Context, wallet common.Address, chainID uint64) ([]*PendingTx, error)
// ListAllPending returns all pending/broadcasted transactions across all wallets/networks.
// Used during recovery.
ListAllPending(ctx context.Context) ([]*PendingTx, error)
// UpdateStatus updates the status of a transaction and optionally sets the receipt.
UpdateStatus(ctx context.Context, hash common.Hash, status PendingTxStatus, receipt *types.Receipt) error
// Delete removes a transaction record.
Delete(ctx context.Context, hash common.Hash) error
// DeleteOlderThan removes transactions older than the given duration.
// Used for cleanup of old completed transactions.
DeleteOlderThan(ctx context.Context, age time.Duration) (int, error)
}
TxStore provides persistence for in-flight transaction tracking. Implement this interface to track and recover pending transactions across restarts.
Thread Safety: Implementations MUST be safe for concurrent use.
type WalletManager ¶
type WalletManager struct {
// contains filtered or unexported fields
}
WalletManager manages
- multiple wallets and their informations in its life time. It basically gives next nonce to do transaction for specific wallet and specific network. It queries the node to check the nonce in lazy maner, it also takes mining txs into account.
- multiple networks gas price. The gas price will be queried lazily prior to txs and will be stored as cache for a while
- txs in the context manager's life time
- circuit breakers for RPC node failover
- idempotency keys for preventing duplicate transactions
- default configuration that TxRequest inherits
func NewWalletManager ¶
func NewWalletManager(opts ...WalletManagerOption) *WalletManager
NewWalletManager creates a new WalletManager with optional configuration
func (*WalletManager) Account ¶
func (wm *WalletManager) Account(wallet common.Address) *account.Account
Account returns the account for the given wallet address
func (*WalletManager) Analyzer ¶
func (wm *WalletManager) Analyzer(network networks.Network) (*txanalyzer.TxAnalyzer, error)
Analyzer returns the transaction analyzer for the given network. Returns an error if the network could not be initialized or if the circuit breaker is open.
func (*WalletManager) BroadcastTx ¶
func (wm *WalletManager) BroadcastTx( tx *types.Transaction, ) (hash string, broadcasted bool, err BroadcastError)
func (*WalletManager) BroadcastTxSync ¶
func (wm *WalletManager) BroadcastTxSync( tx *types.Transaction, ) (receipt *types.Receipt, err error)
func (*WalletManager) Broadcaster ¶
func (wm *WalletManager) Broadcaster(network networks.Network) (EthBroadcaster, error)
Broadcaster returns the broadcaster for the given network. Returns an error if the network could not be initialized or if the circuit breaker is open.
func (*WalletManager) BuildTx ¶
func (wm *WalletManager) BuildTx( txType uint8, from, to common.Address, nonce *big.Int, value *big.Int, gasLimit uint64, extraGasLimit uint64, gasPrice float64, extraGasPrice float64, tipCapGwei float64, extraTipCapGwei float64, data []byte, network networks.Network, ) (tx *types.Transaction, err error)
func (*WalletManager) Defaults ¶
func (wm *WalletManager) Defaults() ManagerDefaults
Defaults returns the current default configuration. All fields are guaranteed to be non-zero (resolved at construction time).
func (*WalletManager) EnsureTx ¶
func (wm *WalletManager) EnsureTx( txType uint8, from, to common.Address, value *big.Int, gasLimit uint64, extraGasLimit uint64, gasPrice float64, extraGasPrice float64, tipCapGwei float64, extraTipCapGwei float64, data []byte, network networks.Network, ) (tx *types.Transaction, receipt *types.Receipt, err error)
func (*WalletManager) EnsureTxWithHooks ¶
func (wm *WalletManager) EnsureTxWithHooks( numRetries int, sleepDuration time.Duration, txCheckInterval time.Duration, txType uint8, from, to common.Address, value *big.Int, gasLimit uint64, extraGasLimit uint64, gasPrice float64, extraGasPrice float64, tipCapGwei float64, extraTipCapGwei float64, maxGasPrice float64, maxTipCap float64, data []byte, network networks.Network, beforeSignAndBroadcastHook Hook, afterSignAndBroadcastHook Hook, abis []abi.ABI, gasEstimationFailedHook GasEstimationFailedHook, ) (tx *types.Transaction, receipt *types.Receipt, err error)
EnsureTxWithHooks ensures the tx is broadcasted and mined, it will retry until the tx is mined. This is a convenience wrapper that uses context.Background(). For production use, prefer EnsureTxWithHooksContext to allow cancellation.
func (*WalletManager) EnsureTxWithHooksContext ¶
func (wm *WalletManager) EnsureTxWithHooksContext( ctx context.Context, numRetries int, sleepDuration time.Duration, txCheckInterval time.Duration, txType uint8, from, to common.Address, value *big.Int, gasLimit uint64, extraGasLimit uint64, gasPrice float64, extraGasPrice float64, tipCapGwei float64, extraTipCapGwei float64, maxGasPrice float64, maxTipCap float64, data []byte, network networks.Network, beforeSignAndBroadcastHook Hook, afterSignAndBroadcastHook Hook, abis []abi.ABI, gasEstimationFailedHook GasEstimationFailedHook, simulationFailedHook SimulationFailedHook, txMinedHook TxMinedHook, ) (tx *types.Transaction, receipt *types.Receipt, err error)
EnsureTxWithHooksContext ensures the tx is broadcasted and mined, it will retry until the tx is mined. The context allows the caller to cancel the operation at any point.
It returns nil and error if:
- the tx couldn't be built
- the tx couldn't be broadcasted and get mined after numRetries retries
- the context is cancelled
It always returns the tx that was mined, either if the tx was successful or reverted.
Possible errors:
- ErrEstimateGasFailed
- ErrAcquireNonceFailed
- ErrGetGasSettingFailed
- ErrEnsureTxOutOfRetries
- ErrGasPriceLimitReached
- context.Canceled or context.DeadlineExceeded
If the caller wants to know the reason of the error, they can use errors.Is to check if the error is one of the above ¶
After building the tx and before signing and broadcasting, the caller can provide a function hook to receive the tx and building error, if the hook returns an error, the process will be stopped and the error will be returned. If the hook returns nil, the process will continue even if the tx building failed, in this case, it will retry with the same data up to numRetries times and the hook will be called again.
After signing and broadcasting successfully, the caller can provide a function hook to receive the signed tx and broadcast error, if the hook returns an error, the process will be stopped and the error will be returned. If the hook returns nil, the process will continue to monitor the tx to see if the tx is mined or not. If the tx is not mined, the process will retry either with a new nonce or with higher gas price and tip cap to ensure the tx is mined. Hooks will be called again in the retry process.
func (*WalletManager) GasSetting ¶
func (wm *WalletManager) GasSetting(network networks.Network) (*GasInfo, error)
GasSetting returns cached gas settings for the network, refreshing if stale.
func (*WalletManager) GetCircuitBreakerStats ¶
func (wm *WalletManager) GetCircuitBreakerStats(network networks.Network) circuitbreaker.Stats
GetCircuitBreakerStats returns the circuit breaker statistics for a network
func (*WalletManager) IdempotencyStore ¶
func (wm *WalletManager) IdempotencyStore() idempotency.Store
IdempotencyStore returns the configured idempotency store, or nil if not configured
func (*WalletManager) MonitorTx
deprecated
func (wm *WalletManager) MonitorTx(tx *types.Transaction, network networks.Network, txCheckInterval time.Duration) <-chan TxInfo
MonitorTx non-blocking way to monitor the tx status, it returns a channel that will be closed when the tx monitoring is done the channel is supposed to receive the following values:
- "mined" if the tx is mined
- "slow" if the tx is too slow to be mined (so receiver might want to retry with higher gas price)
- other strings if the tx failed and the reason is returned by the node or other debugging error message that the node can return
Deprecated: Use MonitorTxContext instead for better cancellation support.
func (*WalletManager) MonitorTxContext ¶
func (wm *WalletManager) MonitorTxContext(ctx context.Context, tx *types.Transaction, network networks.Network, txCheckInterval time.Duration) <-chan TxInfo
MonitorTxContext is a context-aware version of MonitorTx that supports cancellation. When the context is cancelled, the monitoring goroutine will exit and close the channel.
Status mapping:
- The external TxMonitor returns raw statuses ("done", "reverted", "lost"). These are mapped to TxStatusMined, TxStatusReverted, TxStatusLost respectively.
- TxStatusSlow is NOT from the monitor. It is generated internally when the monitor does not return a terminal status within SlowTxTimeout.
- TxStatusCancelled is generated when the caller's context is cancelled.
- Any unrecognized status from the monitor is treated as "still pending" and the slow timeout is allowed to fire.
Slow timer behavior:
The slow timer is NOT started immediately. It is deferred until the monitor delivers its first non-terminal event (e.g., "pending", unknown status, or channel close). This ensures the monitor has checked the node at least once before judging the transaction as slow. Without this, a SlowTxTimeout shorter than txCheckInterval would always fire before the first check, producing false "slow" signals.
func (*WalletManager) NonceStore ¶
func (wm *WalletManager) NonceStore() NonceStore
NonceStore returns the configured nonce store, or nil if not configured
func (*WalletManager) R ¶
func (wm *WalletManager) R() *TxRequest
R creates a new transaction request (similar to go-resty's R() method). The request inherits default configuration from the WalletManager.
func (*WalletManager) Reader ¶
func (wm *WalletManager) Reader(network networks.Network) (EthReader, error)
Reader returns the reader for the given network. Returns an error if the network could not be initialized or if the circuit breaker is open.
func (*WalletManager) RecordNetworkFailure ¶
func (wm *WalletManager) RecordNetworkFailure(network networks.Network)
RecordNetworkFailure records a failed network operation for the circuit breaker
func (*WalletManager) RecordNetworkSuccess ¶
func (wm *WalletManager) RecordNetworkSuccess(network networks.Network)
RecordNetworkSuccess records a successful network operation for the circuit breaker
func (*WalletManager) Recover ¶
func (wm *WalletManager) Recover(ctx context.Context) (*RecoveryResult, error)
Recover performs recovery after a crash or restart. It reconciles nonce state with the chain and resumes monitoring pending transactions.
This should be called once during application startup before processing new transactions. If no persistence stores are configured, this is a no-op.
func (*WalletManager) RecoverWithOptions ¶
func (wm *WalletManager) RecoverWithOptions(ctx context.Context, opts RecoveryOptions) (*RecoveryResult, error)
RecoverWithOptions performs recovery with custom options.
func (*WalletManager) ReleaseNonce ¶
func (wm *WalletManager) ReleaseNonce(wallet common.Address, network networks.Network, nonce uint64)
ReleaseNonce releases a previously acquired nonce that was not used. This allows the nonce to be reused by subsequent transactions. Note: This only affects local tracking. If the transaction was already broadcast to some nodes, calling this may cause issues.
func (*WalletManager) ResetCircuitBreaker ¶
func (wm *WalletManager) ResetCircuitBreaker(network networks.Network)
ResetCircuitBreaker resets the circuit breaker for a network
func (*WalletManager) ResumePendingTransaction ¶
func (wm *WalletManager) ResumePendingTransaction( ctx context.Context, pendingTx *PendingTx, opts ResumeTransactionOptions, ) (*types.Transaction, *types.Receipt, error)
ResumePendingTransaction resumes the EnsureTx flow for a previously broadcast transaction. This is used during crash recovery to continue monitoring and retry logic (including gas bumping) for transactions that were pending when the application crashed.
The pendingTx.Transaction field must be non-nil as it contains the original transaction data.
This method enters the same execution flow as EnsureTxWithHooksContext, starting from the monitoring phase. If the transaction is slow, it will bump gas and retry. If it's lost, it will retry with a new nonce.
func (*WalletManager) SetAccount ¶
func (wm *WalletManager) SetAccount(acc *account.Account)
SetAccount registers an account with the wallet manager
func (*WalletManager) SetDefaults ¶
func (wm *WalletManager) SetDefaults(defaults ManagerDefaults)
SetDefaults updates the default configuration. Zero-value fields are filled with package-level constants automatically.
func (*WalletManager) SignTx ¶
func (wm *WalletManager) SignTx( wallet common.Address, tx *types.Transaction, network networks.Network, ) (signedAddr common.Address, signedTx *types.Transaction, err error)
func (*WalletManager) TxStore ¶
func (wm *WalletManager) TxStore() TxStore
TxStore returns the configured transaction store, or nil if not configured
func (*WalletManager) UnlockAccount ¶
UnlockAccount unlocks an account from the jarvis wallet store and registers it
type WalletManagerOption ¶
type WalletManagerOption func(*WalletManager)
WalletManagerOption is a function that configures a WalletManager
func WithBroadcasterFactory ¶
func WithBroadcasterFactory(factory NetworkBroadcasterFactory) WalletManagerOption
WithBroadcasterFactory sets a custom broadcaster factory for testing or alternative implementations
func WithDefaultExtraGasLimit ¶
func WithDefaultExtraGasLimit(extraGasLimit uint64) WalletManagerOption
WithDefaultExtraGasLimit sets the default extra gas limit added to estimates
func WithDefaultExtraGasPrice ¶
func WithDefaultExtraGasPrice(extraGasPrice float64) WalletManagerOption
WithDefaultExtraGasPrice sets the default extra gas price added to suggestions
func WithDefaultExtraTipCap ¶
func WithDefaultExtraTipCap(extraTipCap float64) WalletManagerOption
WithDefaultExtraTipCap sets the default extra tip cap added to suggestions
func WithDefaultGasPriceBumpFactor ¶
func WithDefaultGasPriceBumpFactor(factor float64) WalletManagerOption
WithDefaultGasPriceBumpFactor sets the gas price multiplier when tx is slow. For example, 1.2 means 20% increase.
func WithDefaultGasPriceIncreasePercent
deprecated
func WithDefaultGasPriceIncreasePercent(percent float64) WalletManagerOption
Deprecated: Use WithDefaultGasPriceBumpFactor instead.
func WithDefaultIdempotencyStore ¶
func WithDefaultIdempotencyStore(ttl time.Duration) WalletManagerOption
WithDefaultIdempotencyStore sets up an in-memory idempotency store with the given TTL
func WithDefaultMaxGasPrice ¶
func WithDefaultMaxGasPrice(maxGasPrice float64) WalletManagerOption
WithDefaultMaxGasPrice sets the default maximum gas price protection limit
func WithDefaultMaxTipCap ¶
func WithDefaultMaxTipCap(maxTipCap float64) WalletManagerOption
WithDefaultMaxTipCap sets the default maximum tip cap protection limit
func WithDefaultNetwork ¶
func WithDefaultNetwork(network networks.Network) WalletManagerOption
WithDefaultNetwork sets the default network for transactions
func WithDefaultNumRetries ¶
func WithDefaultNumRetries(numRetries int) WalletManagerOption
WithDefaultNumRetries sets the default number of retries for transactions
func WithDefaultSleepDuration ¶
func WithDefaultSleepDuration(duration time.Duration) WalletManagerOption
WithDefaultSleepDuration sets the default sleep duration between retries
func WithDefaultSlowTxTimeout ¶
func WithDefaultSlowTxTimeout(timeout time.Duration) WalletManagerOption
WithDefaultSlowTxTimeout sets the timeout before considering a transaction "slow"
func WithDefaultTipCapBumpFactor ¶
func WithDefaultTipCapBumpFactor(factor float64) WalletManagerOption
WithDefaultTipCapBumpFactor sets the tip cap multiplier when tx is slow. For example, 1.1 means 10% increase.
func WithDefaultTipCapIncreasePercent
deprecated
func WithDefaultTipCapIncreasePercent(percent float64) WalletManagerOption
Deprecated: Use WithDefaultTipCapBumpFactor instead.
func WithDefaultTxCheckInterval ¶
func WithDefaultTxCheckInterval(interval time.Duration) WalletManagerOption
WithDefaultTxCheckInterval sets the default transaction check interval
func WithDefaultTxType ¶
func WithDefaultTxType(txType uint8) WalletManagerOption
WithDefaultTxType sets the default transaction type
func WithDefaults ¶
func WithDefaults(defaults ManagerDefaults) WalletManagerOption
WithDefaults sets all default configuration at once
func WithIdempotencyStore ¶
func WithIdempotencyStore(store idempotency.Store) WalletManagerOption
WithIdempotencyStore sets a custom idempotency store
func WithNetworkResolver ¶
func WithNetworkResolver(resolver NetworkResolver) WalletManagerOption
WithNetworkResolver sets a custom network resolver for looking up networks by chain ID. This is required when using custom networks that are not built into jarvis (e.g., private chains, custom testnets).
The resolver is used by:
- Crash recovery (to resume pending transactions)
- BroadcastTx and BroadcastTxSync (to determine which network to broadcast to)
If not set, defaults to jarvis networks.GetNetworkByID which supports standard EVM networks (Ethereum, Polygon, Arbitrum, Optimism, etc.).
Example for custom networks:
wm := walletarmy.NewWalletManager(
walletarmy.WithNetworkResolver(func(chainID uint64) (networks.Network, error) {
switch chainID {
case 12345:
return myCustomNetwork, nil
default:
return networks.GetNetworkByID(chainID) // fallback to jarvis
}
}),
)
func WithNonceStore ¶
func WithNonceStore(store NonceStore) WalletManagerOption
WithNonceStore sets a custom nonce store for persisting nonce state across restarts. This enables crash recovery for nonce tracking.
func WithReaderFactory ¶
func WithReaderFactory(factory NetworkReaderFactory) WalletManagerOption
WithReaderFactory sets a custom reader factory for testing or alternative implementations
func WithTxMonitorFactory ¶
func WithTxMonitorFactory(factory NetworkTxMonitorFactory) WalletManagerOption
WithTxMonitorFactory sets a custom tx monitor factory for testing or alternative implementations
func WithTxStore ¶
func WithTxStore(store TxStore) WalletManagerOption
WithTxStore sets a custom transaction store for tracking in-flight transactions. This enables crash recovery for pending transactions.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
fund_distribution
command
|
|
|
racing
command
racing runs two independent WalletManager instances in parallel using the same ephemeral wallet on the same chain.
|
racing runs two independent WalletManager instances in parallel using the same ephemeral wallet on the same chain. |
|
Package idempotency provides an idempotency key store for preventing duplicate transaction submissions.
|
Package idempotency provides an idempotency key store for preventing duplicate transaction submissions. |
|
internal
|
|
|
circuitbreaker
Package circuitbreaker provides a simple circuit breaker implementation for protecting RPC node calls from cascading failures.
|
Package circuitbreaker provides a simple circuit breaker implementation for protecting RPC node calls from cascading failures. |
|
nonce
Package nonce provides thread-safe nonce tracking for Ethereum wallets.
|
Package nonce provides thread-safe nonce tracking for Ethereum wallets. |
|
Package testutil provides testing utilities for walletarmy.
|
Package testutil provides testing utilities for walletarmy. |