diff --git a/README.md b/README.md index e30ae77..97a92be 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ Reduce Chaos in MemPool 😌 - [Inspecting tx(s) in pending pool](#pending-pool) - [Pending For >= `X`](#pending-for-more-than-X) - [Pending For <= `X`](#pending-for-less-than-X) + - [Pending With >= `X` ( Gwei )](#pending-with-more-than-X) + - [Pending With <= `X` ( Gwei )](#pending-with-less-than-X) - [Pending From Address `A`](#pending-from-A) - [Pending To Address `A`](#pending-to-A) - [Top `X` Pending Tx(s)](#top-X-pending) @@ -37,6 +39,8 @@ Reduce Chaos in MemPool 😌 - [Inspecting tx(s) in queued pool](#queued-pool) - [Queued For >= `X`](#queued-for-more-than-X) - [Queued For <= `X`](#queued-for-less-than-X) + - [Queued With >= `X` ( Gwei )](#queued-with-more-than-X) + - [Queued With <= `X` ( Gwei )](#queued-with-less-than-X) - [Queued From Address `A`](#queued-from-A) - [Queued To Address `A`](#queued-to-A) - [Top `X` Queued Tx(s)](#top-X-queued) @@ -434,6 +438,48 @@ query { --- +### Pending with more than `X` + +For listing all tx(s) pending with gas price >= `x` GWei, send graphQL query + +Method : **POST** + +URL : **/v1/graphql** + + +```graphql +query { + pendingWithMoreThan(x: 20.1) { + from + hash + gasPriceGwei + } +} +``` + +--- + +### Pending with less than `X` + +For listing all tx(s) pending with gas price <= `x` GWei, send graphQL query + +Method : **POST** + +URL : **/v1/graphql** + + +```graphql +query { + pendingWithLessThan(x: 10.1) { + from + hash + gasPriceGwei + } +} +``` + +--- + ### Pending from `A` For getting a list of all pending tx(s) `from` specific address, send a graphQL query like 👇 @@ -846,6 +892,48 @@ query { --- +### Queued with more than `X` + +For listing all tx(s) queued with gas price >= `x` GWei, send graphQL query + +Method : **POST** + +URL : **/v1/graphql** + + +```graphql +query { + queuedWithMoreThan(x: 20.1) { + from + hash + gasPriceGwei + } +} +``` + +--- + +### Queued with less than `X` + +For listing all tx(s) queued with gas price <= `x` GWei, send graphQL query + +Method : **POST** + +URL : **/v1/graphql** + + +```graphql +query { + queuedWithLessThan(x: 10.1) { + from + hash + gasPriceGwei + } +} +``` + +--- + ### Queued from `A` For getting a list of all queued tx(s) `from` specific address, send a graphQL query like 👇 diff --git a/app/data/pending.go b/app/data/pending.go index 38ee6af..dfae066 100644 --- a/app/data/pending.go +++ b/app/data/pending.go @@ -975,6 +975,58 @@ func (p *PendingPool) FresherThanX(x time.Duration) []*MemPoolTx { } +// HigherThanX - Returns a list of pending txs which are paid with +// gas price >= `X` +func (p *PendingPool) HigherThanX(x float64) []*MemPoolTx { + txs := p.DescListTxs() + if txs == nil { + return nil + } + + txCount := uint64(len(txs)) + result := make([]*MemPoolTx, 0, txCount) + + for i := 0; i < len(txs); i++ { + // Stop ASAP, because iterating over + // descending sorted ( w.r.t. gas price ) + // tx list + if !txs[i].HasGasPriceMoreThan(x) { + break + } + + result = append(result, txs[i]) + } + + CleanSlice(txs) + return result +} + +// LowerThanX - Returns a list of pending txs which are paid with +// gas price <= `X` +func (p *PendingPool) LowerThanX(x float64) []*MemPoolTx { + txs := p.AscListTxs() + if txs == nil { + return nil + } + + txCount := uint64(len(txs)) + result := make([]*MemPoolTx, 0, txCount) + + for i := 0; i < len(txs); i++ { + // Stop ASAP, because iterating over + // ascending sorted ( w.r.t. gas price ) + // tx list + if !txs[i].HasGasPriceLessThan(x) { + break + } + + result = append(result, txs[i]) + } + + CleanSlice(txs) + return result +} + // Add - Attempts to add new tx found in pending pool into // harmony mempool, so that further manipulation can be performed on it // diff --git a/app/data/pool.go b/app/data/pool.go index 5a2607f..fe2c3a7 100644 --- a/app/data/pool.go +++ b/app/data/pool.go @@ -102,6 +102,26 @@ func (m *MemPool) QueuedForLTE(x time.Duration) []*MemPoolTx { return m.Queued.FresherThanX(x) } +// PendingWithGTE - Returns list of tx(s), pending with gas price >= `X` +func (m *MemPool) PendingWithGTE(x float64) []*MemPoolTx { + return m.Pending.HigherThanX(x) +} + +// PendingWithLTE - Returns list of tx(s), pending with gas price <= `X` +func (m *MemPool) PendingWithLTE(x float64) []*MemPoolTx { + return m.Pending.LowerThanX(x) +} + +// QueuedWithGTE - Returns list of tx(s), queued with gas price >= `X` +func (m *MemPool) QueuedWithGTE(x float64) []*MemPoolTx { + return m.Queued.HigherThanX(x) +} + +// QueuedWithLTE - Returns list of tx(s), queued with gas price <= `X` +func (m *MemPool) QueuedWithLTE(x float64) []*MemPoolTx { + return m.Queued.LowerThanX(x) +} + // PendingFrom - List of tx(s) pending from address // // @note These are going to be same nonce tx(s), only one of them will diff --git a/app/data/queued.go b/app/data/queued.go index ebcda9e..bfea797 100644 --- a/app/data/queued.go +++ b/app/data/queued.go @@ -758,6 +758,58 @@ func (q *QueuedPool) FresherThanX(x time.Duration) []*MemPoolTx { } +// HigherThanX - Returns a list of queued txs which are paid with +// gas price >= `X` +func (q *QueuedPool) HigherThanX(x float64) []*MemPoolTx { + txs := q.DescListTxs() + if txs == nil { + return nil + } + + txCount := uint64(len(txs)) + result := make([]*MemPoolTx, 0, txCount) + + for i := 0; i < len(txs); i++ { + // Stop ASAP, because iterating over + // descending sorted ( w.r.t. gas price ) + // tx list + if !txs[i].HasGasPriceMoreThan(x) { + break + } + + result = append(result, txs[i]) + } + + CleanSlice(txs) + return result +} + +// LowerThanX - Returns a list of queued txs which are paid with +// gas price <= `X` +func (q *QueuedPool) LowerThanX(x float64) []*MemPoolTx { + txs := q.AscListTxs() + if txs == nil { + return nil + } + + txCount := uint64(len(txs)) + result := make([]*MemPoolTx, 0, txCount) + + for i := 0; i < len(txs); i++ { + // Stop ASAP, because iterating over + // ascending sorted ( w.r.t. gas price ) + // tx list + if !txs[i].HasGasPriceLessThan(x) { + break + } + + result = append(result, txs[i]) + } + + CleanSlice(txs) + return result +} + // Add - Attempts to add new tx found in pending pool into // harmony mempool, so that further manipulation can be performed on it // diff --git a/app/data/tx.go b/app/data/tx.go index 1e57584..44f70d7 100644 --- a/app/data/tx.go +++ b/app/data/tx.go @@ -2,6 +2,7 @@ package data import ( "context" + "math/big" "time" "github.com/ethereum/go-ethereum/common" @@ -186,6 +187,30 @@ func (m *MemPoolTx) IsUnstuck(ctx context.Context, rpc *rpc.Client) (bool, error } +// HasGasPriceMoreThan - Returns true if gas price of this tx +// is more than or equals to `X` +func (m *MemPoolTx) HasGasPriceMoreThan(x float64) bool { + gp, err := BigHexToBigFloat(m.GasPrice) + if err != nil { + return false + } + + given := big.NewFloat(x * 1_000_000_000) + return gp.Cmp(given) >= 0 +} + +// HasGasPriceLessThan - Returns true if gas price of this tx +// is less than or equals to `X` +func (m *MemPoolTx) HasGasPriceLessThan(x float64) bool { + gp, err := BigHexToBigFloat(m.GasPrice) + if err != nil { + return false + } + + given := big.NewFloat(x * 1_000_000_000) + return gp.Cmp(given) <= 0 +} + // ToMessagePack - Serialize to message pack encoded byte array format func (m *MemPoolTx) ToMessagePack() ([]byte, error) { diff --git a/app/graph/generated/generated.go b/app/graph/generated/generated.go index 4a4f959..b65abf2 100644 --- a/app/graph/generated/generated.go +++ b/app/graph/generated/generated.go @@ -68,11 +68,15 @@ type ComplexityRoot struct { PendingForMoreThan func(childComplexity int, x string) int PendingFrom func(childComplexity int, addr string) int PendingTo func(childComplexity int, addr string) int + PendingWithLessThan func(childComplexity int, x float64) int + PendingWithMoreThan func(childComplexity int, x float64) int QueuedDuplicates func(childComplexity int, hash string) int QueuedForLessThan func(childComplexity int, x string) int QueuedForMoreThan func(childComplexity int, x string) int QueuedFrom func(childComplexity int, addr string) int QueuedTo func(childComplexity int, addr string) int + QueuedWithLessThan func(childComplexity int, x float64) int + QueuedWithMoreThan func(childComplexity int, x float64) int TopXPendingWithHighGasPrice func(childComplexity int, x int) int TopXPendingWithLowGasPrice func(childComplexity int, x int) int TopXQueuedWithHighGasPrice func(childComplexity int, x int) int @@ -120,6 +124,10 @@ type QueryResolver interface { TopXQueuedWithLowGasPrice(ctx context.Context, x int) ([]*model.MemPoolTx, error) PendingDuplicates(ctx context.Context, hash string) ([]*model.MemPoolTx, error) QueuedDuplicates(ctx context.Context, hash string) ([]*model.MemPoolTx, error) + PendingWithMoreThan(ctx context.Context, x float64) ([]*model.MemPoolTx, error) + PendingWithLessThan(ctx context.Context, x float64) ([]*model.MemPoolTx, error) + QueuedWithMoreThan(ctx context.Context, x float64) ([]*model.MemPoolTx, error) + QueuedWithLessThan(ctx context.Context, x float64) ([]*model.MemPoolTx, error) } type SubscriptionResolver interface { NewPendingTx(ctx context.Context) (<-chan *model.MemPoolTx, error) @@ -326,6 +334,30 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.PendingTo(childComplexity, args["addr"].(string)), true + case "Query.pendingWithLessThan": + if e.complexity.Query.PendingWithLessThan == nil { + break + } + + args, err := ec.field_Query_pendingWithLessThan_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.PendingWithLessThan(childComplexity, args["x"].(float64)), true + + case "Query.pendingWithMoreThan": + if e.complexity.Query.PendingWithMoreThan == nil { + break + } + + args, err := ec.field_Query_pendingWithMoreThan_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.PendingWithMoreThan(childComplexity, args["x"].(float64)), true + case "Query.queuedDuplicates": if e.complexity.Query.QueuedDuplicates == nil { break @@ -386,6 +418,30 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.QueuedTo(childComplexity, args["addr"].(string)), true + case "Query.queuedWithLessThan": + if e.complexity.Query.QueuedWithLessThan == nil { + break + } + + args, err := ec.field_Query_queuedWithLessThan_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.QueuedWithLessThan(childComplexity, args["x"].(float64)), true + + case "Query.queuedWithMoreThan": + if e.complexity.Query.QueuedWithMoreThan == nil { + break + } + + args, err := ec.field_Query_queuedWithMoreThan_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.QueuedWithMoreThan(childComplexity, args["x"].(float64)), true + case "Query.topXPendingWithHighGasPrice": if e.complexity.Query.TopXPendingWithHighGasPrice == nil { break @@ -769,6 +825,12 @@ type Query { pendingDuplicates(hash: String!): [MemPoolTx!]! queuedDuplicates(hash: String!): [MemPoolTx!]! + + pendingWithMoreThan(x: Float!): [MemPoolTx!]! + pendingWithLessThan(x: Float!): [MemPoolTx!]! + + queuedWithMoreThan(x: Float!): [MemPoolTx!]! + queuedWithLessThan(x: Float!): [MemPoolTx!]! } type Subscription { @@ -903,6 +965,36 @@ func (ec *executionContext) field_Query_pendingTo_args(ctx context.Context, rawA return args, nil } +func (ec *executionContext) field_Query_pendingWithLessThan_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 float64 + if tmp, ok := rawArgs["x"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("x")) + arg0, err = ec.unmarshalNFloat2float64(ctx, tmp) + if err != nil { + return nil, err + } + } + args["x"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_pendingWithMoreThan_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 float64 + if tmp, ok := rawArgs["x"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("x")) + arg0, err = ec.unmarshalNFloat2float64(ctx, tmp) + if err != nil { + return nil, err + } + } + args["x"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_queuedDuplicates_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -978,6 +1070,36 @@ func (ec *executionContext) field_Query_queuedTo_args(ctx context.Context, rawAr return args, nil } +func (ec *executionContext) field_Query_queuedWithLessThan_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 float64 + if tmp, ok := rawArgs["x"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("x")) + arg0, err = ec.unmarshalNFloat2float64(ctx, tmp) + if err != nil { + return nil, err + } + } + args["x"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_queuedWithMoreThan_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 float64 + if tmp, ok := rawArgs["x"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("x")) + arg0, err = ec.unmarshalNFloat2float64(ctx, tmp) + if err != nil { + return nil, err + } + } + args["x"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_topXPendingWithHighGasPrice_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -2414,6 +2536,174 @@ func (ec *executionContext) _Query_queuedDuplicates(ctx context.Context, field g return ec.marshalNMemPoolTx2ᚕᚖgithubᚗcomᚋitzmeanjanᚋharmonyᚋappᚋgraphᚋmodelᚐMemPoolTxᚄ(ctx, field.Selections, res) } +func (ec *executionContext) _Query_pendingWithMoreThan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_pendingWithMoreThan_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().PendingWithMoreThan(rctx, args["x"].(float64)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.MemPoolTx) + fc.Result = res + return ec.marshalNMemPoolTx2ᚕᚖgithubᚗcomᚋitzmeanjanᚋharmonyᚋappᚋgraphᚋmodelᚐMemPoolTxᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_pendingWithLessThan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_pendingWithLessThan_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().PendingWithLessThan(rctx, args["x"].(float64)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.MemPoolTx) + fc.Result = res + return ec.marshalNMemPoolTx2ᚕᚖgithubᚗcomᚋitzmeanjanᚋharmonyᚋappᚋgraphᚋmodelᚐMemPoolTxᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_queuedWithMoreThan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_queuedWithMoreThan_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().QueuedWithMoreThan(rctx, args["x"].(float64)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.MemPoolTx) + fc.Result = res + return ec.marshalNMemPoolTx2ᚕᚖgithubᚗcomᚋitzmeanjanᚋharmonyᚋappᚋgraphᚋmodelᚐMemPoolTxᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_queuedWithLessThan(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_queuedWithLessThan_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().QueuedWithLessThan(rctx, args["x"].(float64)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.MemPoolTx) + fc.Result = res + return ec.marshalNMemPoolTx2ᚕᚖgithubᚗcomᚋitzmeanjanᚋharmonyᚋappᚋgraphᚋmodelᚐMemPoolTxᚄ(ctx, field.Selections, res) +} + func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -4983,6 +5273,62 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } return res }) + case "pendingWithMoreThan": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_pendingWithMoreThan(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "pendingWithLessThan": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_pendingWithLessThan(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "queuedWithMoreThan": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_queuedWithMoreThan(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) + case "queuedWithLessThan": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_queuedWithLessThan(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": diff --git a/app/graph/schema.graphqls b/app/graph/schema.graphqls index 6311ce4..36bf440 100644 --- a/app/graph/schema.graphqls +++ b/app/graph/schema.graphqls @@ -37,6 +37,12 @@ type Query { pendingDuplicates(hash: String!): [MemPoolTx!]! queuedDuplicates(hash: String!): [MemPoolTx!]! + + pendingWithMoreThan(x: Float!): [MemPoolTx!]! + pendingWithLessThan(x: Float!): [MemPoolTx!]! + + queuedWithMoreThan(x: Float!): [MemPoolTx!]! + queuedWithLessThan(x: Float!): [MemPoolTx!]! } type Subscription { diff --git a/app/graph/schema.resolvers.go b/app/graph/schema.resolvers.go index 1577c76..4b3e8e0 100644 --- a/app/graph/schema.resolvers.go +++ b/app/graph/schema.resolvers.go @@ -128,6 +128,38 @@ func (r *queryResolver) QueuedDuplicates(ctx context.Context, hash string) ([]*m return toGraphQL(memPool.QueuedDuplicates(common.HexToHash(hash))), nil } +func (r *queryResolver) PendingWithMoreThan(ctx context.Context, x float64) ([]*model.MemPoolTx, error) { + if !(x >= 0) { + return nil, errors.New("bad gas price ( in Gwei )") + } + + return toGraphQL(memPool.PendingWithGTE(x)), nil +} + +func (r *queryResolver) PendingWithLessThan(ctx context.Context, x float64) ([]*model.MemPoolTx, error) { + if !(x >= 0) { + return nil, errors.New("bad gas price ( in Gwei )") + } + + return toGraphQL(memPool.PendingWithLTE(x)), nil +} + +func (r *queryResolver) QueuedWithMoreThan(ctx context.Context, x float64) ([]*model.MemPoolTx, error) { + if !(x >= 0) { + return nil, errors.New("bad gas price ( in Gwei )") + } + + return toGraphQL(memPool.QueuedWithGTE(x)), nil +} + +func (r *queryResolver) QueuedWithLessThan(ctx context.Context, x float64) ([]*model.MemPoolTx, error) { + if !(x >= 0) { + return nil, errors.New("bad gas price ( in Gwei )") + } + + return toGraphQL(memPool.QueuedWithLTE(x)), nil +} + func (r *subscriptionResolver) NewPendingTx(ctx context.Context) (<-chan *model.MemPoolTx, error) { _pubsub, err := SubscribeToPendingTxEntry(ctx) if err != nil {