coffer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +43 -0
- data/Rakefile +1 -0
- data/Vagrantfile +122 -0
- data/bin/coffer +6 -0
- data/coffer.gemspec +28 -0
- data/coins/auroracoin.rb +18 -0
- data/coins/bottlecaps.rb +12 -0
- data/coins/dogecoin.rb +22 -0
- data/coins/feathercoin.rb +20 -0
- data/coins/fedoracoin.rb +18 -0
- data/coins/litecoin.rb +14 -0
- data/coins/megacoin.rb +12 -0
- data/coins/mincoin.rb +12 -0
- data/coins/worldcoin.rb +13 -0
- data/lib/coffer/cli.rb +72 -0
- data/lib/coffer/configuration.rb +19 -0
- data/lib/coffer/definition.rb +137 -0
- data/lib/coffer/installer.rb +186 -0
- data/lib/coffer/registry.rb +60 -0
- data/lib/coffer/version.rb +3 -0
- data/lib/coffer.rb +8 -0
- data/newcoin.sh +28 -0
- data/run_test.rb +20 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7ca2c5d3113286b6f76e188960d077dd9728d231
|
4
|
+
data.tar.gz: 7fb1cbda0e8b230158d2805a23b6439e3a724e57
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0ec5974676159236f78a7f49ab098feb28efca2c9f10d3664b2572bdbd10a2326b9793b9dae1fb74a63ee6481b1640d69fdfd754710826038a4893e73646df47
|
7
|
+
data.tar.gz: df82ed776d4cf9b768fd422e9e73c8847d73de93c2c07a31a2d37fbc3ea95eabc775ebf31f99a6424ca9468befbbfeca27c5d125aa4e4e9ace81e2ba783d52fe
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Spike Grobstein
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Coffer
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'coffer'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install coffer
|
18
|
+
|
19
|
+
## Requirements
|
20
|
+
|
21
|
+
On ubuntu:
|
22
|
+
|
23
|
+
* git
|
24
|
+
* build-essential
|
25
|
+
* libboost-all-dev
|
26
|
+
* libssl-dev
|
27
|
+
* libdb++-dev
|
28
|
+
* libminiupnpc-dev
|
29
|
+
* autoconf
|
30
|
+
|
31
|
+
Probably ruby 2.x
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
TODO: Write usage instructions here
|
36
|
+
|
37
|
+
## Contributing
|
38
|
+
|
39
|
+
1. Fork it
|
40
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
41
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
42
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
43
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/Vagrantfile
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
5
|
+
VAGRANTFILE_API_VERSION = "2"
|
6
|
+
|
7
|
+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
8
|
+
# All Vagrant configuration is done here. The most common configuration
|
9
|
+
# options are documented and commented below. For a complete reference,
|
10
|
+
# please see the online documentation at vagrantup.com.
|
11
|
+
|
12
|
+
# Every Vagrant virtual environment requires a box to build off of.
|
13
|
+
config.vm.box = "https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-i386-vagrant-disk1.box"
|
14
|
+
|
15
|
+
# Disable automatic box update checking. If you disable this, then
|
16
|
+
# boxes will only be checked for updates when the user runs
|
17
|
+
# `vagrant box outdated`. This is not recommended.
|
18
|
+
# config.vm.box_check_update = false
|
19
|
+
|
20
|
+
# Create a forwarded port mapping which allows access to a specific port
|
21
|
+
# within the machine from a port on the host machine. In the example below,
|
22
|
+
# accessing "localhost:8080" will access port 80 on the guest machine.
|
23
|
+
# config.vm.network "forwarded_port", guest: 80, host: 8080
|
24
|
+
|
25
|
+
# Create a private network, which allows host-only access to the machine
|
26
|
+
# using a specific IP.
|
27
|
+
# config.vm.network "private_network", ip: "192.168.33.10"
|
28
|
+
|
29
|
+
# Create a public network, which generally matched to bridged network.
|
30
|
+
# Bridged networks make the machine appear as another physical device on
|
31
|
+
# your network.
|
32
|
+
# config.vm.network "public_network"
|
33
|
+
|
34
|
+
# If true, then any SSH connections made will enable agent forwarding.
|
35
|
+
# Default value: false
|
36
|
+
# config.ssh.forward_agent = true
|
37
|
+
|
38
|
+
# Share an additional folder to the guest VM. The first argument is
|
39
|
+
# the path on the host to the actual folder. The second argument is
|
40
|
+
# the path on the guest to mount the folder. And the optional third
|
41
|
+
# argument is a set of non-required options.
|
42
|
+
config.vm.synced_folder ".", "/home/vagrant/coffer"
|
43
|
+
|
44
|
+
# Provider-specific configuration so you can fine-tune various
|
45
|
+
# backing providers for Vagrant. These expose provider-specific options.
|
46
|
+
# Example for VirtualBox:
|
47
|
+
#
|
48
|
+
config.vm.provider "virtualbox" do |vb|
|
49
|
+
# Don't boot with headless mode
|
50
|
+
# vb.gui = true
|
51
|
+
|
52
|
+
# Use VBoxManage to customize the VM. For example to change memory:
|
53
|
+
vb.customize ["modifyvm", :id, "--memory", "2048"]
|
54
|
+
end
|
55
|
+
#
|
56
|
+
# View the documentation for the provider you're using for more
|
57
|
+
# information on available options.
|
58
|
+
|
59
|
+
# Enable provisioning with CFEngine. CFEngine Community packages are
|
60
|
+
# automatically installed. For example, configure the host as a
|
61
|
+
# policy server and optionally a policy file to run:
|
62
|
+
#
|
63
|
+
# config.vm.provision "cfengine" do |cf|
|
64
|
+
# cf.am_policy_hub = true
|
65
|
+
# # cf.run_file = "motd.cf"
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# You can also configure and bootstrap a client to an existing
|
69
|
+
# policy server:
|
70
|
+
#
|
71
|
+
# config.vm.provision "cfengine" do |cf|
|
72
|
+
# cf.policy_server_address = "10.0.2.15"
|
73
|
+
# end
|
74
|
+
|
75
|
+
# Enable provisioning with Puppet stand alone. Puppet manifests
|
76
|
+
# are contained in a directory path relative to this Vagrantfile.
|
77
|
+
# You will need to create the manifests directory and a manifest in
|
78
|
+
# the file default.pp in the manifests_path directory.
|
79
|
+
#
|
80
|
+
# config.vm.provision "puppet" do |puppet|
|
81
|
+
# puppet.manifests_path = "manifests"
|
82
|
+
# puppet.manifest_file = "site.pp"
|
83
|
+
# end
|
84
|
+
|
85
|
+
# Enable provisioning with chef solo, specifying a cookbooks path, roles
|
86
|
+
# path, and data_bags path (all relative to this Vagrantfile), and adding
|
87
|
+
# some recipes and/or roles.
|
88
|
+
#
|
89
|
+
# config.vm.provision "chef_solo" do |chef|
|
90
|
+
# chef.cookbooks_path = "../my-recipes/cookbooks"
|
91
|
+
# chef.roles_path = "../my-recipes/roles"
|
92
|
+
# chef.data_bags_path = "../my-recipes/data_bags"
|
93
|
+
# chef.add_recipe "mysql"
|
94
|
+
# chef.add_role "web"
|
95
|
+
#
|
96
|
+
# # You may also specify custom JSON attributes:
|
97
|
+
# chef.json = { mysql_password: "foo" }
|
98
|
+
# end
|
99
|
+
|
100
|
+
# Enable provisioning with chef server, specifying the chef server URL,
|
101
|
+
# and the path to the validation key (relative to this Vagrantfile).
|
102
|
+
#
|
103
|
+
# The Opscode Platform uses HTTPS. Substitute your organization for
|
104
|
+
# ORGNAME in the URL and validation key.
|
105
|
+
#
|
106
|
+
# If you have your own Chef Server, use the appropriate URL, which may be
|
107
|
+
# HTTP instead of HTTPS depending on your configuration. Also change the
|
108
|
+
# validation key to validation.pem.
|
109
|
+
#
|
110
|
+
# config.vm.provision "chef_client" do |chef|
|
111
|
+
# chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
|
112
|
+
# chef.validation_key_path = "ORGNAME-validator.pem"
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# If you're using the Opscode platform, your validator client is
|
116
|
+
# ORGNAME-validator, replacing ORGNAME with your organization name.
|
117
|
+
#
|
118
|
+
# If you have your own Chef Server, the default validation client name is
|
119
|
+
# chef-validator, unless you changed the configuration.
|
120
|
+
#
|
121
|
+
# chef.validation_client_name = "ORGNAME-validator"
|
122
|
+
end
|
data/bin/coffer
ADDED
data/coffer.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'coffer/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "coffer"
|
8
|
+
spec.version = Coffer::VERSION
|
9
|
+
spec.authors = ["Spike Grobstein"]
|
10
|
+
spec.email = ["me@spike.cx"]
|
11
|
+
spec.description = %q{Cryptocurrency wallet manager}
|
12
|
+
spec.summary = %q{Cryptocurrency wallet manager -- like homebrew, but for your wallets. Linux-only right now.}
|
13
|
+
spec.homepage = "https://github.com/spikegrobstein/coffer"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "pry"
|
24
|
+
|
25
|
+
spec.add_dependency 'activesupport'
|
26
|
+
spec.add_dependency 'git'
|
27
|
+
spec.add_dependency 'thor'
|
28
|
+
end
|
data/coins/auroracoin.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Coffer
|
2
|
+
module Coin
|
3
|
+
class Auroracoin < Coffer::Definition
|
4
|
+
|
5
|
+
git_repo 'https://github.com/baldurodinsson/auroracoin-project.git'
|
6
|
+
|
7
|
+
home_page 'http://auroracoin.org'
|
8
|
+
|
9
|
+
symbol :AUR
|
10
|
+
|
11
|
+
wallet_executable 'auroracoind'
|
12
|
+
directory 'auroracoin'
|
13
|
+
config_file 'auroracoin.conf'
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/coins/bottlecaps.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Coffer
|
2
|
+
module Coin
|
3
|
+
class Bottlecaps < Coffer::Definition
|
4
|
+
git_repo 'https://github.com/bottlecaps-foundation/bottlecaps.git'
|
5
|
+
home_page 'https://cryptocointalk.com/forum/242-bottlecaps-cap/'
|
6
|
+
symbol :CAP
|
7
|
+
wallet_executable 'bottlecapsd'
|
8
|
+
directory 'BottleCaps'
|
9
|
+
config_file 'BottleCaps.conf'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/coins/dogecoin.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# May have issues
|
2
|
+
|
3
|
+
module Coffer
|
4
|
+
module Coin
|
5
|
+
class Dogecoin < Coffer::Definition
|
6
|
+
git_repo 'https://github.com/dogecoin/dogecoin.git'
|
7
|
+
home_page 'http://dogecoin.com'
|
8
|
+
symbol :DOGE
|
9
|
+
wallet_executable 'dogecoind'
|
10
|
+
directory 'dogecoin'
|
11
|
+
config_file 'dogecoin.conf'
|
12
|
+
|
13
|
+
build <<-BUILD
|
14
|
+
./autogen.sh
|
15
|
+
./configure --with-incompatible-bdb
|
16
|
+
make
|
17
|
+
BUILD
|
18
|
+
|
19
|
+
build_dir '/'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Coffer
|
2
|
+
module Coin
|
3
|
+
class Feathercoin < Coffer::Definition
|
4
|
+
|
5
|
+
git_repo 'https://github.com/FeatherCoin/Feathercoin.git'
|
6
|
+
|
7
|
+
home_page 'https://www.feathercoin.com'
|
8
|
+
|
9
|
+
symbol :FTC
|
10
|
+
|
11
|
+
wallet_executable 'feathercoind'
|
12
|
+
|
13
|
+
directory 'feathercoin'
|
14
|
+
|
15
|
+
config_file 'feathercoin.conf'
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/coins/fedoracoin.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Coffer
|
2
|
+
module Coin
|
3
|
+
class Fedoracoin < Coffer::Definition
|
4
|
+
|
5
|
+
home_page 'http://fedoraco.in'
|
6
|
+
git_repo 'https://github.com/fedoracoin/fedoracoin.git'
|
7
|
+
|
8
|
+
symbol :TIPS
|
9
|
+
|
10
|
+
wallet_executable 'fedoracoind'
|
11
|
+
directory 'fedoracoin'
|
12
|
+
config_file 'fedoracoin.conf'
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/coins/litecoin.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Coffer
|
2
|
+
module Coin
|
3
|
+
class Litecoin < Coffer::Definition
|
4
|
+
git_branch 'master-0.8'
|
5
|
+
git_repo 'https://github.com/litecoin-project/litecoin.git'
|
6
|
+
home_page 'https://litecoin.org'
|
7
|
+
symbol :LTC
|
8
|
+
wallet_executable 'litecoind'
|
9
|
+
directory 'litecoin'
|
10
|
+
config_file 'litecoin.conf'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
data/coins/megacoin.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Coffer
|
2
|
+
module Coin
|
3
|
+
class Megacoin < Coffer::Definition
|
4
|
+
git_repo 'https://github.com/megacoin/megacoin.git'
|
5
|
+
home_page 'http://megacoin.co.nz'
|
6
|
+
symbol :MEC
|
7
|
+
wallet_executable 'megacoind'
|
8
|
+
directory 'Megacoin'
|
9
|
+
config_file 'megacoin.conf'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/coins/mincoin.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Coffer
|
2
|
+
module Coin
|
3
|
+
class Mincoin < Coffer::Definition
|
4
|
+
git_repo 'https://github.com/mincoin/mincoin.git'
|
5
|
+
home_page 'https://mincoin.io'
|
6
|
+
symbol :MNC
|
7
|
+
wallet_executable 'mincoind'
|
8
|
+
directory 'Mincoin'
|
9
|
+
config_file 'mincoind.conf'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/coins/worldcoin.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Coffer
|
2
|
+
module Coin
|
3
|
+
class Worldcoin < Coffer::Definition
|
4
|
+
git_branch 'v0.8.6.2'
|
5
|
+
git_repo 'https://github.com/worldcoinproject/worldcoin-v0.8.git'
|
6
|
+
home_page 'http://www.worldcoinalliance.net'
|
7
|
+
symbol :WDC
|
8
|
+
wallet_executable 'worldcoind'
|
9
|
+
directory 'Worldcoin'
|
10
|
+
config_file 'worldcoin.conf'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/coffer/cli.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'coffer'
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
module Coffer
|
6
|
+
class CLI < Thor
|
7
|
+
desc "list", "List all coins"
|
8
|
+
def list
|
9
|
+
Coffer::Registry.instance.coins.each do |coin|
|
10
|
+
puts "%-20s (%s)" % [ coin.name, coin.symbol ]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "search", "Search for coins"
|
15
|
+
def search
|
16
|
+
warn "not implemented"
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "install <coin>", "Install the given coin."
|
20
|
+
def install(coin)
|
21
|
+
coin = Coffer::Registry.instance.find( coin )
|
22
|
+
|
23
|
+
if coin.nil?
|
24
|
+
warn "Unable to find a coin with a name or symbol of #{ coin }"
|
25
|
+
end
|
26
|
+
|
27
|
+
warn "installing coin: #{ coin.name } (#{coin.symbol})"
|
28
|
+
|
29
|
+
installer = Coffer::Installer.new(coin)
|
30
|
+
if installer.install
|
31
|
+
puts "success!"
|
32
|
+
else
|
33
|
+
puts "Failed to install coin..."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "start <coin>", "Start the given coin."
|
38
|
+
def start(coin)
|
39
|
+
coin = Coffer::Registry.instance.find(coin)
|
40
|
+
|
41
|
+
if coin.nil?
|
42
|
+
warn "Unable to find a coin with a name or symbol of #{ coin }"
|
43
|
+
end
|
44
|
+
|
45
|
+
coin.start
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "stop <coin>", "Stop the given coin."
|
49
|
+
def stop(coin)
|
50
|
+
coin = Coffer::Registry.instance.find(coin)
|
51
|
+
|
52
|
+
if coin.nil?
|
53
|
+
warn "Unable to find a coin with a name or symbol of #{ coin }"
|
54
|
+
end
|
55
|
+
|
56
|
+
coin.stop
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.handle_no_command_error(command, has_namespace=$thor_runner)
|
60
|
+
coin = Coffer::Registry.instance.find(command)
|
61
|
+
|
62
|
+
if coin.nil?
|
63
|
+
# warn "Unable to find a coin with a name or symbol of #{ coin }"
|
64
|
+
super
|
65
|
+
return
|
66
|
+
end
|
67
|
+
|
68
|
+
ARGV.shift
|
69
|
+
coin.call_rpc( *ARGV )
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Coffer
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
attr_accessor :fields
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@fields = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add( key, value )
|
11
|
+
@fields << [ key, value ]
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_config
|
15
|
+
@fields.map { |f| f.join('=') }.join("\n")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
require 'coffer/configuration'
|
5
|
+
|
6
|
+
module Coffer
|
7
|
+
class Definition
|
8
|
+
|
9
|
+
attr_accessor :config
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
validate!
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate!
|
16
|
+
raise "Git repo required!" if @@git_repo.nil?
|
17
|
+
raise "wallet_executable required!" if @@wallet_executable.nil?
|
18
|
+
raise "directory required!" if @@directory.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def requirements
|
22
|
+
@@requirements
|
23
|
+
end
|
24
|
+
|
25
|
+
def name
|
26
|
+
self.class.name
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
|
31
|
+
def name
|
32
|
+
name = ActiveSupport::Inflector.demodulize(self)
|
33
|
+
name = ActiveSupport::Inflector.underscore(name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def config_field( key, value )
|
37
|
+
@config_fields ||= []
|
38
|
+
@config_fields << [key,value]
|
39
|
+
end
|
40
|
+
|
41
|
+
def executable_path
|
42
|
+
"/opt/coffer/bin/#{ wallet_executable }"
|
43
|
+
end
|
44
|
+
|
45
|
+
def installed?
|
46
|
+
File.exists? executable_path
|
47
|
+
end
|
48
|
+
|
49
|
+
# TODO: parse output and return
|
50
|
+
def call_rpc(*args)
|
51
|
+
pid = Process.spawn(
|
52
|
+
executable_path, *args
|
53
|
+
)
|
54
|
+
|
55
|
+
Process.wait pid
|
56
|
+
end
|
57
|
+
|
58
|
+
# TODO: figure out if launch was successful
|
59
|
+
def start
|
60
|
+
pid = Process.spawn(
|
61
|
+
executable_path, "-daemon",
|
62
|
+
:out => '/dev/null', :err => '/dev/null')
|
63
|
+
|
64
|
+
# Detach the spawned process
|
65
|
+
Process.detach pid
|
66
|
+
end
|
67
|
+
|
68
|
+
def stop
|
69
|
+
pid = Process.spawn(
|
70
|
+
executable_path, "stop",
|
71
|
+
:out => '/dev/null', :err => '/dev/null')
|
72
|
+
|
73
|
+
# Detach the spawned process
|
74
|
+
Process.detach pid
|
75
|
+
end
|
76
|
+
|
77
|
+
def build_config
|
78
|
+
return @config if @config
|
79
|
+
|
80
|
+
@config = Configuration.new
|
81
|
+
|
82
|
+
@config.add :rpcuser, 'cofferuser'
|
83
|
+
@config.add :rpcpassword, 'cofferpass'
|
84
|
+
@config.add :server, '1'
|
85
|
+
@config.add :rpcallowip, '127.0.0.1'
|
86
|
+
@config.add :listen, '1'
|
87
|
+
@config.add :port, '4444' #Coffer::Registry.port
|
88
|
+
|
89
|
+
# now custom fields
|
90
|
+
if @config_fields
|
91
|
+
fields.each do |f|
|
92
|
+
@config.add f[0], f[1]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
@config
|
97
|
+
end
|
98
|
+
|
99
|
+
def attr_field( name, default=nil )
|
100
|
+
@defaults ||= {}
|
101
|
+
@defaults[name] = default
|
102
|
+
|
103
|
+
@attr_fields ||= []
|
104
|
+
@attr_fields << name
|
105
|
+
|
106
|
+
instance_variable_set "@#{name}", default
|
107
|
+
|
108
|
+
define_singleton_method(name) do |v=nil|
|
109
|
+
unless v.nil?
|
110
|
+
instance_variable_set "@#{name}", v
|
111
|
+
end
|
112
|
+
|
113
|
+
basecoin = self.ancestors[1]
|
114
|
+
|
115
|
+
instance_variable_get("@#{name}") || basecoin.instance_variable_get(:'@defaults')[name]
|
116
|
+
end
|
117
|
+
|
118
|
+
define_method(name) do
|
119
|
+
self.class.instance_variable_get "@#{name}"
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
attr_field :git_repo
|
126
|
+
attr_field :git_branch, 'master'
|
127
|
+
attr_field :wallet_executable
|
128
|
+
attr_field :symbol
|
129
|
+
attr_field :home_page
|
130
|
+
attr_field :directory
|
131
|
+
attr_field :config_file
|
132
|
+
attr_field :build
|
133
|
+
attr_field :build_dir, 'src'
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'git'
|
2
|
+
|
3
|
+
module Coffer
|
4
|
+
class Installer
|
5
|
+
|
6
|
+
CACHE_DIR = '/opt/coffer/cache'
|
7
|
+
BIN_DIR = '/opt/coffer/bin'
|
8
|
+
|
9
|
+
attr_reader :coin
|
10
|
+
|
11
|
+
def initialize( coin )
|
12
|
+
@coin = coin
|
13
|
+
end
|
14
|
+
|
15
|
+
def install
|
16
|
+
mkdir CACHE_DIR, 0755
|
17
|
+
mkdir BIN_DIR, 0755
|
18
|
+
|
19
|
+
update_repo
|
20
|
+
# preconfigure
|
21
|
+
|
22
|
+
Dir.chdir( File.join( repo_path, @coin.build_dir) ) do
|
23
|
+
mkdir 'obj', 0755
|
24
|
+
make
|
25
|
+
|
26
|
+
check_results
|
27
|
+
end
|
28
|
+
|
29
|
+
copy_built_executable
|
30
|
+
create_directories
|
31
|
+
create_config
|
32
|
+
end
|
33
|
+
|
34
|
+
# ensure that this git repo is running the latest
|
35
|
+
# version and is cloned and all that
|
36
|
+
def update_repo
|
37
|
+
[ clone, pull ].count { |i| i } > 0
|
38
|
+
end
|
39
|
+
|
40
|
+
# clone a repo to the correct directory
|
41
|
+
# if the directory already exists and is a git repo
|
42
|
+
# then do nothing.
|
43
|
+
def clone
|
44
|
+
return false if File.directory?( repo_path )
|
45
|
+
|
46
|
+
warn "Cloning repo... #{repo_path}"
|
47
|
+
|
48
|
+
g = Git.clone( coin.git_repo, File.basename(repo_path), :path => File.dirname(repo_path) )
|
49
|
+
|
50
|
+
g.checkout @coin.git_branch
|
51
|
+
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
# pull the latest changes and ensure we have the correct
|
56
|
+
# ref checked out.
|
57
|
+
def pull
|
58
|
+
raise "Not a git repository! (#{ repo_path })" unless File.directory?( repo_path )
|
59
|
+
|
60
|
+
warn "Updating repo... #{repo_path}"
|
61
|
+
|
62
|
+
g = Git.open( repo_path, :logger => Logger.new(STDOUT) )
|
63
|
+
|
64
|
+
# store the current SHA1
|
65
|
+
old_sha = g.object('HEAD').sha
|
66
|
+
|
67
|
+
# ensure the remote is configured as expected
|
68
|
+
if g.remote.url != coin.git_repo
|
69
|
+
g.remove_remote 'origin'
|
70
|
+
g.add_remote 'origin', coin.git_repo, :fetch => true
|
71
|
+
end
|
72
|
+
|
73
|
+
# make sure the tree is clean
|
74
|
+
g.reset_hard
|
75
|
+
g.clean :force => true, :d => true
|
76
|
+
|
77
|
+
# fetch data from remote, checkout the right branch and merge into local branch
|
78
|
+
g.checkout @coin.git_branch
|
79
|
+
g.pull('origin', @coin.git_branch)
|
80
|
+
|
81
|
+
# check if there are any changes.
|
82
|
+
old_sha != g.object('HEAD').sha
|
83
|
+
end
|
84
|
+
|
85
|
+
def copy_built_executable
|
86
|
+
FileUtils.cp built_executable_path, installed_executable_path
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_directories
|
90
|
+
mkdir wallet_home_directory, 0700
|
91
|
+
end
|
92
|
+
|
93
|
+
def wallet_home_directory
|
94
|
+
File.expand_path("~/.#{ @coin.directory }")
|
95
|
+
end
|
96
|
+
|
97
|
+
def create_config
|
98
|
+
if File.exists?( config_path )
|
99
|
+
puts "Not creating config. (#{ config_path })"
|
100
|
+
return
|
101
|
+
end
|
102
|
+
|
103
|
+
File.open( config_path , 'w' ) do |f|
|
104
|
+
f.write @coin.build_config.to_config
|
105
|
+
end
|
106
|
+
|
107
|
+
FileUtils.chmod 0600, config_path
|
108
|
+
end
|
109
|
+
|
110
|
+
def config_path
|
111
|
+
File.join( wallet_home_directory, @coin.config_file )
|
112
|
+
end
|
113
|
+
|
114
|
+
def start
|
115
|
+
`#{ installed_executable_path } -daemon`
|
116
|
+
end
|
117
|
+
|
118
|
+
def check_results
|
119
|
+
raise "Build failed. No executable!" unless built_executable_valid?
|
120
|
+
end
|
121
|
+
|
122
|
+
def make
|
123
|
+
if @coin.build.nil?
|
124
|
+
cmd = "make -f '#{ makefile_name }'"
|
125
|
+
|
126
|
+
puts `#{cmd}`
|
127
|
+
|
128
|
+
retval = $?
|
129
|
+
if retval != 0
|
130
|
+
warn "ERROR from command: (#{ cmd }): #{ retval }"
|
131
|
+
end
|
132
|
+
else
|
133
|
+
@coin.build.split("\n").each do |cmd|
|
134
|
+
cmd = cmd.strip
|
135
|
+
puts "EXEC> #{ cmd }"
|
136
|
+
puts `#{cmd}`
|
137
|
+
|
138
|
+
retval = $?
|
139
|
+
if retval != 0
|
140
|
+
warn "ERROR from command (#{cmd}): #{ retval }"
|
141
|
+
return false
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
true
|
147
|
+
end
|
148
|
+
|
149
|
+
def makefile_name
|
150
|
+
sys = `uname`.chomp.downcase
|
151
|
+
|
152
|
+
if sys == 'darwin'
|
153
|
+
'makefile.osx'
|
154
|
+
elsif sys == 'linux'
|
155
|
+
'makefile.unix'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def mkdir( path, mode=0700 )
|
160
|
+
begin
|
161
|
+
FileUtils.mkdir_p path, :mode => mode
|
162
|
+
rescue Errno::EEXIST
|
163
|
+
#pass
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def repo_path
|
168
|
+
File.join CACHE_DIR, @coin.name
|
169
|
+
end
|
170
|
+
|
171
|
+
def installed_executable_path
|
172
|
+
File.join BIN_DIR, @coin.wallet_executable
|
173
|
+
end
|
174
|
+
|
175
|
+
def built_executable_path
|
176
|
+
File.join repo_path, 'src', @coin.wallet_executable
|
177
|
+
end
|
178
|
+
|
179
|
+
def built_executable_valid?
|
180
|
+
File.exists?( built_executable_path ) \
|
181
|
+
&& File.executable?( built_executable_path )
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'active_support' # FIXME: this takes about half a second to load
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
module Coffer
|
6
|
+
class Registry
|
7
|
+
include Singleton
|
8
|
+
|
9
|
+
BASE_DIR = '/opt/coffer'
|
10
|
+
BIN_DIR = File.join(BASE_DIR, 'bin')
|
11
|
+
DATA_FILE = File.join(BASE_DIR, 'coins.dat')
|
12
|
+
|
13
|
+
attr_reader :coins
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
make_directories
|
17
|
+
@coins = []
|
18
|
+
load_coins File.join(File.dirname(__FILE__), '../../coins')
|
19
|
+
end
|
20
|
+
|
21
|
+
def make_directories
|
22
|
+
FileUtils.mkdir_p BIN_DIR
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_coins(directory)
|
26
|
+
Dir["#{ directory }/*.rb"].each do |d|
|
27
|
+
require d
|
28
|
+
|
29
|
+
self.load File.basename(d, '.rb')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.load(coin)
|
34
|
+
instance.load coin
|
35
|
+
end
|
36
|
+
|
37
|
+
def load( coin )
|
38
|
+
if coin.is_a?(Symbol) || coin.is_a?(String)
|
39
|
+
coin = ActiveSupport::Inflector.camelize( coin, true )
|
40
|
+
coin = Coffer::Coin.const_get( coin )
|
41
|
+
elsif coin.is_a?(Coffer::Definition)
|
42
|
+
# pass
|
43
|
+
else
|
44
|
+
raise "Wrong type! (#{ coin.class.to_s })"
|
45
|
+
end
|
46
|
+
|
47
|
+
@coins << coin
|
48
|
+
|
49
|
+
# warn "Loaded coin: #{ coin.inspect } #{ coin.symbol }"
|
50
|
+
end
|
51
|
+
|
52
|
+
def find( coin )
|
53
|
+
coin = coin.downcase
|
54
|
+
@coins.find do |c|
|
55
|
+
c.name.downcase == coin || c.symbol.to_s.downcase == coin
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
data/lib/coffer.rb
ADDED
data/newcoin.sh
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#! /bin/bash -
|
2
|
+
|
3
|
+
echo "Creating new coin..."
|
4
|
+
|
5
|
+
read -p "Name: " COIN_NAME
|
6
|
+
read -p "Git repo: " GIT_REPO
|
7
|
+
read -p "Homepage: " HOME_PAGE
|
8
|
+
read -p "Symbol: " SYMBOL
|
9
|
+
read -p "Wallet executable: " WALLET_EXECUTABLE
|
10
|
+
read -p "Directory: " DIRECTORY
|
11
|
+
read -p "Config file: " CONFIG_FILE
|
12
|
+
|
13
|
+
FILENAME=$( echo $COIN_NAME | tr '[:upper:]' '[:lower:]' )
|
14
|
+
|
15
|
+
cat > coins/${FILENAME}.rb <<EOF
|
16
|
+
module Coffer
|
17
|
+
module Coin
|
18
|
+
class ${COIN_NAME} < Coffer::Definition
|
19
|
+
git_repo '${GIT_REPO}'
|
20
|
+
home_page '${HOME_PAGE}'
|
21
|
+
symbol :${SYMBOL}
|
22
|
+
wallet_executable '${WALLET_EXECUTABLE}'
|
23
|
+
directory '${COIN_NAME}'
|
24
|
+
config_file '${CONFIG_FILE}'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
EOF
|
data/run_test.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'coffer/registry'
|
3
|
+
require 'coffer/installer'
|
4
|
+
require 'coffer/definition'
|
5
|
+
|
6
|
+
require 'pry'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
# cleanup
|
10
|
+
# FileUtils.rm_rf '/tmp/coffer'
|
11
|
+
|
12
|
+
Coffer::Registry.instance
|
13
|
+
|
14
|
+
c = Coffer::Coin::Feathercoin.new
|
15
|
+
|
16
|
+
installer = Coffer::Installer.new( c )
|
17
|
+
installer.install
|
18
|
+
|
19
|
+
puts "Built: #{ c.executable_path }"
|
20
|
+
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: coffer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Spike Grobstein
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: git
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: thor
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Cryptocurrency wallet manager
|
98
|
+
email:
|
99
|
+
- me@spike.cx
|
100
|
+
executables:
|
101
|
+
- coffer
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- .gitignore
|
106
|
+
- Gemfile
|
107
|
+
- LICENSE.txt
|
108
|
+
- README.md
|
109
|
+
- Rakefile
|
110
|
+
- Vagrantfile
|
111
|
+
- bin/coffer
|
112
|
+
- coffer.gemspec
|
113
|
+
- coins/auroracoin.rb
|
114
|
+
- coins/bottlecaps.rb
|
115
|
+
- coins/dogecoin.rb
|
116
|
+
- coins/feathercoin.rb
|
117
|
+
- coins/fedoracoin.rb
|
118
|
+
- coins/litecoin.rb
|
119
|
+
- coins/megacoin.rb
|
120
|
+
- coins/mincoin.rb
|
121
|
+
- coins/worldcoin.rb
|
122
|
+
- lib/coffer.rb
|
123
|
+
- lib/coffer/cli.rb
|
124
|
+
- lib/coffer/configuration.rb
|
125
|
+
- lib/coffer/definition.rb
|
126
|
+
- lib/coffer/installer.rb
|
127
|
+
- lib/coffer/registry.rb
|
128
|
+
- lib/coffer/version.rb
|
129
|
+
- newcoin.sh
|
130
|
+
- run_test.rb
|
131
|
+
homepage: https://github.com/spikegrobstein/coffer
|
132
|
+
licenses:
|
133
|
+
- MIT
|
134
|
+
metadata: {}
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - '>='
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubyforge_project:
|
151
|
+
rubygems_version: 2.0.14
|
152
|
+
signing_key:
|
153
|
+
specification_version: 4
|
154
|
+
summary: Cryptocurrency wallet manager -- like homebrew, but for your wallets. Linux-only
|
155
|
+
right now.
|
156
|
+
test_files: []
|