-
Notifications
You must be signed in to change notification settings - Fork 18
/
chainlink.go
129 lines (109 loc) · 2.44 KB
/
chainlink.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
// Copyright 2022 Fluidity Money. All rights reserved. Use of this
// source code is governed by a GPL-style license that can be found in the
// LICENSE.md file.
package chainlink
import (
"fmt"
"math/big"
ethAbi "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/fluidity-money/fluidity-app/common/ethereum"
"github.com/fluidity-money/fluidity-app/lib/log"
ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)
// Context to use for logging
const Context = "CHAINLINK"
const chainlinkPriceFeedAbiString = `[
{
"inputs": [],
"name": "latestRoundData",
"outputs": [
{
"internalType": "uint80",
"name": "roundID",
"type": "uint80"
},
{
"internalType": "int256",
"name": "price",
"type": "int256"
},
{
"internalType": "uint256",
"name": "startedAt",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "timeStamp",
"type": "uint256"
},
{
"internalType": "uint80",
"name": "answeredInRound",
"type": "uint80"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "decimals",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
}
]`
var priceFeedAbi ethAbi.ABI
// GetPrice using a Chainlink feed, caching the results in an internal
// server to make it thread safe
func GetPrice(client *ethclient.Client, priceFeedAddress ethCommon.Address) (*big.Rat, error) {
log.Debug(func(k *log.Log) {
k.Context = Context
k.Format(
"Using the Chainlink decimals cache to look up decimals for price feed %v",
priceFeedAddress,
)
})
resp := make(chan *big.Rat)
decimalsServer <- request{
client: client,
priceFeedAddress: priceFeedAddress,
resp: resp,
}
decimals := <-resp
priceRes, err := ethereum.StaticCall(
client,
priceFeedAddress,
priceFeedAbi,
"latestRoundData",
)
if err != nil {
return nil, fmt.Errorf(
"Failed to get latestRoundData! %w",
err,
)
}
if count := len(priceRes); count != 5 {
return nil, fmt.Errorf(
"returned results for latestRoundData did not have length of 5! was %v",
count,
)
}
price, ok := priceRes[1].(*big.Int)
if !ok {
return nil, fmt.Errorf(
"failed to read a *big.Int from the result of latestRoundData!",
)
}
priceRat := new(big.Rat).SetInt(price)
priceRat.Quo(priceRat, decimals)
return priceRat, nil
}