-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathsource_proxy.go
More file actions
93 lines (82 loc) · 2.65 KB
/
source_proxy.go
File metadata and controls
93 lines (82 loc) · 2.65 KB
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
package monitoring
import (
"context"
"encoding/json"
"fmt"
"math/big"
relayMonitoring "github.com/smartcontractkit/chainlink-common/pkg/monitoring"
)
// ProxyData is a subset of the data returned by the Cosmos feed proxy contract's "latest_round_data" method.
type ProxyData struct {
Answer *big.Int
}
// NewProxySourceFactory does wisott.
func NewProxySourceFactory(client ChainReader, log relayMonitoring.Logger) relayMonitoring.SourceFactory {
return &proxySourceFactory{client, log}
}
type proxySourceFactory struct {
client ChainReader
log relayMonitoring.Logger
}
func (p *proxySourceFactory) NewSource(
chainConfig relayMonitoring.ChainConfig,
feedConfig relayMonitoring.FeedConfig,
) (relayMonitoring.Source, error) {
cosmosConfig, ok := chainConfig.(CosmosConfig)
if !ok {
return nil, fmt.Errorf("expected chainConfig to be of type CosmosConfig not %T", chainConfig)
}
cosmosFeedConfig, ok := feedConfig.(CosmosFeedConfig)
if !ok {
return nil, fmt.Errorf("expected feedConfig to be of type CosmosFeedConfig not %T", feedConfig)
}
return &proxySource{
p.client,
p.log,
cosmosConfig,
cosmosFeedConfig,
}, nil
}
func (p *proxySourceFactory) GetType() string {
return "proxy"
}
type proxySource struct {
client ChainReader
log relayMonitoring.Logger
cosmosConfig CosmosConfig
cosmosFeedConfig CosmosFeedConfig
}
func (p *proxySource) Fetch(ctx context.Context) (interface{}, error) {
if p.cosmosFeedConfig.ProxyAddressBech32 == "" {
p.log.Debugw("skipping fetch because no proxy contract is configured", "feed", p.cosmosFeedConfig.ContractAddressBech32)
return nil, relayMonitoring.ErrNoUpdate
}
answer, err := p.fetchLatestRoundFromProxy(ctx)
if err != nil {
return nil, err
}
return ProxyData{answer}, nil
}
// latestRoundDataRes corresponds to a subset of the Round type in the proxy contract.
type latestRoundDataRes struct {
Answer string `json:"answer,omitempty"`
}
func (p *proxySource) fetchLatestRoundFromProxy(ctx context.Context) (*big.Int, error) {
res, err := p.client.ContractState(
ctx,
p.cosmosFeedConfig.ProxyAddress,
[]byte(`{"latest_round_data":{}}`),
)
if err != nil {
return nil, fmt.Errorf("failed to read latest_round_data from the proxy contract: %w", err)
}
latestRoundData := latestRoundDataRes{}
if err := json.Unmarshal(res, &latestRoundData); err != nil {
return nil, fmt.Errorf("failed to unmarshal round data from the response '%s': %w", string(res), err)
}
answer, success := new(big.Int).SetString(latestRoundData.Answer, 10)
if !success {
return nil, fmt.Errorf("failed to parse proxy answer '%s' into a big.Int", latestRoundData.Answer)
}
return answer, nil
}