Skip to content

Commit ae4a7c1

Browse files
s1nashekhirin
authored andcommitted
graphql: encode Long values as hex (ethereum#26894)
This is a breaking GraphQL API change. All numeric values are now encoded as hex strings. The motivation for this change is matching JSON-RPC outputs more closely. Numbers in query parameters are accepted as both decimal integers and hex strings.
1 parent 703473b commit ae4a7c1

File tree

3 files changed

+78
-81
lines changed

3 files changed

+78
-81
lines changed

graphql/graphql.go

Lines changed: 54 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"math/big"
2525
"sort"
2626
"strconv"
27+
"strings"
2728
"sync"
2829

2930
"github.com/ethereum/go-ethereum"
@@ -54,16 +55,16 @@ func (b *Long) UnmarshalGraphQL(input interface{}) error {
5455
switch input := input.(type) {
5556
case string:
5657
// uncomment to support hex values
57-
//if strings.HasPrefix(input, "0x") {
58-
// // apply leniency and support hex representations of longs.
59-
// value, err := hexutil.DecodeUint64(input)
60-
// *b = Long(value)
61-
// return err
62-
//} else {
63-
value, err := strconv.ParseInt(input, 10, 64)
64-
*b = Long(value)
65-
return err
66-
//}
58+
if strings.HasPrefix(input, "0x") {
59+
// apply leniency and support hex representations of longs.
60+
value, err := hexutil.DecodeUint64(input)
61+
*b = Long(value)
62+
return err
63+
} else {
64+
value, err := strconv.ParseInt(input, 10, 64)
65+
*b = Long(value)
66+
return err
67+
}
6768
case int32:
6869
*b = Long(input)
6970
case int64:
@@ -156,8 +157,8 @@ func (l *Log) Account(ctx context.Context, args BlockNumberArgs) *Account {
156157
}
157158
}
158159

159-
func (l *Log) Index(ctx context.Context) int32 {
160-
return int32(l.log.Index)
160+
func (l *Log) Index(ctx context.Context) hexutil.Uint64 {
161+
return hexutil.Uint64(l.log.Index)
161162
}
162163

163164
func (l *Log) Topics(ctx context.Context) []common.Hash {
@@ -391,7 +392,7 @@ func (t *Transaction) Block(ctx context.Context) (*Block, error) {
391392
return block, nil
392393
}
393394

394-
func (t *Transaction) Index(ctx context.Context) (*int32, error) {
395+
func (t *Transaction) Index(ctx context.Context) (*hexutil.Uint64, error) {
395396
_, block, err := t.resolve(ctx)
396397
if err != nil {
397398
return nil, err
@@ -400,7 +401,7 @@ func (t *Transaction) Index(ctx context.Context) (*int32, error) {
400401
if block == nil {
401402
return nil, nil
402403
}
403-
index := int32(t.index)
404+
index := hexutil.Uint64(t.index)
404405
return &index, nil
405406
}
406407

@@ -421,33 +422,33 @@ func (t *Transaction) getReceipt(ctx context.Context) (*types.Receipt, error) {
421422
return receipts[t.index], nil
422423
}
423424

424-
func (t *Transaction) Status(ctx context.Context) (*Long, error) {
425+
func (t *Transaction) Status(ctx context.Context) (*hexutil.Uint64, error) {
425426
receipt, err := t.getReceipt(ctx)
426427
if err != nil || receipt == nil {
427428
return nil, err
428429
}
429430
if len(receipt.PostState) != 0 {
430431
return nil, nil
431432
}
432-
ret := Long(receipt.Status)
433+
ret := hexutil.Uint64(receipt.Status)
433434
return &ret, nil
434435
}
435436

436-
func (t *Transaction) GasUsed(ctx context.Context) (*Long, error) {
437+
func (t *Transaction) GasUsed(ctx context.Context) (*hexutil.Uint64, error) {
437438
receipt, err := t.getReceipt(ctx)
438439
if err != nil || receipt == nil {
439440
return nil, err
440441
}
441-
ret := Long(receipt.GasUsed)
442+
ret := hexutil.Uint64(receipt.GasUsed)
442443
return &ret, nil
443444
}
444445

445-
func (t *Transaction) CumulativeGasUsed(ctx context.Context) (*Long, error) {
446+
func (t *Transaction) CumulativeGasUsed(ctx context.Context) (*hexutil.Uint64, error) {
446447
receipt, err := t.getReceipt(ctx)
447448
if err != nil || receipt == nil {
448449
return nil, err
449450
}
450-
ret := Long(receipt.CumulativeGasUsed)
451+
ret := hexutil.Uint64(receipt.CumulativeGasUsed)
451452
return &ret, nil
452453
}
453454

@@ -503,12 +504,12 @@ func (t *Transaction) getLogs(ctx context.Context, hash common.Hash) (*[]*Log, e
503504
return &ret, nil
504505
}
505506

506-
func (t *Transaction) Type(ctx context.Context) (*int32, error) {
507+
func (t *Transaction) Type(ctx context.Context) (*hexutil.Uint64, error) {
507508
tx, _, err := t.resolve(ctx)
508509
if err != nil {
509510
return nil, err
510511
}
511-
txType := int32(tx.Type())
512+
txType := hexutil.Uint64(tx.Type())
512513
return &txType, nil
513514
}
514515

@@ -649,13 +650,13 @@ func (b *Block) resolveReceipts(ctx context.Context) ([]*types.Receipt, error) {
649650
return receipts, nil
650651
}
651652

652-
func (b *Block) Number(ctx context.Context) (Long, error) {
653+
func (b *Block) Number(ctx context.Context) (hexutil.Uint64, error) {
653654
header, err := b.resolveHeader(ctx)
654655
if err != nil {
655656
return 0, err
656657
}
657658

658-
return Long(header.Number.Uint64()), nil
659+
return hexutil.Uint64(header.Number.Uint64()), nil
659660
}
660661

661662
func (b *Block) Hash(ctx context.Context) (common.Hash, error) {
@@ -664,20 +665,20 @@ func (b *Block) Hash(ctx context.Context) (common.Hash, error) {
664665
return b.hash, nil
665666
}
666667

667-
func (b *Block) GasLimit(ctx context.Context) (Long, error) {
668+
func (b *Block) GasLimit(ctx context.Context) (hexutil.Uint64, error) {
668669
header, err := b.resolveHeader(ctx)
669670
if err != nil {
670671
return 0, err
671672
}
672-
return Long(header.GasLimit), nil
673+
return hexutil.Uint64(header.GasLimit), nil
673674
}
674675

675-
func (b *Block) GasUsed(ctx context.Context) (Long, error) {
676+
func (b *Block) GasUsed(ctx context.Context) (hexutil.Uint64, error) {
676677
header, err := b.resolveHeader(ctx)
677678
if err != nil {
678679
return 0, err
679680
}
680-
return Long(header.GasUsed), nil
681+
return hexutil.Uint64(header.GasUsed), nil
681682
}
682683

683684
func (b *Block) BaseFeePerGas(ctx context.Context) (*hexutil.Big, error) {
@@ -793,12 +794,12 @@ func (b *Block) OmmerHash(ctx context.Context) (common.Hash, error) {
793794
return header.UncleHash, nil
794795
}
795796

796-
func (b *Block) OmmerCount(ctx context.Context) (*int32, error) {
797+
func (b *Block) OmmerCount(ctx context.Context) (*hexutil.Uint64, error) {
797798
block, err := b.resolve(ctx)
798799
if err != nil || block == nil {
799800
return nil, err
800801
}
801-
count := int32(len(block.Uncles()))
802+
count := hexutil.Uint64(len(block.Uncles()))
802803
return &count, err
803804
}
804805

@@ -869,7 +870,7 @@ type BlockNumberArgs struct {
869870
// TODO: Ideally we could use input unions to allow the query to specify the
870871
// block parameter by hash, block number, or tag but input unions aren't part of the
871872
// standard GraphQL schema SDL yet, see: https://github.com/graphql/graphql-spec/issues/488
872-
Block *hexutil.Uint64
873+
Block *Long
873874
}
874875

875876
// NumberOr returns the provided block number argument, or the "current" block number or hash if none
@@ -900,12 +901,12 @@ func (b *Block) Miner(ctx context.Context, args BlockNumberArgs) (*Account, erro
900901
}, nil
901902
}
902903

903-
func (b *Block) TransactionCount(ctx context.Context) (*int32, error) {
904+
func (b *Block) TransactionCount(ctx context.Context) (*hexutil.Uint64, error) {
904905
block, err := b.resolve(ctx)
905906
if err != nil || block == nil {
906907
return nil, err
907908
}
908-
count := int32(len(block.Transactions()))
909+
count := hexutil.Uint64(len(block.Transactions()))
909910
return &count, err
910911
}
911912

@@ -927,7 +928,7 @@ func (b *Block) Transactions(ctx context.Context) (*[]*Transaction, error) {
927928
return &ret, nil
928929
}
929930

930-
func (b *Block) TransactionAt(ctx context.Context, args struct{ Index int32 }) (*Transaction, error) {
931+
func (b *Block) TransactionAt(ctx context.Context, args struct{ Index Long }) (*Transaction, error) {
931932
block, err := b.resolve(ctx)
932933
if err != nil || block == nil {
933934
return nil, err
@@ -946,7 +947,7 @@ func (b *Block) TransactionAt(ctx context.Context, args struct{ Index int32 }) (
946947
}, nil
947948
}
948949

949-
func (b *Block) OmmerAt(ctx context.Context, args struct{ Index int32 }) (*Block, error) {
950+
func (b *Block) OmmerAt(ctx context.Context, args struct{ Index Long }) (*Block, error) {
950951
block, err := b.resolve(ctx)
951952
if err != nil || block == nil {
952953
return nil, err
@@ -1037,7 +1038,7 @@ func (b *Block) Account(ctx context.Context, args struct {
10371038
type CallData struct {
10381039
From *common.Address // The Ethereum address the call is from.
10391040
To *common.Address // The Ethereum address the call is to.
1040-
Gas *hexutil.Uint64 // The amount of gas provided for the call.
1041+
Gas *Long // The amount of gas provided for the call.
10411042
GasPrice *hexutil.Big // The price of each unit of gas, in wei.
10421043
MaxFeePerGas *hexutil.Big // The max price of each unit of gas, in wei (1559).
10431044
MaxPriorityFeePerGas *hexutil.Big // The max tip of each unit of gas, in wei (1559).
@@ -1047,20 +1048,20 @@ type CallData struct {
10471048

10481049
// CallResult encapsulates the result of an invocation of the `call` accessor.
10491050
type CallResult struct {
1050-
data hexutil.Bytes // The return data from the call
1051-
gasUsed Long // The amount of gas used
1052-
status Long // The return status of the call - 0 for failure or 1 for success.
1051+
data hexutil.Bytes // The return data from the call
1052+
gasUsed hexutil.Uint64 // The amount of gas used
1053+
status hexutil.Uint64 // The return status of the call - 0 for failure or 1 for success.
10531054
}
10541055

10551056
func (c *CallResult) Data() hexutil.Bytes {
10561057
return c.data
10571058
}
10581059

1059-
func (c *CallResult) GasUsed() Long {
1060+
func (c *CallResult) GasUsed() hexutil.Uint64 {
10601061
return c.gasUsed
10611062
}
10621063

1063-
func (c *CallResult) Status() Long {
1064+
func (c *CallResult) Status() hexutil.Uint64 {
10641065
return c.status
10651066
}
10661067

@@ -1071,32 +1072,31 @@ func (b *Block) Call(ctx context.Context, args struct {
10711072
if err != nil {
10721073
return nil, err
10731074
}
1074-
status := Long(1)
1075+
status := hexutil.Uint64(1)
10751076
if result.Failed() {
10761077
status = 0
10771078
}
10781079

10791080
return &CallResult{
10801081
data: result.ReturnData,
1081-
gasUsed: Long(result.UsedGas),
1082+
gasUsed: hexutil.Uint64(result.UsedGas),
10821083
status: status,
10831084
}, nil
10841085
}
10851086

10861087
func (b *Block) EstimateGas(ctx context.Context, args struct {
10871088
Data ethapi.TransactionArgs
1088-
}) (Long, error) {
1089-
gas, err := ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, b.r.backend.RPCGasCap())
1090-
return Long(gas), err
1089+
}) (hexutil.Uint64, error) {
1090+
return ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, b.r.backend.RPCGasCap())
10911091
}
10921092

10931093
type Pending struct {
10941094
r *Resolver
10951095
}
10961096

1097-
func (p *Pending) TransactionCount(ctx context.Context) (int32, error) {
1097+
func (p *Pending) TransactionCount(ctx context.Context) (hexutil.Uint64, error) {
10981098
txs, err := p.r.backend.GetPoolTransactions()
1099-
return int32(len(txs)), err
1099+
return hexutil.Uint64(len(txs)), err
11001100
}
11011101

11021102
func (p *Pending) Transactions(ctx context.Context) (*[]*Transaction, error) {
@@ -1135,24 +1135,23 @@ func (p *Pending) Call(ctx context.Context, args struct {
11351135
if err != nil {
11361136
return nil, err
11371137
}
1138-
status := Long(1)
1138+
status := hexutil.Uint64(1)
11391139
if result.Failed() {
11401140
status = 0
11411141
}
11421142

11431143
return &CallResult{
11441144
data: result.ReturnData,
1145-
gasUsed: Long(result.UsedGas),
1145+
gasUsed: hexutil.Uint64(result.UsedGas),
11461146
status: status,
11471147
}, nil
11481148
}
11491149

11501150
func (p *Pending) EstimateGas(ctx context.Context, args struct {
11511151
Data ethapi.TransactionArgs
1152-
}) (Long, error) {
1152+
}) (hexutil.Uint64, error) {
11531153
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
1154-
gas, err := ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, pendingBlockNr, p.r.backend.RPCGasCap())
1155-
return Long(gas), err
1154+
return ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, pendingBlockNr, p.r.backend.RPCGasCap())
11561155
}
11571156

11581157
// Resolver is the top-level object in the GraphQL hierarchy.
@@ -1260,8 +1259,8 @@ func (r *Resolver) SendRawTransaction(ctx context.Context, args struct{ Data hex
12601259

12611260
// FilterCriteria encapsulates the arguments to `logs` on the root resolver object.
12621261
type FilterCriteria struct {
1263-
FromBlock *hexutil.Uint64 // beginning of the queried range, nil means genesis block
1264-
ToBlock *hexutil.Uint64 // end of the range, nil means latest block
1262+
FromBlock *Long // beginning of the queried range, nil means genesis block
1263+
ToBlock *Long // end of the range, nil means latest block
12651264
Addresses *[]common.Address // restricts matches to events created by specific contracts
12661265

12671266
// The Topic list restricts matches to particular event topics. Each event has a list

0 commit comments

Comments
 (0)