bigchaindb 0.0.1

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.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/bigchaindb.rb +209 -0
  3. metadata +45 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 75278d885cda3901ce62bb12f72c9ede8154ebba
4
+ data.tar.gz: da03ed58b252b7c7f777fcedb33811f9bf147ce7
5
+ SHA512:
6
+ metadata.gz: acb954f8b2fe74207b1bd30c3e83389a9e42006d377df2f853835630d14a9715746be9049f3b76698df76cb0a90d78278c2a4a6a1eb852f4678b60013ce9db70
7
+ data.tar.gz: 7eecdd5cec8b1ff43816ba8014c0b06dfce99525dfcf9016c939c98a5671fbc41a9ab1dea9079c22971c112de81ceb491fa09468c2db505bf111f9c00a295d2d
data/lib/bigchaindb.rb ADDED
@@ -0,0 +1,209 @@
1
+ require 'json'
2
+ require 'shellwords'
3
+ require 'httparty'
4
+
5
+ module Bdb
6
+ def self.generate_keys
7
+ JSON.parse(`bdb generate_keys`)
8
+ # {"public"=> "x", "private"=> "y"} #Base58 256-bit numbers
9
+ end
10
+
11
+ def self.generate_output(owner_after, amount = 1)
12
+ # owner_after = who can consume this output? Can be a single pubkey or a m-of-n ThresholdSha256 condition
13
+ JSON.parse(`bdb generate_output --amount #{[amount,owner_after].shelljoin}`)
14
+ end
15
+
16
+ def self.create_txn(owner_before, output, asset_data, metadata)
17
+ # owner_before is the issuer of the asset
18
+ args = [
19
+ "--asset-data", asset_data.to_json,
20
+ "--metadata", metadata.to_json,
21
+ owner_before,
22
+ output.to_json
23
+ ]
24
+ command = "bdb create #{args.shelljoin}"
25
+ JSON.parse(`#{command}`)
26
+ end
27
+
28
+ def self.transfer_txn(inputs, outputs, asset, metadata = nil)
29
+ if metadata
30
+ args = [inputs.to_json, outputs.to_json, asset.to_json, metadata.to_json]
31
+ else
32
+ args = [inputs.to_json, outputs.to_json, asset.to_json]
33
+ end
34
+ JSON.parse(`bdb transfer #{args.shelljoin}`)
35
+ end
36
+
37
+ def self.get_asset(txn)
38
+ args = [txn.to_json]
39
+ JSON.parse(`bdb get_asset #{args.shelljoin}`)
40
+ end
41
+
42
+ def self.sign(txn,privkey)
43
+ args = [txn.to_json, privkey]
44
+ JSON.parse(`bdb sign #{args.shelljoin}`)
45
+ end
46
+
47
+ def self.spend(txn, output_ids = [])
48
+ # Convert outputs in txn to signable/spendable inputs.
49
+ if output_ids.any?
50
+ args = [txn.to_json]
51
+ else
52
+ args = [txn.to_json, output_ids.to_json]
53
+ end
54
+ JSON.parse(`bdb spend #{args.shelljoin}`)
55
+ end
56
+
57
+ def self.unspent_outputs(ipdb, pubkey)
58
+ resp = self.get_outputs_by_pubkey(ipdb, pubkey, spent = :both)
59
+ JSON.parse(resp.body)
60
+ end
61
+
62
+ def self.transfer_asset(ipdb, receiver_pubkey, sender_pubkey, sender_privkey, inputs, amount, asset_id, metadata = {"ts"=> Time.now.to_s})
63
+ asset = { "id" => asset_id}
64
+ input_amount = inputs["outputs"].inject(0) { |sum,out| sum + out["amount"].to_i }
65
+ if amount > input_amount
66
+ puts "input_amount < amount"
67
+ return nil
68
+ end
69
+ outputs = [Bdb.generate_output(receiver_pubkey,amount)]
70
+ if amount < input_amount
71
+ # left-over amount should be transferred back to sender
72
+ outputs.push(Bdb.generate_output(sender_pubkey,input_amount - amount))
73
+ end
74
+ input = Bdb.spend(inputs)
75
+ transfer = Bdb.transfer_txn(input, outputs, asset, metadata)
76
+ signed_transfer = Bdb.sign(transfer, sender_privkey)
77
+ resp = post_transaction(ipdb, signed_transfer)
78
+ if resp.code == 202
79
+ puts "Transaction posted. Now checking status..."
80
+ sleep(5)
81
+ txn = JSON.parse(resp.body)
82
+ status_resp = get_transaction_status(ipdb, txn["id"])
83
+ if (status_resp.code == 200) && JSON.parse(status_resp.body)["status"] == "valid"
84
+ return {"transfer" => transfer, "txn" => txn}
85
+ else
86
+ puts "Trying again: #{status_resp.code} #{status_resp.body}"
87
+ sleep(5)
88
+ status_resp = get_transaction_status(ipdb, txn["id"])
89
+ if (status_resp.code == 200) && JSON.parse(status_resp.body)["status"] == "valid"
90
+ return {"transfer" => transfer, "txn" => txn}
91
+ else
92
+ puts "Tried twice but failed. #{status_resp.code} #{status_resp.body}"
93
+ return nil
94
+ end
95
+ end
96
+ else
97
+ puts "Error in transfer_asset: #{resp.code} #{resp.body}"
98
+ return nil
99
+ end
100
+ end
101
+
102
+ # Bdb.create_asset(IPDB, ENV["SLACKBOT_ADMIN_PROMO_PUBKEY"], ENV["SLACKBOT_ADMIN_PROMO_PRIVKEY"], {"name"=> "indtest"}, 13, {"g"=> 4})
103
+ def self.create_asset(ipdb, public_key, private_key, asset_data, amount = 1, metadata = {"x"=> "y"})
104
+ output = Bdb.generate_output(public_key, amount)
105
+ create = Bdb.create_txn(public_key, output, asset_data, metadata)
106
+ signed_create = Bdb.sign(create, private_key)
107
+ resp = post_transaction(ipdb, signed_create)
108
+ if resp.code == 202
109
+ puts "Transaction posted. Now checking status..."
110
+ sleep(5)
111
+ txn = JSON.parse(resp.body)
112
+ status_resp = get_transaction_status(ipdb, txn["id"])
113
+ if (status_resp.code == 200) && JSON.parse(status_resp.body)["status"] == "valid"
114
+ return {"create" => create, "txn" => txn}
115
+ else
116
+ puts "Trying again: #{status_resp.code} #{status_resp.body}"
117
+ sleep(5)
118
+ status_resp = get_transaction_status(ipdb, txn["id"])
119
+ if (status_resp.code == 200) && JSON.parse(status_resp.body)["status"] == "valid"
120
+ return {"create" => create, "txn" => txn}
121
+ else
122
+ puts "Tried twice but failed. #{status_resp.code} #{status_resp.body}"
123
+ return nil
124
+ end
125
+ end
126
+ else
127
+ puts "Error in create_asset: #{resp.code} #{resp.body}"
128
+ return nil
129
+ end
130
+ end
131
+
132
+ def self.test
133
+ # Generate key-pairs
134
+ alice = Bdb.generate_keys
135
+ puts "alice = #{alice.to_json}\n\n"
136
+ bob = Bdb.generate_keys
137
+ puts "bob = #{bob.to_json}\n\n"
138
+
139
+ # Define the metadata for an asset, null should work too
140
+ asset_data = { "name" => "mycoin", "symbol" => "MC" }
141
+ puts "asset = #{asset_data.to_json}\n\n"
142
+
143
+ # To create a CREATE txn, we need output and asset. metadata is optional
144
+ # Let's generate the output first: we'll need receiver and amount
145
+ output = Bdb.generate_output(alice["public"],100)
146
+ puts "output = #{output.to_json}\n\n"
147
+
148
+ metadata = {"msg" => "creating mycoin asset"}
149
+ create = Bdb.create_txn(alice["public"], output, asset_data, metadata)
150
+ puts "create = #{create.to_json}\n\n"
151
+
152
+ signed_create = Bdb.sign(create, alice["private"])
153
+ puts "signed_create = #{signed_create.to_json}\n\n"
154
+
155
+ # This signed CREATE txn can be sent to BigChainDB over HTTP api
156
+ ipdb = { "url" => ENV["IPDB_URL"], "app_id" => ENV["IPDB_APP_ID"], "app_key" => ENV["IPDB_APP_KEY"]}
157
+ resp = post_transaction(ipdb, signed_create)
158
+ puts "resp = #{resp.code} #{resp.body}"
159
+
160
+ # Now let's create a TRANSFER txn and transfer 10 coins to bob
161
+ # we'll need: inputs, outputs, asset and metadata
162
+ # asset for transfer is just { "id": "id of the create txn"}
163
+ asset = { "id" => signed_create["id"]}
164
+ output = Bdb.generate_output(bob["public"],10)
165
+ input = Bdb.spend(create)
166
+ puts "input = #{input.to_json}\n\n"
167
+
168
+ transfer = Bdb.transfer_txn(input, output, asset, {"msg" => "txferring"})
169
+ puts "transfer = #{transfer.to_json}\n\n"
170
+
171
+ signed_transfer = Bdb.sign(transfer, alice["private"])
172
+ puts "signed_transfer = #{signed_transfer.to_json}\n\n"
173
+ # Now send this to server
174
+ resp = post_transaction(ipdb, signed_transfer)
175
+ puts "resp = #{resp.code} #{resp.body}"
176
+
177
+ # Get all txns for this asset
178
+ txns = JSON.parse(get_transactions_by_asset(root_url, asset["id"]).body)
179
+
180
+ # txfr status
181
+ puts get_transaction_status(ipdb, txns.first["id"]).body
182
+ puts get_transaction_status(ipdb, txns.last["id"]).body
183
+ end
184
+
185
+ def self.post_transaction(ipdb, txn)
186
+ HTTParty.post(ipdb["url"] + "/transactions/", {:body => txn.to_json, :headers => {"Content-Type" => "application/json", "app_id" => ipdb["app_id"], "app_key" => ipdb["app_key"]}})
187
+ end
188
+
189
+ def self.get_transaction_by_id(ipdb, txn_id)
190
+ HTTParty.get(ipdb["url"] + "/transactions/#{txn_id}")
191
+ end
192
+
193
+ def self.get_transactions_by_asset(ipdb, asset_id)
194
+ HTTParty.get(ipdb["url"] + "/transactions?asset_id=#{asset_id}")
195
+ end
196
+
197
+ def self.get_outputs_by_pubkey(ipdb, pubkey, spent = :both)
198
+ return HTTParty.get(ipdb["url"] + "/outputs?public_key=#{pubkey}") if spent == :both
199
+ return HTTParty.get(ipdb["url"] + "/outputs?public_key=#{pubkey}&spent=#{spent}") # true or false
200
+ end
201
+
202
+ def self.get_transaction_status(ipdb, txn_id)
203
+ HTTParty.get(ipdb["url"] + "/statuses?transaction_id=#{txn_id}")
204
+ end
205
+
206
+ def self.get_assets(ipdb, query)
207
+ HTTParty.get(ipdb["url"] + "/assets?search=#{query}")
208
+ end
209
+ end
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bigchaindb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nilesh Trivedi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-31 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Library for preparing transactions and submitting them or querying a
14
+ BigchainDB/IPDB node
15
+ email: github@nileshtrivedi.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/bigchaindb.rb
21
+ homepage: http://rubygems.org/gems/bigchaindb
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubyforge_project:
41
+ rubygems_version: 2.6.11
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: BigchainDB / IPDB client
45
+ test_files: []