coffer 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|