Class: Bitcoin::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/bc.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(user, password, host = '127.0.0.1', port = 8331, ssl = false) ⇒ Client

Returns a new instance of Client.



557
558
559
560
561
562
563
564
565
566
567
568
# File 'lib/bc.rb', line 557

def initialize(user, password, host='127.0.0.1', port=8331, ssl=false)
	%w{user password host port ssl}.each do |var|
		instance_variable_set("@#{var}", eval(var))
	end

	@jr = Jr::Jr.new(@host, @port, @user, @password, ssl)

	@accounts = Hash.new
	@addresses = Hash.new
	@blocks = Hash.new
	@transactions = Hash.new
end

Instance Attribute Details

#hostObject (readonly)

Returns the value of attribute host.



553
554
555
# File 'lib/bc.rb', line 553

def host
  @host
end

#jrObject (readonly)

Returns the value of attribute jr.



555
556
557
# File 'lib/bc.rb', line 555

def jr
  @jr
end

#passwordObject (readonly)

Returns the value of attribute password.



553
554
555
# File 'lib/bc.rb', line 553

def password
  @password
end

#portObject (readonly)

Returns the value of attribute port.



553
554
555
# File 'lib/bc.rb', line 553

def port
  @port
end

#sslObject (readonly)

Returns the value of attribute ssl.



553
554
555
# File 'lib/bc.rb', line 553

def ssl
  @ssl
end

#userObject (readonly)

Returns the value of attribute user.



553
554
555
# File 'lib/bc.rb', line 553

def user
  @user
end

Instance Method Details

#accountsObject

Get an Array of every Account we have.



578
579
580
581
582
# File 'lib/bc.rb', line 578

def accounts
	@jr.listreceivedbyaccount(0, true).map do |acct_info|
		(acct_info.fetch('account'))
	end
end

#addressesObject

Get an Array of every Address we have.



571
572
573
574
575
# File 'lib/bc.rb', line 571

def addresses
	@jr.listreceivedbyaddress(0, true).map do |addr_info|
		get_address(addr_info.fetch('address'))
	end
end

#backup_wallet(path) ⇒ Object

Safely copies our wallet to destination at path. If path is a directory, we will copy our wallet to path/wallet.dat.



725
726
727
# File 'lib/bc.rb', line 725

def backup_wallet(path)
	@jr.backupwallet(path)
end

#balanceObject

Get the total balance of all our accounts. (This includes all transactions with at least 1 confirmation.)



767
768
769
# File 'lib/bc.rb', line 767

def balance
	@jr.getbalance()
end

#bitcoind_versionObject

This [Fixnum] is the version of bitcoind we’re connecting to.



809
810
811
# File 'lib/bc.rb', line 809

def bitcoind_version
	@jr.getinfo().fetch('version')
end

#block_countObject

How many blocks are there (that we know about) in the block chain?



772
773
774
# File 'lib/bc.rb', line 772

def block_count
	@jr.getblockcount()
end

#change_wallet_passwd(old_passwd, new_passwd) ⇒ Object

Change the wallet’s passphrase from old_passwd to new_passwd.



735
736
737
738
739
740
741
742
743
744
745
# File 'lib/bc.rb', line 735

def change_wallet_passwd(old_passwd, new_passwd)
	begin
		@jr.walletpassphrasechange(old_passwd, new_passwd)
	rescue Jr::ServerError => ex
		if ex.code == -14
			raise InvalidPassphrase, passwd
		else
			raise
		end
	end
end

#connection_countObject

How many peers are we connected to?



777
778
779
# File 'lib/bc.rb', line 777

def connection_count
	@jr.getconnectioncount()
end

#difficultyObject

This is a Float representing the difficulty associated with finding the next block. The higher the number, the more difficult it is. (c.f. en.bitcoin.it/wiki/Difficulty)



784
785
786
# File 'lib/bc.rb', line 784

def difficulty
	@jr.getdifficulty()
end

Donate amount to katmagic (bc’s author).



713
714
715
716
717
718
719
720
721
# File 'lib/bc.rb', line 713

def donate(amount)
	tx = send('1LzDffumxiCSh8wEpxWE8fUozb2LUTcL8L', amount)

	if STDOUT.tty?
		puts('katmagic l♥ves y♥u ♥♥dles!')
	end

	tx
end

#each_transaction_since(block) ⇒ Object

Call the (Ruby) block passed for every transaction that has occurred since block (which may be a Block, a block ID, or a block height). We return the last Block processed.



633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
# File 'lib/bc.rb', line 633

def each_transaction_since(block)
	unless block.is_a?(Block)
		block = get_block(block)
	end

	info = @jr.listsinceblock(block.block_id)

	txes = info.fetch('transactions')
	txes.map!{ |tx| tx.fetch('txid') }
	txes.uniq!

	txes.each do |txid|
		transaction = get_transaction(txid)
		yield(transaction)
	end

	get_block(info.fetch('lastblock'))
end

#encrypt_wallet(passwd) ⇒ Object

Encrypt the wallet with passwd and stop bitcoind.



730
731
732
# File 'lib/bc.rb', line 730

def encrypt_wallet(passwd)
	@jr.encryptwallet(passwd)
end

#generate=(should_generate) ⇒ Object

If should_generate is true, we instruct bitcoind to begin (or continue) to generate a block. If it is false, we do the opposite.



797
798
799
800
# File 'lib/bc.rb', line 797

def generate=(should_generate)
	@jr.setgenerate(should_generate)
	should_generate
end

#generate?Boolean Also known as: generate

Are we trying to generate a block?

Returns:

  • (Boolean)


789
790
791
# File 'lib/bc.rb', line 789

def generate?
	@jr.getgenerate()
end

#get_account(label) ⇒ Object Also known as: []

Get the account associated with the String label, or create it if it doesn’t already exist. The result of this function is cached.



592
593
594
# File 'lib/bc.rb', line 592

def (label)
	@accounts[label] ||= Account.new(self, label)
end

#get_address(addr) ⇒ Object

Get the Address addr. If addr is invalid, we raise InvalidAddress. The result of this function is cached.



586
587
588
# File 'lib/bc.rb', line 586

def get_address(addr)
	@addresses[addr] ||= Address.new(self, addr)
end

#get_block(block_id) ⇒ Object

Get the Block with a hash of block_id, or if block_id is a Fixnum, the Block with a height of block_id. If block_id is an unknown block ID, we raise UnknownBlock+; if block_id is a Fixnum and there is no associated block, we raise RangeError. The result of this function is cached.



607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
# File 'lib/bc.rb', line 607

def get_block(block_id)
	if block_id.is_a?(Fixnum)
		begin
			block_id = @jr.getblockhash(block_id)
		rescue Jr::ServerError => ex
			if ex.code == -1
				raise RangeError, "block_id #{block_id.inspect} is out of range."
			else
				raise
			end
		end
	end

	@blocks[block_id] ||= Block.new(self, block_id)
end

#get_transaction(transaction_id) ⇒ Object

Get the Transaction with the ID transaction_id. We raise UnknownTransaction if we don’t know about a Transaction with that ID. The result of this function is cached.



626
627
628
# File 'lib/bc.rb', line 626

def get_transaction(transaction_id)
	@transactions[transaction_id] ||= Transaction.new(self, transaction_id)
end

#has_account?(acct) ⇒ Boolean

Does acct have any associated addresses?

Returns:

  • (Boolean)


598
599
600
# File 'lib/bc.rb', line 598

def has_account?(acct)
	!(acct).addresses.empty?
end

#hashes_per_secondObject

How many blocks are we hashing per second? This will be zero unless we’re trying to generate a block.



804
805
806
# File 'lib/bc.rb', line 804

def hashes_per_second
	@jr.gethashespersec()
end

#import_private_key(key, label = nil) ⇒ Object

Import a Bitcoin private key. We will fail if the key already exists in our wallet. We return an Address. (c.f. get_private_key())



863
864
865
866
# File 'lib/bc.rb', line 863

def import_private_key(key, label=nil)
	label ||= ''
	@jr.get_address( @jr.importprivkey(key, label) )
end

#is_valid?(addr) ⇒ Boolean

Is addr a valid bitcoin address? If we’re using the testnet, normal addresses won’t be valid; if we’re not, testnet addresses won’t be valid.

Returns:

  • (Boolean)


888
889
890
# File 'lib/bc.rb', line 888

def is_valid?(addr)
	@jr.validateaddress(addr.to_s)['isvalid']
end

#key_pool_sizeObject

This is the (Fixnum) size of our key pool. The key pool is a pre-generated set of Bitcoin keys which are then allocated through the other address allocation mechanisms. It exists so that backups will (hopefully) contain all the private keys we actually used.



850
851
852
# File 'lib/bc.rb', line 850

def key_pool_size
	@jr.getinfo().fetch('keypoolsize')
end

#latest_blockObject

This is the latest Block we’ve processed.



664
665
666
# File 'lib/bc.rb', line 664

def latest_block
	get_block( @jr.getinfo().fetch('blocks') )
end

#latest_remote_block_heightObject

This returns the height of the last processed block according to blockexplorer.com. Be cautious—this information is provided by a third party! This method may raise exceptions of numerous different types.



671
672
673
674
675
676
# File 'lib/bc.rb', line 671

def latest_remote_block_height
	con = Net::HTTP.new('blockexplorer.com', 443)
	con.use_ssl = true

	con.get((testnet? ? '/testnet' : '') + '/q/getblockcount').body.to_i
end

#lock_walletObject

Lock the wallet.



761
762
763
# File 'lib/bc.rb', line 761

def lock_wallet()
	@jr.walletlock()
end

#memory_poolObject

This is a Hash containing data about the next block that will be generated (c.f. the documentation regarding the getmemorypool API call in en.bitcoin.it/wiki/Original_Bitcoin_client/API_Calls_list)



857
858
859
# File 'lib/bc.rb', line 857

def memory_pool
	@jr.getmemorypool()
end

#oldest_keyObject

This is the Time the oldest key in our key pool was created. (c.f. key_pool_size())



842
843
844
# File 'lib/bc.rb', line 842

def oldest_key
	Time.at(@jr.getinfo().fetch('keypoololdest'))
end

#percent_completeObject

Return the percent of the blockchain we have downloaded according to the number fetched by latest_remote_block_height(). The warnings there apply here, too.



681
682
683
# File 'lib/bc.rb', line 681

def percent_complete
	(latest_block.height / latest_remote_block_height) * 100
end

#protocol_versionObject

This (Fixnum) is the version of the Bitcoin RPC protocol we’re communicating in.



815
816
817
# File 'lib/bc.rb', line 815

def protocol_version
	@jr.getinfo().fetch('protocolversion')
end

#proxyObject

This is the proxy bitcoind is using, or nil if we’re not using a proxy.



820
821
822
# File 'lib/bc.rb', line 820

def proxy
	@jr.getinfo().fetch('proxy')
end

#proxy?Boolean

Is bitcoind using a proxy?

Returns:

  • (Boolean)


825
826
827
# File 'lib/bc.rb', line 825

def proxy?
	!!proxy
end

#refill_key_poolObject

Refill our key pool. (c.f. key_pool_size())



869
870
871
# File 'lib/bc.rb', line 869

def refill_key_pool()
	@jr.keypoolrefill()
end

#send(dest, amount) ⇒ Object

Send amount Bitcoin to dest. amount should be a positive real number; dest can either be a String bitcoin address, or an Address instance. We return a Transaction.



688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
# File 'lib/bc.rb', line 688

def send(dest, amount)
	dest = dest.to_s

	begin
		txid = @jr.sendtoaddress(dest, amount)
	rescue Jr::ServerError => ex
		case ex.code
			when -13
				raise LockedWallet

			when -6
				raise InsufficientFunds.new(amount, balance)

			when -5
				raise InvalidAddress, dest

			else
				raise
		end
	end

	get_transaction(txid)
end

#stopObject

Stop bitcoind.



882
883
884
# File 'lib/bc.rb', line 882

def stop()
	@jr.stop()
end

#testnet?Boolean

Are we on the testnet?

Returns:

  • (Boolean)


830
831
832
# File 'lib/bc.rb', line 830

def testnet?
	@jr.getinfo().fetch('testnet')
end

#transaction_feeObject

This is how much we’re configured to use as our transaction fee. (c.f. en.bitcoin.it/wiki/Transaction_fees)



836
837
838
# File 'lib/bc.rb', line 836

def transaction_fee
	@jr.getinfo().fetch('paytxfee')
end

#transaction_fee=(fee) ⇒ Object

Set the transaction fee to fee. (c.f. en.bitcoin.it/wiki/Transaction_fees)



875
876
877
878
879
# File 'lib/bc.rb', line 875

def transaction_fee=(fee)
	fee = fee.to_d
	@jr.settxfee(fee)
	fee
end

#transactionsObject

Get an Array of every Transaction involving one of our addresses.



653
654
655
656
657
658
659
660
661
# File 'lib/bc.rb', line 653

def transactions
	transactions = Array.new

	each_transaction_since(0) do |tx|
		transactions << tx
	end

	transactions
end

#unlock_wallet(passwd, timeout = 300) ⇒ Object

Unlock the wallet with passwd for timeout seconds.



748
749
750
751
752
753
754
755
756
757
758
# File 'lib/bc.rb', line 748

def unlock_wallet(passwd, timeout=300)
	begin
		@jr.walletpassphrase(passwd, timeout)
	rescue Jr::ServerError => ex
		if ex.code == -14
			raise InvalidPassphrase, passwd
		else
			raise
		end
	end
end