Add base for parsing config, wallets & trades
This commit is contained in:
parent
7328239ac1
commit
207b417c3d
19 changed files with 378 additions and 24 deletions
54
src/actions.cr
Normal file
54
src/actions.cr
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class Action
|
||||||
|
enum Type
|
||||||
|
Report
|
||||||
|
TextUi
|
||||||
|
WebUi
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.match(action)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(config : ConfigModel)
|
||||||
|
@config = config
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform
|
||||||
|
wallets = {} of Tuple(String,String) => Float32
|
||||||
|
@config.trades.each do |trade|
|
||||||
|
tr = trade.transaction
|
||||||
|
from_id = {tr.from.wallet, tr.from.sym}
|
||||||
|
to_id = {tr.to.wallet, tr.to.sym}
|
||||||
|
fee_id = {tr.from.wallet, tr.fee.sym}
|
||||||
|
|
||||||
|
wallets[from_id] ||= 0
|
||||||
|
wallets[fee_id] ||= 0
|
||||||
|
wallets[to_id] ||= 0
|
||||||
|
wallets[from_id] -= tr.from.amount
|
||||||
|
wallets[fee_id] -= tr.fee.amount
|
||||||
|
wallets[to_id] += tr.from.amount
|
||||||
|
|
||||||
|
pp tr
|
||||||
|
pp wallets
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ActionFactory
|
||||||
|
def self.build(options, config)
|
||||||
|
action_class = Action
|
||||||
|
[ReportAction, WebUiAction, TextUiAction].each do |cls|
|
||||||
|
action_class = cls if cls.match(options[:action])
|
||||||
|
end
|
||||||
|
action = action_class.new(config)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require "./actions/report"
|
||||||
|
require "./actions/tui"
|
||||||
|
require "./actions/web"
|
||||||
|
|
10
src/actions/report.cr
Normal file
10
src/actions/report.cr
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
require "../actions"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class ReportAction < Action
|
||||||
|
def self.match(action)
|
||||||
|
return (action == Action::Type::Report)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
10
src/actions/tui.cr
Normal file
10
src/actions/tui.cr
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
require "../actions"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class TextUiAction < Action
|
||||||
|
def self.match(action)
|
||||||
|
return (action == Action::Type::TextUi)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
10
src/actions/web.cr
Normal file
10
src/actions/web.cr
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
require "../actions"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class WebUiAction < Action
|
||||||
|
def self.match(action)
|
||||||
|
return (action == Action::Type::WebUi)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
130
src/cli.cr
130
src/cli.cr
|
@ -1,58 +1,144 @@
|
||||||
|
|
||||||
|
require "./models"
|
||||||
|
require "./actions"
|
||||||
|
require "./models"
|
||||||
|
|
||||||
module Hodler
|
module Hodler
|
||||||
class Cli
|
class Cli
|
||||||
alias Options = {
|
alias Options = {
|
||||||
wallet_file: String,
|
action: Action::Type,
|
||||||
|
verbose_enable: Bool,
|
||||||
|
config_file: String
|
||||||
}
|
}
|
||||||
|
|
||||||
# @config : Config?
|
property config : ConfigModel?
|
||||||
@options : Options?
|
property options : Options?
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
# @config = nil
|
@config = nil
|
||||||
@options = nil
|
@options = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_options(args) : Options
|
def self.parse_options(args) : Options
|
||||||
# default values
|
# default values
|
||||||
wallet_file = XDGBasedir.full_path("hodler/wallet.yml", :config, :read).as(String)
|
action = Action::Type::Report
|
||||||
|
config_file = XDGBasedir.full_path("hodler/wallet.yml", :config, :read).as(String)
|
||||||
|
verbose_enable = true
|
||||||
|
|
||||||
# parse
|
# parse
|
||||||
OptionParser.parse(args) do |parser|
|
OptionParser.parse(args) do |parser|
|
||||||
parser.banner = "Usage: hodler [arguments]"
|
parser.banner = "Usage: #{Version::PROGRAM} [options] [commands] [arguments]"
|
||||||
|
|
||||||
parser.on "-w WALLET_FILE", "--wallet=WALLET_FILE", "Use the following wallet file" do |file|
|
parser.separator
|
||||||
wallet_file = file
|
parser.separator "Options"
|
||||||
|
|
||||||
|
parser.on "-c CONFIG_FILE", "--config=CONFIG_FILE", "Use the following config file" do |file|
|
||||||
|
config_file = file
|
||||||
end
|
end
|
||||||
|
|
||||||
# parser.on "-f DOCKER_COMPOSE_YML", "--config=DOCKER_COMPOSE_YML", "Use the following docker-compose file" do |file|
|
parser.on "-v", "--verbose", "Be verbose" do
|
||||||
# docker_compose_yml = file
|
verbose_enable = !verbose_enable
|
||||||
# end
|
end
|
||||||
|
|
||||||
parser.on "-v", "--version", "Show version" do
|
parser.on "--version", "Show version" do
|
||||||
puts "version #{Version::VERSION}"
|
puts "version #{Version::VERSION}"
|
||||||
exit 0
|
exit 0
|
||||||
end
|
end
|
||||||
parser.on "-h", "--help", "Show help" do
|
|
||||||
|
parser.on "-h", "--help", "Show this help" do
|
||||||
puts parser
|
puts parser
|
||||||
exit 0
|
exit 0
|
||||||
end
|
end
|
||||||
|
|
||||||
complete_with "hodler", parser
|
parser.on "--completion", "Provide autocompletion for bash" do
|
||||||
|
# nothing here
|
||||||
|
end
|
||||||
|
complete_with Version::PROGRAM, parser
|
||||||
|
|
||||||
|
parser.separator
|
||||||
|
parser.separator "Commands"
|
||||||
|
|
||||||
|
parser.on("report", "Compute report") do
|
||||||
|
parser.banner = "Usage: #{Version::PROGRAM} list [arguments]"
|
||||||
|
action = Action::Type::Report
|
||||||
end
|
end
|
||||||
|
|
||||||
@options = {
|
parser.on("tui", "Run ncurses interactive UI") do
|
||||||
wallet_file: wallet_file
|
parser.banner = "Usage: #{Version::PROGRAM} tui [arguments]"
|
||||||
}
|
action = Action::Type::TextUi
|
||||||
|
end
|
||||||
|
|
||||||
return @options.as(Options)
|
parser.on("web", "Run web interactive UI") do
|
||||||
|
parser.banner = "Usage: #{Version::PROGRAM} web [arguments]"
|
||||||
|
action = Action::Type::WebUi
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.separator
|
||||||
|
|
||||||
|
parser.missing_option do |flag|
|
||||||
|
STDERR.puts parser
|
||||||
|
STDERR.puts "ERROR: #{flag} requires an argument.".colorize(:red)
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.invalid_option do |flag|
|
||||||
|
STDERR.puts parser
|
||||||
|
STDERR.puts "ERROR: #{flag} is not a valid option.".colorize(:red)
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.unknown_args do |unknown_args|
|
||||||
|
unknown_args = unknown_args - %w(report web tui)
|
||||||
|
next if unknown_args.empty?
|
||||||
|
|
||||||
|
STDERR.puts parser
|
||||||
|
STDERR.puts "ERROR: \"#{unknown_args[0]}\" is not a valid command.".colorize(:red)
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
verbose_enable: verbose_enable,
|
||||||
|
config_file: config_file,
|
||||||
|
action: action
|
||||||
|
}.as(Options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.parse_config(options)
|
||||||
|
puts "Loading configuration...".colorize(:yellow) if options[:verbose_enable]
|
||||||
|
config_file = options[:config_file]
|
||||||
|
|
||||||
|
if ! File.exists? config_file
|
||||||
|
STDERR.puts "ERROR: Unable to read configuration file '#{config_file}'".colorize(:red)
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
yaml_str = File.read(config_file)
|
||||||
|
config = ConfigModel.from_yaml(yaml_str)
|
||||||
|
|
||||||
|
if config.nil?
|
||||||
|
STDERR.puts "ERROR: Invalid YAML content in '#{config_file}'"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return config
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.run(args)
|
def self.run(args)
|
||||||
app = Cli.new
|
app = Cli.new
|
||||||
app.parse_options(args)
|
options = Cli.parse_options(args)
|
||||||
# config = app.load_config(opts["config_file"])
|
config = Cli.parse_config(options)
|
||||||
# env_config = App.get_config(config, opts["environment"])
|
app.options = options
|
||||||
|
app.config = config
|
||||||
|
|
||||||
|
portfolio = PortfolioFactory.build(options, config)
|
||||||
|
|
||||||
|
action = ActionFactory.build(options, config)
|
||||||
|
action.perform
|
||||||
|
|
||||||
|
rescue ex : YAML::ParseException
|
||||||
|
STDERR.puts "ERROR: #{ex.message}".colorize(:red)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,10 +5,10 @@ require "colorize"
|
||||||
require "xdg_basedir"
|
require "xdg_basedir"
|
||||||
require "completion"
|
require "completion"
|
||||||
|
|
||||||
# require "./config"
|
|
||||||
require "./version"
|
require "./version"
|
||||||
|
require "./types"
|
||||||
|
require "./models"
|
||||||
require "./cli"
|
require "./cli"
|
||||||
|
|
||||||
|
|
||||||
Hodler::Cli.run(ARGV)
|
Hodler::Cli.run(ARGV)
|
||||||
|
|
||||||
|
|
21
src/models.cr
Normal file
21
src/models.cr
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
require "yaml"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class Model
|
||||||
|
include YAML::Serializable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require "./types"
|
||||||
|
require "./models/config"
|
||||||
|
require "./models/deposit"
|
||||||
|
require "./models/fee_trade"
|
||||||
|
require "./models/portfolio"
|
||||||
|
require "./models/ref_wallet"
|
||||||
|
require "./models/trade"
|
||||||
|
require "./models/transaction_trade"
|
||||||
|
require "./models/ui_config"
|
||||||
|
require "./models/wallet"
|
||||||
|
require "./models/wallet_value_trade"
|
||||||
|
|
13
src/models/config.cr
Normal file
13
src/models/config.cr
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class ConfigModel < Model
|
||||||
|
|
||||||
|
property version : String
|
||||||
|
property ui : UiConfigModel
|
||||||
|
property wallets : Array(WalletModel)
|
||||||
|
property deposits : Array(DepositModel)
|
||||||
|
property trades : Array(TradeModel)
|
||||||
|
end
|
||||||
|
end
|
12
src/models/deposit.cr
Normal file
12
src/models/deposit.cr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class DepositModel < Model
|
||||||
|
include YAML::Serializable
|
||||||
|
|
||||||
|
property id : String?
|
||||||
|
property date : String
|
||||||
|
property deposit : WalletValueTradeModel
|
||||||
|
end
|
||||||
|
end
|
9
src/models/fee_trade.cr
Normal file
9
src/models/fee_trade.cr
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class FeeTradeModel < Model
|
||||||
|
property amount : AmountT
|
||||||
|
property sym : String
|
||||||
|
end
|
||||||
|
end
|
36
src/models/portfolio.cr
Normal file
36
src/models/portfolio.cr
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class PortfolioModel < Model
|
||||||
|
|
||||||
|
property wallets : Array(WalletModel)
|
||||||
|
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@wallets = [] of WalletModel
|
||||||
|
end
|
||||||
|
|
||||||
|
def import_wallets(wallets : Array(WalletModel))
|
||||||
|
wallets.each do |wallet_config|
|
||||||
|
wallet = WalletModel.new(wallet_config.name, wallet_config.type)
|
||||||
|
# wallet.import(wallet_config)
|
||||||
|
pp wallet_config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_wallet
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_wallet
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class PortfolioFactory
|
||||||
|
def self.build(options : Cli::Options, config : ConfigModel)
|
||||||
|
portfolio = PortfolioModel.new
|
||||||
|
|
||||||
|
portfolio.import_wallets(config.wallets)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
10
src/models/ref_wallet.cr
Normal file
10
src/models/ref_wallet.cr
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class RefWalletModel < Model
|
||||||
|
|
||||||
|
property sym : String
|
||||||
|
property address : String?
|
||||||
|
end
|
||||||
|
end
|
12
src/models/trade.cr
Normal file
12
src/models/trade.cr
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class TradeModel < Model
|
||||||
|
include YAML::Serializable
|
||||||
|
|
||||||
|
property id : String?
|
||||||
|
property date : String
|
||||||
|
property transaction : TransactionTradeModel
|
||||||
|
end
|
||||||
|
end
|
11
src/models/transaction_trade.cr
Normal file
11
src/models/transaction_trade.cr
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
require "yaml"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class TransactionTradeModel < Model
|
||||||
|
property from : WalletValueTradeModel
|
||||||
|
property to : WalletValueTradeModel
|
||||||
|
property fee : FeeTradeModel
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
11
src/models/ui_config.cr
Normal file
11
src/models/ui_config.cr
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class UiConfigModel < Model
|
||||||
|
|
||||||
|
property refresh_per_sec : UInt32
|
||||||
|
property default_sym : String
|
||||||
|
property columns : Array(String)
|
||||||
|
end
|
||||||
|
end
|
34
src/models/wallet.cr
Normal file
34
src/models/wallet.cr
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class WalletModel < Model
|
||||||
|
enum Type
|
||||||
|
Web
|
||||||
|
Software
|
||||||
|
Cold
|
||||||
|
end
|
||||||
|
|
||||||
|
property name : String
|
||||||
|
property type : Type
|
||||||
|
property refs : Array(RefWalletModel)
|
||||||
|
|
||||||
|
def initialize(name, type : Type)
|
||||||
|
@name = name
|
||||||
|
@type = type
|
||||||
|
@refs = [] of RefWalletModel
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_symbol
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_symbol
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_transaction
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_transaction
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
10
src/models/wallet_value_trade.cr
Normal file
10
src/models/wallet_value_trade.cr
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
class WalletValueTradeModel < Model
|
||||||
|
property wallet : String
|
||||||
|
property amount : AmountT
|
||||||
|
property sym : String
|
||||||
|
end
|
||||||
|
end
|
4
src/types.cr
Normal file
4
src/types.cr
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
module Hodler
|
||||||
|
alias AmountT = Float32 | Int32
|
||||||
|
end
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
module Hodler
|
module Hodler
|
||||||
class Version
|
class Version
|
||||||
|
PROGRAM = "hodler"
|
||||||
VERSION = "0.1.0"
|
VERSION = "0.1.0"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue