Skip to content

Commit

Permalink
lint
Browse files Browse the repository at this point in the history
  • Loading branch information
ilija42 committed Feb 9, 2025
1 parent 2eb51fe commit cea06d3
Showing 1 changed file with 140 additions and 92 deletions.
232 changes: 140 additions & 92 deletions pkg/solana/chainreader/chain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,98 +202,6 @@ func (s *ContractReaderService) GetLatestValue(ctx context.Context, readIdentifi
return nil
}

func (s *ContractReaderService) handleGetTokenPricesGetLatestValue(ctx context.Context, params any, values readValues, returnVal any) error {
val := reflect.ValueOf(params)
if val.Kind() == reflect.Ptr {
// Dereference so we can access fields
val = val.Elem()
}

// Make sure we actually have a struct
if val.Kind() != reflect.Struct {
return fmt.Errorf("expected struct, got: %s", val.Kind())
}

// Attempt to get the "Tokens" field
field := val.FieldByName("Tokens")
if !field.IsValid() {
return fmt.Errorf("no field named 'Tokens' found")
}

// Convert that field’s interface value into the correct type
tokens, ok := field.Interface().(*[][32]uint8)
if !ok {
return fmt.Errorf("'Tokens' field is not *[][32]uint8")
}
programAddress, err := solana.PublicKeyFromBase58(values.address)
if err != nil {
return fmt.Errorf("%w: failed to parse program address: %q for contract %q", types.ErrInvalidConfig, values.address, values.contract)
}

var pdaAddresses []solana.PublicKey
for _, token := range *tokens {
tokenAddr := solana.PublicKeyFromBytes(token[:])
if tokenAddr.IsOnCurve() && !tokenAddr.IsZero() {
return fmt.Errorf("bad token address: %v for contract: %q read: %q", tokenAddr, values.contract, values.multiRead[0])
}

pdaAddress, _, err := solana.FindProgramAddress([][]byte{[]byte("fee_billing_token_config"), tokenAddr.Bytes()}, programAddress)
if err != nil {
return fmt.Errorf("%w: failed find program address for PDA: %w", types.ErrInvalidConfig, err)
}

pdaAddresses = append(pdaAddresses, pdaAddress)
}

data, err := s.client.GetMultipleAccountData(ctx, pdaAddresses...)
if err != nil {
return err
}

type TimestampedUnixBig struct {
Value *big.Int `json:"value"`
Timestamp uint32 `json:"timestamp"`
}

returnSliceVal := reflect.ValueOf(returnVal)
if returnSliceVal.Kind() == reflect.Ptr {
returnSliceVal = returnSliceVal.Elem()
if returnSliceVal.Kind() == reflect.Ptr {
returnSliceVal = returnSliceVal.Elem()
}
if returnSliceVal.Kind() != reflect.Slice {
return fmt.Errorf("expected slice, got: %s", returnSliceVal.Kind())
}
}

elemType := returnSliceVal.Type().Elem()
newElem := reflect.New(elemType).Elem()

for _, d := range data {
wrapper := fee_quoter.BillingTokenConfigWrapper{}
err = wrapper.UnmarshalWithDecoder(bin.NewBorshDecoder(d))
if err != nil {
return err
}
v := big.NewInt(0)
v.SetBytes(wrapper.Config.UsdPerToken.Value[:])

valueField := newElem.FieldByName("Value")
if !valueField.IsValid() {
return errors.New("struct does not have a field named 'Value'")
}
valueField.Set(reflect.ValueOf(v))

timestampField := newElem.FieldByName("Timestamp")
if !timestampField.IsValid() {
return errors.New("struct does not have a field named 'Timestamp'")
}
timestampField.Set(reflect.ValueOf(uint32(wrapper.Config.UsdPerToken.Timestamp)))
returnSliceVal.Set(reflect.Append(returnSliceVal, newElem))
}
return nil
}

// BatchGetLatestValues implements the types.ContractReader interface.
func (s *ContractReaderService) BatchGetLatestValues(ctx context.Context, request types.BatchGetLatestValuesRequest) (types.BatchGetLatestValuesResult, error) {
idxLookup := make(map[types.BoundContract][]int)
Expand Down Expand Up @@ -600,3 +508,143 @@ func applyIndexedFieldTuple(lookup map[string]uint64, subKeys [4][]string, conf
subKeys[idx] = strings.Split(conf.OnChainPath, ".")
}
}

func (s *ContractReaderService) handleGetTokenPricesGetLatestValue(
ctx context.Context,
params any,
values readValues,
returnVal any,
) error {
pdaAddresses, err := s.getPDAsForGetTokenPrices(params, values)
if err != nil {
return err
}

data, err := s.client.GetMultipleAccountData(ctx, pdaAddresses...)
if err != nil {
return fmt.Errorf(
"for contract %q read %q: failed to get multiple account data: %w",
values.contract, values.multiRead[0], err,
)
}

// -------------- Fill out the returnVal slice with data --------------
type TimestampedUnixBig struct {
Value *big.Int `json:"value"`
Timestamp uint32 `json:"timestamp"`
}

// can't typecast returnVal so we have to use reflection here

// Ensure `returnVal` is a pointer to a slice we can populate.
returnSliceVal := reflect.ValueOf(returnVal)
if returnSliceVal.Kind() == reflect.Ptr {
returnSliceVal = returnSliceVal.Elem()
if returnSliceVal.Kind() == reflect.Ptr {
returnSliceVal = returnSliceVal.Elem()
}
}
if returnSliceVal.Kind() != reflect.Slice {
return fmt.Errorf(
"for contract %q read %q: expected `returnVal` to be a slice, got %s",
values.contract, values.multiRead[0], returnSliceVal.Kind(),
)
}

elemType := returnSliceVal.Type().Elem()
for _, d := range data {
var wrapper fee_quoter.BillingTokenConfigWrapper
if err = wrapper.UnmarshalWithDecoder(bin.NewBorshDecoder(d)); err != nil {
return fmt.Errorf(
"for contract %q read %q: failed to unmarshal account data: %w",
values.contract, values.multiRead[0], err,
)
}

newElem := reflect.New(elemType).Elem()

valueField := newElem.FieldByName("Value")
if !valueField.IsValid() {
return fmt.Errorf(
"for contract %q read %q: struct type missing `Value` field",
values.contract, values.multiRead[0],
)
}
valueField.Set(reflect.ValueOf(big.NewInt(0).SetBytes(wrapper.Config.UsdPerToken.Value[:])))

timestampField := newElem.FieldByName("Timestamp")
if !timestampField.IsValid() {
return fmt.Errorf(
"for contract %q read %q: struct type missing `Timestamp` field",
values.contract, values.multiRead[0],
)
}
timestampField.Set(reflect.ValueOf(uint32(wrapper.Config.UsdPerToken.Timestamp)))

returnSliceVal.Set(reflect.Append(returnSliceVal, newElem))
}

return nil
}

func (s *ContractReaderService) getPDAsForGetTokenPrices(params any, values readValues) ([]solana.PublicKey, error) {
val := reflect.ValueOf(params)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
if val.Kind() != reflect.Struct {
return nil, fmt.Errorf(
"for contract %q read %q: expected `params` to be a struct, got %s",
values.contract, values.multiRead[0], val.Kind(),
)
}

field := val.FieldByName("Tokens")
if !field.IsValid() {
return nil, fmt.Errorf(
"for contract %q read %q: no field named 'Tokens' found in params",
values.contract, values.multiRead[0],
)
}

tokens, ok := field.Interface().(*[][32]uint8)
if !ok {
return nil, fmt.Errorf(
"for contract %q read %q: 'Tokens' field is not of type *[][32]uint8",
values.contract, values.multiRead[0],
)
}

programAddress, err := solana.PublicKeyFromBase58(values.address)
if err != nil {
return nil, fmt.Errorf(
"for contract %q read %q: %w (could not parse program address %q)",
values.contract, values.multiRead[0], types.ErrInvalidConfig, values.address,
)
}

// Build the PDA addresses for all tokens.
var pdaAddresses []solana.PublicKey
for _, token := range *tokens {
tokenAddr := solana.PublicKeyFromBytes(token[:])
if tokenAddr.IsOnCurve() && !tokenAddr.IsZero() {
return nil, fmt.Errorf(
"for contract %q read %q: invalid token address %v (on-curve or zero)",
values.contract, values.multiRead[0], tokenAddr,
)
}

pdaAddress, _, err := solana.FindProgramAddress(
[][]byte{[]byte("fee_billing_token_config"), tokenAddr.Bytes()},
programAddress,
)
if err != nil {
return nil, fmt.Errorf(
"for contract %q read %q: %w (failed to find PDA for token %v)",
values.contract, values.multiRead[0], types.ErrInvalidConfig, tokenAddr,
)
}
pdaAddresses = append(pdaAddresses, pdaAddress)
}
return pdaAddresses, nil
}

0 comments on commit cea06d3

Please sign in to comment.