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.



563
564
565
566
567
568
569
570
571
572
573
574
# File 'lib/bc.rb', line 563

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::BigDecimalJr.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.



559
560
561
# File 'lib/bc.rb', line 559

def host
  @host
end

#jrObject (readonly)

Returns the value of attribute jr.



561
562
563
# File 'lib/bc.rb', line 561

def jr
  @jr
end

#passwordObject (readonly)

Returns the value of attribute password.



559
560
561
# File 'lib/bc.rb', line 559

def password
  @password
end

#portObject (readonly)

Returns the value of attribute port.



559
560
561
# File 'lib/bc.rb', line 559

def port
  @port
end

#sslObject (readonly)

Returns the value of attribute ssl.



559
560
561
# File 'lib/bc.rb', line 559

def ssl
  @ssl
end

#userObject (readonly)

Returns the value of attribute user.



559
560
561
# File 'lib/bc.rb', line 559

def user
  @user
end

Instance Method Details

#accountsObject

Get an Array of every Account we have.



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

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.



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

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.



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

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



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

def balance
	@jr.getbalance()
end

#bitcoind_versionObject

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



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

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

#block_countObject

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



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

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.



741
742
743
744
745
746
747
748
749
750
751
# File 'lib/bc.rb', line 741

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?



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

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)



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

def difficulty
	@jr.getdifficulty()
end

Donate amount to katmagic (bc’s author).



719
720
721
722
723
724
725
726
727
# File 'lib/bc.rb', line 719

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.



639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
# File 'lib/bc.rb', line 639

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.



736
737
738
# File 'lib/bc.rb', line 736

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.



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

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)


795
796
797
# File 'lib/bc.rb', line 795

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.



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

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.



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

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.



613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
# File 'lib/bc.rb', line 613

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.



632
633
634
# File 'lib/bc.rb', line 632

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)


604
605
606
# File 'lib/bc.rb', line 604

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.



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

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



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

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)


894
895
896
# File 'lib/bc.rb', line 894

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.



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

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

#latest_blockObject

This is the latest Block we’ve processed.



670
671
672
# File 'lib/bc.rb', line 670

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.



677
678
679
680
681
682
# File 'lib/bc.rb', line 677

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.



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

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)



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

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



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

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.



687
688
689
# File 'lib/bc.rb', line 687

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.



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

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.



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

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

#proxy?Boolean

Is bitcoind using a proxy?

Returns:

  • (Boolean)


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

def proxy?
	!!proxy
end

#refill_key_poolObject

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



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

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.



694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
# File 'lib/bc.rb', line 694

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.



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

def stop()
	@jr.stop()
end

#testnet?Boolean

Are we on the testnet?

Returns:

  • (Boolean)


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

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)



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

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)



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

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.



659
660
661
662
663
664
665
666
667
# File 'lib/bc.rb', line 659

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.



754
755
756
757
758
759
760
761
762
763
764
# File 'lib/bc.rb', line 754

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