Skip to content

Commit

Permalink
add QueryKey helper functions (#613)
Browse files Browse the repository at this point in the history
* add QueryKey helper functions
  • Loading branch information
EasterTheBunny authored Nov 25, 2024
1 parent 97ceadb commit 59c388b
Show file tree
Hide file tree
Showing 2 changed files with 364 additions and 0 deletions.
164 changes: 164 additions & 0 deletions pkg/types/query/key_filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package query

import (
"time"

"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
)

// IndexedSequencesKeyFilter creates a KeyFilter that filters logs for the provided sequence property values at the
// specified property name. Sequence value filters are 'OR'ed together. A sequence read name is the value that
// identifies the sequence type. The signature value name is the sequence property to apply the filter to and the
// sequence values are the individual values to search for in the provided property.
func IndexedSequencesKeyFilter(
readName string,
comparatorName string,
values []string,
confidence primitives.ConfidenceLevel,
) KeyFilter {
return KeyFilter{
Key: readName,
Expressions: []Expression{
filtersForValues(comparatorName, values),
Confidence(confidence),
},
}
}

// IndexedSequencesByBlockRangeKeyFilter creates a KeyFilter that filters sequences for the provided property values at
// the specified property name. Value filters are 'OR'ed together and results are limited by provided cursor range. A
// read name is the value that identifies the sequence type. The signature property name is the sequence property to
// apply the filter to and the sequence values are the individual values to search for in the provided property.
func IndexedSequencesByBlockRangeKeyFilter(
readName string,
start, end string,
comparatorName string,
values []string,
) KeyFilter {
return KeyFilter{
Key: readName,
Expressions: []Expression{
filtersForValues(comparatorName, values),
Block(start, primitives.Gte),
Block(end, primitives.Lte),
},
}
}

// IndexedSequencesValueGreaterThanKeyFilter creates a KeyFilter that filters sequences for the provided property value
// and name at or above the specified confidence level. A sequence read name is the value that identifies the sequence
// type. The property name is the sequence property to apply the filter to and the value is the individual value to
// search for in the provided property.
func IndexedSequencesValueGreaterThanKeyFilter(
readName string,
comparatorName, value string,
confidence primitives.ConfidenceLevel,
) KeyFilter {
return KeyFilter{
Key: readName,
Expressions: []Expression{
valueComparator(comparatorName, value, primitives.Gte),
Confidence(confidence),
},
}
}

// IndexedSequencesValueRangeKeyFilter creates a KeyFilter that filters logs on the provided sequence property between
// the provided min and max, endpoints inclusive. A sequence read name is the value that identifies the sequence type.
func IndexedSequencesValueRangeKeyFilter(
readName string,
comparatorName string,
min, max string,
confidence primitives.ConfidenceLevel,
) KeyFilter {
return KeyFilter{
Key: readName,
Expressions: []Expression{
valueComparator(comparatorName, min, primitives.Gte),
valueComparator(comparatorName, max, primitives.Lte),
Confidence(confidence),
},
}
}

// IndexedSequencesByTxHashKeyFilter creates a KeyFilter that filters logs for the provided transaction hash. A sequence
// read name is the value that identifies the sequence type.
func IndexedSequencesByTxHashKeyFilter(
readName, txHash string,
) KeyFilter {
return KeyFilter{
Key: readName,
Expressions: []Expression{
TxHash(txHash),
},
}
}

// SequencesByBlockRangeKeyFilter creates a KeyFilter that filters sequences for the provided block range, endpoints inclusive.
func SequencesByBlockRangeKeyFilter(
readName string,
start, end string,
) KeyFilter {
return KeyFilter{
Key: readName,
Expressions: []Expression{
Block(start, primitives.Gte),
Block(end, primitives.Lte),
},
}
}

// SequencesCreatedAfterKeyFilter creates a KeyFilter that filters sequences for after but not equal to the provided time value.
func SequencesCreatedAfterKeyFilter(
readName string,
timestamp time.Time,
confidence primitives.ConfidenceLevel,
) KeyFilter {
return KeyFilter{
Key: readName,
Expressions: []Expression{
Timestamp(uint64(timestamp.Unix()), primitives.Gt),
Confidence(confidence),
},
}
}

// IndexedSequencesCreatedAfterKeyFilter creates a KeyFilter that filters sequences for the provided property and values
// created after the provided time value. Sequence property values filters are 'OR'ed. A sequence read name is the value
// that identifies the sequence type.
func IndexedSequencesCreatedAfterKeyFilter(
readName string,
comparatorName string,
values []string,
timestamp time.Time,
confidence primitives.ConfidenceLevel,
) KeyFilter {
return KeyFilter{
Key: readName,
Expressions: []Expression{
filtersForValues(comparatorName, values),
Timestamp(uint64(timestamp.Unix()), primitives.Gt),
Confidence(confidence),
},
}
}

func valueComparator(comparatorName, value string, op primitives.ComparisonOperator) Expression {
return Comparator(comparatorName, primitives.ValueComparator{
Value: value,
Operator: op,
})
}

func filtersForValues(comparatorName string, values []string) Expression {
valueFilters := BoolExpression{
Expressions: make([]Expression, len(values)),
BoolOperator: OR,
}

for idx, value := range values {
valueFilters.Expressions[idx] = valueComparator(comparatorName, value, primitives.Eq)
}

return Expression{BoolExpression: valueFilters}
}
200 changes: 200 additions & 0 deletions pkg/types/query/key_filter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package query_test

import (
"testing"
"time"

"github.com/stretchr/testify/require"

"github.com/smartcontractkit/chainlink-common/pkg/types/query"
"github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives"
)

func TestIndexedSequencesKeyFilter(t *testing.T) {
t.Parallel()

filter := query.IndexedSequencesKeyFilter("readName", "property", []string{"value1", "value2"}, primitives.Finalized)
expected := query.KeyFilter{
Key: "readName",
Expressions: []query.Expression{
{BoolExpression: query.BoolExpression{
Expressions: []query.Expression{
{
Primitive: &primitives.Comparator{
Name: "property",
ValueComparators: []primitives.ValueComparator{{Value: "value1", Operator: primitives.Eq}},
},
},
{
Primitive: &primitives.Comparator{
Name: "property",
ValueComparators: []primitives.ValueComparator{{Value: "value2", Operator: primitives.Eq}},
},
},
},
BoolOperator: query.OR,
}},
{Primitive: &primitives.Confidence{ConfidenceLevel: primitives.Finalized}},
},
}

require.Equal(t, expected, filter)
}

func TestIndexedSequencesByBlockRangeKeyFilter(t *testing.T) {
t.Parallel()

filter := query.IndexedSequencesByBlockRangeKeyFilter("readName", "start", "end", "property", []string{"value1", "value2"})
expected := query.KeyFilter{
Key: "readName",
Expressions: []query.Expression{
{BoolExpression: query.BoolExpression{
Expressions: []query.Expression{
{
Primitive: &primitives.Comparator{
Name: "property",
ValueComparators: []primitives.ValueComparator{{Value: "value1", Operator: primitives.Eq}},
},
},
{
Primitive: &primitives.Comparator{
Name: "property",
ValueComparators: []primitives.ValueComparator{{Value: "value2", Operator: primitives.Eq}},
},
},
},
BoolOperator: query.OR,
}},
{Primitive: &primitives.Block{Block: "start", Operator: primitives.Gte}},
{Primitive: &primitives.Block{Block: "end", Operator: primitives.Lte}},
},
}

require.Equal(t, expected, filter)
}

func TestIndexedSequencesValueGreaterThanKeyFilter(t *testing.T) {
t.Parallel()

filter := query.IndexedSequencesValueGreaterThanKeyFilter("readName", "property", "value1", primitives.Finalized)
expected := query.KeyFilter{
Key: "readName",
Expressions: []query.Expression{
{
Primitive: &primitives.Comparator{
Name: "property",
ValueComparators: []primitives.ValueComparator{{Value: "value1", Operator: primitives.Gte}},
},
},
{Primitive: &primitives.Confidence{ConfidenceLevel: primitives.Finalized}},
},
}

require.Equal(t, expected, filter)
}

func TestIndexedSequencesValueRangeKeyFilter(t *testing.T) {
t.Parallel()

filter := query.IndexedSequencesValueRangeKeyFilter("readName", "property", "min", "max", primitives.Finalized)
expected := query.KeyFilter{
Key: "readName",
Expressions: []query.Expression{
{
Primitive: &primitives.Comparator{
Name: "property",
ValueComparators: []primitives.ValueComparator{{Value: "min", Operator: primitives.Gte}},
},
},
{
Primitive: &primitives.Comparator{
Name: "property",
ValueComparators: []primitives.ValueComparator{{Value: "max", Operator: primitives.Lte}},
},
},
{Primitive: &primitives.Confidence{ConfidenceLevel: primitives.Finalized}},
},
}

require.Equal(t, expected, filter)
}

func TestIndexedSequencesByTxHashKeyFilter(t *testing.T) {
t.Parallel()

filter := query.IndexedSequencesByTxHashKeyFilter("readName", "hash")
expected := query.KeyFilter{
Key: "readName",
Expressions: []query.Expression{
{Primitive: &primitives.TxHash{TxHash: "hash"}},
},
}

require.Equal(t, expected, filter)
}

func TestSequencesByBlockRangeKeyFilter(t *testing.T) {
t.Parallel()

filter := query.SequencesByBlockRangeKeyFilter("readName", "start", "end")
expected := query.KeyFilter{
Key: "readName",
Expressions: []query.Expression{
{Primitive: &primitives.Block{Block: "start", Operator: primitives.Gte}},
{Primitive: &primitives.Block{Block: "end", Operator: primitives.Lte}},
},
}

require.Equal(t, expected, filter)
}

func TestSequencesCreatedAfterKeyFilter(t *testing.T) {
t.Parallel()

now := time.Now()

filter := query.SequencesCreatedAfterKeyFilter("readName", now, primitives.Finalized)
expected := query.KeyFilter{
Key: "readName",
Expressions: []query.Expression{
{Primitive: &primitives.Timestamp{Timestamp: uint64(now.Unix()), Operator: primitives.Gt}},
{Primitive: &primitives.Confidence{ConfidenceLevel: primitives.Finalized}},
},
}

require.Equal(t, expected, filter)
}

func TestIndexedSequencesCreatedAfterKeyFilter(t *testing.T) {
t.Parallel()

now := time.Now()

filter := query.IndexedSequencesCreatedAfterKeyFilter("readName", "property", []string{"value1", "value2"}, now, primitives.Finalized)
expected := query.KeyFilter{
Key: "readName",
Expressions: []query.Expression{
{BoolExpression: query.BoolExpression{
Expressions: []query.Expression{
{
Primitive: &primitives.Comparator{
Name: "property",
ValueComparators: []primitives.ValueComparator{{Value: "value1", Operator: primitives.Eq}},
},
},
{
Primitive: &primitives.Comparator{
Name: "property",
ValueComparators: []primitives.ValueComparator{{Value: "value2", Operator: primitives.Eq}},
},
},
},
BoolOperator: query.OR,
}},
{Primitive: &primitives.Timestamp{Timestamp: uint64(now.Unix()), Operator: primitives.Gt}},
{Primitive: &primitives.Confidence{ConfidenceLevel: primitives.Finalized}},
},
}

require.Equal(t, expected, filter)
}

0 comments on commit 59c388b

Please sign in to comment.