Skip to content

Instantly share code, notes, and snippets.

@NickPiscitelli
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NickPiscitelli/9716089 to your computer and use it in GitHub Desktop.
Save NickPiscitelli/9716089 to your computer and use it in GitHub Desktop.
CryptoCurrency Altcoin Wallet Backup Manager - Manage Wallet backups among PCs using Dropbox (Directory is configurable)

Perl script to make management of alt coin wallets easier.

Support for performing limited actions of pre-configured coins.

Run on either all or coins passed in argument. Execute examples listed below.

Script Arguments

conf: Location of JSON Wallet conf file. (Defaults to ~/wallet_conf.json)

actions: Comma separated list of actions (See below)

wallets: Comma separated list of wallets (Must be defined in conf file)

backup_dir: Directory to backup wallets to (Defaults to ~/Dropbox)

make_dir: Directory to build clients when making. (Defaults to pwd)

quiet: Suppress output (Default False)

force: Send a -9 to the kill client command (Default False)

disable_prompt: By default, the script prompts to continue in the event no wallets are specified. This is help to mitigate accidental actions, but can be disabled if needed. (Default False)

Script Actions:

Launch - launches coin Qt clients

Kill - Kill Qt client (See optional force parameter)

Restart - Restart Qt client (Performs kill, launch)

Backup - Backups wallet files into hierarchical date format to given directory (Dropbox Recommended)

Reload - Kills Qt client, grabs latest backup from backup directory, launches client.

Make - This is experimental, it was added to ease me deploying this on other computers, it likely won't work for anyone else, but it can be tried.

Wallet Config Options:

name: The name of the Wallet directory

dir: The full path of Wallet src directory

url: The Github Src URL, required for "make"

qt_exe: Optional name of built executable if different

wallet_file: Location to wallet file if different

pre_make: Optional bash commands to run before qmake/make if using "make" action

Examples

Launch all wallets - Skip prompt on all coin modification

./wallet_manager.pl --actions="launch" --disable-prompt

Kills all wallets - Suppress output

./wallet_manager.pl --actions="kill" --quiet

Force Kills DopeCoin client

./wallet_manager.pl --actions="kill" --wallets="DopeCoin" --force

Restart dogecoin, litecoin client

./wallet_manager.pl --actions="restart" --wallets="dogecoin, litecoin"

Backup then kill all wallets and clients

./wallet_manager.pl --actions="backup, kill" --backup_dir="/home/user/Dropbox/"

Reload (Update wallet from backup) all clients

./wallet_manager.pl --actions="reload"

Make all clients in conf file

./wallet_manager.pl --actions="make" --make_dir="/home/user/Wallets"

{
"wallets": [
{
"name": "vertcoin",
"dir": "/home/<user>/Downloads/vertcoin",
"url": "https://github.com/vertcoin/vertcoin"
},
{
"name": "darkcoin",
"dir": "/home/<user>/Downloads/darkcoin",
"url": "https://github.com/evan82/darkcoin"
},
{
"name": "reddcoin",
"url": "https://github.com/reddcoin/reddcoin"
},
{
"name": "dogecoin",
"dir": "/home/<user>/Downloads/dogecoin",
"url": "https://github.com/dogecoin/dogecoin"
},
{
"name": "litecoin",
"dir": "/home/<user>/Downloads/litecoin",
"url": "https://github.com/litecoin-project/litecoin"
},
{
"name": "Hirocoin",
"qt_exe": "hirocoin-qt",
"wallet_file": "/home/<user>/.hirocoin/wallet.dat",
"dir": "/home/<user>/Downloads/Hirocoin",
"url": "https://github.com/HiroSatou/Hirocoin"
},
{
"name": "DopeCoin",
"dir": "/home/<user>/Downloads/DopeCoin",
"url": "https://github.com/dopecoin-dev/DopeCoin",
"pre_make": "cd src/; make -f makefile.unix; cd ..; "
}
]
}
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use JSON::XS;
use DateTime;
use File::Path qw(make_path);
my ($conf_file,$actions,$wallets,$backup_dir,$make_dir,$quiet, $force, $disable_prompt);
GetOptions(
"conf=s" => \$conf_file, # location of wallet JSON conf file - defaults to ~/wallet_conf.json
"actions=s" => \$actions, # comma seperated list of actions - REQUIRED
# launch reload kill backup make restart
"wallets=s" => \$wallets, # comma seperated list of coins - defaults to all in conf file!
"backup_dir=s" => \$backup_dir, #where to put wallet backups - defaults to ~/Dropbox
"make_dir=s" => \$make_dir, #where to put wallet builds - defaults to pwd
"quiet" => \$quiet, # suppress output - default false
"force" => \$force, #send -9 to process kill - default false,
"disable_prompt" => \$disable_prompt #skip prompt when modifying every wallet - default false
);
die "An action is required!"
unless $actions;
if (!$wallets && !$disable_prompt){
print "\nYou did not specify a wallet, are you sure you want to perform this action on all wallets (Y/N)?\n";
my $prompt = <>;
if ($prompt !~ /y/i){
print "Exiting due to negative response.\n";
exit;
}
}
my $base = '/home/'.$ENV{USER}.'/';
$conf_file ||= $base.'wallet_conf.json';
$actions ||= 'lauch';
$make_dir ||= `pwd`;
chomp $make_dir;
my $conf;
{
local $/ = undef;
open my $f, $conf_file or
die "Error opening configuation file: $!";
$conf = JSON::XS::decode_json(<$f>);
close $f;
}
$backup_dir ||= $base.'/Dropbox/';
$wallets = $wallets ? [
map {
fetch_wallet($_)
} (split /\s*,\s*/, $wallets)
] : $conf->{wallets};
my $update_conf;
my %wallet_dispacther = dispatcher_subs();
for my $wallet (@$wallets){
for my $action (split /\s*,\s*/, $actions){
$wallet_dispacther{$action}->($wallet);
}
}
if ($update_conf) {
open my $f, '>', $conf_file or
die "Error opening configuation file: $!";
my $json = JSON::XS->new->pretty(1)->encode($conf);
print $f $json;
close $f;
}
sub fetch_wallet {
my $wallet = shift;
my $wallet_conf = (grep {
$_->{name} eq $wallet
} @{$conf->{wallets}})[0];
die "Can't get wallet conf for $wallet!"
unless ref $wallet_conf eq 'HASH';
return $wallet_conf;
};
sub proc_exists {
my $wallet = shift;
my $proc = $wallet->{qt_exe} || lc $wallet->{name}.'-qt';
my $exists = `ps -aef | grep $proc | grep -v grep`;
return $exists ? 1 : 0;
};
sub dispatcher_subs {
return (
launch => sub {
my ($wallet) = @_;
if (proc_exists($wallet)){
print "$wallet->{name} is already running!\n"
unless $quiet;
return 1;
}
$wallet->{qt_exe} ||= lc $wallet->{name}.'-qt';
my $command = sprintf '%1$s/%2$s',
($wallet->{dir} || $base.$wallet->{name}),
$wallet->{qt_exe};
system("$command &");
print "Lauched $wallet->{name} wallet!\n"
unless $quiet;
sleep(5);
return 1;
},
kill => sub {
my $wallet = shift;
my $proc = $wallet->{qt_exe} || lc $wallet->{name}.'-qt';
if (!proc_exists($wallet)){
print "$wallet->{name} is not running!\n"
unless $quiet;
return 1;
}
my $level = $force ? ' -9 ' : '';
system("pkill $level $proc");
print "$wallet->{name} has been killed!\n"
unless $quiet;
return 1;
},
backup => sub {
my $wallet = shift;
$wallet->{wallet_file} ||= sprintf '~/.%1$s/wallet.dat',
lc $wallet->{name};
my $path = $backup_dir;
my $date = DateTime->now->ymd('');
$path .= join '/', (
'Wallets',$wallet->{name},$date
);
make_path($path);
system("cp $wallet->{wallet_file} $backup_dir/Wallets/$wallet->{name}/$date/wallet.dat");
print "$wallet->{name} wallet backed up!\n"
unless $quiet;
return 1;
},
restart => sub {
my $wallet = shift;
if (!proc_exists($wallet)){
print "$wallet->{name} was not running!\n"
unless $quiet;
} else {
$wallet_dispacther{kill}->($wallet);
}
return $wallet_dispacther{launch}->($wallet);
},
reload => sub {
my $wallet = shift;
$wallet->{wallet_file} ||= sprintf '~/.%1$s/wallet.dat',
lc $wallet->{name};
opendir my($dh), "$backup_dir/Wallets/$wallet->{name}"
or die "Couldn't open backup dir for '$wallet': $!";
my @files = readdir $dh;
closedir $dh;
my $dir = (sort {
$b cmp $a
} @files)[0];
$dir = "${backup_dir}Wallets/$wallet->{name}/$dir";
$wallet_dispacther{kill}->($wallet);
system("cp $dir/wallet.dat $wallet->{wallet_file}");
$wallet_dispacther{launch}->($wallet);
print "$wallet->{name} wallet reloaded!\n"
unless $quiet;
return 1;
},
make => sub {
my $wallet = shift;
print "make_dir arg is required to make!\n"
unless $make_dir;
print "$wallet->{name} source url is required to make!\n"
unless $wallet->{url};
return unless $wallet->{url};
my $opt = '';
$opt = $wallet->{pre_make}
if $wallet->{pre_make};
system("git clone $wallet->{url} $make_dir/$wallet->{name}");
system("cd $make_dir/$wallet->{name}; $opt qmake; make;");
print "$wallet->{name} wallet built!\n"
unless $quiet;
$wallet->{dir} = "$make_dir/$wallet->{name}";
$update_conf = 1;
$wallet_dispacther{launch}->($wallet);
return 1;
},);
};
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment