Documentation ¶
Index ¶
- Constants
- type Accounts
- type Blocks
- type BroadcasterConfig
- type BroadcasterListenerConfig
- type BroadcasterTransactionsConfig
- type ChainReceipt
- type Client
- type ConfirmerConfig
- type ConfirmerDatabaseConfig
- type ConfirmerTransactionsConfig
- type Events
- type ForwarderManager
- type ID
- type KeyStore
- type QueryerFunc
- type ReaperConfig
- type ReaperTransactionsConfig
- type ReceiptPlus
- type ResenderConfig
- type ResenderTransactionsConfig
- type Sequence
- type TransactionManagerConfig
- type TransactionManagerTransactionsConfig
- type Transactions
- type TransmitCheckerSpec
- type TransmitCheckerType
- type Tx
- func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetChecker() (TransmitCheckerSpec[ADDR], error)
- func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetError() error
- func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetID() string
- func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetLogger(lgr logger.Logger) logger.Logger
- func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetMeta() (*TxMeta[ADDR, TX_HASH], error)
- type TxAttempt
- type TxAttemptBuilder
- type TxAttemptState
- type TxHistoryReaper
- type TxMeta
- type TxRequest
- type TxState
- type TxStore
- type TxStrategy
- type TxmClient
- type UnstartedTxQueuePruner
Constants ¶
const ( TxAttemptInProgress = TxAttemptState("in_progress") // TODO: Make name chain-agnostic (https://smartcontract-it.atlassian.net/browse/BCI-981) TxAttemptInsufficientEth = TxAttemptState("insufficient_eth") TxAttemptBroadcast = TxAttemptState("broadcast") )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Accounts ¶ added in v2.1.0
type Accounts[ADDR types.Hashable, SEQ Sequence] interface { BalanceAt(ctx context.Context, accountAddress ADDR, blockNumber *big.Int) (*big.Int, error) TokenBalance(ctx context.Context, accountAddress ADDR, tokenAddress ADDR) (*big.Int, error) SequenceAt(ctx context.Context, accountAddress ADDR, blockNumber *big.Int) (SEQ, error) }
type BroadcasterConfig ¶ added in v2.1.0
type BroadcasterListenerConfig ¶ added in v2.3.0
type BroadcasterTransactionsConfig ¶ added in v2.3.0
type BroadcasterTransactionsConfig interface {
MaxInFlight() uint32
}
type ChainReceipt ¶ added in v2.2.0
type Client ¶ added in v2.1.0
type Client[ CHAINID ID, SEQ Sequence, ADDR types.Hashable, BLOCK any, BLOCKHASH types.Hashable, TX any, TXHASH types.Hashable, TXRECEIPT any, EVENT any, EVENTOPS any, ] interface { // ChainID stored for quick access ConfiguredChainID() CHAINID // ChainID RPC call ChainID() (CHAINID, error) Accounts[ADDR, SEQ] Transactions[TX, TXHASH, TXRECEIPT] Events[EVENT, EVENTOPS] Blocks[BLOCK, BLOCKHASH] CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error }
A generic client interface for communication with the RPC node Every native chain must implement independently
type ConfirmerConfig ¶ added in v2.1.0
type ConfirmerDatabaseConfig ¶ added in v2.3.0
type ConfirmerTransactionsConfig ¶ added in v2.3.0
type ForwarderManager ¶
type ID ¶ added in v2.1.0
ID represents the base type, for any chain's ID. It should be convertible to a string, that can uniquely identify this chain
type KeyStore ¶ added in v2.1.0
type KeyStore[ ADDR types.Hashable, CHAIN_ID ID, SEQ Sequence, ] interface { CheckEnabled(address ADDR, chainID CHAIN_ID) error NextSequence(address ADDR, chainID CHAIN_ID, qopts ...pg.QOpt) (SEQ, error) EnabledAddressesForChain(chainId CHAIN_ID) ([]ADDR, error) IncrementNextSequence(address ADDR, chainID CHAIN_ID, currentSequence SEQ, qopts ...pg.QOpt) error SubscribeToKeyChanges() (ch chan struct{}, unsub func()) }
KeyStore encompasses the subset of keystore used by txmgr
type QueryerFunc ¶
type ReaperConfig ¶ added in v2.1.0
type ReaperConfig interface { // gas config FinalityDepth() uint32 }
ReaperConfig is the config subset used by the reaper
type ReaperTransactionsConfig ¶ added in v2.3.0
type ReceiptPlus ¶
type ReceiptPlus[R any] struct { ID uuid.UUID `db:"pipeline_run_id"` Receipt R `db:"receipt"` FailOnRevert bool `db:"fail_on_revert"` }
R is the raw unparsed transaction receipt
type ResenderConfig ¶ added in v2.1.0
type ResenderConfig interface {
RPCDefaultBatchSize() uint32
}
type ResenderTransactionsConfig ¶ added in v2.3.0
type Sequence ¶ added in v2.1.0
type Sequence interface { fmt.Stringer Int64() int64 // needed for numeric sequence confirmation - to be removed with confirmation logic generalization: https://smartcontract-it.atlassian.net/browse/BCI-860 }
Sequence represents the base type, for any chain's sequence object. It should be convertible to a string
type TransactionManagerConfig ¶
type TransactionManagerConfig interface { BroadcasterConfig ConfirmerConfig ResenderConfig ReaperConfig SequenceAutoSync() bool }
type TransactionManagerTransactionsConfig ¶ added in v2.3.0
type TransactionManagerTransactionsConfig interface { BroadcasterTransactionsConfig ConfirmerTransactionsConfig ResenderTransactionsConfig ReaperTransactionsConfig ForwardersEnabled() bool MaxQueued() uint64 }
type Transactions ¶ added in v2.1.0
type Transactions[TX any, TXHASH types.Hashable, TXRECEIPT any] interface { SendTransaction(ctx context.Context, tx *TX) error SimulateTransaction(ctx context.Context, tx *TX) error TransactionByHash(ctx context.Context, txHash TXHASH) (*TX, error) TransactionReceipt(ctx context.Context, txHash TXHASH) (*TXRECEIPT, error) }
type TransmitCheckerSpec ¶ added in v2.1.0
type TransmitCheckerSpec[ADDR types.Hashable] struct { // CheckerType is the type of check that should be performed. Empty indicates no check. CheckerType TransmitCheckerType `json:",omitempty"` // VRFCoordinatorAddress is the address of the VRF coordinator that should be used to perform // VRF transmit checks. This should be set iff CheckerType is TransmitCheckerTypeVRFV2. VRFCoordinatorAddress *ADDR `json:",omitempty"` // VRFRequestBlockNumber is the block number in which the provided VRF request has been made. // This should be set iff CheckerType is TransmitCheckerTypeVRFV2. VRFRequestBlockNumber *big.Int `json:",omitempty"` }
TransmitCheckerSpec defines the check that should be performed before a transaction is submitted on chain.
type TransmitCheckerType ¶ added in v2.1.0
type TransmitCheckerType string
TransmitCheckerType describes the type of check that should be performed before a transaction is executed on-chain.
type Tx ¶ added in v2.2.0
type Tx[ CHAIN_ID ID, ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, SEQ Sequence, FEE feetypes.Fee, ] struct { ID int64 Sequence *SEQ FromAddress ADDR ToAddress ADDR EncodedPayload []byte Value big.Int // FeeLimit on the Tx is always the conceptual gas limit, which is not // necessarily the same as the on-chain encoded value (i.e. Optimism) FeeLimit uint32 Error null.String // BroadcastAt is updated every time an attempt for this eth_tx is re-sent // In almost all cases it will be within a second or so of the actual send time. BroadcastAt *time.Time // InitialBroadcastAt is recorded once, the first ever time this eth_tx is sent InitialBroadcastAt *time.Time CreatedAt time.Time State TxState TxAttempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] `json:"-"` // Marshalled TxMeta // Used for additional context around transactions which you want to log // at send time. Meta *datatypes.JSON Subject uuid.NullUUID ChainID CHAIN_ID PipelineTaskRunID uuid.NullUUID MinConfirmations clnull.Uint32 // TransmitChecker defines the check that should be performed before a transaction is submitted on // chain. TransmitChecker *datatypes.JSON }
func (*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetChecker ¶ added in v2.2.0
func (e *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetChecker() (TransmitCheckerSpec[ADDR], error)
GetChecker returns an Tx's transmit checker spec in struct form, unmarshalling it from JSON first.
func (*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) GetID ¶ added in v2.2.0
GetID allows Tx to be used as jsonapi.MarshalIdentifier
type TxAttempt ¶ added in v2.2.0
type TxAttempt[ CHAIN_ID ID, ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, SEQ Sequence, FEE feetypes.Fee, ] struct { ID int64 TxID int64 Tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] TxFee FEE // ChainSpecificFeeLimit on the TxAttempt is always the same as the on-chain encoded value for fee limit ChainSpecificFeeLimit uint32 SignedRawTx []byte Hash TX_HASH CreatedAt time.Time BroadcastBeforeBlockNum *int64 State TxAttemptState Receipts []ChainReceipt[TX_HASH, BLOCK_HASH] `json:"-"` TxType int }
type TxAttemptBuilder ¶
type TxAttemptBuilder[ CHAIN_ID ID, HEAD types.Head[BLOCK_HASH], ADDR types.Hashable, TX_HASH, BLOCK_HASH types.Hashable, SEQ Sequence, FEE feetypes.Fee, ] interface { // interfaces for running the underlying estimator services.ServiceCtx types.HeadTrackable[HEAD, BLOCK_HASH] // NewTxAttempt builds a transaction using the configured transaction type and fee estimator (new estimation) NewTxAttempt(ctx context.Context, tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, opts ...feetypes.Opt) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], fee FEE, feeLimit uint32, retryable bool, err error) // NewTxAttemptWithType builds a transaction using the configured fee estimator (new estimation) + passed in tx type NewTxAttemptWithType(ctx context.Context, tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, txType int, opts ...feetypes.Opt) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], fee FEE, feeLimit uint32, retryable bool, err error) // NewBumpTxAttempt builds a transaction using the configured fee estimator (bumping) + tx type from previous attempt // this should only be used after an initial attempt has been broadcast and the underlying gas estimator only needs to bump the fee NewBumpTxAttempt(ctx context.Context, tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], previousAttempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], priorAttempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], bumpedFee FEE, bumpedFeeLimit uint32, retryable bool, err error) // NewCustomTxAttempt builds a transaction using the passed in fee + tx type NewCustomTxAttempt(tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], fee FEE, gasLimit uint32, txType int, lggr logger.Logger) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], retryable bool, err error) // NewEmptyTxAttempt is used in ForceRebroadcast to create a signed tx with zero value sent to the zero address NewEmptyTxAttempt(seq SEQ, feeLimit uint32, fee FEE, fromAddress ADDR) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) }
TxAttemptBuilder takes the base unsigned transaction + optional parameters (tx type, gas parameters) and returns a signed TxAttempt it is able to estimate fees and sign transactions
type TxAttemptState ¶
type TxAttemptState string
type TxHistoryReaper ¶ added in v2.2.0
type TxMeta ¶ added in v2.1.0
type TxMeta[ADDR types.Hashable, TX_HASH types.Hashable] struct { JobID *int32 `json:"JobID,omitempty"` // Pipeline fields FailOnRevert null.Bool `json:"FailOnRevert,omitempty"` // VRF-only fields RequestID *TX_HASH `json:"RequestID,omitempty"` RequestTxHash *TX_HASH `json:"RequestTxHash,omitempty"` // Batch variants of the above RequestIDs []TX_HASH `json:"RequestIDs,omitempty"` RequestTxHashes []TX_HASH `json:"RequestTxHashes,omitempty"` // Used for the VRFv2 - max link this tx will bill // should it get bumped MaxLink *string `json:"MaxLink,omitempty"` // Used for the VRFv2 - the subscription ID of the // requester of the VRF. SubID *uint64 `json:"SubId,omitempty"` // Used for keepers UpkeepID *string `json:"UpkeepID,omitempty"` // Used only for forwarded txs, tracks the original destination address. // When this is set, it indicates tx is forwarded through To address. FwdrDestAddress *ADDR `json:"ForwarderDestAddress,omitempty"` // MessageIDs is used by CCIP for tx to executed messages correlation in logs MessageIDs []string `json:"MessageIDs,omitempty"` // SeqNumbers is used by CCIP for tx to committed sequence numbers correlation in logs SeqNumbers []uint64 `json:"SeqNumbers,omitempty"` }
TxMeta contains fields of the transaction metadata Not all fields are guaranteed to be present
type TxRequest ¶ added in v2.3.0
type TxRequest[ADDR types.Hashable, TX_HASH types.Hashable] struct { FromAddress ADDR ToAddress ADDR EncodedPayload []byte Value big.Int FeeLimit uint32 Meta *TxMeta[ADDR, TX_HASH] ForwarderAddress ADDR // Pipeline variables - if you aren't calling this from ethtx task within // the pipeline, you don't need these variables MinConfirmations clnull.Uint32 PipelineTaskRunID *uuid.UUID Strategy TxStrategy // Checker defines the check that should be run before a transaction is submitted on chain. Checker TransmitCheckerSpec[ADDR] }
type TxStore ¶ added in v2.1.0
type TxStore[ ADDR types.Hashable, CHAIN_ID ID, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R ChainReceipt[TX_HASH, BLOCK_HASH], SEQ Sequence, FEE feetypes.Fee, ] interface { UnstartedTxQueuePruner TxHistoryReaper[CHAIN_ID] CheckTxQueueCapacity(fromAddress ADDR, maxQueuedTransactions uint64, chainID CHAIN_ID, qopts ...pg.QOpt) (err error) CountUnconfirmedTransactions(fromAddress ADDR, chainID CHAIN_ID, qopts ...pg.QOpt) (count uint32, err error) CountUnstartedTransactions(fromAddress ADDR, chainID CHAIN_ID, qopts ...pg.QOpt) (count uint32, err error) CreateTransaction(txRequest TxRequest[ADDR, TX_HASH], chainID CHAIN_ID, qopts ...pg.QOpt) (tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) DeleteInProgressAttempt(ctx context.Context, attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error FindReceiptsPendingConfirmation(ctx context.Context, blockNum int64, chainID CHAIN_ID) (receiptsPlus []ReceiptPlus[R], err error) FindTxsRequiringGasBump(ctx context.Context, address ADDR, blockNum, gasBumpThreshold, depth int64, chainID CHAIN_ID) (etxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindTxsRequiringResubmissionDueToInsufficientFunds(address ADDR, chainID CHAIN_ID, qopts ...pg.QOpt) (etxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindTxAttemptsConfirmedMissingReceipt(chainID CHAIN_ID) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindTxAttemptsRequiringReceiptFetch(chainID CHAIN_ID) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindTxAttemptsRequiringResend(olderThan time.Time, maxInFlightTransactions uint32, chainID CHAIN_ID, address ADDR) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindTxWithSequence(fromAddress ADDR, seq SEQ) (etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindNextUnstartedTransactionFromAddress(etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], fromAddress ADDR, chainID CHAIN_ID, qopts ...pg.QOpt) error FindTransactionsConfirmedInBlockRange(highBlockNumber, lowBlockNumber int64, chainID CHAIN_ID) (etxs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) GetTxInProgress(fromAddress ADDR, qopts ...pg.QOpt) (etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) GetInProgressTxAttempts(ctx context.Context, address ADDR, chainID CHAIN_ID) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) HasInProgressTransaction(account ADDR, chainID CHAIN_ID, qopts ...pg.QOpt) (exists bool, err error) LoadTxAttempts(etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], qopts ...pg.QOpt) error MarkAllConfirmedMissingReceipt(chainID CHAIN_ID) (err error) MarkOldTxesMissingReceiptAsErrored(blockNum int64, finalityDepth uint32, chainID CHAIN_ID, qopts ...pg.QOpt) error PreloadTxes(attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], qopts ...pg.QOpt) error SaveConfirmedMissingReceiptAttempt(ctx context.Context, timeout time.Duration, attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], broadcastAt time.Time) error SaveFetchedReceipts(receipts []R, chainID CHAIN_ID) (err error) SaveInProgressAttempt(attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error SaveInsufficientFundsAttempt(timeout time.Duration, attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], broadcastAt time.Time) error SaveReplacementInProgressAttempt(oldAttempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], replacementAttempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], qopts ...pg.QOpt) error SaveSentAttempt(timeout time.Duration, attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], broadcastAt time.Time) error SetBroadcastBeforeBlockNum(blockNum int64, chainID CHAIN_ID) error UpdateBroadcastAts(now time.Time, etxIDs []int64) error UpdateKeyNextSequence(newNextSequence, currentNextSequence SEQ, address ADDR, chainID CHAIN_ID, qopts ...pg.QOpt) error UpdateTxAttemptInProgressToBroadcast(etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], NewAttemptState TxAttemptState, incrNextSequenceCallback QueryerFunc, qopts ...pg.QOpt) error UpdateTxsUnconfirmed(ids []int64) error UpdateTxUnstartedToInProgress(etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt *TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], qopts ...pg.QOpt) error UpdateTxFatalError(etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], qopts ...pg.QOpt) error UpdateTxForRebroadcast(etx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], etxAttempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error Close() Abandon(id CHAIN_ID, addr ADDR) error }
type TxStrategy ¶
type TxStrategy interface { // Subject will be saved txes.subject if not null Subject() uuid.NullUUID // PruneQueue is called after tx insertion // It accepts the service responsible for deleting // unstarted txs and deletion options PruneQueue(pruneService UnstartedTxQueuePruner, qopt pg.QOpt) (n int64, err error) }
TxStrategy controls how txes are queued and sent
type TxmClient ¶ added in v2.2.0
type TxmClient[ CHAIN_ID ID, ADDR types.Hashable, TX_HASH types.Hashable, BLOCK_HASH types.Hashable, R ChainReceipt[TX_HASH, BLOCK_HASH], SEQ Sequence, FEE feetypes.Fee, ] interface { ConfiguredChainID() CHAIN_ID BatchSendTransactions( ctx context.Context, store TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE], attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], bathSize int, lggr logger.Logger, ) ([]clienttypes.SendTxReturnCode, []error, error) SendTransactionReturnCode( ctx context.Context, tx Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], lggr logger.Logger, ) (clienttypes.SendTxReturnCode, error) PendingSequenceAt(ctx context.Context, addr ADDR) (SEQ, error) SequenceAt(ctx context.Context, addr ADDR, blockNum *big.Int) (SEQ, error) BatchGetReceipts( ctx context.Context, attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], ) (txReceipt []R, txErr []error, err error) SendEmptyTransaction( ctx context.Context, newTxAttempt func(seq SEQ, feeLimit uint32, fee FEE, fromAddress ADDR) (attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error), seq SEQ, gasLimit uint32, fee FEE, fromAddress ADDR, ) (txhash string, err error) CallContract( ctx context.Context, attempt TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], blockNumber *big.Int, ) (rpcErr fmt.Stringer, extractErr error) }