Archived
1
0
Fork 0

fix: Convert big integers to float64

Large numbers can be returned by the Flexpool API reaching the `int64`
limit. Blocks reward were seen as 0 ETH. Using `float64` instead. Also
converting signed int64 to unsigned int64 for non-timestamp numbers.

BREAKING CHANGE: please follow the upgrades instructions from 1.2 to
1.3 to convert such types in the database.

Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
Julien Riou 2021-10-15 18:20:38 +02:00
parent ac0903cf9d
commit 3d4c049323
No known key found for this signature in database
GPG key ID: FF42D23B580C89F7
7 changed files with 63 additions and 25 deletions

View file

@ -1,9 +1,19 @@
# General notes
In the next commands, you should replace `flexassistant.db` by the content of the `database_file` setting if it's has been changed.
# 1.2 to 1.3
The balance has reached maximum of **int64** type so the column should be converted to **real** to handle large numbers:
```
sqlite3 flexassistant.db < migrations/1.2_to_1.3.sql
```
# 1.0 to 1.1 # 1.0 to 1.1
Some numeric types have been updated from **float64** to **int64**. Upgrade the database types by running the following migration: Some numeric types have been updated from **float64** to **int64**. Upgrade the database types by running the following migration:
``` ```
sqlite3 flexassistant.db < migrations/1.0_to_1.1.sql sqlite3 flexassistant.db < migrations/1.0_to_1.1.sql
``` ```
And replace `flexassistant.db` by the content of the `database_file` setting if it's has been changed.

View file

@ -66,12 +66,12 @@ func (f *FlexpoolClient) request(url string) ([]byte, error) {
type BalanceResponse struct { type BalanceResponse struct {
Error string `json:"error"` Error string `json:"error"`
Result struct { Result struct {
Balance int64 `json:"balance"` Balance float64 `json:"balance"`
} `json:"result"` } `json:"result"`
} }
// MinerBalance returns the current unpaid balance // MinerBalance returns the current unpaid balance
func (f *FlexpoolClient) MinerBalance(coin string, address string) (int64, error) { func (f *FlexpoolClient) MinerBalance(coin string, address string) (float64, error) {
body, err := f.request(fmt.Sprintf("%s/miner/balance?coin=%s&address=%s", FlexpoolAPIURL, coin, address)) body, err := f.request(fmt.Sprintf("%s/miner/balance?coin=%s&address=%s", FlexpoolAPIURL, coin, address))
if err != nil { if err != nil {
return 0, err return 0, err
@ -87,9 +87,9 @@ type PaymentsResponse struct {
Error string `json:"error"` Error string `json:"error"`
Result struct { Result struct {
Data []struct { Data []struct {
Hash string `json:"hash"` Hash string `json:"hash"`
Value int64 `json:"value"` Value float64 `json:"value"`
Timestamp int64 `json:"timestamp"` Timestamp int64 `json:"timestamp"`
} `json:"data"` } `json:"data"`
} `json:"result"` } `json:"result"`
} }
@ -165,9 +165,9 @@ type BlocksResponse struct {
Error string `json:"error"` Error string `json:"error"`
Result struct { Result struct {
Data []struct { Data []struct {
Hash string `json:"hash"` Hash string `json:"hash"`
Number int64 `json:"number"` Number uint64 `json:"number"`
Reward int64 `json:"reward"` Reward float64 `json:"reward"`
} `json:"data"` } `json:"data"`
} `json:"result"` } `json:"result"`
} }

View file

@ -132,7 +132,7 @@ func main() {
log.Warnf("Could not fetch unpaid balance: %v", err) log.Warnf("Could not fetch unpaid balance: %v", err)
continue continue
} }
log.Debugf("Unpaid balance %d", balance) log.Debugf("Unpaid balance %.0f", balance)
miner.Balance = balance miner.Balance = balance
if miner.Balance != dbMiner.Balance { if miner.Balance != dbMiner.Balance {
dbMiner.Balance = balance dbMiner.Balance = balance

28
migrations/1.2_to_1.3.sql Normal file
View file

@ -0,0 +1,28 @@
-- Migrate from 1.2 to 1.3
-- SQLite doesn't support ALTER TABLE... ALTER TYPE
-- This migration file creates the new structures with "real" types
-- instead of "integer", move data to this new table then drop the old one.
-- miners
ALTER TABLE `miners` RENAME TO `miners_old`;
CREATE TABLE `miners` (
`id` integer,
`created_at` datetime,
`updated_at` datetime,
`deleted_at` datetime,
`coin` text,
`address` text NOT NULL UNIQUE,
`balance` real,
`last_payment_timestamp` integer,
PRIMARY KEY (`id`)
);
INSERT INTO `miners` SELECT * FROM `miners_old`;
DROP TABLE `miners_old`;
CREATE INDEX `idx_miners_deleted_at` ON `miners`(`deleted_at`);
SELECT "Database migrated to 1.3"

View file

@ -19,7 +19,7 @@ type Miner struct {
gorm.Model gorm.Model
Coin string Coin string
Address string `gorm:"unique;not null"` Address string `gorm:"unique;not null"`
Balance int64 Balance float64
LastPaymentTimestamp int64 LastPaymentTimestamp int64
} }
@ -56,12 +56,12 @@ func (m *Miner) String() string {
// Payment to store payment attributes // Payment to store payment attributes
type Payment struct { type Payment struct {
Hash string Hash string
Value int64 Value float64
Timestamp int64 Timestamp int64
} }
// NewPayment creates a Payment // NewPayment creates a Payment
func NewPayment(hash string, value int64, timestamp int64) *Payment { func NewPayment(hash string, value float64, timestamp int64) *Payment {
return &Payment{ return &Payment{
Hash: hash, Hash: hash,
Value: value, Value: value,

10
pool.go
View file

@ -10,7 +10,7 @@ import (
type Pool struct { type Pool struct {
gorm.Model gorm.Model
Coin string `gorm:"unique;not null"` Coin string `gorm:"unique;not null"`
LastBlockNumber int64 LastBlockNumber uint64
} }
// NewPool creates a Pool // NewPool creates a Pool
@ -25,13 +25,13 @@ func (p *Pool) String() string {
// Block to store block attributes // Block to store block attributes
type Block struct { type Block struct {
Hash string `gorm:"unique;not null"` Hash string `gorm:"unique;not null"`
Number int64 `gorm:"not null"` Number uint64 `gorm:"not null"`
Reward int64 `gorm:"not null"` Reward float64 `gorm:"not null"`
} }
// NewBlock creates a Block // NewBlock creates a Block
func NewBlock(hash string, number int64, reward int64) *Block { func NewBlock(hash string, number uint64, reward float64) *Block {
return &Block{ return &Block{
Hash: hash, Hash: hash,
Number: number, Number: number,

View file

@ -12,7 +12,7 @@ const MojoToXCHDivider = 1000000000000
// ConvertCurrency divides the smallest unit of the currency to the currency itself // ConvertCurrency divides the smallest unit of the currency to the currency itself
// Example: for "eth", convert from Weis to ETH // Example: for "eth", convert from Weis to ETH
func ConvertCurrency(coin string, value int64) (float64, error) { func ConvertCurrency(coin string, value float64) (float64, error) {
switch coin { switch coin {
case "eth": case "eth":
return ConvertWeis(value), nil return ConvertWeis(value), nil
@ -24,13 +24,13 @@ func ConvertCurrency(coin string, value int64) (float64, error) {
} }
// ConvertWeis converts the value from Weis to ETH // ConvertWeis converts the value from Weis to ETH
func ConvertWeis(value int64) float64 { func ConvertWeis(value float64) float64 {
return float64(value) / WeisToETHDivider return value / WeisToETHDivider
} }
// ConvertMojo converts the value from Mojo to XCH // ConvertMojo converts the value from Mojo to XCH
func ConvertMojo(value int64) float64 { func ConvertMojo(value float64) float64 {
return float64(value) / MojoToXCHDivider return value / MojoToXCHDivider
} }
// ConvertAction returns "Miner" for Ethereum and "Farmer" for Chia // ConvertAction returns "Miner" for Ethereum and "Farmer" for Chia