bigchaindb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []