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.
- checksums.yaml +7 -0
- data/lib/bigchaindb.rb +209 -0
- 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: []
|