DEV Community

Cover image for Are You Lucky Bastard?

Posted on

Are You Lucky Bastard?

LuckyBastard Preview


This is a fun-only project, just to do something fun while drinking amazing cold Nescafe-Shake.

So how it works? SecureRandom create 32bits random hex string. This string is used by Money-Tree gem to make Master Node of Bip32 HD wallet. I could just let money-tree to create random seed, but where's my fun then?

Let's start!

You can add gems into Gemfile, then use it for luckybastard, but most of ruby devs have this gems installed. In case you don't have:

# install gems localy with:
gem install money-tree colorize


# create Gemfile and add gems
# run `bundle install` to install them
gem 'money-tree'
gem 'colorize'
Enter fullscreen mode Exit fullscreen mode

Now create file called luckybastard.rb and open it. Write shebang (because I guess you're on linux, if you are on windows, go install linux), and require needed dependencies.

#!/usr/bin/env ruby

require 'securerandom'
require 'money-tree'
require 'open-uri'
require 'colorize'
require 'net/http'
Enter fullscreen mode Exit fullscreen mode

MoneyTree and Colorize are gems we need to install, and other dependencies need to require.

Let's create our class LuckyBastard

  # class LuckyBastard - code is part of this

  # max-time to sleep if request fail
  SLEEP = 2

  # default type of checking address
  TYPE  = :sent

  def initialize( max_sleep = SLEEP, type = TYPE )

    # count all requests (generated seeds)
    @counter = 0

    # this counter reset on 10, to show in terminal
    @count = 0

    # type of address-check
    @type = type

    # is loop paused
    @work = false

    # max_sleep between fail requests
    @pause = max_sleep

    # start time
    @start =
Enter fullscreen mode Exit fullscreen mode

After initializing variables, it's time to make methods to get/set/use them.

  # set max_pause time
  def pause=(max_sleep)
    @pause = max_sleep

  # get max_pause time
  def pause

  # check is paused or not
  def pause? 
    @work == true

  # start or stop loop
  def pause!
    if pause? then start else stop end

  # stop loop
  def stop
    @loop = false

  # start loop if paused (or not)
  def start
    pause! if pause?
    until pause? do execute end      

  # from check(address)
  def success?
    @balance > 0.0
Enter fullscreen mode Exit fullscreen mode

That's all for public methods. Now we need LuckyBastard#execute (used in #start). That method will use another to generate seed and check for address balance. This methods should be private.

Private methods you can't call directly. You put them inside public method to run.

# ... public code


  # called from #start
  def execute

    # generate random keys

    # check address balance
    check @address 
    @count += 1

    # if balance is more then 0.0
    if success?
      @end = - @start

      # write valid data to file and print them
      write_to_file(@address, @balance, @hex_seed)
      puts "[*] Valid seed found in #{(@end / 60)} minutes".yellow
      puts "[!] Enter 'Q' to quit, or any key to continue (q/Q):".yellow

      # get answer from input, exit if include q/Q
      answer = STDIN.gets.chomp
      %w[q Q].include?(answer) ? exit(1) : start

    # when fail, print data if 10 seeds generated
    elsif @count >= 10

      # add previous seeds to total counter 
      @counter += @count

      # clean screen and print number of generated seeds
      system 'clear' or system 'cls'
      print "\n >> Looking for [".green + "#{@type.to_s.upcase}".yellow + "]".green
      puts " coins on random address".green
      puts "\n " +" #{@counter} ".black.on_yellow + " random seeds checked...".yellow
      puts ""

      # print fail address data, do not save
      write_to_file(@address, @balance, @hex_seed, save: false)

      # reset count, so we can count next 10 seeds
      @count = 0

      # sleep random time, we defined maximum
      sleep rand(pause)

  def random_private_key!

    # generate random 32bit hex string
    @hex_seed = SecureRandom.hex 32

    # make new master node, and get address
    @address = @hex_seed).to_address

  def check(address)

    # define to check for `received/sent` by address
    type = @type.to_s 
    url  = "{type}byaddress/#{address}"
    data = Net::HTTP.get URI url

    # get balance in float
    return @balance = data.to_f 

    # if request fail, sleep 1 min and repeat
    puts 'request timeout, repeating process in 60 seconds...'
    sleep(60) and start

  def write_to_file(address, balance, seed, opt = {})
    @data = " #{}" + "\n"
    @data += "\n Address: #{address}\n Balance: #{balance}\n HexSeed: #{seed}"

    # do not save if option save is true (for invalid seed)
    File.write("#{address}.txt", @data) unless opt[:save] == false

    # print red for fail, green for success (balance > 0)
    clr = success? ? :green : :red
    puts @data.colorize(clr)
Enter fullscreen mode Exit fullscreen mode

After you put this code inside LuckyBastard class, you can write one more method as a shortcut to run loop

class LuckyBastard

  # all previous code here

  def self.start!(max_sleep = 2, type = :sent), type).start

Enter fullscreen mode Exit fullscreen mode

You need a way to run it from terminal. Without arguments print help instructions, which tell us to run with --start, and to add --sent if we want.

  # check for received coins unless args include `--sent`
  type = ARGV.include?('--sent') ? :sent : :received

  # start if args include start, or print help
  if ARGV.include?('--start')
    system 'clear'
    puts "\n Starting random seed generation..."
    LuckyBastard.start! 2, type
    puts "\n              Are You Lucky Bastard?".green.bold
    puts "      Generate random hex seed and find out!".green.bold
    print ' '
    50.times { print '='.green } and puts
    puts "  Get received by address:".white
    puts "   $ ruby luckybastard.rb --start".light_green
    puts "  Get sent by address:".white
    puts "   $ ruby luckybastard.rb --start --sent\n".light_green
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

devlorenzo profile image

*The link is broken

decentralizuj profile image

Sorry I am on mobile, will write more soon.