diff --git a/eth/filters/api.go b/eth/filters/api.go index 9f9209aea7e9..a3ed00f33b3d 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -299,15 +299,27 @@ func (api *FilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subsc return rpcSub, nil } -// TransactionReceiptsFilter defines criteria for transaction receipts subscription. -// If TransactionHashes is nil or empty, receipts for all transactions included in new blocks will be delivered. -// Otherwise, only receipts for the specified transactions will be delivered. -type TransactionReceiptsFilter struct { - TransactionHashes []common.Hash `json:"transactionHashes,omitempty"` +// TransactionReceiptsQuery defines criteria for transaction receipts subscription. +// Same as ethereum.TransactionReceiptsQuery but with UnmarshalJSON() method. +type TransactionReceiptsQuery ethereum.TransactionReceiptsQuery + +// UnmarshalJSON sets *args fields with given data. +func (args *TransactionReceiptsQuery) UnmarshalJSON(data []byte) error { + type input struct { + TransactionHashes []common.Hash `json:"transactionHashes"` + } + + var raw input + if err := json.Unmarshal(data, &raw); err != nil { + return err + } + + args.TransactionHashes = raw.TransactionHashes + return nil } // TransactionReceipts creates a subscription that fires transaction receipts when transactions are included in blocks. -func (api *FilterAPI) TransactionReceipts(ctx context.Context, filter *TransactionReceiptsFilter) (*rpc.Subscription, error) { +func (api *FilterAPI) TransactionReceipts(ctx context.Context, filter *TransactionReceiptsQuery) (*rpc.Subscription, error) { notifier, supported := rpc.NotifierFromContext(ctx) if !supported { return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 1195929f7d2e..8b26f5b3cad1 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -350,6 +350,15 @@ func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (* return r, err } +// SubscribeTransactionReceipts subscribes to notifications about transaction receipts. +func (ec *Client) SubscribeTransactionReceipts(ctx context.Context, q *ethereum.TransactionReceiptsQuery, ch chan<- []*types.Receipt) (ethereum.Subscription, error) { + sub, err := ec.c.EthSubscribe(ctx, ch, "transactionReceipts", q) + if err != nil { + return nil, err + } + return sub, nil +} + // SyncProgress retrieves the current progress of the sync algorithm. If there's // no sync currently running, it returns nil. func (ec *Client) SyncProgress(ctx context.Context) (*ethereum.SyncProgress, error) { diff --git a/interfaces.go b/interfaces.go index be5b97085155..2828af1cc9a5 100644 --- a/interfaces.go +++ b/interfaces.go @@ -62,6 +62,13 @@ type ChainReader interface { SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (Subscription, error) } +// TransactionReceiptsQuery defines criteria for transaction receipts subscription. +// If TransactionHashes is empty, receipts for all transactions included in new blocks will be delivered. +// Otherwise, only receipts for the specified transactions will be delivered. +type TransactionReceiptsQuery struct { + TransactionHashes []common.Hash +} + // TransactionReader provides access to past transactions and their receipts. // Implementations may impose arbitrary restrictions on the transactions and receipts that // can be retrieved. Historic transactions may not be available. @@ -81,6 +88,11 @@ type TransactionReader interface { // transaction may not be included in the current canonical chain even if a receipt // exists. TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) + // SubscribeTransactionReceipts subscribes to notifications about transaction receipts. + // The receipts are delivered in batches when transactions are included in blocks. + // If q is nil or has empty TransactionHashes, all receipts from new blocks will be delivered. + // Otherwise, only receipts for the specified transaction hashes will be delivered. + SubscribeTransactionReceipts(ctx context.Context, q *TransactionReceiptsQuery, ch chan<- []*types.Receipt) (Subscription, error) } // ChainStateReader wraps access to the state trie of the canonical blockchain. Note that