DEV Community

Cover image for Are You Lucky Bastard?
decentralizuj
decentralizuj

Posted on

Are You Lucky Bastard?

LuckyBastard Preview

Introduction

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

or

# 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 = Time.now.to_i
  end
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
  end

  # get max_pause time
  def pause
    @pause
  end

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

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

  # stop loop
  def stop
    @loop = false
  end

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

  # from check(address)
  def success?
    @balance > 0.0
  end
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

  private

  # called from #start
  def execute

    # generate random keys
    random_private_key!

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

    # if balance is more then 0.0
    if success?
      @end = Time.now.to_i - @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)
    end
  end


  def random_private_key!

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

    # make new master node, and get address
    @address = MoneyTree::Master.new(seed_hex: @hex_seed).to_address
  end


  def check(address)

    # define to check for `received/sent` by address
    type = @type.to_s 
    url  = "https://blockchain.info/q/get#{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
    rescue
    puts 'request timeout, repeating process in 60 seconds...'
    sleep(60) and start
  end


  def write_to_file(address, balance, seed, opt = {})
    @data = " #{Time.now.to_s}" + "\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)
  end
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)
    LuckyBastard.new(max_sleep, type).start
  end

end
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
  else
    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
  end
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
lorenzoblog profile image
Lorenzo

*The link is broken

Collapse
 
decentralizuj profile image
decentralizuj

Sorry I am on mobile, will write more soon.