-
Notifications
You must be signed in to change notification settings - Fork 7
/
chain.go
157 lines (133 loc) · 3.67 KB
/
chain.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package ethereum
import (
"bytes"
"context"
"crypto/ecdsa"
"embed"
"encoding/hex"
"fmt"
"strings"
"sync"
"github.com/ethereum/go-ethereum/ethclient"
"cosmossdk.io/log"
"github.com/strangelove-ventures/noble-cctp-relayer/types"
)
//go:embed abi/MessageTransmitter.json
var content embed.FS
var _ types.Chain = (*Ethereum)(nil)
type Ethereum struct {
// from config
name string
chainID int64
domain types.Domain
rpcURL string
wsURL string
messageTransmitterAddress string
startBlock uint64
lookbackPeriod uint64
privateKey *ecdsa.PrivateKey
minterAddress string
maxRetries int
retryIntervalSeconds int
minAmount uint64
MetricsDenom string
MetricsExponent int
mu sync.Mutex
wsClient *ethclient.Client
rpcClient *ethclient.Client
latestBlock uint64
lastFlushedBlock uint64
}
func NewChain(
name string,
domain types.Domain,
chainID int64,
rpcURL string,
wsURL string,
messageTransmitterAddress string,
startBlock uint64,
lookbackPeriod uint64,
privateKey string,
maxRetries int,
retryIntervalSeconds int,
minAmount uint64,
metricsDenom string,
metricsExponent int,
) (*Ethereum, error) {
privEcdsaKey, ethereumAddress, err := GetEcdsaKeyAddress(privateKey)
if err != nil {
return nil, err
}
return &Ethereum{
name: name,
chainID: chainID,
domain: domain,
rpcURL: rpcURL,
wsURL: wsURL,
messageTransmitterAddress: messageTransmitterAddress,
startBlock: startBlock,
lookbackPeriod: lookbackPeriod,
privateKey: privEcdsaKey,
minterAddress: ethereumAddress,
maxRetries: maxRetries,
retryIntervalSeconds: retryIntervalSeconds,
minAmount: minAmount,
MetricsDenom: metricsDenom,
MetricsExponent: metricsExponent,
}, nil
}
func (e *Ethereum) Name() string {
return e.name
}
func (e *Ethereum) Domain() types.Domain {
return e.domain
}
func (e *Ethereum) LatestBlock() uint64 {
e.mu.Lock()
block := e.latestBlock
e.mu.Unlock()
return block
}
func (e *Ethereum) SetLatestBlock(block uint64) {
e.mu.Lock()
e.latestBlock = block
e.mu.Unlock()
}
func (e *Ethereum) LastFlushedBlock() uint64 {
return e.lastFlushedBlock
}
func (e *Ethereum) IsDestinationCaller(destinationCaller []byte) (isCaller bool, readableAddress string) {
zeroByteArr := make([]byte, 32)
decodedMinter, err := hex.DecodeString(strings.ReplaceAll(e.minterAddress, "0x", ""))
if err != nil && bytes.Equal(destinationCaller, zeroByteArr) {
return true, ""
}
decodedMinterPadded := make([]byte, 32)
copy(decodedMinterPadded[12:], decodedMinter)
encodedCaller := "0x" + hex.EncodeToString(destinationCaller)[24:]
if bytes.Equal(destinationCaller, zeroByteArr) || bytes.Equal(destinationCaller, decodedMinterPadded) {
return true, encodedCaller
}
return false, encodedCaller
}
func (e *Ethereum) InitializeClients(ctx context.Context, logger log.Logger) error {
var err error
e.wsClient, err = ethclient.DialContext(ctx, e.wsURL)
if err != nil {
return fmt.Errorf("unable to initialize websocket ethereum client; err: %w", err)
}
e.rpcClient, err = ethclient.DialContext(ctx, e.rpcURL)
if err != nil {
return fmt.Errorf("unable to initialize rpc ethereum client; err: %w", err)
}
return nil
}
func (e *Ethereum) CloseClients() error {
if e.wsClient != nil {
e.wsClient.Close()
}
if e.rpcClient != nil {
e.rpcClient.Close()
}
return nil
}