Skip to content

Commit a50021b

Browse files
author
krasi
committed
Merge remote-tracking branch 'tellor/main' into reporter-mtls-pr
2 parents 35e5ba3 + 1ccd739 commit a50021b

7 files changed

Lines changed: 80 additions & 142 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
The daemon loads environment variables from the current directory's `.env` file, or from `../.env` when run from a subdirectory. See [`env.example`](./env.example) for a complete starting point.
88

9-
Most CLI flags can also be provided as environment variables by uppercasing the flag name and replacing `-` or `.` with `_`, for example `--keyring-backend` becomes `KEYRING_BACKEND`. `LAYER_HOME` is preferred for the Layer home directory so the daemon does not accidentally use the shell's `HOME`.
9+
Most CLI flags can also be provided as environment variables by uppercasing the flag name and replacing `-` or `.` with `_`, for example `--keyring-backend` becomes `KEYRING_BACKEND` and `--from` becomes `FROM`. `LAYER_HOME` is preferred for the Layer home directory so the daemon does not accidentally use the shell's `HOME`.
1010

1111
Layer endpoint configuration can be provided with comma-separated environment variables:
1212

@@ -42,7 +42,7 @@ BRIDGE_CHAIN_RPC_NODES=https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY,https://
4242

4343
Ethereum mainnet custom query contract reads use the built-in mainnet endpoint templates by default. If `BRIDGE_CHAIN_RPC_NODES` points at a non-mainnet bridge chain such as Sepolia, set `ETH_MAINNET_RPC_NODES` to a comma-separated Ethereum mainnet endpoint list for custom queries.
4444

45-
Custom query API keys are read from the generated `custom_query_config.toml` entries that reference environment placeholders. The current built-in templates use `CMC_PRO_API_KEY`, `CGPRO_API_KEY`, and `SUBGRAPH_API_KEY`.
45+
Custom query API keys are read from the generated `custom_query_config.toml` entries that reference environment placeholders. The current built-in templates use `CMC_PRO_API_KEY`, `CGPRO_API_KEY`, and `SUBGRAPH_API_KEY`. Built-in Ethereum mainnet RPC URL templates also expand `INFURA_API_KEY` and `ALCHEMY_API_KEY` when `ETH_MAINNET_RPC_NODES` is not set (see [`env.example`](./env.example)).
4646

4747
## Task loops
4848

cmd/main.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ var rootCmd = &cobra.Command{
3939
}
4040
// Keep viper in sync for downstream consumers reading "home".
4141
viper.Set(flags.FlagHome, homePath)
42+
testMode := viper.GetBool("test")
43+
testQueryID := viper.GetString("test-query-id")
44+
prometheusPort := viper.GetInt("prometheus-port")
4245
logLevelstr := viper.GetString(flags.FlagLogLevel)
4346
configs.WriteDefaultPricefeedExchangeToml(homePath)
4447
configs.WriteDefaultMarketParamsToml(homePath)
@@ -131,12 +134,6 @@ var rootCmd = &cobra.Command{
131134
},
132135
}
133136

134-
var (
135-
prometheusPort int
136-
testMode bool
137-
testQueryID string
138-
)
139-
140137
func main() {
141138
daemonflags.AddDaemonFlagsToCmd(rootCmd)
142139
if err := rootCmd.Execute(); err != nil {
@@ -153,7 +150,7 @@ func init() {
153150
rootCmd.Flags().String(flags.FlagLogLevel, zerolog.InfoLevel.String(), "The logging level (trace|debug|info|warn|error|fatal|panic|disabled or '*:<level>,<key>:<level>')")
154151
rootCmd.Flags().String(flags.FlagBroadcastMode, flags.BroadcastSync, "Transaction broadcasting mode (sync|async)")
155152
rootCmd.Flags().String(flags.FlagNode, "", "<host>:<port> to CometBFT RPC interface for layer")
156-
rootCmd.Flags().IntVar(&prometheusPort, "prometheus-port", 26661, "Port to serve Prometheus metrics on (default 26661). Applicable only if telemetry is enabled in app.toml.")
153+
rootCmd.Flags().Int("prometheus-port", 26661, "Port to serve Prometheus metrics on (default 26661). Applicable only if telemetry is enabled in app.toml.")
157154

158155
// Price Guard Flags
159156
rootCmd.Flags().Bool("price-guard-enabled", false, "Enable price guard to prevent reporting prices that differ from last reported price by a given threshold")
@@ -162,8 +159,8 @@ func init() {
162159
rootCmd.Flags().Bool("price-guard-update-on-blocked", false, "Update last known price even if submission is blocked (default false)")
163160

164161
// Test mode flag
165-
rootCmd.Flags().BoolVar(&testMode, "test", false, "Test mode: verify price feed configurations and calculate medians without starting daemon")
166-
rootCmd.Flags().StringVar(&testQueryID, "test-query-id", "", "With --test, only run this custom query id (64-char hex); skips exchange/market tests. Exits non-zero if the query fails.")
162+
rootCmd.Flags().Bool("test", false, "Test mode: verify price feed configurations and calculate medians without starting daemon")
163+
rootCmd.Flags().String("test-query-id", "", "With --test, only run this custom query id (64-char hex); skips exchange/market tests. Exits non-zero if the query fails.")
167164
// Automatic Unbonding flags
168165
rootCmd.Flags().Uint32("auto-unbonding-frequency", 0, "Enable automatic unbonding every N days (0 = disabled, 1 - 21 days = valid)")
169166
rootCmd.Flags().Uint32("auto-unbonding-amount", 0, "Amount of tokens in loya to unbond each unbonding transaction (0 = disabled)")

cmd/viper_flags_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package main
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/spf13/cobra"
8+
"github.com/spf13/viper"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func bindViperForTest(t *testing.T, cmd *cobra.Command) {
13+
t.Helper()
14+
viper.Reset()
15+
require.NoError(t, viper.BindPFlags(cmd.Flags()))
16+
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_"))
17+
viper.AutomaticEnv()
18+
}
19+
20+
func TestViperReadsPrometheusPortFromEnv(t *testing.T) {
21+
t.Setenv("PROMETHEUS_PORT", "12345")
22+
23+
cmd := &cobra.Command{}
24+
cmd.Flags().Int("prometheus-port", 26661, "")
25+
bindViperForTest(t, cmd)
26+
27+
require.Equal(t, 12345, viper.GetInt("prometheus-port"))
28+
}
29+
30+
func TestViperReadsTestModeFlagsFromEnv(t *testing.T) {
31+
t.Setenv("TEST", "true")
32+
t.Setenv("TEST_QUERY_ID", "abc123")
33+
34+
cmd := &cobra.Command{}
35+
cmd.Flags().Bool("test", false, "")
36+
cmd.Flags().String("test-query-id", "", "")
37+
bindViperForTest(t, cmd)
38+
39+
require.True(t, viper.GetBool("test"))
40+
require.Equal(t, "abc123", viper.GetString("test-query-id"))
41+
}

custom_query/constants.go

Lines changed: 0 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -156,46 +156,6 @@ var StaticQueriesConfig = map[string]*QueryConfig{
156156
},
157157
},
158158
},
159-
"e010d752f28dcd2804004d0b57ab1bdc4eca092895d49160204120af11d15f3e": {
160-
ID: "e010d752f28dcd2804004d0b57ab1bdc4eca092895d49160204120af11d15f3e",
161-
AggregationMethod: "median",
162-
MinResponses: 1,
163-
MaxSpreadPercent: 100.0,
164-
ResponseType: "ufixed256x18",
165-
Endpoints: []EndpointConfig{
166-
{
167-
EndpointType: "coingeckoPro",
168-
ResponsePath: []string{"noble-dollar-usdn", "usd"},
169-
Params: map[string]string{
170-
"coin_id": "noble-dollar-usdn",
171-
},
172-
MarketId: "USDN-USD",
173-
},
174-
{
175-
EndpointType: "coinmarketcap",
176-
ResponsePath: []string{"data", "36538", "quote", "USD", "price"},
177-
Params: map[string]string{
178-
// "symbol": "USDN",
179-
"id": "36538",
180-
},
181-
MarketId: "USDN-USD",
182-
},
183-
{
184-
EndpointType: "osmosis",
185-
Handler: "osmosis_pool_price_handler",
186-
ResponsePath: []string{"pool"},
187-
Params: map[string]string{
188-
"pool_id": "3061",
189-
"target_token": "ibc/0C39BD03B5C57A1753A9B73164705871A9B549F1A5226CFD7E39BE7BF73CF8CF",
190-
"quote_token": "ibc/498A0751C798A0D9A389AA3691123DADA57DAA4FE165D5C75894505B876BA6E4",
191-
"target_decimals": "6",
192-
"quote_decimals": "6",
193-
},
194-
UsdViaID: exchange_common.USDCUSD_ID,
195-
MarketId: "USDN-USD",
196-
},
197-
},
198-
},
199159
"59ae85cec665c779f18255dd4f3d97821e6a122691ee070b9a26888bc2a0e45a": {
200160
ID: "59ae85cec665c779f18255dd4f3d97821e6a122691ee070b9a26888bc2a0e45a",
201161
AggregationMethod: "median",
@@ -229,21 +189,6 @@ var StaticQueriesConfig = map[string]*QueryConfig{
229189
},
230190
},
231191
},
232-
"35155b44678db9e9e021c2cf49dd20c31b49e03415325c2beffb5221cf63882d": {
233-
ID: "35155b44678db9e9e021c2cf49dd20c31b49e03415325c2beffb5221cf63882d",
234-
AggregationMethod: "median",
235-
MaxSpreadPercent: 10.0,
236-
MinResponses: 1,
237-
ResponseType: "ufixed256x18",
238-
Endpoints: []EndpointConfig{
239-
{
240-
EndpointType: "contract",
241-
Handler: "yieldfi_yusd_handler",
242-
Chain: "ethereum",
243-
MarketId: "YTOKEN-USD",
244-
},
245-
},
246-
},
247192
"03731257e35c49e44b267640126358e5decebdd8f18b5e8f229542ec86e318cf": {
248193
ID: "03731257e35c49e44b267640126358e5decebdd8f18b5e8f229542ec86e318cf",
249194
AggregationMethod: "median",
@@ -394,21 +339,6 @@ var StaticQueriesConfig = map[string]*QueryConfig{
394339
},
395340
},
396341
},
397-
"91513b15db3cef441d52058b24412957f9cc8645c53aecf39446ac9b0d2dcca4": {
398-
ID: "91513b15db3cef441d52058b24412957f9cc8645c53aecf39446ac9b0d2dcca4",
399-
AggregationMethod: "median",
400-
MaxSpreadPercent: 10.0,
401-
MinResponses: 1,
402-
ResponseType: "ufixed256x18",
403-
Endpoints: []EndpointConfig{
404-
{
405-
EndpointType: "contract",
406-
Handler: "yieldfi_vyusd_handler",
407-
Chain: "ethereum",
408-
MarketId: "VYUSD-USD",
409-
},
410-
},
411-
},
412342
"187f74d310dc494e6efd928107713d4229cd319c2cf300224de02776090809f1": {
413343
ID: "187f74d310dc494e6efd928107713d4229cd319c2cf300224de02776090809f1",
414344
AggregationMethod: "median",
@@ -483,19 +413,4 @@ var StaticQueriesConfig = map[string]*QueryConfig{
483413
},
484414
},
485415
},
486-
"9874c1c7b7e76b78afdfdda6dcecef56edf6bf3d49d6d6ef2a98404ea2e04a59": {
487-
ID: "9874c1c7b7e76b78afdfdda6dcecef56edf6bf3d49d6d6ef2a98404ea2e04a59",
488-
AggregationMethod: "median",
489-
MaxSpreadPercent: 10.0,
490-
MinResponses: 1,
491-
ResponseType: "ufixed256x18",
492-
Endpoints: []EndpointConfig{
493-
{
494-
EndpointType: "contract",
495-
Handler: "yieldfi_yeth_handler",
496-
Chain: "ethereum",
497-
MarketId: "YIELDFI-YETH-USD",
498-
},
499-
},
500-
},
501416
}

custom_query/query_feed_comment.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ var combinedHandlerLabel = map[string]string{
4545

4646
// queryTargetAsset overrides inferred display names for specific query IDs.
4747
var queryTargetAsset = map[string]string{
48-
"35155b44678db9e9e021c2cf49dd20c31b49e03415325c2beffb5221cf63882d": "yUSD",
4948
"187f74d310dc494e6efd928107713d4229cd319c2cf300224de02776090809f1": "SUSN",
50-
"9874c1c7b7e76b78afdfdda6dcecef56edf6bf3d49d6d6ef2a98404ea2e04a59": "yETH",
5149
}
5250

5351
// ClassifyQueryFeed returns the feed type, target asset symbol, and collateral asset

custom_query/query_feed_comment_test.go

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,10 @@ func TestClassifyQueryFeed(t *testing.T) {
2020
feedType: customquery.FeedTypeMarket,
2121
target: "SDAI",
2222
},
23-
"e010d752f28dcd2804004d0b57ab1bdc4eca092895d49160204120af11d15f3e": {
24-
feedType: customquery.FeedTypeMarket,
25-
target: "USDN",
26-
},
2723
"59ae85cec665c779f18255dd4f3d97821e6a122691ee070b9a26888bc2a0e45a": {
2824
feedType: customquery.FeedTypeMarket,
2925
target: "SUSDS",
3026
},
31-
"35155b44678db9e9e021c2cf49dd20c31b49e03415325c2beffb5221cf63882d": {
32-
feedType: customquery.FeedTypeFundamental,
33-
target: "yUSD",
34-
collateral: "USDC",
35-
},
3627
"03731257e35c49e44b267640126358e5decebdd8f18b5e8f229542ec86e318cf": {
3728
feedType: customquery.FeedTypeFundamental,
3829
target: "SUSDE",
@@ -60,11 +51,6 @@ func TestClassifyQueryFeed(t *testing.T) {
6051
feedType: customquery.FeedTypeMarket,
6152
target: "stATOM",
6253
},
63-
"91513b15db3cef441d52058b24412957f9cc8645c53aecf39446ac9b0d2dcca4": {
64-
feedType: customquery.FeedTypeFundamental,
65-
target: "VYUSD",
66-
collateral: "USDC",
67-
},
6854
"187f74d310dc494e6efd928107713d4229cd319c2cf300224de02776090809f1": {
6955
feedType: customquery.FeedTypeFundamental,
7056
target: "SUSN",
@@ -75,11 +61,6 @@ func TestClassifyQueryFeed(t *testing.T) {
7561
target: "SFRXUSD",
7662
collateral: "FRX",
7763
},
78-
"9874c1c7b7e76b78afdfdda6dcecef56edf6bf3d49d6d6ef2a98404ea2e04a59": {
79-
feedType: customquery.FeedTypeFundamental,
80-
target: "yETH",
81-
collateral: "ETH",
82-
},
8364
}
8465

8566
for queryID, tc := range tests {
@@ -105,7 +86,6 @@ func TestGenerateFeedComment(t *testing.T) {
10586
tests := map[string]string{
10687
"05cddb6b67074aa61fcbe1d2fd5924e028bb699b506267df28c88f7deac4edc6": "SDAI/USD: (market) median of 3 sources.",
10788
"03731257e35c49e44b267640126358e5decebdd8f18b5e8f229542ec86e318cf": "SUSDE/USD: (fundamental) ratio from susde contract × USDE/USD pricefeed cache.",
108-
"35155b44678db9e9e021c2cf49dd20c31b49e03415325c2beffb5221cf63882d": "yUSD/USD: (fundamental) ratio from yieldfi-yusd contract × USDC/USD pricefeed cache.",
10989
"187f74d310dc494e6efd928107713d4229cd319c2cf300224de02776090809f1": "SUSN/USD: (fundamental) ratio from susn contract × median USN/USD from 3 sources.",
11090
"ab30caa3e7827a27c153063bce02c0b260b29c0c164040c003f0f9ec66002510": "SFRXUSD/USD: (fundamental) ratio from sfrxusd contract × median FRX/USD from 3 sources.",
11191
}

env.example

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,67 @@
11
# Copy to .env and fill in values for the features you want.
22
# .env is loaded from the current directory, or ../.env from subdirectories.
33

4-
# Reporter
4+
## REQUIRED VARIABLES ##
55
LAYER_HOME=/home/<reporter-username>/.layer
66
FROM=your-key-name
7-
KEYRING_BACKEND=file
7+
KEYRING_BACKEND=test
88
# KEYRING_PASSWORD_FILE=/etc/layer-daemons/reporter-keyring-password
9-
# BROADCAST_MODE=sync
10-
# LOG_LEVEL=info
11-
# PROMETHEUS_PORT=26661
129

1310
# Layer endpoints (comma-separated primary, then fallbacks)
14-
RPC_NODES=http://node_endpoint1:26657,http://node_endpoint2:26657
15-
GRPC_NODES=node1:9090,node2:9090
11+
RPC_NODES=http://node_endpoint1:26657,https://node_endpoint2:26657
12+
GRPC_NODES=0.0.0.0:9090,node2_ip:9090
1613

1714
# Bridge-chain RPC endpoints for token bridge reads
1815
BRIDGE_CHAIN_RPC_NODES=https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY,https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY
19-
# Optional Ethereum mainnet RPC endpoints for custom query contract reads.
20-
# Use this when BRIDGE_CHAIN_RPC_NODES points at a non-mainnet bridge chain such as Sepolia.
21-
# ETH_MAINNET_RPC_NODES=https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY,https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY
16+
# Ethereum mainnet RPC endpoints for custom query contract reads.
17+
ETH_MAINNET_RPC_NODES=https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY,https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY
2218

23-
# Optional local/custom-chain token bridge contract override
24-
# TOKEN_BRIDGE_TEST_CONTRACT=0x0000000000000000000000000000000000000000
19+
# Custom query API keys (endpoint auth and Ethereum mainnet RPC template expansion)
20+
CMC_PRO_API_KEY=your_coinmarketcap_api_key
21+
CGPRO_API_KEY=your_coingecko_pro_api_key
22+
SUBGRAPH_API_KEY=your_the_graph_api_key
23+
# Used by built-in Ethereum mainnet RPC templates when ETH_MAINNET_RPC_NODES is unset
24+
INFURA_API_KEY=YOUR_INFURA_API_KEY
25+
ALCHEMY_API_KEY=YOUR_ALCHEMY_API_KEY
26+
27+
## OPTIONAL VARIABLES ##
28+
# daemon settings:
29+
# BROADCAST_MODE=sync
30+
# LOG_LEVEL=info
31+
# PROMETHEUS_PORT=26661
2532

26-
# Reward withdrawals
33+
# Set Automatic Reward withdrawals:
2734
# REPORTERS_VALIDATOR_ADDRESS=tellorvaloper1...
2835
# WITHDRAW_FREQUENCY=43200
2936

30-
# Price guard
37+
# Price guard:
3138
# PRICE_GUARD_ENABLED=false
3239
# PRICE_GUARD_THRESHOLD=0.5 # 50%
3340
# PRICE_GUARD_MAX_AGE=1h
3441
# PRICE_GUARD_UPDATE_ON_BLOCKED=false
3542

36-
# Auto-unbonding
43+
# Auto-unbonding:
3744
# AUTO_UNBONDING_FREQUENCY=7
3845
# AUTO_UNBONDING_AMOUNT=1000000
3946
# AUTO_UNBONDING_MAX_STAKE_PERCENTAGE=0.1
4047

41-
# Auto balance-to-keep bridge
48+
# Auto balance-to-keep bridge:
4249
# AUTO_BALANCE_TO_KEEP=5000000
4350
# AUTO_BALANCE_EXECUTION_TIME=03:00
4451
# AUTO_BALANCE_BRIDGE_TO_ETH_ADDR=0x0000000000000000000000000000000000000000
4552

46-
# Gas estimate cache refresh
53+
# Gas estimate cache refresh:
4754
# REFRESH_GAS_ESTIMATES_INTERVAL=12h
4855

49-
# Daemon internals
56+
# Daemon internals:
5057
# UNIX_SOCKET_ADDRESS=/tmp/daemons.sock
5158
# PANIC_ON_DAEMON_FAILURE_ENABLED=true
5259
# MAX_DAEMON_UNHEALTHY_SECONDS=300
5360
# PRICE_DAEMON_LOOP_DELAY_MS=3000
5461

55-
# Custom query API keys
56-
CMC_PRO_API_KEY=your_coinmarketcap_api_key
57-
CGPRO_API_KEY=your_coingecko_pro_api_key
58-
SUBGRAPH_API_KEY=your_the_graph_api_key
59-
ALCHEMY_API_KEY=YOUR_ALCHEMY_API_KEY
60-
INFURA_API_KEY=YOUR_INFURA_API_KEY
62+
# for testing: local/custom-chain token bridge contract override:
63+
# TOKEN_BRIDGE_TEST_CONTRACT=0x0000000000000000000000000000000000000000
64+
65+
# Test mode (verify configs without starting the daemon):
66+
# TEST=true
67+
# TEST_QUERY_ID=0000000000000000000000000000000000000000000000000000000000000000

0 commit comments

Comments
 (0)