counterparty_ruby 0.9.0 → 1.1.0

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.
data/Gemfile.lock CHANGED
@@ -1,24 +1,31 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- counterparty_ruby (0.9.0)
4
+ counterparty_ruby (1.1.0)
5
5
  bitcoin-ruby
6
6
  ffi
7
- rest_client
7
+ rest-client
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
12
  bitcoin-ruby (0.0.6)
13
13
  diff-lcs (1.2.5)
14
- ffi (1.9.6)
14
+ domain_name (0.5.23)
15
+ unf (>= 0.0.5, < 1.0.0)
16
+ ffi (1.9.8)
17
+ http-cookie (1.0.2)
18
+ domain_name (~> 0.5)
15
19
  json (1.8.1)
16
- netrc (0.7.9)
20
+ mime-types (2.4.3)
21
+ netrc (0.10.3)
17
22
  rake (10.3.2)
18
23
  rdoc (4.2.0)
19
24
  json (~> 1.4)
20
- rest_client (1.8.2)
21
- netrc (~> 0.7.7)
25
+ rest-client (1.8.0)
26
+ http-cookie (>= 1.0.2, < 2.0)
27
+ mime-types (>= 1.16, < 3.0)
28
+ netrc (~> 0.7)
22
29
  rspec (3.1.0)
23
30
  rspec-core (~> 3.1.0)
24
31
  rspec-expectations (~> 3.1.0)
@@ -34,6 +41,9 @@ GEM
34
41
  rspec-mocks (3.1.3)
35
42
  rspec-support (~> 3.1.0)
36
43
  rspec-support (3.1.2)
44
+ unf (0.1.4)
45
+ unf_ext
46
+ unf_ext (0.0.6)
37
47
 
38
48
  PLATFORMS
39
49
  ruby
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- counterparty_ruby
1
+ counterparty_ruby [![Gem Version](https://badge.fury.io/rb/counterparty_ruby.svg)](http://badge.fury.io/rb/counterparty_ruby)
2
2
  =================
3
3
  A ruby gem for communicating with a Counterparty (Bitcoin / XCP) API server.
4
4
 
@@ -25,10 +25,22 @@ setting everything up.
25
25
 
26
26
  ![Party On Wayne](http://data.whicdn.com/images/24796384/tumblr_m0ng6rBeWT1qhd0xso1_500_large.jpg)
27
27
 
28
+ ## Changelog
29
+ _Version 1.1_
30
+ * Minor Updates to support changes in counterpartyd 1.1
31
+ * Removed support for relaying transactions through counterparty
32
+ * Implemented bitcoin-ruby based transaction signing
33
+ * Added a blockr.io library for relaying signed transactions via http
34
+ * save() syntax now requires that a private key be provided to persist transactions
35
+ * Default test and production counterparty servers were changed to the vennd.io public servers
36
+
37
+ _Version 0.9_
38
+ * First release!
39
+
28
40
  ## Examples
29
41
  Documentation on the objects is available via:
30
42
  * [counterparty_ruby's rubydoc](http://www.rubydoc.info/github/brighton36/counterparty_ruby/master),
31
- * [The Counterparty official API guide](https://github.com/CounterpartyXCP/counterpartyd/blob/master/docs/API.rst#read-api-function-reference).
43
+ * [The Counterparty official API guide](http://counterparty.io/docs/api/).
32
44
 
33
45
  #### Find the first burn
34
46
  Here we retrieve burns from the blockchain using ActiveRecord style method calls.
@@ -78,7 +90,7 @@ Here we create an asset and persist that asset intothe blockchain using ActiveRe
78
90
  divisible: false,
79
91
  quantity: 100 )
80
92
 
81
- transaction_id = first_asset.save!
93
+ transaction_id = first_asset.save!('private-key-here')
82
94
 
83
95
  puts "Transaction %s has been entered into the mempool" % transaction_id
84
96
  ```
@@ -125,7 +137,64 @@ an outcome to the network.
125
137
 
126
138
  puts "Gold was broadcast down in transaction %s" % tx_id
127
139
  ```
140
+ #### Broadcast a Feed, Place Bets, Resolve the Bet
141
+ In this example, we declare a bet that open, and have two people bet each other
142
+ on the outcome. The bet is then resolved.
143
+
144
+
145
+ ```ruby
146
+ require 'counterparty_ruby'
147
+ require 'active_support/time'
148
+ require "active_support/core_ext/numeric/time"
149
+
150
+ TEAM_BLUE_WINS = 1
151
+ TEAM_RED_WINS = 2
152
+
153
+ ALICE_ADDRESS = 'n4m2u8GwmFB8VDE1szCTkX5ikEEQLiR2Kj'
154
+ JOHN_ADDRESS = 'mu23MfDNhYmQkJF36aJZ783dLDMrqUi9Fa'
155
+
156
+ ORACLE_ADDRESS = 'msCXwsPVbv1Q1pc5AjXd5TdVwy3a1fSYB2'
157
+
158
+ Counterparty.test!
159
+
160
+ broadcast_text = "Winner of game, %s. %s=red %s=blue" % [
161
+ Time.now.strftime("%I%p %Z %b%-d"), TEAM_RED_WINS, TEAM_BLUE_WINS]
162
+
163
+ # Announce the availability of a Bet:
164
+ # NOTE: All times are in UTC
165
+ tx_init = Counterparty::Broadcast.new( source: ORACLE_ADDRESS,
166
+ value: Counterparty::Broadcast::OPEN_BROADCAST, timestamp: Time.now.to_i,
167
+ text: broadcast_text, fee_fraction: 0.00, allow_unconfirmed_inputs: true ).save!('private-key-here')
168
+
169
+ # Alice Bets on Blue:
170
+ tx_bet_on_blue = Counterparty::Bet.new(source: ALICE_ADDRESS,
171
+ feed_address: ORACLE_ADDRESS, bet_type: Counterparty::Bet::EQUAL,
172
+ deadline: 10.minutes.from_now.to_i, wager_quantity: 5,
173
+ counterwager_quantity: 1, expiration: 5,
174
+ target_value: TEAM_BLUE_WINS, leverage: Counterparty::Bet::LEVERAGE_BASIS,
175
+ allow_unconfirmed_inputs: true ).save!('private-key-here')
176
+
177
+ puts "Alice on Blue: %s" % tx_bet_on_blue
128
178
 
179
+ # John Bets on Red:
180
+ tx_bet_on_red = Counterparty::Bet.new(source: JOHN_ADDRESS,
181
+ feed_address: ORACLE_ADDRESS, bet_type: Counterparty::Bet::EQUAL,
182
+ deadline: 10.minutes.from_now.to_i, wager_quantity: 5,
183
+ counterwager_quantity: 1, expiration: 5,
184
+ target_value: TEAM_RED_WINS, leverage: Counterparty::Bet::LEVERAGE_BASIS,
185
+ allow_unconfirmed_inputs: true ).save!('private-key-here')
186
+
187
+ puts "John on Red: %s" % tx_bet_on_red
188
+
189
+ # Close the broadcast : Team Blue wins!
190
+ tx_outcome = Counterparty::Broadcast.new( source: ORACLE_ADDRESS,
191
+ value: TEAM_BLUE_WINS, timestamp: 20.minutes.from_now.to_i,
192
+ fee_fraction: 0.00,
193
+ text: broadcast_text, allow_unconfirmed_inputs: true ).save!('private-key-here')
194
+
195
+ puts "Oracle says: %s" % tx_outcome
196
+
197
+ ```
129
198
  #### Compile, Publish and Execute a Serpent Contract
130
199
  This is still beta behavior, and only supported on testnet, but here's a quick
131
200
  example of how Smart Contracts are published and executed. Note that we require
@@ -171,19 +240,19 @@ the serpent CLI executable is installed on the running system
171
240
 
172
241
  contract_id = Counterparty::Publish.new( source: SOURCE_ADDRESS,
173
242
  code_hex: compiled_script, gasprice: 1, startgas: 1000000, endowment: 0,
174
- allow_unconfirmed_inputs: true ).save!
243
+ allow_unconfirmed_inputs: true ).save!('private-key-here')
175
244
 
176
245
  datalist = serpent.encode_datalist '53'
177
246
 
178
247
  execute_id = Counterparty::Execute.new( source: SOURCE_ADDRESS,
179
248
  contract_id: contract_id, payload_hex: datalist, gasprice: 5,
180
- startgas: 160000, value: 10, allow_unconfirmed_inputs: true ).save!
249
+ startgas: 160000, value: 10, allow_unconfirmed_inputs: true ).save!('private-key-here')
181
250
 
182
251
  puts "Executed Transaction ID: %s" % execute_id
183
252
  ```
184
253
 
185
254
  ## Have questions?
186
- The _best_ place to start is the [Counterparty API reference](https://github.com/CounterpartyXCP/counterpartyd/blob/master/docs/API.rst#read-api-function-reference).
255
+ The _best_ place to start is the [Counterparty API reference](http://counterparty.io/docs/api/).
187
256
  You'll soon find that this gem is merely a wrapper around the official
188
257
  counterpartyd json API.
189
258
 
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.required_ruby_version = '>= 1.9'
17
17
  gem.license = 'LGPL'
18
18
 
19
- ['rest_client', 'bitcoin-ruby', 'ffi'].each do |dependency|
19
+ ['rest-client', 'bitcoin-ruby', 'ffi'].each do |dependency|
20
20
  gem.add_runtime_dependency dependency
21
21
  end
22
22
  ['rspec', 'rspec-its', 'rake', 'rdoc'].each do |dependency|
data/lib/blockr_io.rb ADDED
@@ -0,0 +1,42 @@
1
+ # This is a 'driver' meant to emulate bitcoin-client calls, by way of the blockr.io
2
+ # API
3
+ class BlockrIo
4
+ class ResponseError < StandardError; end
5
+
6
+ def initialize(is_testing = false)
7
+ @is_testing = is_testing
8
+ end
9
+
10
+ def api_url
11
+ 'http://%s.blockr.io/api/v1' % (is_testing? ? 'tbtc' : 'btc')
12
+ end
13
+
14
+ def getrawtransaction(tx_id)
15
+ json_get('tx', 'raw', tx_id.to_s)['data']['tx']['hex']
16
+ end
17
+
18
+ def sendrawtransaction(raw_tx)
19
+ request('tx', 'push'){|req| req.post( {hex: raw_tx}.to_json,
20
+ accept: 'json', content_type: 'json' ) }['data']
21
+ end
22
+
23
+ def is_testing?
24
+ @is_testing
25
+ end
26
+
27
+ private
28
+
29
+ def request(*path, &block)
30
+ json = JSON.parse(block.call(client(*path)))
31
+ raise ResponseError unless json['status'] == 'success' && json['code'] == 200
32
+ json
33
+ end
34
+
35
+ def client(*path_parts)
36
+ RestClient::Resource.new( ([api_url]+path_parts).join('/') )
37
+ end
38
+
39
+ def json_get(*path)
40
+ request(*path){ |req| req.get content_type: 'json' }
41
+ end
42
+ end
@@ -13,7 +13,7 @@ module Counterparty
13
13
  # which means the library will wait indefinitely before timing out
14
14
  attr_writer :timeout
15
15
 
16
- def initialize(port=14000, username='rpc', password='1234', host='localhost')
16
+ def initialize(port=4000, username='counterparty', password='1234', host='xcp-dev.vennd.io')
17
17
  @host,@port,@username,@password=host.to_s,port.to_i,username.to_s,password.to_s
18
18
  @timeout = DEFAULT_TIMEOUT
19
19
  end
@@ -28,17 +28,12 @@ module Counterparty
28
28
  request 'sign_tx', unsigned_tx_hex: raw_tx, privkey: private_key
29
29
  end
30
30
 
31
- # Broadcasts a signed transaction onto the bitcoin blockchain
32
- def broadcast_tx(signed_tx)
33
- request 'broadcast_tx', signed_tx_hex: signed_tx
34
- end
35
-
36
31
  # Issue a request to the counterpartyd server for the given method, with the
37
32
  # given params.
38
33
  def request(method, params)
39
34
  client = RestClient::Resource.new api_url, :timeout => @timeout
40
- response = JSON.parse client.post({ method: method,
41
- params: params, jsonrpc: '2.0', id: '0' }.to_json,
35
+ request = { method: method, params: params, jsonrpc: '2.0', id: '0' }.to_json
36
+ response = JSON.parse client.post(request,
42
37
  user: @username, password: @password, accept: 'json',
43
38
  content_type: 'json' )
44
39
 
@@ -53,136 +48,9 @@ module Counterparty
53
48
  # as to be future-proof here going forward
54
49
  def self.resource_request(klass) # :nodoc:
55
50
  define_method(klass.to_get_request){ |params| klass.find params }
56
- define_method(klass.to_do_request){ |params| klass.create(params).save! }
57
51
  define_method(klass.to_create_request){ |params| klass.create(params).to_raw_tx }
58
52
  end
59
53
 
60
- # :method: do_balance
61
- # # Sends a do_balance call to the counterpartyd server, given the provided params
62
-
63
- # :method: create_balance
64
- # # Sends a create_balance call to the counterpartyd server, given the provided params
65
-
66
- # :method: do_bet
67
- # # Sends a do_bet call to the counterpartyd server, given the provided params
68
-
69
- # :method: create_bet
70
- # # Sends a create_bet call to the counterpartyd server, given the provided params
71
-
72
- # :method: do_betmatch
73
- # # Sends a do_betmatch call to the counterpartyd server, given the provided params
74
-
75
- # :method: create_betmatch
76
- # # Sends a create_betmatch call to the counterpartyd server, given the provided params
77
-
78
- # :method: do_broadcast
79
- # # Sends a do_broadcast call to the counterpartyd server, given the provided params
80
-
81
- # :method: create_broadcast
82
- # # Sends a create_broadcast call to the counterpartyd server, given the provided params
83
-
84
- # :method: do_btcpays
85
- # # Sends a do_btcpays call to the counterpartyd server, given the provided params
86
-
87
- # :method: create_btcpay
88
- # # Sends a create_btcpay call to the counterpartyd server, given the provided params
89
-
90
- # :method: do_burn
91
- # # Sends a do_burn call to the counterpartyd server, given the provided params
92
-
93
- # :method: create_burn
94
- # # Sends a create_burn call to the counterpartyd server, given the provided params
95
-
96
- # :method: do_callback
97
- # # Sends a do_callback call to the counterpartyd server, given the provided params
98
-
99
- # :method: create_callback
100
- # # Sends a create_callback call to the counterpartyd server, given the provided params
101
-
102
- # :method: do_cancel
103
- # # Sends a do_cancel call to the counterpartyd server, given the provided params
104
-
105
- # :method: create_cancel
106
- # # Sends a create_cancel call to the counterpartyd server, given the provided params
107
-
108
- # :method: do_credit
109
- # # Sends a do_credit call to the counterpartyd server, given the provided params
110
-
111
- # :method: create_credit
112
- # # Sends a create_credit call to the counterpartyd server, given the provided params
113
-
114
- # :method: do_debit
115
- # # Sends a do_debit call to the counterpartyd server, given the provided params
116
-
117
- # :method: create_debit
118
- # # Sends a create_debit call to the counterpartyd server, given the provided params
119
-
120
- # :method: do_dividend
121
- # # Sends a do_dividend call to the counterpartyd server, given the provided params
122
-
123
- # :method: create_dividend
124
- # # Sends a create_dividend call to the counterpartyd server, given the provided params
125
-
126
- # :method: do_issuance
127
- # # Sends a do_issuance call to the counterpartyd server, given the provided params
128
-
129
- # :method: create_issuance
130
- # # Sends a create_issuance call to the counterpartyd server, given the provided params
131
-
132
- # :method: do_order
133
- # # Sends a do_order call to the counterpartyd server, given the provided params
134
-
135
- # :method: create_order
136
- # # Sends a create_order call to the counterpartyd server, given the provided params
137
-
138
- # :method: do_ordermatch
139
- # # Sends a do_ordermatch call to the counterpartyd server, given the provided params
140
-
141
- # :method: create_ordermatch
142
- # # Sends a create_ordermatch call to the counterpartyd server, given the provided params
143
-
144
- # :method: do_send
145
- # # Sends a do_send call to the counterpartyd server, given the provided params
146
-
147
- # :method: create_send
148
- # # Sends a create_send call to the counterpartyd server, given the provided params
149
-
150
- # :method: do_message
151
- # # Sends a do_message call to the counterpartyd server, given the provided params
152
-
153
- # :method: create_message
154
- # # Sends a create_message call to the counterpartyd server, given the provided params
155
-
156
- # :method: do_callback
157
- # # Sends a do_callback call to the counterpartyd server, given the provided params
158
-
159
- # :method: create_callback
160
- # # Sends a create_callback call to the counterpartyd server, given the provided params
161
-
162
- # :method: do_betexpiration
163
- # # Sends a do_betexpiration call to the counterpartyd server, given the provided params
164
-
165
- # :method: create_betexpiration
166
- # # Sends a create_betexpiration call to the counterpartyd server, given the provided params
167
-
168
- # :method: do_orderexpiration
169
- # # Sends a do_orderexpiration call to the counterpartyd server, given the provided params
170
-
171
- # :method: create_orderexpiration
172
- # # Sends a create_orderexpiration call to the counterpartyd server, given the provided params
173
-
174
- # :method: do_betmatchexpiration
175
- # # Sends a do_betmatchexpiration call to the counterpartyd server, given the provided params
176
-
177
- # :method: create_betmatchexpiration
178
- # # Sends a create_betmatchexpiration call to the counterpartyd server, given the provided params
179
-
180
- # :method: do_ordermatchexpiration
181
- # # Sends a do_ordermatchexpiration call to the counterpartyd server, given the provided params
182
-
183
- # :method: create_ordermatchexpiration
184
- # # Sends a create_ordermatchexpiration call to the counterpartyd server, given the provided params
185
-
186
54
  # Go ahead and setup the defined resources, and throw them into the native-style
187
55
  # api methods:
188
56
  Counterparty.constants.each do |c|
@@ -65,7 +65,7 @@ class RawTx
65
65
  # Convert an array of 8 bit numbers into an unsigned int,
66
66
  # Remember that for each input byte, the most significant nibble comes last.
67
67
  def self.bytes_to_ui(bytes)
68
- nibbles = bytes.collect{|b| [b & 0x0f, b >> 4]}.flatten
68
+ nibbles = bytes.collect{|b| [b & 0x0f, (b & 0xf0) >> 4]}.flatten
69
69
  nibbles.each_with_index.inject(0){|sum,(b,i)| sum += b * 16**i}
70
70
  end
71
71
 
@@ -47,9 +47,6 @@ module Counterparty
47
47
 
48
48
  # Given the provided private key, this method returns a signed transaction
49
49
  # suitable for broadcasting on the network.
50
- #
51
- # NOTE: This method communicates your private key to the counterpartyd
52
- # server, which might not be what you want!
53
50
  def to_signed_tx(private_key)
54
51
  sign_tx to_raw_tx, private_key
55
52
  end
@@ -57,12 +54,8 @@ module Counterparty
57
54
  # Commit this object to the blockchain. If a private key is passed, the
58
55
  # transaction is signed using this key via a create_ call and a subsequent
59
56
  # sign_tx call.
60
- # NOTE: This method communicates your private key to the counterpartyd
61
- # server, which might not be what you want!
62
- def save!(private_key = nil)
63
- (private_key) ?
64
- connection.broadcast_tx( to_signed_tx(private_key) ) :
65
- connection.request(self.class.to_do_request, to_params)
57
+ def save!(private_key)
58
+ bitcoin.sendrawtransaction to_signed_tx(private_key)
66
59
  end
67
60
 
68
61
  private
@@ -71,59 +64,36 @@ module Counterparty
71
64
  # is a stub for when we decide in the future to Use the bitcoin-client gem
72
65
  # to perform signatures
73
66
  def sign_tx(raw_tx, pkey_wif)
74
- key = ::Bitcoin.open_key pkey_wif
75
- raw_tx_hash = RawTx.new(raw_tx).to_hash
76
-
77
- prev_hash = raw_tx_hash['vin'][0]['txid']
78
- prior_tx_json = open("http://test.webbtc.com/tx/#{prev_hash}.json").read
79
- puts prior_tx_json.inspect
80
- prev_tx = Bitcoin::P::Tx.from_json(prior_tx_json.to_s)
81
-
82
-
83
- puts "HERE"
84
- signed_tx = Bitcoin::Protocol::Tx.new
85
- signed_tx.ver = raw_tx_hash['ver']
86
- signed_tx.lock = raw_tx_hash['lock_time']
87
-
88
- tx_in= TxInBuilder.new
89
- tx_in.prev_out prev_tx
90
- tx_in.prev_out_index 0
91
- tx_in.signature_key key
92
-
93
- signed_tx.add_in tx_in.tx
94
-
95
- # Here's how we put them in the raw
96
- # @block.tx << tx
97
-
98
-
99
- # We need to compare against
100
- # Primarily: http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html
101
- # With Some of this: https://bitcoin.org/en/developer-reference#signrawtransaction
102
- =begin
103
- def sign(tx, i, priv, hashcode=SIGHASH_ALL):
104
- i = int(i)
105
- if not re.match('^[0-9a-fA-F]*$', tx):
106
- return binascii.unhexlify(sign(binascii.hexlify(tx), i, priv))
107
- if len(priv) <= 33:
108
- priv = binascii.hexlify(priv)
109
- pub = privkey_to_pubkey(priv)
110
- address = pubkey_to_address(pub)
111
- signing_tx = signature_form(tx, i, mk_pubkey_script(address), hashcode)
112
- sig = ecdsa_tx_sign(signing_tx, priv, hashcode)
113
- txobj = deserialize(tx)
114
- txobj["ins"][i]["script"] = serialize_script([sig, pub])
115
- return serialize(txobj)
116
- =end
117
-
118
-
119
- scriptSig = Bitcoin.sign_data(key,
120
- raw_tx_hash["in"][0]["scriptSig"] ).unpack('h*').first
121
- # TODO: We may have to iterate over each input
122
- raw_tx_hash["in"][0]["scriptSig"] = scriptSig
123
-
124
- ret = Bitcoin::Protocol::Tx.from_hash(raw_tx_hash).to_payload.unpack('h*').first
125
-
126
- ret
67
+ # Seems like this is your quintessential reference:
68
+ # http://www.righto.com/2014/02/bitcoins-hard-way-using-raw-bitcoin.html
69
+
70
+ # I think this is the right way to do it...
71
+ Bitcoin.network = (bitcoin.is_testing?) ? :testnet3 : :bitcoin
72
+
73
+ # This parses the binary-encoded raw transaction:
74
+ tx = Bitcoin::P::Tx.new [raw_tx].pack('H*')
75
+
76
+ # This is the input transaction, which we'll need for signining:
77
+ prev_hash = tx.in[0].prev_out.reverse_hth
78
+
79
+ # let's parse the keys:
80
+ key = Bitcoin::Key.from_base58 pkey_wif
81
+
82
+ pubkey = [key.pub].pack('H*')
83
+
84
+ # And parse the input transaction:
85
+ prev_tx = Bitcoin::P::Tx.new [bitcoin.getrawtransaction(prev_hash)].pack('H*')
86
+
87
+ # And, now we're ready to sign:
88
+ subscript = tx.signature_hash_for_input 0, prev_tx
89
+ sig = Bitcoin.sign_data Bitcoin.open_key(key.priv), subscript
90
+ tx.in[0].script_sig = Bitcoin::Script.to_signature_pubkey_script sig, pubkey
91
+
92
+ tx.to_payload.unpack('H*')[0]
93
+ end
94
+
95
+ def bitcoin
96
+ self.class.bitcoin
127
97
  end
128
98
 
129
99
  def connection
@@ -153,9 +123,10 @@ def sign(tx, i, priv, hashcode=SIGHASH_ALL):
153
123
  @connection || Counterparty.connection
154
124
  end
155
125
 
156
- # Returns the method name of a do_* request for this resource
157
- def to_do_request
158
- 'do_%s' % api_name
126
+ # Returns the currently assigned connection object, or if one hasn't
127
+ # been set, the default specified in the Counterparty module
128
+ def bitcoin
129
+ @bitcoin || Counterparty.bitcoin
159
130
  end
160
131
 
161
132
  # Returns the method name of a create_* request for this resource
@@ -14,6 +14,22 @@ module Counterparty
14
14
 
15
15
  # An object that describes a specific bet.
16
16
  class Bet < CounterResource
17
+ # Bet Type: Bullish CFD
18
+ BULLISH_CFD = 0
19
+
20
+ # Bet Type: Bearish CFD
21
+ BEARISH_CFD = 1
22
+
23
+ # Bet Type: Equal
24
+ EQUAL = 2
25
+
26
+ # Bet Type: Not Equal
27
+ NOT_EQUAL = 3
28
+
29
+ # Denominator by which the leverage integer is divided by. It's effectively
30
+ # a 'magic' number that allows us to keep the leverage parameter an integer
31
+ LEVERAGE_BASIS = 5040
32
+
17
33
  # (integer): The transaction index
18
34
  attr_accessor :tx_index
19
35
 
@@ -67,11 +83,11 @@ module Counterparty
67
83
  attr_accessor :validity
68
84
 
69
85
  # (integer): The quantity of XCP to wager. (Only used in Create)
70
- attr_accessor :wager
86
+ attr_accessor :wager_quantity
71
87
 
72
88
  # (integer): The minimum quantity of XCP to be
73
89
  # wagered against, for the bets to match. (Only used in Create)
74
- attr_accessor :counterwager
90
+ attr_accessor :counterwager_quantity
75
91
  end
76
92
 
77
93
  # An object that describes a specific occurance of two bets being matched
@@ -147,6 +163,9 @@ module Counterparty
147
163
  # An object that describes a specific occurance of a broadcast event
148
164
  # (i.e. creating/extending a feed)
149
165
  class Broadcast < CounterResource
166
+ # Value: Open Broadcast
167
+ OPEN_BROADCAST = -1.0
168
+
150
169
  # (integer): The transaction index
151
170
  attr_accessor :tx_index
152
171
 
@@ -1,4 +1,4 @@
1
1
  module Counterparty
2
2
  # The library version string
3
- VERSION = "0.9.0"
3
+ VERSION = "1.1.0"
4
4
  end
@@ -3,6 +3,7 @@ require 'rest_client'
3
3
  require 'open-uri'
4
4
  require 'bitcoin'
5
5
 
6
+ require 'blockr_io'
6
7
  require 'counterparty/raw_tx'
7
8
  require 'counterparty/version'
8
9
  require 'counterparty/resource'
@@ -46,6 +47,9 @@ module Counterparty
46
47
  end
47
48
 
48
49
  class << self
50
+ # Sets/Gets the default bitcoin (connection) object
51
+ attr_writer :bitcoin
52
+
49
53
  # Sets/Gets the default connection object
50
54
  attr_writer :connection
51
55
 
@@ -55,16 +59,24 @@ module Counterparty
55
59
  @connection || Connection.new
56
60
  end
57
61
 
62
+ # Returns the current default bitcoin object, or creates a new test-mode
63
+ # connection, if none has been defined
64
+ def bitcoin
65
+ @bitcoin || BlockrIo.new
66
+ end
67
+
58
68
  # Establishes the default connection for new objects as being the default
59
69
  # counterparty production mode port/user/ip
60
70
  def production!
61
- @connection = Connection.new 4000
71
+ @connection = Connection.new
72
+ @bitcoin = BlockrIo.new
62
73
  end
63
74
 
64
75
  # Establishes the default connection for new objects as being the default
65
76
  # counterparty test mode port/user/ip
66
77
  def test!
67
- @connection = Connection.new
78
+ @connection = Connection.new 14000
79
+ @bitcoin = BlockrIo.new true
68
80
  end
69
81
  end
70
82
  end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ # This is a fairly stand-alone test, and doesn't require much from the
4
+ # helpers.
5
+ describe BlockrIo do
6
+ include_context 'globals'
7
+
8
+ let(:blockr_main) { BlockrIo.new }
9
+ let(:blockr_test) { BlockrIo.new true }
10
+
11
+ describe "#new" do
12
+ # It should default to the test network parameters
13
+ subject{BlockrIo.new}
14
+
15
+ its(:is_testing?){ should eq(false) }
16
+ end
17
+
18
+ context "testnet" do
19
+ describe "#getrawtransaction" do
20
+ it "should get raw testnet transactions" do
21
+ tx_hash = '686c2e3c9d4b681b3589aa4ce2ba9ecb99c6d7dcbc1c754441ee0762f463f47a'
22
+
23
+ expect(blockr_test.getrawtransaction(tx_hash)).to eq(
24
+ '01000000017a2bf2ea931670ecb165f1f3a2586d9d2d338a50066d1096a3fc8e'+
25
+ 'b52e9667f8020000006a47304402201e92eebc6d9737472d085fc46f6ab45e8e'+
26
+ 'c6696ad3efb79261e5559ab0c517ac02200a905c54ebb9ac28e8402e6651ddf8'+
27
+ 'e067fa1305cd8c8685a40cb432bb7ef5f601210286b1e4f15de57fd34bde19cf'+
28
+ '64ad9302e454c4c377677581a951579a124b86e7ffffffff03781e0000000000'+
29
+ '0069512102a12853504fc4e79fea5e996f87e00e3e8e1d6a79c1e85c367e4ed4'+
30
+ '4d4120f14521032247831fc423ee7c96a44fa088e64231b5f00cbc9fc755bf3b'+
31
+ 'dd41f64b80cbf9210286b1e4f15de57fd34bde19cf64ad9302e454c4c3776775'+
32
+ '81a951579a124b86e753ae781e00000000000069512103852853504fc4e79fea'+
33
+ '6fa406f7d61deeae390f1aee8b33580d3a98060111a18c2102502ee07ae44c88'+
34
+ '5cf1cb23c4a4c67303f4bd2ce9cb8475f25aaf229e7aaeebb2210286b1e4f15d'+
35
+ 'e57fd34bde19cf64ad9302e454c4c377677581a951579a124b86e753aea0be00'+
36
+ '00000000001976a9148025b288cb325d88bcd7ef5d1ab1f8827778d5ee88ac00'+
37
+ '000000' )
38
+ end
39
+ end
40
+ end
41
+
42
+ context "mainnet" do
43
+ describe "#getrawtransaction" do
44
+ it "should retrieve the first burn" do
45
+ tx_hash = '685623401c3f5e9d2eaaf0657a50454e56a270ee7630d409e98d3bc257560098'
46
+
47
+ expect(blockr_main.getrawtransaction(tx_hash)).to eq(
48
+ '010000000150326ab8ff04aa5bfd83f3dfc78b45716fd46864c872e2bd424fef'+
49
+ 'd580d5cf3e010000006b483045022100bf49d487f78345aa450c6f5fcb67a732'+
50
+ '53d23cce1ae557f3edc6ed58a383f16a022032a4a4736b15bcf0d4c208cd8c5c'+
51
+ 'e43ced848ccc2b91acb82f4c87d95eb67a960121035bceeb417f25beaa28d133'+
52
+ 'ee7b28faa1e4f5c2f76b8daf12c3fab18261718790ffffffff0350c300000000'+
53
+ '00001976a914818895f3dc2c178629d3d2d8fa3ec4a3f817982188ac00000000'+
54
+ '00000000196a17434e5452505254590000003c50726f6f664f664275726e2030'+
55
+ '0500000000001976a914f8195d523aa0c10d9d20eca785041815257f3ec888ac'+
56
+ '00000000' )
57
+ end
58
+
59
+ it "should fail on bad transaction" do
60
+ expect{blockr_main.getrawtransaction('bad_tx')}.to raise_error(RestClient::ResourceNotFound)
61
+ end
62
+ end
63
+
64
+ describe "#sendrawtransaction" do
65
+ # I think the way to test this is simply to do so in the resource_create
66
+ end
67
+ end
68
+ end
@@ -5,10 +5,10 @@ describe Counterparty::Connection do
5
5
  # It should default to the test network parameters
6
6
  subject{Counterparty::Connection.new}
7
7
 
8
- its(:host){ should eq('localhost') }
9
- its(:port){ should eq(14000) }
10
- its(:username){ should eq('rpc') }
8
+ its(:host){ should eq('xcp-dev.vennd.io') }
9
+ its(:port){ should eq(4000) }
10
+ its(:username){ should eq('counterparty') }
11
11
  its(:password){ should eq('1234') }
12
- its(:api_url){ should eq('http://rpc:1234@localhost:14000/api/') }
12
+ its(:api_url){ should eq('http://counterparty:1234@xcp-dev.vennd.io:4000/api/') }
13
13
  end
14
14
  end
@@ -3,6 +3,11 @@ require 'spec_helper'
3
3
  describe Counterparty::ResponseError do
4
4
  include_context 'globals'
5
5
 
6
+ before(:all) do
7
+ Counterparty.test!
8
+ Counterparty.connection = local_counterpartyd :test if use_local_counterpartyd?
9
+ end
10
+
6
11
  let(:bad_issuance) do
7
12
  Counterparty::Issuance.new source: source_address,
8
13
  asset: 'THISASSETNAMEISFARTOOLONGANDINVALID',
@@ -15,12 +20,12 @@ describe Counterparty::ResponseError do
15
20
  end
16
21
 
17
22
  it "should fail on save!" do
18
- expect{ bad_issuance.save! }.to raise_error Counterparty::ResponseError
23
+ expect{ bad_issuance.save!(source_privkey) }.to raise_error Counterparty::ResponseError
19
24
  end
20
25
 
21
26
  subject do
22
27
  begin
23
- bad_issuance.save!
28
+ bad_issuance.save!(source_privkey)
24
29
  rescue => error
25
30
  error
26
31
  end
@@ -11,8 +11,6 @@ describe RawTx do
11
11
  '2E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C70'+
12
12
  '2B6BF11D5FAC00000000'
13
13
  genesis_double_sha = '4A5E1E4BAAB89F3A32518A88C31BC87F618F76673E2CC77AB2127B7AFDEDA33B'
14
-
15
- pending
16
14
  end
17
15
 
18
16
  describe ".nibbles_to_ui" do
@@ -114,8 +112,6 @@ describe RawTx do
114
112
  "ecd13e658bbecc0b2b4c87306f637828917838c02a5d95d0e1bdff9b040000000000" +
115
113
  "0000002f73733331312f00906b570400000000e4050000ffffffff01bf2087950000" +
116
114
  "00001976a9145399c3093d31e4b0af4be1215d59b857b861ad5d88ac00000000").to_hash }
117
-
118
- pending
119
115
  end
120
116
 
121
117
  end
@@ -7,12 +7,10 @@ require 'spec_helper'
7
7
  describe Counterparty do
8
8
  include_context 'globals'
9
9
 
10
- before(:all) { Counterparty.test! }
11
-
12
- # TODO: deprecate?
13
- #it "Ensure test account has BTC" do
14
- #expect(bitcoin.getreceivedbyaddress(source_address)).to be > 0
15
- #end
10
+ before(:all) do
11
+ Counterparty.test!
12
+ Counterparty.connection = local_counterpartyd :test if use_local_counterpartyd?
13
+ end
16
14
 
17
15
  describe "Ensure test account has XCP" do
18
16
  subject do
@@ -35,7 +33,10 @@ describe Counterparty do
35
33
  end
36
34
 
37
35
  its(:to_raw_tx) { should_not be_empty }
38
- its(:save!) { should_not be_empty }
36
+
37
+ it "should persist asset send" do
38
+ expect(subject.save!(source_privkey)).to_not be_empty
39
+ end
39
40
  end
40
41
 
41
42
  describe "#do_issuance" do
@@ -46,7 +47,10 @@ describe Counterparty do
46
47
  end
47
48
 
48
49
  its(:to_raw_tx) { should_not be_empty }
49
- its(:save!) { should_not be_empty }
50
+
51
+ it "should persist issuance" do
52
+ expect(subject.save!(source_privkey)).to_not be_empty
53
+ end
50
54
  end
51
55
 
52
56
  describe "signed #create_broadcast" do
@@ -54,14 +58,13 @@ describe Counterparty do
54
58
  # We want the save(private_key) syntax here
55
59
  Counterparty::Broadcast.new source: source_address, fee_fraction: 0.05,
56
60
  text: "Price of gold, 12AM UTC March1. 1=inc 2=dec/const", value: 2.0,
57
- timestamp: 1418926641,
61
+ timestamp: Time.now.to_i,
58
62
  allow_unconfirmed_inputs: true
59
63
  end
60
64
 
61
65
  its(:to_raw_tx) { should_not be_empty }
62
66
 
63
- it "should persist using a provided key" do
64
- # TODO: Make this work
67
+ it "should persist broadcast" do
65
68
  expect(subject.save!(source_privkey)).to_not be_empty
66
69
  end
67
70
  end
@@ -5,7 +5,10 @@ require 'spec_helper'
5
5
  describe Counterparty do
6
6
  include_context 'globals'
7
7
 
8
- before(:all) { Counterparty.production! }
8
+ before(:all) do
9
+ Counterparty.production!
10
+ Counterparty.connection = local_counterpartyd :main if use_local_counterpartyd?
11
+ end
9
12
 
10
13
  # Get all burns between blocks 280537 and 280539 where greater than .2 BTC was
11
14
  # burned, sorting by tx_hash (ascending order) With this (and the rest of the
data/spec/spec_helper.rb CHANGED
@@ -4,10 +4,22 @@ require 'yaml'
4
4
  require 'rspec/its'
5
5
  require 'counterparty_ruby'
6
6
 
7
+ def config_yaml(file = 'config.yml')
8
+ YAML.load File.open([File.dirname(__FILE__),file].join('/')).read
9
+ end
10
+
11
+ def local_counterpartyd(network)
12
+ config = config_yaml('config.local.yml')
13
+ args = %w(port username password host).collect{ |a| config[network.to_s][a] }
14
+ Counterparty::Connection.new *args
15
+ end
16
+
17
+ def use_local_counterpartyd?
18
+ File.exists? [File.dirname(__FILE__),'config.local.yml'].join('/')
19
+ end
20
+
7
21
  shared_context 'globals' do
8
- let(:config) do
9
- YAML.load File.open([File.dirname(__FILE__),'config.yml'].join('/')).read
10
- end
22
+ let(:config){ config_yaml }
11
23
 
12
24
  let(:source_address) { config['source_address'] }
13
25
  let(:source_privkey) { config['source_privkey'] }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: counterparty_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,10 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-01-07 00:00:00.000000000 Z
12
+ date: 2015-04-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: rest_client
15
+ name: rest-client
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
@@ -137,12 +137,14 @@ files:
137
137
  - README.md
138
138
  - Rakefile
139
139
  - counterparty_ruby.gemspec
140
+ - lib/blockr_io.rb
140
141
  - lib/counterparty/connection.rb
141
142
  - lib/counterparty/raw_tx.rb
142
143
  - lib/counterparty/resource.rb
143
144
  - lib/counterparty/resources.rb
144
145
  - lib/counterparty/version.rb
145
146
  - lib/counterparty_ruby.rb
147
+ - spec/blockr_io_spec.rb
146
148
  - spec/config.yml
147
149
  - spec/connection_spec.rb
148
150
  - spec/exceptions_spec.rb
@@ -176,6 +178,7 @@ signing_key:
176
178
  specification_version: 3
177
179
  summary: An ActiveRecord-esque abstraction of the Counterparty API
178
180
  test_files:
181
+ - spec/blockr_io_spec.rb
179
182
  - spec/config.yml
180
183
  - spec/connection_spec.rb
181
184
  - spec/exceptions_spec.rb