Skip to content

Commit

Permalink
wip: parsing tx details framework
Browse files Browse the repository at this point in the history
  • Loading branch information
aalu1418 committed Apr 12, 2024
1 parent 70d2ca6 commit 3f0203e
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 3 deletions.
81 changes: 81 additions & 0 deletions pkg/monitoring/source_txdetails.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package monitoring

import (
"context"
"fmt"

"github.com/gagliardetto/solana-go/rpc"
commonMonitoring "github.com/smartcontractkit/chainlink-common/pkg/monitoring"

"github.com/smartcontractkit/chainlink-solana/pkg/monitoring/config"
"github.com/smartcontractkit/chainlink-solana/pkg/monitoring/types"
)

func NewTxDetailsSourceFactory(client ChainReader, log commonMonitoring.Logger) commonMonitoring.SourceFactory {
return &txDetailsSourceFactory{client, log}
}

type txDetailsSourceFactory struct {
client ChainReader
log commonMonitoring.Logger
}

func (f *txDetailsSourceFactory) NewSource(cfg commonMonitoring.Params) (commonMonitoring.Source, error) {
solanaFeedConfig, ok := cfg.FeedConfig.(config.SolanaFeedConfig)
if !ok {
return nil, fmt.Errorf("expected feedConfig to be of type config.SolanaFeedConfig not %T", cfg.FeedConfig)
}

return &txDetailsSource{
client: f.client,
sigSource: &txResultsSource{
client: f.client,
log: f.log,
feedConfig: solanaFeedConfig,
},
}, nil
}

func (f *txDetailsSourceFactory) GetType() string {
return types.TxDetailsType
}

type txDetailsSource struct {
client ChainReader
sigSource *txResultsSource // reuse underlying logic for getting signatures
}

func (s *txDetailsSource) Fetch(ctx context.Context) (interface{}, error) {
_, sigs, err := s.sigSource.fetch(ctx)
if err != nil {
return types.TxDetails{}, err
}
if len(sigs) == 0 {
return types.TxDetails{}, nil
}

for _, sig := range sigs {
if sig == nil {
continue // skip for nil signatures
}

// TODO: async?
tx, err := s.client.GetTransaction(ctx, sig.Signature, &rpc.GetTransactionOpts{})
if err != nil {
return types.TxDetails{}, err
}
if tx == nil {
return types.TxDetails{}, fmt.Errorf("GetTransaction returned nil")
}

// TODO: parse transaction

// TODO: filter signatures/transactions based on known operator/sender

// TODO: parse observations from remaining transactions

// TODO: add to proper list for averaging
}

return types.TxDetails{}, nil
}
13 changes: 10 additions & 3 deletions pkg/monitoring/source_txresults.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,14 @@ type txResultsSource struct {
latestSigMu sync.Mutex
}

// Fetch is the externally called method that returns the specific TxResults output
func (t *txResultsSource) Fetch(ctx context.Context) (interface{}, error) {
out, _, err := t.fetch(ctx)
return out, err
}

// fetch is the internal method that returns data from the GetSignaturesForAddress RPC call
func (t *txResultsSource) fetch(ctx context.Context) (commonMonitoring.TxResults, []*rpc.TransactionSignature, error) {
txSigsPageSize := 100
txSigs, err := t.client.GetSignaturesForAddressWithOpts(
ctx,
Expand All @@ -72,10 +79,10 @@ func (t *txResultsSource) Fetch(ctx context.Context) (interface{}, error) {
},
)
if err != nil {
return nil, fmt.Errorf("failed to fetch transactions for state account: %w", err)
return commonMonitoring.TxResults{}, nil, fmt.Errorf("failed to fetch transactions for state account: %w", err)
}
if len(txSigs) == 0 {
return commonMonitoring.TxResults{NumSucceeded: 0, NumFailed: 0}, nil
return commonMonitoring.TxResults{NumSucceeded: 0, NumFailed: 0}, nil, nil
}
var numSucceeded, numFailed uint64 = 0, 0
for _, txSig := range txSigs {
Expand All @@ -90,5 +97,5 @@ func (t *txResultsSource) Fetch(ctx context.Context) (interface{}, error) {
defer t.latestSigMu.Unlock()
t.latestSig = txSigs[0].Signature
}()
return commonMonitoring.TxResults{NumSucceeded: numSucceeded, NumFailed: numFailed}, nil
return commonMonitoring.TxResults{NumSucceeded: numSucceeded, NumFailed: numFailed}, txSigs, nil
}
60 changes: 60 additions & 0 deletions pkg/monitoring/types/txdetails.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package types

import (
"fmt"

"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
)

var (
TxDetailsType = "txdetails"
)

// TxDetails expands on TxResults and contains additional detail on a set of tx signatures specific to solana
type TxDetails struct {
count int // total signatures processed

// TODO: PerOperator categorizes TxResults based on sender/operator
// PerOperator map[string]commonMonitoring.TxResults

// observation counts within each report
obsLatest int // number of observations in latest included report/tx
obsAvg int // average number of observations across all seen txs/reports from operators
obsSuccessAvg int // average number of observations included in successful reports
obsFailedAvg int // average number of observations included in failed reports

// TODO: implement - parse fee using shared logic from fee/computebudget.go
// feeAvg
// feeSuccessAvg
// feeFailedAvg
}

type ParsedTx struct {
Err interface{}
Fee uint64

Sender solana.PublicKey

// report information
ObservationCount int
}

func ParseTx(txResult *rpc.GetTransactionResult) (ParsedTx, error) {
out := ParsedTx{}
if txResult == nil {
return out, fmt.Errorf("txResult is nil")
}
if txResult.Meta == nil {
return out, fmt.Errorf("txResult.Meta is nil")
}

out.Err = txResult.Meta.Err
out.Fee = txResult.Meta.Fee

// determine sender

// find OCR2 transmit instruction

return out, nil
}

0 comments on commit 3f0203e

Please sign in to comment.