Sitelet https://github.com/Fantom-foundation/go-opera/commit/a06bdb721124031ee42ac7a7ff3ff01df6c812ac
Skip to content

Commit a06bdb7

Browse files
committed
Merge pull request #159 from rus-alex/feature/ethclient
ftmclient package
2 parents 4a466cf + 2d11eca commit a06bdb7

7 files changed

Lines changed: 298 additions & 77 deletions

File tree

‎ethapi/api.go‎

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"strings"
2626
"time"
2727

28-
"github.com/Fantom-foundation/lachesis-base/hash"
2928
"github.com/davecgh/go-spew/spew"
3029
"github.com/ethereum/go-ethereum/accounts"
3130
"github.com/ethereum/go-ethereum/accounts/abi"
@@ -47,7 +46,6 @@ import (
4746
"github.com/tyler-smith/go-bip39"
4847

4948
"github.com/Fantom-foundation/go-opera/evmcore"
50-
"github.com/Fantom-foundation/go-opera/inter"
5149
"github.com/Fantom-foundation/go-opera/opera"
5250
"github.com/Fantom-foundation/go-opera/utils/gsignercache"
5351
)
@@ -1143,73 +1141,6 @@ func FormatLogs(logs []vm.StructLog) []StructLogRes {
11431141
return formatted
11441142
}
11451143

1146-
// RPCMarshalEventHeader converts the given header to the RPC output .
1147-
func RPCMarshalEventHeader(header inter.EventI) map[string]interface{} {
1148-
return map[string]interface{}{
1149-
"epoch": hexutil.Uint64(header.Epoch()),
1150-
"seq": hexutil.Uint64(header.Seq()),
1151-
"id": hexutil.Bytes(header.ID().Bytes()),
1152-
"frame": hexutil.Uint64(header.Frame()),
1153-
"creator": hexutil.Uint64(header.Creator()),
1154-
"prevEpochHash": header.PrevEpochHash(),
1155-
"parents": eventIDsToHex(header.Parents()),
1156-
"lamport": hexutil.Uint64(header.Lamport()),
1157-
"creationTime": hexutil.Uint64(header.CreationTime()),
1158-
"medianTime": hexutil.Uint64(header.MedianTime()),
1159-
"extraData": hexutil.Bytes(header.Extra()),
1160-
"transactionsRoot": hexutil.Bytes(header.TxHash().Bytes()),
1161-
"gasPowerLeft": map[string]interface{}{
1162-
"shortTerm": hexutil.Uint64(header.GasPowerLeft().Gas[inter.ShortTermGas]),
1163-
"longTerm": hexutil.Uint64(header.GasPowerLeft().Gas[inter.LongTermGas]),
1164-
},
1165-
"gasPowerUsed": hexutil.Uint64(header.GasPowerUsed()),
1166-
}
1167-
}
1168-
1169-
// RPCMarshalEvent converts the given event to the RPC output which depends on fullTx. If inclTx is true transactions are
1170-
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
1171-
// transaction hashes.
1172-
func RPCMarshalEvent(event inter.EventPayloadI, inclTx bool, fullTx bool) (map[string]interface{}, error) {
1173-
fields := RPCMarshalEventHeader(event)
1174-
fields["size"] = hexutil.Uint64(event.Size())
1175-
1176-
if inclTx {
1177-
formatTx := func(tx *types.Transaction) (interface{}, error) {
1178-
return tx.Hash(), nil
1179-
}
1180-
if fullTx {
1181-
// TODO full txs for events API
1182-
//formatTx = func(tx *types.Transaction) (interface{}, error) {
1183-
// return newRPCTransactionFromBlockHash(event, tx.Hash()), nil
1184-
//}
1185-
}
1186-
txs := event.Txs()
1187-
transactions := make([]interface{}, len(txs))
1188-
var err error
1189-
for i, tx := range txs {
1190-
if transactions[i], err = formatTx(tx); err != nil {
1191-
return nil, err
1192-
}
1193-
}
1194-
1195-
fields["transactions"] = transactions
1196-
}
1197-
1198-
return fields, nil
1199-
}
1200-
1201-
func eventIDsToHex(ids hash.Events) []hexutil.Bytes {
1202-
res := make([]hexutil.Bytes, len(ids))
1203-
for i, id := range ids {
1204-
res[i] = eventIDToHex(id)
1205-
}
1206-
return res
1207-
}
1208-
1209-
func eventIDToHex(id hash.Event) hexutil.Bytes {
1210-
return hexutil.Bytes(id.Bytes())
1211-
}
1212-
12131144
// RPCMarshalHeader converts the given header to the RPC output .
12141145
func RPCMarshalHeader(head *evmcore.EvmHeader, bloom types.Bloom) map[string]interface{} {
12151146
return map[string]interface{}{

‎ethapi/dag_api.go‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"github.com/ethereum/go-ethereum/common/hexutil"
1010
"github.com/ethereum/go-ethereum/log"
1111
"github.com/ethereum/go-ethereum/rpc"
12+
13+
"github.com/Fantom-foundation/go-opera/inter"
1214
)
1315

1416
// PublicDAGChainAPI provides an API to access the directed acyclic graph chain.
@@ -31,7 +33,7 @@ func (s *PublicDAGChainAPI) GetEvent(ctx context.Context, shortEventID string) (
3133
if header == nil {
3234
return nil, fmt.Errorf("event %s not found", shortEventID)
3335
}
34-
return RPCMarshalEventHeader(header), nil
36+
return inter.RPCMarshalEvent(header), nil
3537
}
3638

3739
// GetEventPayload returns Lachesis event by hash or short ID.
@@ -43,7 +45,7 @@ func (s *PublicDAGChainAPI) GetEventPayload(ctx context.Context, shortEventID st
4345
if event == nil {
4446
return nil, fmt.Errorf("event %s not found", shortEventID)
4547
}
46-
return RPCMarshalEvent(event, inclTx, false)
48+
return inter.RPCMarshalEventPayload(event, inclTx, false)
4749
}
4850

4951
// GetHeads returns IDs of all the epoch events with no descendants.
@@ -56,7 +58,7 @@ func (s *PublicDAGChainAPI) GetHeads(ctx context.Context, epoch rpc.BlockNumber)
5658
return nil, err
5759
}
5860

59-
return eventIDsToHex(res), nil
61+
return inter.EventIDsToHex(res), nil
6062
}
6163

6264
// GetEpochStats returns epoch statistics.

‎ftmclient/dag_api.go‎

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package ftmclient
2+
3+
import (
4+
"context"
5+
"math/big"
6+
7+
"github.com/Fantom-foundation/lachesis-base/hash"
8+
"github.com/ethereum/go-ethereum"
9+
"github.com/ethereum/go-ethereum/common"
10+
"github.com/ethereum/go-ethereum/common/hexutil"
11+
12+
"github.com/Fantom-foundation/go-opera/inter"
13+
)
14+
15+
// GetEvent returns Lachesis event by hash or short ID.
16+
func (ec *Client) GetEvent(ctx context.Context, h hash.Event) (e inter.EventI, err error) {
17+
var raw map[string]interface{}
18+
err = ec.c.CallContext(ctx, &raw, "dag_getEvent", h.Hex())
19+
if err != nil {
20+
return
21+
} else if len(raw) == 0 {
22+
err = ethereum.NotFound
23+
return
24+
}
25+
26+
e = inter.RPCUnmarshalEvent(raw)
27+
return
28+
}
29+
30+
// GetEvent returns Lachesis event by hash or short ID.
31+
func (ec *Client) GetEventPayload(ctx context.Context, h hash.Event, inclTx bool) (e inter.EventI, txs []common.Hash, err error) {
32+
var raw map[string]interface{}
33+
err = ec.c.CallContext(ctx, &raw, "dag_getEventPayload", h.Hex(), inclTx)
34+
if err != nil {
35+
return
36+
} else if len(raw) == 0 {
37+
err = ethereum.NotFound
38+
return
39+
}
40+
41+
e = inter.RPCUnmarshalEvent(raw)
42+
43+
if inclTx {
44+
vv := raw["transactions"].([]interface{})
45+
txs = make([]common.Hash, len(vv))
46+
for i, v := range vv {
47+
txs[i] = common.HexToHash(v.(string))
48+
}
49+
}
50+
51+
return
52+
}
53+
54+
// GetHeads returns IDs of all the epoch events with no descendants.
55+
// * When epoch is -2 the heads for latest epoch are returned.
56+
// * When epoch is -1 the heads for latest sealed epoch are returned.
57+
func (ec *Client) GetHeads(ctx context.Context, epoch *big.Int) (hash.Events, error) {
58+
var raw []interface{}
59+
err := ec.c.CallContext(ctx, &raw, "dag_getHeads", toBlockNumArg(epoch))
60+
if err != nil {
61+
return nil, err
62+
}
63+
64+
return inter.HexToEventIDs(raw), nil
65+
}
66+
67+
// GetEpochStats returns epoch statistics.
68+
// * When epoch is -2 the statistics for latest epoch is returned.
69+
// * When epoch is -1 the statistics for latest sealed epoch is returned.
70+
func (ec *Client) GetEpochStats(ctx context.Context, epoch *big.Int) (map[string]interface{}, error) {
71+
var raw map[string]interface{}
72+
err := ec.c.CallContext(ctx, &raw, "dag_getEpochStats", toBlockNumArg(epoch))
73+
if err != nil {
74+
return nil, err
75+
} else if len(raw) == 0 {
76+
return nil, ethereum.NotFound
77+
}
78+
79+
return raw, nil
80+
}
81+
82+
func toBlockNumArg(number *big.Int) string {
83+
if number == nil {
84+
return "latest"
85+
}
86+
pending := big.NewInt(-1)
87+
if number.Cmp(pending) == 0 {
88+
return "pending"
89+
}
90+
return hexutil.EncodeBig(number)
91+
}

‎ftmclient/ethclient.go‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package ftmclient
2+
3+
import (
4+
"context"
5+
6+
"github.com/ethereum/go-ethereum/ethclient"
7+
"github.com/ethereum/go-ethereum/rpc"
8+
)
9+
10+
// Client extends Ethereum API client with typed wrappers for the FTM API.
11+
type Client struct {
12+
ethclient.Client
13+
c *rpc.Client
14+
}
15+
16+
// Dial connects a client to the given URL.
17+
func Dial(rawurl string) (*Client, error) {
18+
return DialContext(context.Background(), rawurl)
19+
}
20+
21+
func DialContext(ctx context.Context, rawurl string) (*Client, error) {
22+
c, err := rpc.DialContext(ctx, rawurl)
23+
if err != nil {
24+
return nil, err
25+
}
26+
return NewClient(c), nil
27+
}
28+
29+
// NewClient creates a client that uses the given RPC client.
30+
func NewClient(c *rpc.Client) *Client {
31+
return &Client{
32+
Client: *ethclient.NewClient(c),
33+
c: c,
34+
}
35+
}

‎inter/event.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,10 @@ func (me *MutableEventPayload) immutable() *EventPayload {
191191
}
192192

193193
func (e *MutableEventPayload) Build() *EventPayload {
194-
if e.txs.Len() < 1 {
194+
if e.txHash == hash.Zero && e.txs.Len() == 0 {
195195
e.txHash = EmptyTxHash
196196
}
197+
197198
eventSer, _ := e.immutable().Event.MarshalBinary()
198199
h := eventHash(eventSer)
199200
payloadSer, _ := e.immutable().MarshalBinary()

0 commit comments

Comments
 (0)