counterparty_ruby 0.9.0 → 1.1.0

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