counterparty_ruby 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,70 @@
1
+ require 'json'
2
+ require 'rest_client'
3
+ require 'open-uri'
4
+ require 'bitcoin'
5
+
6
+ require 'counterparty/raw_tx'
7
+ require 'counterparty/version'
8
+ require 'counterparty/resource'
9
+ require 'counterparty/resources'
10
+ require 'counterparty/connection'
11
+
12
+ # The main module, under which all classes in the library are defined.
13
+ module Counterparty
14
+ # One XCP, in units of Satoshi
15
+ ONE_XCP = 100_000_000
16
+
17
+ # One BTC, in units of Satoshi
18
+ ONE_BTC = 100_000_000
19
+
20
+ # This exception is typically raised by errors related to the params and/or
21
+ # request format
22
+ class JsonResponseError < StandardError; end
23
+
24
+ # This exception comes from an error relating to a proper request, but an
25
+ # inability to complete the request via the counterpartyd api
26
+ class ResponseError < StandardError
27
+ attr_reader :data_type
28
+ attr_reader :data_args
29
+ attr_reader :data_message
30
+ attr_reader :code
31
+ attr_reader :message_class
32
+
33
+ def initialize(json)
34
+ @message_class, @code = json['message'], json['code']
35
+
36
+ json['data'].each_pair do |(k,v)|
37
+ instance_variable_set '@data_%s' % k, v
38
+ end if json.has_key? 'data'
39
+
40
+ super
41
+ end
42
+
43
+ def message
44
+ '%s: %s' % [@message_class,@data_message]
45
+ end
46
+ end
47
+
48
+ class << self
49
+ # Sets/Gets the default connection object
50
+ attr_writer :connection
51
+
52
+ # Returns the current default connection object, or creates a new test-mode
53
+ # connection, if none has been defined
54
+ def connection
55
+ @connection || Connection.new
56
+ end
57
+
58
+ # Establishes the default connection for new objects as being the default
59
+ # counterparty production mode port/user/ip
60
+ def production!
61
+ @connection = Connection.new 4000
62
+ end
63
+
64
+ # Establishes the default connection for new objects as being the default
65
+ # counterparty test mode port/user/ip
66
+ def test!
67
+ @connection = Connection.new
68
+ end
69
+ end
70
+ end
data/spec/config.yml ADDED
@@ -0,0 +1,3 @@
1
+ source_address: msCXwsPVbv1Q1pc5AjXd5TdVwy3a1fSYB2
2
+ source_privkey: cP7ufwcbZujaa1qkKthLbVZUaP88RS5r9awyXerJE5rAEMTRVmzc
3
+ spend_destination: msj42CCGruhRsFrGATiUuh25dtxYtnpbTx
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Counterparty::Connection do
4
+ describe "#new" do
5
+ # It should default to the test network parameters
6
+ subject{Counterparty::Connection.new}
7
+
8
+ its(:host){ should eq('localhost') }
9
+ its(:port){ should eq(14000) }
10
+ its(:username){ should eq('rpc') }
11
+ its(:password){ should eq('1234') }
12
+ its(:api_url){ should eq('http://rpc:1234@localhost:14000/api/') }
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Counterparty::ResponseError do
4
+ include_context 'globals'
5
+
6
+ let(:bad_issuance) do
7
+ Counterparty::Issuance.new source: source_address,
8
+ asset: 'THISASSETNAMEISFARTOOLONGANDINVALID',
9
+ quantity: 1000, description: "my asset is uncool",
10
+ allow_unconfirmed_inputs: true
11
+ end
12
+
13
+ it "should fail on to_raw_tx" do
14
+ expect{ bad_issuance.to_raw_tx }.to raise_error Counterparty::ResponseError
15
+ end
16
+
17
+ it "should fail on save!" do
18
+ expect{ bad_issuance.save! }.to raise_error Counterparty::ResponseError
19
+ end
20
+
21
+ subject do
22
+ begin
23
+ bad_issuance.save!
24
+ rescue => error
25
+ error
26
+ end
27
+ end
28
+
29
+ its(:data_type) { should eq('AssetNameError') }
30
+ its(:data_args) { should eq(["long asset names must be numeric"]) }
31
+ its(:data_message) { should eq("long asset names must be numeric") }
32
+ its(:code) { should eq(-32000) }
33
+ its(:message) { should eq("Server error: long asset names must be numeric") }
34
+ end
35
+
36
+ describe Counterparty::JsonResponseError do
37
+ pending
38
+ end
@@ -0,0 +1,122 @@
1
+ require 'spec_helper'
2
+
3
+ describe RawTx do
4
+ describe ".double_sha256" do
5
+ # http://bitcoin.stackexchange.com/questions/2177/how-to-calculate-a-hash-of-a-tx
6
+ genesis_block = '01000000010000000000000000000000000000000000000000000'+
7
+ '000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D657320'+
8
+ '30332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F6'+
9
+ '6207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F205'+
10
+ '2A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A6796'+
11
+ '2E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C70'+
12
+ '2B6BF11D5FAC00000000'
13
+ genesis_double_sha = '4A5E1E4BAAB89F3A32518A88C31BC87F618F76673E2CC77AB2127B7AFDEDA33B'
14
+
15
+ pending
16
+ end
17
+
18
+ describe ".nibbles_to_ui" do
19
+ it "should fail on byte arrays larger than 32 bits" do
20
+ expect{ RawTx.nibbles_to_ui([1,0,0,0,0]) }.to raise_error(ArgumentError)
21
+ end
22
+
23
+ # Remember that the least significant byte is first here:
24
+ it ("should convert 0x10 to 1") { expect(RawTx.nibbles_to_ui([1,0])).to eq(1) }
25
+ it ("should convert 0x01 to 16") { expect(RawTx.nibbles_to_ui([0,1])).to eq(16) }
26
+ it ("should convert 0xf to 15") { expect(RawTx.nibbles_to_ui([0xf])).to eq(15) }
27
+ it ("should convert 0x11 to 17") { expect(RawTx.nibbles_to_ui([1,1])).to eq(17) }
28
+ it ("should convert 0xf1 to 31") { expect(RawTx.nibbles_to_ui([0xf,1])).to eq(31) }
29
+ it ("should convert 0xff to 255") { expect(RawTx.nibbles_to_ui([0xf,0xf])).to eq(255) }
30
+ end
31
+
32
+ describe ".bytes_to_base64_s" do
33
+ it "should convert 0x14FB9C03D97E to FPucA91+" do
34
+ bytes = [0x14, 0xFB, 0x9C, 0x03, 0xD9, 0x7E]
35
+ expect(RawTx.bytes_to_base64_s bytes).to eq("FPucA9l+")
36
+ end
37
+
38
+ it "should convert 0x14FB9C03D9 to FPucA9k=" do
39
+ bytes = [0x14, 0xFB, 0x9C, 0x03, 0xD9]
40
+ expect(RawTx.bytes_to_base64_s bytes).to eq("FPucA9k=")
41
+ end
42
+
43
+ it "should convert 0x14FB9C03 to FPucAw==" do
44
+ bytes = [0x14, 0xFB, 0x9C, 0x03]
45
+ expect(RawTx.bytes_to_base64_s bytes).to eq("FPucAw==")
46
+ end
47
+ end
48
+
49
+ describe "#to_hash" do
50
+ # NOTE that these spec values were obtained via:
51
+ # bitcoind -testnet decoderawtransaction [subject]
52
+ subject{ RawTx.new(
53
+ "0100000001ec549bdf53cfb319201d672fc0933500e48505724010dad615a9344b99" +
54
+ "1721cc010000001976a9148025b288cb325d88bcd7ef5d1ab1f8827778d5ee88acff" +
55
+ "ffffff03781e0000000000006951210286cdf9ec8742c452bd13299771fe40130124" +
56
+ "038e2198ffc402204c48cc2d32da21033de0df1555e81783f42e00458d0b542ff293" +
57
+ "d9d04fbc7704650448ee07728a8a210286b1e4f15de57fd34bde19cf64ad9302e454" +
58
+ "c4c377677581a951579a124b86e753ae781e00000000000069512102a2cdf9ec8742" +
59
+ "c452bd2214fe01c9f33b0d0066ed0efb90aa715400038c1c621921034f89bc707587" +
60
+ "71a393416c21a12b651db3def9851bff574904762b86365caaea210286b1e4f15de5" +
61
+ "7fd34bde19cf64ad9302e454c4c377677581a951579a124b86e753aec0ba770d0000" +
62
+ "00001976a9148025b288cb325d88bcd7ef5d1ab1f8827778d5ee88ac00000000").to_hash }
63
+
64
+ its(['ver']){should eq(1)}
65
+ its(['lock_time']){should eq(0)}
66
+ its(['size']){should eq(338)}
67
+ its(['vin_sz']){should eq(1)}
68
+ its(['vout_sz']){should eq(3)}
69
+
70
+ its(['vin']) do
71
+ # If we're testing to base64, the hash would look like:
72
+ # RawTx.bytes_to_base64_s(out_hash.scan(/../).collect(&:hex))
73
+ should eq([
74
+ { "txid" => "cc2117994b34a915d6da1040720585e4003593c02f671d2019b3cf53df9b54ec",
75
+ "vout" => 1,
76
+ "scriptSig" => {
77
+ "hex" => "76a9148025b288cb325d88bcd7ef5d1ab1f8827778d5ee88ac",
78
+ "asm" => %w(OP_DUP OP_HASH160
79
+ 8025b288cb325d88bcd7ef5d1ab1f8827778d5ee OP_EQUALVERIFY
80
+ OP_CHECKSIG).join(' ')
81
+ }, "sequence" => 4294967295 }])
82
+ end
83
+
84
+ its(['vout']) do
85
+ should eq( [
86
+ { "value" => 0.00007800, "n" => 0,
87
+ "scriptPubKey" => {
88
+ "hex" => "51210286cdf9ec8742c452bd13299771fe40130124038e2198ffc40"+
89
+ "2204c48cc2d32da21033de0df1555e81783f42e00458d0b542ff293d9d04f"+
90
+ "bc7704650448ee07728a8a210286b1e4f15de57fd34bde19cf64ad9302e45"+
91
+ "4c4c377677581a951579a124b86e753ae",
92
+ "asm" => "1 0286cdf9ec8742c452bd13299771fe40130124038e2198ffc402204c48cc2d32da 033de0df1555e81783f42e00458d0b542ff293d9d04fbc7704650448ee07728a8a 0286b1e4f15de57fd34bde19cf64ad9302e454c4c377677581a951579a124b86e7 3 OP_CHECKMULTISIG" }
93
+ },
94
+ { "value" => 0.00007800, "n" => 1,
95
+ "scriptPubKey" => {
96
+ "hex" => "512102a2cdf9ec8742c452bd2214fe01c9f33b0d0066ed0efb90aa71"+
97
+ "5400038c1c621921034f89bc70758771a393416c21a12b651db3def9851bf"+
98
+ "f574904762b86365caaea210286b1e4f15de57fd34bde19cf64ad9302e454"+
99
+ "c4c377677581a951579a124b86e753ae",
100
+ "asm" => "1 02a2cdf9ec8742c452bd2214fe01c9f33b0d0066ed0efb90aa715400038c1c6219 034f89bc70758771a393416c21a12b651db3def9851bff574904762b86365caaea 0286b1e4f15de57fd34bde19cf64ad9302e454c4c377677581a951579a124b86e7 3 OP_CHECKMULTISIG" }
101
+ },
102
+ { "value" => 2.25950400, "n" => 2,
103
+ "scriptPubKey" => {
104
+ "hex" => "76a9148025b288cb325d88bcd7ef5d1ab1f8827778d5ee88ac",
105
+ "asm" => "OP_DUP OP_HASH160 8025b288cb325d88bcd7ef5d1ab1f8827778d5ee OP_EQUALVERIFY OP_CHECKSIG" } } ] )
106
+ end
107
+ end
108
+
109
+ describe("#to_hash coinbase") do
110
+
111
+ subject{ RawTx.new(
112
+ "01000000010000000000000000000000000000000000000000000000000000000000" +
113
+ "000000ffffffff53038349040d00456c69676975730052d8f72ffabe6d6dd991088d" +
114
+ "ecd13e658bbecc0b2b4c87306f637828917838c02a5d95d0e1bdff9b040000000000" +
115
+ "0000002f73733331312f00906b570400000000e4050000ffffffff01bf2087950000" +
116
+ "00001976a9145399c3093d31e4b0af4be1215d59b857b861ad5d88ac00000000").to_hash }
117
+
118
+ pending
119
+ end
120
+
121
+ end
122
+
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ # NOTE: Most of these examples are from:
4
+ # https://github.com/CounterpartyXCP/counterpartyd/blob/master/docs/API.rst#id8
5
+ # The tests have to run in the specified order, as we populate our test account
6
+ # before running test operations
7
+ describe Counterparty do
8
+ include_context 'globals'
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
16
+
17
+ describe "Ensure test account has XCP" do
18
+ subject do
19
+ Counterparty::Balance.find( filters:
20
+ { field: 'address', op: '==', value: source_address}
21
+ ).find{|b| b.asset == 'XCP' }
22
+ end
23
+
24
+ its(:quantity){ should be > Counterparty::ONE_XCP }
25
+ end
26
+
27
+ # Send 1 XCP (specified in satoshis) from one address to another (you must have
28
+ # the sending address in your bitcoind wallet and it will be broadcast as a
29
+ # multisig transaction
30
+ describe "#do_send" do
31
+ subject do
32
+ Counterparty::Send.new source: source_address, destination: destination_address,
33
+ asset: "XCP", quantity: Counterparty::ONE_XCP,
34
+ allow_unconfirmed_inputs: true
35
+ end
36
+
37
+ its(:to_raw_tx) { should_not be_empty }
38
+ its(:save!) { should_not be_empty }
39
+ end
40
+
41
+ describe "#do_issuance" do
42
+ subject do
43
+ Counterparty::Issuance.new source: source_address, asset: unique_asset_name,
44
+ quantity: 1000, description: "my asset is cool", divisible: true,
45
+ allow_unconfirmed_inputs: true
46
+ end
47
+
48
+ its(:to_raw_tx) { should_not be_empty }
49
+ its(:save!) { should_not be_empty }
50
+ end
51
+
52
+ describe "signed #create_broadcast" do
53
+ subject do
54
+ # We want the save(private_key) syntax here
55
+ Counterparty::Broadcast.new source: source_address, fee_fraction: 0.05,
56
+ text: "Price of gold, 12AM UTC March1. 1=inc 2=dec/const", value: 2.0,
57
+ timestamp: 1418926641,
58
+ allow_unconfirmed_inputs: true
59
+ end
60
+
61
+ its(:to_raw_tx) { should_not be_empty }
62
+
63
+ it "should persist using a provided key" do
64
+ # TODO: Make this work
65
+ expect(subject.save!(source_privkey)).to_not be_empty
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ # NOTE: Most of these examples are from:
4
+ # https://github.com/CounterpartyXCP/counterpartyd/blob/master/docs/API.rst#id8
5
+ describe Counterparty do
6
+ include_context 'globals'
7
+
8
+ before(:all) { Counterparty.production! }
9
+
10
+ # Get all burns between blocks 280537 and 280539 where greater than .2 BTC was
11
+ # burned, sorting by tx_hash (ascending order) With this (and the rest of the
12
+ # examples below) we use positional arguments, instead of keyword-based arguments
13
+ describe "#get_burns" do
14
+ burn_params = {
15
+ order_by: 'tx_hash',
16
+ order_dir: 'asc',
17
+ start_block: 280537,
18
+ end_block: 280539 }
19
+
20
+ subject{ Counterparty::Burn.find burn_params }
21
+
22
+ it("should equal get_burns") do
23
+ expect(subject).to eq(Counterparty.connection.get_burns(burn_params))
24
+ end
25
+
26
+ its('length'){ should eq(10) }
27
+ its('first') do
28
+ should eq(Counterparty::Burn.new(
29
+ tx_index: 1096,
30
+ source: '1ADpYypUcnbezuuYpCyRCY7G4KD6a9YXiF',
31
+ block_index: 280537,
32
+ earned: 129754545455,
33
+ status: "valid",
34
+ burned: 100000000,
35
+ tx_hash: '6e905ec73870d6c6cdc8f4e64767ec41f74c8f07a24cc7c54811134f5b6aa6a7'
36
+ ) )
37
+ end
38
+ end
39
+
40
+ # Fetch all balances for all assets for both of two addresses, using keyword-
41
+ # based arguments
42
+ describe "#get_balances" do
43
+ balance_params = { filters: {
44
+ field: 'address', op: '==', value: "14qqz8xpzzEtj6zLs3M1iASP7T4mj687yq" } }
45
+
46
+ subject{ Counterparty::Balance.find balance_params }
47
+
48
+ it("should equal get_balances") do
49
+ expect(subject).to eq(Counterparty.connection.get_balances(balance_params))
50
+ end
51
+
52
+ its('length'){ should eq(1) }
53
+ its('first') do
54
+ should eq(Counterparty::Balance.new(
55
+ quantity: 0,
56
+ asset: "XCP",
57
+ address: "14qqz8xpzzEtj6zLs3M1iASP7T4mj687yq" ) )
58
+ end
59
+ end
60
+
61
+ # Fetch all debits for > 2 XCP between blocks 280537 and 280539, sorting the
62
+ # results by quantity (descending order)
63
+ describe "#get_debits" do
64
+ debit_params = {
65
+ filters: [
66
+ {field: 'asset', op: '==', value: "XCP"},
67
+ {field: 'quantity', op: '>', value: 200000000}
68
+ ],
69
+ filterop: 'AND',
70
+ order_by: 'quantity',
71
+ order_dir: 'desc'}
72
+
73
+ subject{ Counterparty::Debit.find debit_params }
74
+
75
+ it("should equal get_debits") do
76
+ expect(subject).to eq(Counterparty.connection.get_debits(debit_params))
77
+ end
78
+
79
+ its('length'){ should eq(1000) }
80
+ its('first') do
81
+ should eq(Counterparty::Debit.new(
82
+ block_index: 318845,
83
+ asset: "XCP",
84
+ address: "1FxhdSid1TUfzfTyveMcsUhF3ePjRK6qqa",
85
+ action: "send",
86
+ event: "64c26f4dc12fbbdbead62962a9428d4a6b17a44c061d202ff525e2f513cd34e8",
87
+ quantity: 6184957374430
88
+ ) )
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,29 @@
1
+ $:<< File.join(File.dirname(__FILE__), '..','lib')
2
+
3
+ require 'yaml'
4
+ require 'rspec/its'
5
+ require 'counterparty_ruby'
6
+
7
+ shared_context 'globals' do
8
+ let(:config) do
9
+ YAML.load File.open([File.dirname(__FILE__),'config.yml'].join('/')).read
10
+ end
11
+
12
+ let(:source_address) { config['source_address'] }
13
+ let(:source_privkey) { config['source_privkey'] }
14
+ let(:destination_address) { config['spend_destination'] }
15
+
16
+ # Since asset names have to be unique, we try our best to create a unique
17
+ # one here. This asset is composed of the timestamp, plus the machine
18
+ # name we're running on. Be advised this might be a small privacy breach
19
+ # forsensitive operations.
20
+ # There might be some collisions here due to my not handling fixed-width
21
+ # integers greater than 26. I don't think I care about that right now
22
+ let!(:unique_asset_name) do
23
+ base26_time = Time.now.strftime('%y %m %d %H %M %S').split(' ').collect{|c| c.to_i.to_s(26)}
24
+ alpha_encode = base26_time.join.tr((('0'..'9').to_a+('a'..'q').to_a).join, ('A'..'Z').to_a.join)
25
+
26
+ [alpha_encode,`hostname`.upcase.tr('^A-Z','')].join[0...12]
27
+ end
28
+ end
29
+
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: counterparty_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris DeRose
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-01-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest_client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: bitcoin-ruby
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: ffi
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec-its
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rake
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rdoc
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: This gem is designed to abstract communications with the counterpartyd
127
+ api server in an ActiveRecord-esque object model
128
+ email:
129
+ - chris@chrisderose.com
130
+ executables: []
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - .gitignore
135
+ - Gemfile
136
+ - Gemfile.lock
137
+ - README.md
138
+ - Rakefile
139
+ - counterparty_ruby.gemspec
140
+ - lib/counterparty/connection.rb
141
+ - lib/counterparty/raw_tx.rb
142
+ - lib/counterparty/resource.rb
143
+ - lib/counterparty/resources.rb
144
+ - lib/counterparty/version.rb
145
+ - lib/counterparty_ruby.rb
146
+ - spec/config.yml
147
+ - spec/connection_spec.rb
148
+ - spec/exceptions_spec.rb
149
+ - spec/rawtx_decode_spec.rb
150
+ - spec/resource_create_spec.rb
151
+ - spec/resource_read_spec.rb
152
+ - spec/spec_helper.rb
153
+ homepage: https://github.com/brighton36/counterparty_ruby
154
+ licenses:
155
+ - LGPL
156
+ post_install_message:
157
+ rdoc_options: []
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '1.9'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ none: false
168
+ requirements:
169
+ - - ! '>='
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubyforge_project:
174
+ rubygems_version: 1.8.23
175
+ signing_key:
176
+ specification_version: 3
177
+ summary: An ActiveRecord-esque abstraction of the Counterparty API
178
+ test_files:
179
+ - spec/config.yml
180
+ - spec/connection_spec.rb
181
+ - spec/exceptions_spec.rb
182
+ - spec/rawtx_decode_spec.rb
183
+ - spec/resource_create_spec.rb
184
+ - spec/resource_read_spec.rb
185
+ - spec/spec_helper.rb