diff --git a/.gitignore b/.gitignore index c696239..487e7a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -etc bin flexassistant.yaml flexassistant.db \ No newline at end of file diff --git a/README.md b/README.md index 02f6199..7a8cced 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,3 @@ -# END OF LIFE NOTICE - -> **Flexpool.io will officially wind down its operations on November 1, 2023** - -[See the full -announcement](https://www.reddit.com/r/Flexpool/comments/16q72ul/action_required_flexpoolio_shutdown_notice_nov_1/). - # flexassistant [Flexpool.io](https://www.flexpool.io/) is a famous cryptocurrency mining or farming pool supporting @@ -61,57 +54,13 @@ ls -l bin/flexassistant ## Configuration -### Telegram - -Follow [this procedure](https://core.telegram.org/bots#3-how-do-i-create-a-bot) to create a bot `token`. - -Then you have two possible destinations to send messages: -* channel using a `channel_name` (string) -* chat using a `chat_id` (integer) - -For testing purpose, you should store the token in a variable for next sections: -``` -read -s TOKEN -``` - -#### Chat - -To get the chat identifier, you can send a message to your bot then read messages using the API: - -``` -curl -s -XGET "https://api.telegram.org/bot${TOKEN}/getUpdates" | jq -r ".result[].message.chat.id" -``` - -You can test to send messages to a chat with: - -``` -read CHAT_ID -curl -s -XGET "https://api.telegram.org/bot${TOKEN}/sendMessage?chat_id=${CHAT_ID}&text=hello" | jq -``` - -#### Channel - -Public channel names can be used (example: `@mychannel`). For private channels, you should use a `chat_id` instead. - -You can test to send messages to a channel with: - -``` -read CHANNEL_NAME -curl -s -XGET "https://api.telegram.org/bot${TOKEN}/sendMessage?chat_id=${CHANNEL_NAME}&text=hello" | jq -``` - -Don't forget to prefix the channel name with an `@`. - - -### flexassistant - *flexassistant* can be configured using a YaML file. By default, the `flexassistant.yaml` file is used but it can be another file provided by the `-config` argument. As a good start, you can copy the configuration file example: ``` -cp -p flexassistant.example.yaml flexassistant.yaml +cp -p flexassistant.yaml.example flexassistant.yaml ``` Then edit this file at will. @@ -122,13 +71,10 @@ Reference: * `max-blocks` (optional): maximum number of blocks to retreive from the API * `max-payments` (optional): maximum number of payments to retreive from the API * `pools` (optional): list of pools - * `coin`: coin of the pool (ex: `etc`, `eth`, `xch`) + * `coin`: coin of the pool (ex: `eth`, `xch`) * `enable-blocks` (optional): enable block notifications for this pool (disabled by default) - * `min-block-reward` (optional): send notifications when block reward has reached this minimum threshold in crypto - currency unit (ETH, XCH, etc) * `miners` (optional): list of miners and/or farmers * `address`: address of the miner or the farmer registered on the API - * `coin` (optional): coin of the miner (ex: `etc`, `eth`, `xch`) (deduced by default, can be wrong for `etc` coin) * `enable-balance` (optional): enable balance notifications (disabled by default) * `enable-payments` (optional): enable payments notifications (disabled by default) * `enable-offline-workers` (optional): enable offline/online notifications for associated workers (disabled by @@ -137,19 +83,12 @@ Reference: * `token`: token of the Telegram bot * `chat-id` (optional if `channel-name` is present): chat identifier to send Telegram notifications * `channel-name` (optional if `chat-id` is present): channel name to send Telegram notifications -* `notifications` (optional): Notifications configurations - * `balance` (optional): balance notifications settings - * `template` (optional): path to [template](https://pkg.go.dev/text/template) file - * `test` (optional): send a test notification - * `payment` (optional): payment notifications settings - * `template` (optional): path to [template](https://pkg.go.dev/text/template) file - * `test` (optional): send a test notification - * `block` (optional): block notification settings - * `template` (optional): path to [template](https://pkg.go.dev/text/template) file - * `test` (optional): send a test notification - * `offline-worker` (optional): offline workers notification settings - * `template` (optional): path to [template](https://pkg.go.dev/text/template) file - * `test` (optional): send a test notification +* `notification-templates` (optional): path to [template](https://pkg.go.dev/text/template) files for each notification + type + * `balance` (optional): path to template file to format balance notifications + * `payment` (optional): path to template file to format payment notifications + * `block` (optional): path to template file to format block notifications + * `offline-worker` (optional): path to template file to format offline worker notifications ## Templating @@ -172,7 +111,7 @@ The following **data** is available to templates: Default templates are available in the [templates](templates) directory. -Custom template files can be used with the `template` settings (see _Configuration_ section). +Custom template files can be used with the `notification-templates` settings (see _Configuration_ section). ## Usage diff --git a/VERSION b/VERSION index d3bdbdf..7e32cd5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.7 +1.3 diff --git a/client.go b/client.go index b38e775..b2f961d 100644 --- a/client.go +++ b/client.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "math/rand" "net/http" "sort" "time" @@ -87,8 +86,7 @@ func (f *FlexpoolClient) MinerBalance(coin string, address string) (float64, err type PaymentsResponse struct { Error string `json:"error"` Result struct { - TotalPages int `json:"totalPages"` - Data []struct { + Data []struct { Hash string `json:"hash"` Value float64 `json:"value"` Timestamp int64 `json:"timestamp"` @@ -99,9 +97,7 @@ type PaymentsResponse struct { // MinerPayments returns an ordered list of payments func (f *FlexpoolClient) MinerPayments(coin string, address string, limit int) (payments []*Payment, err error) { page := 0 - totalPages := 0 - - for page <= MaxIterations && len(payments) < limit { + for { body, err := f.request(fmt.Sprintf("%s/miner/payments/?coin=%s&address=%s&page=%d", FlexpoolAPIURL, coin, address, page)) if err != nil { return nil, err @@ -110,10 +106,6 @@ func (f *FlexpoolClient) MinerPayments(coin string, address string, limit int) ( var response PaymentsResponse json.Unmarshal(body, &response) - if totalPages == 0 { - totalPages = response.Result.TotalPages - } - for _, result := range response.Result.Data { payment := NewPayment( result.Hash, @@ -122,34 +114,18 @@ func (f *FlexpoolClient) MinerPayments(coin string, address string, limit int) ( ) payments = append(payments, payment) if len(payments) >= limit { - break + // sort by timestamp + sort.Slice(payments, func(p1, p2 int) bool { + return payments[p1].Timestamp > payments[p2].Timestamp + }) + return payments, nil } } - page++ - if page >= totalPages { - break + page = page + 1 + if page > MaxIterations { + return nil, fmt.Errorf("Max iterations of %d reached", MaxIterations) } } - - if page > MaxIterations { - return nil, fmt.Errorf("Max iterations of %d reached", MaxIterations) - } - - // Sort by timestamp - sort.Slice(payments, func(p1, p2 int) bool { - return payments[p1].Timestamp > payments[p2].Timestamp - }) - return payments, nil -} - -// LastMinerPayment return the last payment of a miner -func (f *FlexpoolClient) LastMinerPayment(miner *Miner) (*Payment, error) { - log.Debugf("Fetching last payment of %s", miner) - payments, err := f.MinerPayments(miner.Coin, miner.Address, 1) - if err != nil { - return nil, err - } - return payments[0], nil } // WorkersResponse represents the JSON structure of the Flexpool API response for workers @@ -188,8 +164,7 @@ func (f *FlexpoolClient) MinerWorkers(coin string, address string) (workers []*W type BlocksResponse struct { Error string `json:"error"` Result struct { - TotalPages int `json:"totalPages"` - Data []struct { + Data []struct { Hash string `json:"hash"` Number uint64 `json:"number"` Reward float64 `json:"reward"` @@ -200,9 +175,7 @@ type BlocksResponse struct { // PoolBlocks returns an ordered list of blocks func (f *FlexpoolClient) PoolBlocks(coin string, limit int) (blocks []*Block, err error) { page := 0 - totalPages := 0 - - for page <= MaxIterations && len(blocks) < limit { + for { body, err := f.request(fmt.Sprintf("%s/pool/blocks/?coin=%s&page=%d", FlexpoolAPIURL, coin, page)) if err != nil { return nil, err @@ -211,10 +184,6 @@ func (f *FlexpoolClient) PoolBlocks(coin string, limit int) (blocks []*Block, er var response BlocksResponse json.Unmarshal(body, &response) - if totalPages == 0 { - totalPages = response.Result.TotalPages - } - for _, result := range response.Result.Data { block := NewBlock( result.Hash, @@ -223,98 +192,16 @@ func (f *FlexpoolClient) PoolBlocks(coin string, limit int) (blocks []*Block, er ) blocks = append(blocks, block) if len(blocks) >= limit { - break + // sort by number + sort.Slice(blocks, func(b1, b2 int) bool { + return blocks[b1].Number < blocks[b2].Number + }) + return blocks, nil } } - page++ - if page >= totalPages { - break + page = page + 1 + if page > MaxIterations { + return nil, fmt.Errorf("Max iterations of %d reached", MaxIterations) } } - if page > MaxIterations { - return nil, fmt.Errorf("Max iterations of %d reached", MaxIterations) - } - - // Sort by number - sort.Slice(blocks, func(b1, b2 int) bool { - return blocks[b1].Number < blocks[b2].Number - }) - return blocks, nil -} - -// LastPoolBlock return the last discovered block for a given pool -func (f *FlexpoolClient) LastPoolBlock(pool *Pool) (*Block, error) { - blocks, err := f.PoolBlocks(pool.Coin, 1) - if err != nil { - return nil, err - } - return blocks[0], nil -} - -// CoinsResponse represents the JSON structure of the Flexpool API response for pool coins -type CoinsResponse struct { - Error string `json:"error"` - Result struct { - Coins []struct { - Ticker string `json:"ticker"` - Name string `json:"name"` - } `json:"coins"` - } `json:"result"` -} - -// RandomPool returns a random pool from the API -func (f *FlexpoolClient) RandomPool() (*Pool, error) { - log.Debug("Fetching a random pool") - body, err := f.request(fmt.Sprintf("%s/pool/coins", FlexpoolAPIURL)) - if err != nil { - return nil, err - } - var response CoinsResponse - json.Unmarshal(body, &response) - randomIndex := rand.Intn(len(response.Result.Coins)) - if err != nil { - return nil, err - } - randomCoin := response.Result.Coins[randomIndex] - return NewPool(randomCoin.Ticker), nil -} - -// TopMinersResponse represents the JSON structure of the Flexpool API response for pool top miners -type TopMinersResponse struct { - Error string `json:"error"` - Result []struct { - Address string `json:"address"` - } `json:"result"` -} - -// RandomMiner returns a random miner from the API -func (f *FlexpoolClient) RandomMiner(pool *Pool) (*Miner, error) { - log.Debug("Fetching a random miner") - body, err := f.request(fmt.Sprintf("%s/pool/topMiners?coin=%s", FlexpoolAPIURL, pool.Coin)) - if err != nil { - return nil, err - } - var response TopMinersResponse - json.Unmarshal(body, &response) - randomResult := response.Result[rand.Intn(len(response.Result))] - randomMiner, err := NewMiner(randomResult.Address, pool.Coin) - if err != nil { - return nil, err - } - randomBalance, err := f.MinerBalance(pool.Coin, randomMiner.Address) - if err != nil { - return nil, err - } - randomMiner.Balance = randomBalance - return randomMiner, nil -} - -// RandomWorker returns a random worker from the API -func (f *FlexpoolClient) RandomWorker(miner *Miner) (*Worker, error) { - log.Debug("Fetching a random worker") - workers, err := f.MinerWorkers(miner.Coin, miner.Address) - if err != nil { - return nil, err - } - return workers[rand.Intn(len(workers))], nil } diff --git a/config.go b/config.go index 39afb32..6d3e7ab 100644 --- a/config.go +++ b/config.go @@ -8,26 +8,24 @@ import ( // Config to receive settings from the configuration file type Config struct { - DatabaseFile string `yaml:"database-file"` - MaxBlocks int `yaml:"max-blocks"` - MaxPayments int `yaml:"max-payments"` - Pools []PoolConfig `yaml:"pools"` - Miners []MinerConfig `yaml:"miners"` - TelegramConfig TelegramConfig `yaml:"telegram"` - Notifications NotificationsConfig `yaml:"notifications"` + DatabaseFile string `yaml:"database-file"` + MaxBlocks int `yaml:"max-blocks"` + MaxPayments int `yaml:"max-payments"` + Pools []PoolConfig `yaml:"pools"` + Miners []MinerConfig `yaml:"miners"` + TelegramConfig TelegramConfig `yaml:"telegram"` + NotificationTemplates NotificationTemplatesConfig `yaml:"notification-templates"` } // PoolConfig to store Pool configuration type PoolConfig struct { - Coin string `yaml:"coin"` - EnableBlocks bool `yaml:"enable-blocks"` - MinBlockReward float64 `yaml:"min-block-reward"` + Coin string `yaml:"coin"` + EnableBlocks bool `yaml:"enable-blocks"` } // MinerConfig to store Miner configuration type MinerConfig struct { Address string `yaml:"address"` - Coin string `yaml:"coin"` EnableBalance bool `yaml:"enable-balance"` EnablePayments bool `yaml:"enable-payments"` EnableOfflineWorkers bool `yaml:"enable-offline-workers"` @@ -40,18 +38,12 @@ type TelegramConfig struct { ChannelName string `yaml:"channel-name"` } -// NotificationTemplatesConfig to store all notifications configurations -type NotificationsConfig struct { - Balance NotificationConfig `yaml:"balance"` - Payment NotificationConfig `yaml:"payment"` - Block NotificationConfig `yaml:"block"` - OfflineWorker NotificationConfig `yaml:"offline-worker"` -} - -// NotificationConfig to store a single notification configuration -type NotificationConfig struct { - Template string `yaml:"template"` - Test bool `yaml:"test"` +// NotificationTemplatesConfig to store notifications templates configuration +type NotificationTemplatesConfig struct { + Balance string `yaml:"balance"` + Payment string `yaml:"payment"` + Block string `yaml:"block"` + OfflineWorker string `yaml:"offline-worker"` } // NewConfig creates a Config with default values diff --git a/flexassistant.example.yaml b/flexassistant.yaml.example similarity index 59% rename from flexassistant.example.yaml rename to flexassistant.yaml.example index 1470e55..a4586d4 100644 --- a/flexassistant.example.yaml +++ b/flexassistant.yaml.example @@ -4,36 +4,24 @@ max-blocks: 10 max-payments: 5 miners: - address: 0x0000000000000000000000000000000000000000 - coin: eth enable-balance: true enable-payments: true enable-offline-workers: true - address: xch00000000000000000000000000000000000000000000000000000000000 - coin: xch enable-balance: true enable-payments: true enable-offline-workers: true pools: - coin: eth enable-blocks: true - min-block-reward: 10 - coin: xch enable-blocks: true - min-block-reward: 1.79 telegram: chat-id: 000000000 - channel-name: '@MyTelegramChannel' + channel-name: MyTelegramChannel token: 0000000000000000000000000000000000000000000000 -#notifications: -# balance: -# template: balance.tmpl -# test: true -# block: -# template: block.tmpl -# test: true -# offline-worker: -# template: offline-worker.tmpl -# test: true -# payment: -# template: payment.tmpl -# test: true +notification-templates: + balance: balance.tmpl + block: block.tmpl + offline-worker; offline-worker.tmpl + payment: payment.tmpl \ No newline at end of file diff --git a/main.go b/main.go index f98ce5f..6d426a5 100644 --- a/main.go +++ b/main.go @@ -3,9 +3,7 @@ package main import ( "flag" "fmt" - "math/rand" "os" - "time" log "github.com/sirupsen/logrus" "gorm.io/gorm" @@ -32,7 +30,6 @@ const MaxBlocks = 50 // initialize logging func init() { log.SetOutput(os.Stdout) - rand.Seed(time.Now().UnixNano()) } func main() { @@ -87,20 +84,11 @@ func main() { client := NewFlexpoolClient() // Notifications - notifier, err := NewTelegramNotifier(&config.TelegramConfig, &config.Notifications) + notifier, err := NewTelegramNotifier(&config.TelegramConfig, &config.NotificationTemplates) if err != nil { log.Fatalf("Could not create notifier: %v", err) } - executed, err := notifier.NotifyTest(*client) - if err != nil { - log.Fatalf("Could not send test notifications: %v", err) - } - if executed { - log.Debug("Exit after sending test notifications") - return - } - // Limits var maxPayments int if config.MaxPayments > 0 { @@ -118,7 +106,7 @@ func main() { // Handle miners for _, configuredMiner := range config.Miners { - miner, err := NewMiner(configuredMiner.Address, configuredMiner.Coin) + miner, err := NewMiner(configuredMiner.Address) if err != nil { log.Warnf("Could not parse miner: %v", err) continue @@ -275,11 +263,7 @@ func main() { log.Warnf("Cannot update pool: %v", trx.Error) continue } - convertedReward, err := ConvertCurrency(pool.Coin, block.Reward) - if err != nil { - log.Warnf("Reward for block %d cannot be converted: %v", block.Number, err) - } - if notify && convertedReward >= configuredPool.MinBlockReward { + if notify { err = notifier.NotifyBlock(*pool, *block) if err != nil { log.Warnf("Cannot send notification: %v", err) diff --git a/miner.go b/miner.go index cfbb08b..65466d6 100644 --- a/miner.go +++ b/miner.go @@ -24,15 +24,13 @@ type Miner struct { } // NewMiner creates a Miner -func NewMiner(address string, coin string) (*Miner, error) { - miner := &Miner{Address: address, Coin: coin} - if coin == "" { - coin, err := miner.ParseCoin() - if err != nil { - return nil, err - } - miner.Coin = coin +func NewMiner(address string) (*Miner, error) { + miner := &Miner{Address: address} + coin, err := miner.ParseCoin() + if err != nil { + return nil, err } + miner.Coin = coin return miner, nil } diff --git a/notification.go b/notification.go index ffca65d..6cf6a17 100644 --- a/notification.go +++ b/notification.go @@ -32,20 +32,19 @@ type Notifier interface { NotifyPayment(miner Miner, payment Payment) error NotifyBlock(pool Pool, block Block) error NotifyOfflineWorker(worker Worker) error - NotifyTest(client FlexpoolClient) error } // TelegramNotifier to send notifications using Telegram // Implements the Notifier interface type TelegramNotifier struct { - bot *telegram.BotAPI - chatID int64 - channelName string - configurations *NotificationsConfig + bot *telegram.BotAPI + chatID int64 + channelName string + templatesConfig *NotificationTemplatesConfig } // NewTelegramNotifier to create a TelegramNotifier -func NewTelegramNotifier(config *TelegramConfig, configurations *NotificationsConfig) (*TelegramNotifier, error) { +func NewTelegramNotifier(config *TelegramConfig, templatesConfig *NotificationTemplatesConfig) (*TelegramNotifier, error) { bot, err := telegram.NewBotAPI(config.Token) if err != nil { return nil, err @@ -53,10 +52,10 @@ func NewTelegramNotifier(config *TelegramConfig, configurations *NotificationsCo log.Debugf("Connected to Telegram as %s", bot.Self.UserName) return &TelegramNotifier{ - bot: bot, - chatID: config.ChatID, - channelName: config.ChannelName, - configurations: configurations, + bot: bot, + chatID: config.ChatID, + channelName: config.ChannelName, + templatesConfig: templatesConfig, }, nil } @@ -126,8 +125,8 @@ func fileExists(filename string) bool { // Implements the Notifier interface func (t *TelegramNotifier) NotifyBalance(miner Miner) (err error) { templateName := "templates/balance.tmpl" - if t.configurations.Balance.Template != "" { - templateName = t.configurations.Balance.Template + if t.templatesConfig.Balance != "" { + templateName = t.templatesConfig.Balance } message, err := t.formatMessage(templateName, Attachment{Miner: miner}) if err != nil { @@ -136,26 +135,12 @@ func (t *TelegramNotifier) NotifyBalance(miner Miner) (err error) { return t.sendMessage(message) } -// testNotifyBalance sends a fake balance notification -func (t *TelegramNotifier) testNotifyBalance(client FlexpoolClient) error { - log.Debug("Testing balance notification") - randomPool, err := client.RandomPool() - if err != nil { - return err - } - randomMiner, err := client.RandomMiner(randomPool) - if err != nil { - return err - } - return t.NotifyBalance(*randomMiner) -} - // NotifyPayment to format and send a notification when a new payment has been detected // Implements the Notifier interface func (t *TelegramNotifier) NotifyPayment(miner Miner, payment Payment) error { templateName := "templates/payment.tmpl" - if t.configurations.Payment.Template != "" { - templateName = t.configurations.Payment.Template + if t.templatesConfig.Payment != "" { + templateName = t.templatesConfig.Payment } message, err := t.formatMessage(templateName, Attachment{Miner: miner, Payment: payment}) if err != nil { @@ -164,30 +149,12 @@ func (t *TelegramNotifier) NotifyPayment(miner Miner, payment Payment) error { return t.sendMessage(message) } -// testNotifyPayment sends a fake payment notification -func (t *TelegramNotifier) testNotifyPayment(client FlexpoolClient) error { - log.Debug("Testing payment notification") - randomPool, err := client.RandomPool() - if err != nil { - return err - } - randomMiner, err := client.RandomMiner(randomPool) - if err != nil { - return err - } - randomPayment, err := client.LastMinerPayment(randomMiner) - if err != nil { - return err - } - return t.NotifyPayment(*randomMiner, *randomPayment) -} - // NotifyBlock to format and send a notification when a new block has been detected // Implements the Notifier interface func (t *TelegramNotifier) NotifyBlock(pool Pool, block Block) error { templateName := "templates/block.tmpl" - if t.configurations.Block.Template != "" { - templateName = t.configurations.Block.Template + if t.templatesConfig.Block != "" { + templateName = t.templatesConfig.Block } message, err := t.formatMessage(templateName, Attachment{Pool: pool, Block: block}) if err != nil { @@ -196,25 +163,11 @@ func (t *TelegramNotifier) NotifyBlock(pool Pool, block Block) error { return t.sendMessage(message) } -// testNotifyBlock sends a random block notification -func (t *TelegramNotifier) testNotifyBlock(client FlexpoolClient) error { - log.Debug("Testing block notification") - randomPool, err := client.RandomPool() - if err != nil { - return err - } - randomBlock, err := client.LastPoolBlock(randomPool) - if err != nil { - return err - } - return t.NotifyBlock(*randomPool, *randomBlock) -} - // NotifyOfflineWorker sends a message when a worker is online or offline func (t *TelegramNotifier) NotifyOfflineWorker(worker Worker) error { templateName := "templates/offline-worker.tmpl" - if t.configurations.OfflineWorker.Template != "" { - templateName = t.configurations.OfflineWorker.Template + if t.templatesConfig.OfflineWorker != "" { + templateName = t.templatesConfig.OfflineWorker } message, err := t.formatMessage(templateName, Attachment{Worker: worker}) if err != nil { @@ -222,58 +175,3 @@ func (t *TelegramNotifier) NotifyOfflineWorker(worker Worker) error { } return t.sendMessage(message) } - -// testNotifyOfflineWorker sends a fake worker offline notification -func (t *TelegramNotifier) testNotifyOfflineWorker(client FlexpoolClient) error { - log.Debug("Testing offline worker notification") - randomBlock, err := client.RandomPool() - if err != nil { - return err - } - randomMiner, err := client.RandomMiner(randomBlock) - if err != nil { - return err - } - randomWorker, err := client.RandomWorker(randomMiner) - if err != nil { - return err - } - log.Debugf("%s", randomWorker) - return t.NotifyOfflineWorker(*randomWorker) -} - -// NotifyTest sends fake notifications -func (t *TelegramNotifier) NotifyTest(client FlexpoolClient) (executed bool, err error) { - if t.configurations.Balance.Test { - if err = t.testNotifyBalance(client); err != nil { - return false, err - } else { - executed = true - } - } - - if t.configurations.Payment.Test { - if err = t.testNotifyPayment(client); err != nil { - return false, err - } else { - executed = true - } - } - - if t.configurations.Block.Test { - if err = t.testNotifyBlock(client); err != nil { - return false, err - } else { - executed = true - } - } - - if t.configurations.OfflineWorker.Test { - if err = t.testNotifyOfflineWorker(client); err != nil { - return false, err - } else { - executed = true - } - } - return executed, nil -} diff --git a/utils.go b/utils.go index 97895e2..88c29dd 100644 --- a/utils.go +++ b/utils.go @@ -14,8 +14,6 @@ const MojoToXCHDivider = 1000000000000 // Example: for "eth", convert from Weis to ETH func ConvertCurrency(coin string, value float64) (float64, error) { switch coin { - case "etc": - return ConvertWeis(value), nil case "eth": return ConvertWeis(value), nil case "xch": @@ -38,8 +36,6 @@ func ConvertMojo(value float64) float64 { // FormatBlockURL returns the URL on the respective blockchain explorer given the coin and the block hash func FormatBlockURL(coin string, hash string) (string, error) { switch coin { - case "etc": - return fmt.Sprintf("https://etcblockexplorer.com/block/%s", hash), nil case "eth": return fmt.Sprintf("https://etherscan.io/block/%s", hash), nil case "xch": @@ -51,8 +47,6 @@ func FormatBlockURL(coin string, hash string) (string, error) { // FormatTransactionURL returns the URL on the respective blockchain explorer given the coin and the transaction hash func FormatTransactionURL(coin string, hash string) (string, error) { switch coin { - case "etc": - return fmt.Sprintf("https://etcblockexplorer.com/address/%s", hash), nil case "eth": return fmt.Sprintf("https://etherscan.io/tx/%s", hash), nil case "xch":