blockchain-node 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b783f22fdaaef4c70e77ed848306df99755097442ac07916bb8bcd7482fbd40b
4
- data.tar.gz: 84bc58e6ad3c4e722879aeb5ee9dafea9c2f3eb443451f7434a7acb8d7a3d15b
3
+ metadata.gz: 2eb2210404685d0f9387472304b7192c65e1dabf3a28379fd87e627274641c14
4
+ data.tar.gz: efbe1c81188317edd1056607b6711cc5491c2af673a61214cca5f42417ee853f
5
5
  SHA512:
6
- metadata.gz: 17599574b46a450e6c65e0a03f92fba493c09e2903ca64b0c14a2bdfdc6e17006414dc7d263f772a8a4070ce7ec2c6629e6cf550008a8d58a42f47d581803882
7
- data.tar.gz: 5d70c7b73810567ad137e5db0837d17892bf805c28e563eda338f5856e01ec4b278d0ede804acc6c4db1f85c50a500a13017d6f1b3295c7302ca27348158b602
6
+ metadata.gz: af08f01a79818ede3f831ded4542fcbda935a0b58805b74043485121b5abb032b94c111ace586990a4ebd7c405c9ce36b68f99db06c731f1abed1075b7f85e1c
7
+ data.tar.gz: 902f98131a4ff58824c0c35affee28fa2a5ea399884499e982a1215f046fc39adeb779000da5a4f8ef1c789272e28ab182b2708c7856ac38e078b3ad94eb7ce8
@@ -1,6 +1,78 @@
1
1
  # Ethereum RPC Methods Calls
2
2
 
3
3
 
4
+ ## Personal
5
+
6
+ The personal API manages private keys in the key store.
7
+
8
+ ### personal_listAccounts
9
+
10
+ Returns all the Ethereum account addresses of all keys in the key store.
11
+
12
+
13
+ #### Example
14
+
15
+ ``` ruby
16
+ client.personal_listAccounts
17
+ => ["0x5e97870f263700f46aa00d967821199b9bc5a120", "0x3d80b31a78c30fc628f20b2c89d7ddbf6e53cedc"]
18
+ ```
19
+
20
+
21
+
22
+ ### personal_newAccount
23
+
24
+ Generates a new private key and stores it in the key store directory.
25
+ The key file is encrypted with the given passphrase.
26
+ Returns the address of the new account.
27
+
28
+ #### Parameters
29
+
30
+ | Name | Optional | Description |
31
+ | :----------: | --------- | ------------------------------------------ |
32
+ | password | yes | The password to use to encrypt the wallet |
33
+
34
+ #### Response
35
+
36
+ The address of the new account.
37
+
38
+ #### Example
39
+
40
+ ``` ruby
41
+ client.personal_newAccount('SecurePassword')
42
+ => {:response=>"0x4e6f002a07a7e5f74fdaaa6e730557782405fa05"}
43
+ ```
44
+
45
+
46
+ ## Blockchain Methods
47
+
48
+ ### eth_getBalance
49
+
50
+ Returns the balance of the account of given address at a given block.
51
+
52
+ #### Parameters
53
+
54
+ | Name | Optional | Description |
55
+ | :----------: | --------- | ------------------------------------------ |
56
+ | address | no | The address to check for balance. |
57
+ | block | no | QUANTITY|TAG - integer block number, or the string "latest", "earliest" or "pending" |
58
+
59
+ #### Response
60
+
61
+ `QUANTITY` - integer of the current balance in wei in hex.
62
+
63
+
64
+ #### Example
65
+
66
+ ``` ruby
67
+ client.eth_getBalance('0x5e97870f263700f46aa00d967821199b9bc5a120', 'latest')
68
+ => {:response=>"0x4e6f002a07a7e5f74fdaaa6e730557782405fa05"}
69
+ ```
70
+
71
+
72
+
73
+
74
+ ## Reference: ALL ETH / WEB METHODS
75
+
4
76
  ```
5
77
 
6
78
  web3_clientVersion
@@ -1,10 +1,15 @@
1
- module BlockchainNode
2
- autoload :Client, 'blockchain-node/client'
3
- autoload :Configuration, 'blockchain-node/configuration'
4
- autoload :Errors, 'blockchain-node/errors'
5
- autoload :Request,'blockchain-node/request'
6
- autoload :VERSION,'blockchain-node/version'
1
+ require_relative 'blockchain-node/client'
2
+ require_relative 'blockchain-node/configuration'
3
+ require_relative 'blockchain-node/errors'
4
+ require_relative 'blockchain-node/request'
5
+ require_relative 'blockchain-node/version'
6
+
7
+ require_relative 'blockchain-node/model'
8
+ require_relative 'blockchain-node/model/base'
9
+ require_relative 'blockchain-node/model/bitcoin'
10
+ require_relative 'blockchain-node/model/ethereum'
7
11
 
12
+ module BlockchainNode
8
13
  def self.configure
9
14
  yield Configuration if block_given?
10
15
  end
@@ -16,5 +21,4 @@ module BlockchainNode
16
21
  end
17
22
  config
18
23
  end
19
-
20
24
  end
@@ -4,12 +4,13 @@ module BlockchainNode
4
4
  @@_auth_token
5
5
  AuthToken = Struct.new(:token, :expires_at)
6
6
 
7
+ Details = Struct.new(:id, :blockchain, :network, :status, :height)
8
+
7
9
  attr_accessor :node_id
8
10
  attr_accessor :configuration
9
11
 
10
12
  def initialize(node_id = nil)
11
13
  @node_id = node_id
12
- # allow a different configuration per client instance
13
14
  @configuration = BlockchainNode::Configuration.new
14
15
  end
15
16
 
@@ -19,7 +20,8 @@ module BlockchainNode
19
20
  end
20
21
 
21
22
  def details
22
- request.get(path: nodes_path, auth_token: auth_token)
23
+ r = request.get(path: nodes_path, auth_token: auth_token)
24
+ Details.new(r["id"], r["blockchain"], r["network"], r["status"], Integer(r["height"] || 0))
23
25
  end
24
26
 
25
27
  def auth_token
@@ -37,7 +39,7 @@ module BlockchainNode
37
39
  end
38
40
 
39
41
  def auth_token_expired?
40
- @@_auth_token.nil? || @@_auth_token.expires_at < Time.now.utc - 30
42
+ @@_auth_token.nil? || @@_auth_token.expires_at < Time.now.utc + 30
41
43
  end
42
44
 
43
45
  def get_new_auth_token
@@ -0,0 +1,4 @@
1
+ module BlockchainNode
2
+ module Model
3
+ end
4
+ end
@@ -0,0 +1,14 @@
1
+ module BlockchainNode
2
+ module Model
3
+ class Base
4
+ def initialize(client)
5
+ @client = client
6
+ end
7
+
8
+ def blockchain
9
+ raise "implement me in subclass"
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ module BlockchainNode
2
+ module Model
3
+ class Bitcoin < Base
4
+
5
+ def blockchain
6
+ 'bitcoin'
7
+ end
8
+
9
+ def wallet_info
10
+ @client.getwalletinfo
11
+ end
12
+
13
+ def total_balance
14
+ @client.getbalance
15
+ end
16
+
17
+ def account_balances(account = "")
18
+ @client.listaddressgroupings
19
+ end
20
+
21
+ def new_address(account = "")
22
+ @client.getnewaddress(account)
23
+ end
24
+
25
+ def send_transaction(address, amount)
26
+ @client.sendtoaddress(address, amount)
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,69 @@
1
+ module BlockchainNode
2
+ module Model
3
+ class Ethereum < Base
4
+
5
+ DECIMALS_18 = 1000000000000000000.0
6
+
7
+ def blockchain
8
+ 'ethereum'
9
+ end
10
+
11
+ def accounts
12
+ @client.personal_listAccounts
13
+ end
14
+
15
+ def balanceOf(account)
16
+ resp = @client.eth_getBalance(account, 'latest')
17
+ hex_to_int(resp[:response]) / DECIMALS_18
18
+ end
19
+
20
+ def unlock(account, password, seconds = 30)
21
+ @client.personal_unlockAccount(account, password, seconds)
22
+ end
23
+
24
+ # sends a transaction. Returns the transaction ID
25
+ def send(from, to, ether)
26
+ wei_to_send = (ether * DECIMALS_18).round
27
+ value = '0x' + wei_to_send.to_s(16)
28
+ tx = { from: from, to: to, value: value }
29
+ @client.eth_sendTransaction(tx)[:response]
30
+ end
31
+
32
+ def unlock_and_send(password, from, to, ether)
33
+ unlock(from, password, 10)
34
+ send(from, to, ether)
35
+ end
36
+
37
+ def highest_block
38
+ hex_to_int(@client.eth_blockNumber[:response])
39
+ end
40
+
41
+ def transactions_for_account(account, startBlock = nil, endBlock = nil)
42
+ endBlock = highest_block if endBlock.nil?
43
+ startBlock = endBlock - 1000 if startBlock.nil?
44
+ account.downcase!
45
+
46
+ found_transactions = []
47
+
48
+ (startBlock..endBlock).each do |block|
49
+ response = @client.eth_getBlockByNumber(int_to_hex(block), true)
50
+ found_transactions += response["transactions"].select{ |t| t["from"].try(:downcase) == account || t["to"].try(:downcase) == account }
51
+ end
52
+
53
+ found_transactions
54
+ end
55
+
56
+ private
57
+
58
+ def hex_to_int(hex)
59
+ Integer(hex)
60
+ end
61
+
62
+ def int_to_hex(int)
63
+ '0x' + int.to_s(16)
64
+ end
65
+
66
+ end
67
+ end
68
+ end
69
+
@@ -44,6 +44,7 @@ module BlockchainNode
44
44
  http.request(request)
45
45
  end
46
46
 
47
+ # puts "RAW RESPONSE: #{response.body}"
47
48
  if response.code == "200"
48
49
  begin
49
50
  JSON.parse(response.body)
@@ -2,7 +2,7 @@
2
2
  module BlockchainNode
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- PATCH = 4
5
+ PATCH = 5
6
6
 
7
7
  VERSION = [MAJOR, MINOR, PATCH].join('.').freeze
8
8
  end
@@ -33,18 +33,37 @@ describe BlockchainNode::Configuration do
33
33
 
34
34
  describe "oauth tokens" do
35
35
  it "requests a new token if 1 is expired" do
36
+ Timecop.travel(Time.new(2019,1,10,12,0,0).utc)
37
+
36
38
  expect_any_instance_of(BlockchainNode::Request).to receive(:process_request).exactly(3).times.and_return(
37
39
  {
38
- "access_token" => "a9b29c6810ba513f08f87fafadaa6154690f9246aa663b1b708c1c94a5887386",
39
- "expires_in" => 7200, "created_at" => Time.now.to_i
40
- }
40
+ "access_token" => "token1",
41
+ "expires_in" => 7200, "created_at" => Time.new(2019,1,10,12,0,0).utc.to_i
42
+ },
43
+ {
44
+ "access_token" => "token2",
45
+ "expires_in" => 7200, "created_at" => Time.new(2019,1,10,14,0,0).utc.to_i
46
+ },
47
+ {
48
+ "access_token" => "token3",
49
+ "expires_in" => 7200, "created_at" => Time.new(2019,1,10,15,59,45).utc.to_i
50
+ },
41
51
  )
42
52
  client = BlockchainNode::Client.new(NODE_ID)
43
- client.auth_token
44
- Timecop.travel(Time.now + 7300)
45
- client.auth_token
46
- Timecop.travel(Time.now + 7200)
47
- client.auth_token
53
+ client.auth_token # should get an initial auth token
54
+ expect(client.auth_token).to eq("token1")
55
+
56
+ Timecop.travel(Time.new(2019,1,10,14,0,0))
57
+ client.auth_token # should get a new auth token
58
+ expect(client.auth_token).to eq("token2")
59
+
60
+ Timecop.travel(Time.new(2019,1,10,15,59,15))
61
+ client.auth_token # should NOT get a new token
62
+ expect(client.auth_token).to eq("token2")
63
+
64
+ Timecop.travel(Time.new(2019,1,10,15,59,45))
65
+ client.auth_token # should get a new auth token
66
+ expect(client.auth_token).to eq("token3")
48
67
  end
49
68
  end
50
69
 
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe BlockchainNode::Model::Ethereum do
4
+
5
+ before :all do
6
+ BlockchainNode.configure do |config|
7
+ config.client_id = CLIENT_ID
8
+ config.client_secret = CLIENT_SECRET
9
+ config.request_options = { }
10
+ end
11
+
12
+ @client = BlockchainNode::Client.new(NODE_ID)
13
+ @model = BlockchainNode::Model::Ethereum.new(@client)
14
+ end
15
+
16
+ before :each do
17
+ stub_oauth
18
+ end
19
+
20
+ it "returns a list of accounts" do
21
+ stub_ethereum_list_accounts
22
+ expect(@model.accounts.first).to eq(ETHEREUM_ACCOUNT)
23
+ end
24
+
25
+ it "returns a balance of account" do
26
+ stub_ethereum_balance_of
27
+ expect(@model.balanceOf(ETHEREUM_ACCOUNT)).to eq(10)
28
+ end
29
+
30
+ it "returns the highest block" do
31
+ stub_ethereum_highest_block
32
+ expect(@model.highest_block).to eq(4972496)
33
+ end
34
+
35
+ it "returns sends" do
36
+ stub_ethereum_send
37
+ expect(@model.send("ACCOUNT1", "ACCOUNT2", 1.0)).to eq(ETHEREUM_TRANSACTION)
38
+ end
39
+
40
+ end
@@ -41,3 +41,23 @@ def api_method_body(method, *params)
41
41
  }.to_json
42
42
  end
43
43
 
44
+ # ethereum mocks
45
+ ETHEREUM_ACCOUNT = "0x829bd824b016326a401d083b33d092293333a830"
46
+ ETHEREUM_TRANSACTION = "0x2e9a95887534709e23ba62a54679cfb073b819847be1fd039c1517b851354923"
47
+ def stub_ethereum_list_accounts
48
+ stub_request(:post, "#{BlockchainNode::Request::DEFAULT_BASE_URL}/api/nodes/#{NODE_ID}").
49
+ to_return(status: 200, body: "[\"#{ETHEREUM_ACCOUNT}\"]" )
50
+ end
51
+ def stub_ethereum_balance_of
52
+ stub_request(:post, "#{BlockchainNode::Request::DEFAULT_BASE_URL}/api/nodes/#{NODE_ID}").
53
+ to_return(status: 200, body: "0x8ac7230489e80000" )
54
+ end
55
+ def stub_ethereum_highest_block
56
+ stub_request(:post, "#{BlockchainNode::Request::DEFAULT_BASE_URL}/api/nodes/#{NODE_ID}").
57
+ to_return(status: 200, body: "0x4bdfd0" )
58
+ end
59
+ def stub_ethereum_send
60
+ stub_request(:post, "#{BlockchainNode::Request::DEFAULT_BASE_URL}/api/nodes/#{NODE_ID}").
61
+ with(body: '{"method":"eth_sendTransaction","parameters":[{"from":"ACCOUNT1","to":"ACCOUNT2","value":"0xde0b6b3a7640000"}]}').
62
+ to_return(status: 200, body: ETHEREUM_TRANSACTION )
63
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blockchain-node
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Pestritto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-28 00:00:00.000000000 Z
11
+ date: 2019-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -96,9 +96,14 @@ files:
96
96
  - lib/blockchain-node/client.rb
97
97
  - lib/blockchain-node/configuration.rb
98
98
  - lib/blockchain-node/errors.rb
99
+ - lib/blockchain-node/model.rb
100
+ - lib/blockchain-node/model/base.rb
101
+ - lib/blockchain-node/model/bitcoin.rb
102
+ - lib/blockchain-node/model/ethereum.rb
99
103
  - lib/blockchain-node/request.rb
100
104
  - lib/blockchain-node/version.rb
101
105
  - spec/lib/blockchain-node_spec.rb
106
+ - spec/lib/model/ethereum_spec.rb
102
107
  - spec/spec_helper.rb
103
108
  - spec/support/webmock.rb
104
109
  homepage: https://blockchainnode.io
@@ -123,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
128
  version: '0'
124
129
  requirements: []
125
130
  rubyforge_project:
126
- rubygems_version: 2.7.6
131
+ rubygems_version: 2.7.9
127
132
  signing_key:
128
133
  specification_version: 4
129
134
  summary: BlockchainNode Ruby Client