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.



541
542
543
544
545
546
547
548
549
550
551
552
# File 'lib/bc.rb', line 541

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.



537
538
539
# File 'lib/bc.rb', line 537

def host
  @host
end

#jrObject (readonly)

Returns the value of attribute jr.



539
540
541
# File 'lib/bc.rb', line 539

def jr
  @jr
end

#passwordObject (readonly)

Returns the value of attribute password.



537
538
539
# File 'lib/bc.rb', line 537

def password
  @password
end

#portObject (readonly)

Returns the value of attribute port.



537
538
539
# File 'lib/bc.rb', line 537

def port
  @port
end

#sslObject (readonly)

Returns the value of attribute ssl.



537
538
539
# File 'lib/bc.rb', line 537

def ssl
  @ssl
end

#userObject (readonly)

Returns the value of attribute user.



537
538
539
# File 'lib/bc.rb', line 537

def user
  @user
end

Instance Method Details

#accountsObject

Get an Array of every Account we have.



562
563
564
565
566
# File 'lib/bc.rb', line 562

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.



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

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.



692
693
694
# File 'lib/bc.rb', line 692

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.)



734
735
736
# File 'lib/bc.rb', line 734

def balance
	@jr.getbalance()
end

#bitcoind_versionObject

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



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

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

#block_countObject

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



739
740
741
# File 'lib/bc.rb', line 739

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.



702
703
704
705
706
707
708
709
710
711
712
# File 'lib/bc.rb', line 702

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?



744
745
746
# File 'lib/bc.rb', line 744

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)



751
752
753
# File 'lib/bc.rb', line 751

def difficulty
	@jr.getdifficulty()
end

Donate amount to katmagic (bc’s author).



680
681
682
683
684
685
686
687
688
# File 'lib/bc.rb', line 680

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.



617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
# File 'lib/bc.rb', line 617

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.



697
698
699
# File 'lib/bc.rb', line 697

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.



764
765
766
767
# File 'lib/bc.rb', line 764

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)


756
757
758
# File 'lib/bc.rb', line 756

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.



576
577
578
# File 'lib/bc.rb', line 576

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.



570
571
572
# File 'lib/bc.rb', line 570

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.



591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
# File 'lib/bc.rb', line 591

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.



610
611
612
# File 'lib/bc.rb', line 610

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)


582
583
584
# File 'lib/bc.rb', line 582

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.



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

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())



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

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)


855
856
857
# File 'lib/bc.rb', line 855

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.



817
818
819
# File 'lib/bc.rb', line 817

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

#latest_blockObject

This is the latest Block we’ve processed.



648
649
650
# File 'lib/bc.rb', line 648

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

#lock_walletObject

Lock the wallet.



728
729
730
# File 'lib/bc.rb', line 728

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)



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

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())



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

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

#protocol_versionObject

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



782
783
784
# File 'lib/bc.rb', line 782

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.



787
788
789
# File 'lib/bc.rb', line 787

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

#proxy?Boolean

Is bitcoind using a proxy?

Returns:

  • (Boolean)


792
793
794
# File 'lib/bc.rb', line 792

def proxy?
	!!proxy
end

#refill_key_poolObject

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



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

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.



655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
# File 'lib/bc.rb', line 655

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.



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

def stop()
	@jr.stop()
end

#testnet?Boolean

Are we on the testnet?

Returns:

  • (Boolean)


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

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)



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

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)



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

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

#transactionsObject

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



637
638
639
640
641
642
643
644
645
# File 'lib/bc.rb', line 637

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.



715
716
717
718
719
720
721
722
723
724
725
# File 'lib/bc.rb', line 715

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