dropzone_ruby 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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/Drop Zone - An Anonymous Peer-To-Peer Local Contraband Marketplace.pdf +0 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +69 -0
  6. data/README.md +62 -0
  7. data/bin/dropzone +487 -0
  8. data/dropzone-screenshot.jpg +0 -0
  9. data/dropzone_ruby.gemspec +31 -0
  10. data/lib/blockrio_ext.rb +52 -0
  11. data/lib/dropzone/buyer.rb +21 -0
  12. data/lib/dropzone/command.rb +488 -0
  13. data/lib/dropzone/communication.rb +43 -0
  14. data/lib/dropzone/connection.rb +312 -0
  15. data/lib/dropzone/invoice.rb +23 -0
  16. data/lib/dropzone/item.rb +160 -0
  17. data/lib/dropzone/listing.rb +64 -0
  18. data/lib/dropzone/message_base.rb +178 -0
  19. data/lib/dropzone/payment.rb +36 -0
  20. data/lib/dropzone/profile.rb +86 -0
  21. data/lib/dropzone/record_base.rb +34 -0
  22. data/lib/dropzone/seller.rb +21 -0
  23. data/lib/dropzone/session.rb +161 -0
  24. data/lib/dropzone/state_accumulator.rb +39 -0
  25. data/lib/dropzone/version.rb +4 -0
  26. data/lib/dropzone_ruby.rb +14 -0
  27. data/lib/veto_checks.rb +74 -0
  28. data/spec/bitcoin_spec.rb +115 -0
  29. data/spec/buyer_profile_spec.rb +279 -0
  30. data/spec/buyer_spec.rb +109 -0
  31. data/spec/command_spec.rb +353 -0
  32. data/spec/config.yml +5 -0
  33. data/spec/invoice_spec.rb +129 -0
  34. data/spec/item_spec.rb +294 -0
  35. data/spec/lib/fake_connection.rb +97 -0
  36. data/spec/listing_spec.rb +150 -0
  37. data/spec/payment_spec.rb +152 -0
  38. data/spec/seller_profile_spec.rb +290 -0
  39. data/spec/seller_spec.rb +120 -0
  40. data/spec/session_spec.rb +303 -0
  41. data/spec/sham/buyer.rb +5 -0
  42. data/spec/sham/invoice.rb +5 -0
  43. data/spec/sham/item.rb +8 -0
  44. data/spec/sham/payment.rb +13 -0
  45. data/spec/sham/seller.rb +7 -0
  46. data/spec/spec_helper.rb +49 -0
  47. metadata +267 -0
@@ -0,0 +1,150 @@
1
+ #encoding: utf-8
2
+ require_relative 'spec_helper'
3
+ require_relative 'sham/item'
4
+ require_relative 'sham/seller'
5
+
6
+ describe Dropzone::Listing do
7
+ include_context 'globals'
8
+
9
+ describe "accessors" do
10
+ after{ clear_blockchain! }
11
+
12
+ it "compiles a simple profile" do
13
+ Dropzone::Seller.sham!(:build).save!(test_privkey)
14
+
15
+ # Block height is now 1:
16
+ increment_block_height!
17
+
18
+ tx_id = Dropzone::Item.sham!(:build).save!(test_privkey)
19
+
20
+ # Block height is now 2:
21
+ increment_block_height!
22
+
23
+ listing = Dropzone::Listing.new tx_id
24
+
25
+ expect(listing.valid?).to be_truthy
26
+ expect(listing.description).to eq("Item Description")
27
+ expect(listing.price_currency).to eq('BTC')
28
+ expect(listing.price_in_units).to eq(100_000_000)
29
+ expect(listing.expiration_in).to eq(6)
30
+ expect(listing.expiration_at).to eq(7)
31
+ expect(listing.latitude).to eq(51.500782)
32
+ expect(listing.longitude).to eq(-0.124669)
33
+ expect(listing.radius).to eq(1000)
34
+ expect(listing.addr).to eq(test_pubkey)
35
+ end
36
+
37
+ it "combines attributes from mulitple messages" do
38
+ Dropzone::Seller.sham!(:build).save!(test_privkey)
39
+
40
+ increment_block_height!
41
+
42
+ tx_id = Dropzone::Item.sham!(:build).save!(test_privkey)
43
+
44
+ increment_block_height!
45
+
46
+ Dropzone::Item.new(create_txid: tx_id, receiver_addr: test_pubkey,
47
+ description: 'xyz', price_in_units: 99_999_999, expiration_in: 12
48
+ ).save!(test_privkey)
49
+
50
+ listing = Dropzone::Listing.new tx_id
51
+
52
+ expect(listing.valid?).to be_truthy
53
+ expect(listing.description).to eq("xyz")
54
+ expect(listing.price_currency).to eq('BTC')
55
+ expect(listing.price_in_units).to eq(99_999_999)
56
+ expect(listing.expiration_in).to eq(12)
57
+ expect(listing.expiration_at).to eq(13)
58
+ expect(listing.latitude).to eq(51.500782)
59
+ expect(listing.longitude).to eq(-0.124669)
60
+ expect(listing.radius).to eq(1000)
61
+ expect(listing.addr).to eq(test_pubkey)
62
+ end
63
+
64
+ it "ignores incorrect txid's" do
65
+ Dropzone::Seller.sham!(:build).save!(test_privkey)
66
+
67
+ tx_id = Dropzone::Item.sham!(:build).save!(test_privkey)
68
+
69
+ Dropzone::Item.new(create_txid: tx_id, receiver_addr: test_pubkey,
70
+ description: 'xyz' ).save!(test_privkey)
71
+
72
+ Dropzone::Item.new(create_txid: 'non-existing-txid',
73
+ receiver_addr: test_pubkey, description: '123' ).save!(test_privkey)
74
+
75
+ listing = Dropzone::Listing.new tx_id
76
+
77
+ expect(listing.valid?).to be_truthy
78
+ expect(listing.description).to eq("xyz")
79
+ end
80
+
81
+ it "ignores messages from invalid senders" do
82
+ Dropzone::Seller.sham!(:build).save!(test_privkey)
83
+
84
+ tx_id = Dropzone::Item.sham!(:build).save!(test_privkey)
85
+
86
+ Dropzone::Item.new(create_txid: tx_id, receiver_addr: test_pubkey,
87
+ description: 'xyz' ).save!(TESTER2_PRIVATE_KEY)
88
+
89
+ listing = Dropzone::Listing.new tx_id
90
+
91
+ expect(listing.valid?).to be_truthy
92
+ expect(listing.description).to eq("Item Description")
93
+ end
94
+ end
95
+
96
+ describe "validations" do
97
+ after{ clear_blockchain! }
98
+
99
+ it "Cannot be created from nonsense" do
100
+ listing = Dropzone::Listing.new 'non-existing-txid'
101
+
102
+ expect(listing.valid?).to be_falsey
103
+ expect(listing.errors.count).to eq(2)
104
+ expect(listing.errors.on(:create_item)).to eq(['invalid or missing'])
105
+ expect(listing.errors.on(:seller_profile)).to eq(['invalid or missing'])
106
+ end
107
+
108
+ it "Cannot be created from an update" do
109
+ Dropzone::Seller.sham!(:build).save!(test_privkey)
110
+
111
+ tx_id = Dropzone::Item.new(create_txid: 'non-existing-txid',
112
+ receiver_addr: test_pubkey, description: '123' ).save!(test_privkey)
113
+
114
+ listing = Dropzone::Listing.new tx_id
115
+
116
+ expect(listing.valid?).to be_falsey
117
+ expect(listing.errors.count).to eq(2)
118
+ expect(listing.errors.on(:create_item)).to eq(['invalid or missing'])
119
+ expect(listing.errors.on(:seller_profile)).to eq(['invalid or missing'])
120
+ end
121
+
122
+ it "requires seller declaration" do
123
+ tx_id = Dropzone::Item.sham!(:build).save!(test_privkey)
124
+
125
+ listing = Dropzone::Listing.new tx_id
126
+
127
+ expect(listing.valid?).to be_falsey
128
+ expect(listing.errors.count).to eq(1)
129
+ expect(listing.errors.on(:seller_profile)).to eq(['invalid or missing'])
130
+ end
131
+
132
+ it "requires active seller" do
133
+ # Standard Seller:
134
+ Dropzone::Seller.sham!(:build).save! test_privkey
135
+
136
+ tx_id = Dropzone::Item.sham!(:build).save!(test_privkey)
137
+
138
+ # Seller Deactivates his account:
139
+ Dropzone::Seller.new( receiver_addr: test_pubkey,
140
+ transfer_pkey: 0).save! test_privkey
141
+
142
+ listing = Dropzone::Listing.new tx_id
143
+
144
+ expect(listing.valid?).to be_falsey
145
+ expect(listing.errors.count).to eq(1)
146
+ expect(listing.errors.on(:seller_profile)).to eq(['invalid or missing'])
147
+ end
148
+
149
+ end
150
+ end
@@ -0,0 +1,152 @@
1
+ #encoding: utf-8
2
+ require_relative 'spec_helper'
3
+ require_relative 'sham/payment'
4
+
5
+ describe Dropzone::Payment do
6
+ include_context 'globals'
7
+
8
+ describe "defaults" do
9
+ it "has accessors" do
10
+ payment = Dropzone::Payment.sham!(:build)
11
+
12
+ expect(payment.description).to eq("abc")
13
+ expect(payment.invoice_txid).to be_kind_of(String)
14
+ expect(payment.delivery_quality).to eq(8)
15
+ expect(payment.product_quality).to eq(8)
16
+ expect(payment.communications_quality).to eq(8)
17
+ expect(payment.receiver_addr).to eq(TESTER2_PUBLIC_KEY)
18
+ expect(payment.sender_addr).to eq(nil)
19
+ end
20
+ end
21
+
22
+ describe "serialization" do
23
+ it "serializes to_transaction" do
24
+ expect(Dropzone::Payment.sham!(invoice_txid: '2').to_transaction).to eq({
25
+ tip: 20000, receiver_addr: TESTER2_PUBLIC_KEY,
26
+ data: "INPAID\u0001d\u0003abc\u0001t\u00012\u0001q\b\u0001p\b\u0001c\b".force_encoding('ASCII-8BIT') })
27
+ end
28
+ end
29
+
30
+ describe "database" do
31
+ after{ clear_blockchain! }
32
+
33
+ it ".save() and .find()" do
34
+ payment_id = Dropzone::Payment.sham!(:build).save! test_privkey
35
+ expect(payment_id).to be_kind_of(String)
36
+
37
+ payment = Dropzone::Payment.find payment_id
38
+
39
+ expect(payment.description).to eq("abc")
40
+ expect(payment.invoice_txid).to be_kind_of(String)
41
+ expect(payment.delivery_quality).to eq(8)
42
+ expect(payment.product_quality).to eq(8)
43
+ expect(payment.communications_quality).to eq(8)
44
+ expect(payment.receiver_addr).to eq(TESTER2_PUBLIC_KEY)
45
+ expect(payment.sender_addr).to eq(test_pubkey)
46
+ end
47
+ end
48
+
49
+ describe "associations" do
50
+ it "has_one invoice" do
51
+ payment_id = Dropzone::Payment.sham!(:build).save! test_privkey
52
+
53
+ payment = Dropzone::Payment.find payment_id
54
+ expect(payment.invoice.expiration_in).to eq(6)
55
+ expect(payment.invoice.amount_due).to eq(100_000_000)
56
+ expect(payment.invoice.receiver_addr).to eq(test_pubkey)
57
+ end
58
+ end
59
+
60
+ describe "validations" do
61
+ after{ clear_blockchain! }
62
+
63
+ it "validates default build" do
64
+ expect(Dropzone::Payment.sham!(:build).valid?).to eq(true)
65
+ end
66
+
67
+ it "validates minimal payment" do
68
+ invoice_id = Dropzone::Invoice.sham!(:build).save! TESTER2_PRIVATE_KEY
69
+
70
+ payment = Dropzone::Payment.new receiver_addr: TESTER2_PUBLIC_KEY,
71
+ invoice_txid: invoice_id
72
+
73
+ expect(payment.valid?).to eq(true)
74
+ end
75
+
76
+ it "validates output address must be present" do
77
+ payment = Dropzone::Payment.sham! receiver_addr: nil
78
+
79
+ expect(payment.valid?).to eq(false)
80
+ expect(payment.errors.count).to eq(2)
81
+ expect(payment.errors.on(:receiver_addr)).to eq(['is not present'])
82
+ expect(payment.errors.on(:invoice_txid)).to eq(["can't be found"])
83
+ end
84
+
85
+ it "description must be string" do
86
+ payment = Dropzone::Payment.sham! description: 1
87
+
88
+ expect(payment.valid?).to eq(false)
89
+ expect(payment.errors.count).to eq(1)
90
+ expect(payment.errors.on(:description)).to eq(['is not a string'])
91
+ end
92
+
93
+ it "invoice_txid must be string" do
94
+ payment = Dropzone::Payment.sham! invoice_txid: 500
95
+
96
+ expect(payment.valid?).to eq(false)
97
+ expect(payment.errors.count).to eq(2)
98
+ expect(payment.errors.on(:invoice_txid)).to eq(['is not a string',
99
+ "can't be found"])
100
+ end
101
+
102
+ [:delivery_quality,:product_quality,:communications_quality ].each do |rating_attr|
103
+ it "%s must be numeric" % rating_attr.to_s do
104
+ payment = Dropzone::Payment.sham! rating_attr => 'abc'
105
+
106
+ expect(payment.valid?).to eq(false)
107
+ expect(payment.errors.count).to eq(2)
108
+ expect(payment.errors.on(rating_attr)).to eq(
109
+ ['is not a number', "is not in set: 0..8"])
110
+ end
111
+
112
+ it "%s must be between 0 and 8" % rating_attr.to_s do
113
+ payment = Dropzone::Payment.sham! rating_attr => 9
114
+
115
+ expect(payment.valid?).to eq(false)
116
+ expect(payment.errors.count).to eq(1)
117
+ expect(payment.errors.on(rating_attr)).to eq(['is not in set: 0..8'])
118
+ end
119
+ end
120
+
121
+ it "validates invoice existence" do
122
+ payment = Dropzone::Payment.sham! invoice_txid: 'non-existant-id'
123
+
124
+ expect(payment.valid?).to eq(false)
125
+ expect(payment.errors.count).to eq(1)
126
+ expect(payment.errors.on(:invoice_txid)).to eq(["can't be found"])
127
+ end
128
+
129
+ it "declaration must not be addressed to self" do
130
+ id = Dropzone::Invoice.sham!(receiver_addr: test_pubkey).save! test_privkey
131
+
132
+ invoice = Dropzone::Invoice.find id
133
+
134
+ expect(invoice.valid?).to eq(false)
135
+ expect(invoice.errors.count).to eq(1)
136
+ expect(invoice.errors.on(:receiver_addr)).to eq(['matches sender_addr'])
137
+ end
138
+
139
+ it "must be addressed to transaction_id owner" do
140
+ # The sham'd Invoice is addressed to TESTER2_PUBLIC_KEY
141
+ payment_id = Dropzone::Payment.sham!(
142
+ receiver_addr: TESTER_PUBLIC_KEY).save! TESTER3_PRIVATE_KEY
143
+
144
+ payment = Dropzone::Payment.find payment_id
145
+
146
+ expect(payment.valid?).to eq(false)
147
+ expect(payment.errors.count).to eq(1)
148
+ expect(payment.errors.on(:invoice_txid)).to eq(["can't be found"])
149
+ end
150
+
151
+ end
152
+ end
@@ -0,0 +1,290 @@
1
+ #encoding: utf-8
2
+ require_relative 'spec_helper'
3
+ require_relative 'sham/seller'
4
+
5
+ describe Dropzone::SellerProfile do
6
+ include_context 'globals'
7
+
8
+ describe "accessors" do
9
+ after{ clear_blockchain! }
10
+
11
+ it "compiles a simple profile" do
12
+ Dropzone::Seller.sham!(:build).save! test_privkey
13
+
14
+ profile = Dropzone::SellerProfile.new test_pubkey
15
+
16
+ expect(profile.valid?).to be_truthy
17
+ expect(profile.description).to eq("abc")
18
+ expect(profile.alias).to eq("Satoshi")
19
+ expect(profile.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
20
+ expect(profile.addr).to eq(test_pubkey)
21
+ expect(profile.active?).to be_truthy
22
+ end
23
+
24
+ it "combines attributes from mulitple messages" do
25
+ Dropzone::Seller.sham!(:build).save! test_privkey
26
+ Dropzone::Seller.sham!(:build, :description => 'xyz').save! test_privkey
27
+
28
+ profile = Dropzone::SellerProfile.new test_pubkey
29
+
30
+ expect(profile.valid?).to be_truthy
31
+ expect(profile.description).to eq("xyz")
32
+ expect(profile.alias).to eq("Satoshi")
33
+ expect(profile.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
34
+ expect(profile.addr).to eq(test_pubkey)
35
+ expect(profile.active?).to be_truthy
36
+ end
37
+
38
+ it "supports profile transfers" do
39
+ # Standard Seller:
40
+ Dropzone::Seller.sham!(:build).save! test_privkey
41
+
42
+ # Seller Transfer to Tester2:
43
+ Dropzone::Seller.new( receiver_addr: TESTER2_PUBLIC_KEY,
44
+ transfer_pkey: TESTER2_PUBLIC_KEY).save! test_privkey
45
+
46
+ # Update Tester2 for some added complexity:
47
+ Dropzone::Seller.new( receiver_addr: TESTER2_PUBLIC_KEY,
48
+ :alias => 'New Alias' ).save! TESTER2_PRIVATE_KEY
49
+
50
+ profile = Dropzone::SellerProfile.new TESTER2_PUBLIC_KEY
51
+
52
+ expect(profile.valid?).to be_truthy
53
+ expect(profile.description).to eq("abc")
54
+ expect(profile.alias).to eq("New Alias")
55
+ expect(profile.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
56
+ expect(profile.addr).to eq(TESTER2_PUBLIC_KEY)
57
+ expect(profile.active?).to be_truthy
58
+ end
59
+
60
+ it "supports a transfer in and transfer out" do
61
+ # Standard Seller:
62
+ Dropzone::Seller.sham!(:build).save! test_privkey
63
+
64
+ # Address 1 transfers to Address 2:
65
+ Dropzone::Seller.new( receiver_addr: TESTER2_PUBLIC_KEY,
66
+ transfer_pkey: TESTER2_PUBLIC_KEY).save! test_privkey
67
+
68
+ # Address 2 transfers to Address 3:
69
+ Dropzone::Seller.new( receiver_addr: TESTER3_PUBLIC_KEY,
70
+ transfer_pkey: TESTER3_PUBLIC_KEY).save! TESTER2_PRIVATE_KEY
71
+
72
+ profile = Dropzone::SellerProfile.new TESTER3_PUBLIC_KEY
73
+
74
+ expect(profile.valid?).to be_truthy
75
+ expect(profile.description).to eq("abc")
76
+ expect(profile.alias).to eq("Satoshi")
77
+ expect(profile.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
78
+ expect(profile.addr).to eq(TESTER3_PUBLIC_KEY)
79
+ expect(profile.active?).to be_truthy
80
+ end
81
+
82
+ it "only supports a single transfer in" do
83
+ # Address 1 Declaration:
84
+ Dropzone::Seller.sham!(:build).save! test_privkey
85
+
86
+ # Address 2 Declaration:
87
+ Dropzone::Seller.new( description: 'xyz', alias: 'New Alias',
88
+ receiver_addr: TESTER2_PUBLIC_KEY ).save! TESTER2_PRIVATE_KEY
89
+
90
+ # Address 1 transfers to Address 3:
91
+ Dropzone::Seller.new( receiver_addr: TESTER3_PUBLIC_KEY,
92
+ transfer_pkey: TESTER3_PUBLIC_KEY).save! test_privkey
93
+
94
+ # Address 2 transfers to Address 3:
95
+ Dropzone::Seller.new( receiver_addr: TESTER3_PUBLIC_KEY,
96
+ transfer_pkey: TESTER3_PUBLIC_KEY).save! TESTER2_PRIVATE_KEY
97
+
98
+ profile = Dropzone::SellerProfile.new TESTER3_PUBLIC_KEY
99
+
100
+ expect(profile.valid?).to be_truthy
101
+ expect(profile.description).to eq("abc")
102
+ expect(profile.alias).to eq("Satoshi")
103
+ expect(profile.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
104
+ expect(profile.addr).to eq(TESTER3_PUBLIC_KEY)
105
+ expect(profile.transfer_pkey).to be_nil
106
+ expect(profile.active?).to be_truthy
107
+ end
108
+
109
+ it "supports deactivation" do
110
+ # Standard Seller:
111
+ Dropzone::Seller.sham!(:build).save! test_privkey
112
+
113
+ # Seller Deactivates his account:
114
+ Dropzone::Seller.new( receiver_addr: test_pubkey,
115
+ transfer_pkey: 0).save! test_privkey
116
+
117
+ profile = Dropzone::SellerProfile.new test_pubkey
118
+
119
+ expect(profile.transfer_pkey).to eq(0)
120
+ expect(profile.active?).to be_falsey
121
+ expect(profile.closed?).to be_truthy
122
+ end
123
+
124
+ it "will stop merging attributes after a transfer out" do
125
+ # Standard Seller:
126
+ Dropzone::Seller.sham!(:build).save! test_privkey
127
+
128
+ # Address 1 transfers to Address 2:
129
+ Dropzone::Seller.new( receiver_addr: TESTER2_PUBLIC_KEY,
130
+ transfer_pkey: TESTER2_PUBLIC_KEY).save! test_privkey
131
+
132
+ # Address 1 changes description:
133
+ Dropzone::Seller.new( description: 'xyz' ).save! test_privkey
134
+
135
+ profile1 = Dropzone::SellerProfile.new test_pubkey
136
+ profile2 = Dropzone::SellerProfile.new TESTER2_PUBLIC_KEY
137
+
138
+ expect(profile1.description).to eq("abc")
139
+ expect(profile1.alias).to eq("Satoshi")
140
+ expect(profile1.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
141
+ expect(profile1.addr).to eq(test_pubkey)
142
+ expect(profile1.transfer_pkey).to eq(TESTER2_PUBLIC_KEY)
143
+ expect(profile1.active?).to be_falsey
144
+ expect(profile1.closed?).to be_falsey
145
+
146
+ expect(profile2.description).to eq("abc")
147
+ expect(profile2.alias).to eq("Satoshi")
148
+ expect(profile2.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
149
+ expect(profile2.addr).to eq(TESTER2_PUBLIC_KEY)
150
+ expect(profile2.active?).to be_truthy
151
+ expect(profile2.closed?).to be_falsey
152
+ end
153
+
154
+ it "will stop merging attributes after a cancellation" do
155
+ # Standard Seller:
156
+ Dropzone::Seller.sham!(:build).save! test_privkey
157
+
158
+ # Address 1 closes its account:
159
+ Dropzone::Seller.new( receiver_addr: test_pubkey,
160
+ transfer_pkey: 0 ).save! test_privkey
161
+
162
+ # Address 1 changes description:
163
+ Dropzone::Seller.new( description: 'xyz' ).save! test_privkey
164
+
165
+ profile = Dropzone::SellerProfile.new test_pubkey
166
+
167
+ expect(profile.valid?).to be_truthy
168
+ expect(profile.description).to eq("abc")
169
+ expect(profile.alias).to eq("Satoshi")
170
+ expect(profile.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
171
+ expect(profile.addr).to eq(test_pubkey)
172
+ expect(profile.transfer_pkey).to eq(0)
173
+ expect(profile.active?).to be_falsey
174
+ end
175
+
176
+ it "will merge attributes in a cancellation message" do
177
+ # Standard Seller:
178
+ Dropzone::Seller.sham!(:build).save! test_privkey
179
+
180
+ # Address 1 closes its account:
181
+ Dropzone::Seller.new( receiver_addr: test_pubkey, description: 'xyz',
182
+ transfer_pkey: 0 ).save! test_privkey
183
+
184
+ profile = Dropzone::SellerProfile.new test_pubkey
185
+
186
+ expect(profile.valid?).to be_truthy
187
+ expect(profile.description).to eq("xyz")
188
+ expect(profile.alias).to eq("Satoshi")
189
+ expect(profile.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
190
+ expect(profile.addr).to eq(test_pubkey)
191
+ expect(profile.transfer_pkey).to eq(0)
192
+ expect(profile.active?).to be_falsey
193
+ end
194
+
195
+ it "will merge attributes in a transfer message" do
196
+ # Standard Seller:
197
+ Dropzone::Seller.sham!(:build).save! test_privkey
198
+
199
+ # Address 1 closes its account:
200
+ Dropzone::Seller.new( receiver_addr: TESTER2_PUBLIC_KEY, description: 'xyz',
201
+ transfer_pkey: TESTER2_PUBLIC_KEY ).save! test_privkey
202
+
203
+ profile = Dropzone::SellerProfile.new test_pubkey
204
+
205
+ expect(profile.valid?).to be_truthy
206
+ expect(profile.description).to eq("xyz")
207
+ expect(profile.alias).to eq("Satoshi")
208
+ expect(profile.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
209
+ expect(profile.addr).to eq(test_pubkey)
210
+ expect(profile.transfer_pkey).to eq(TESTER2_PUBLIC_KEY)
211
+ expect(profile.active?).to be_falsey
212
+ end
213
+
214
+ it "won't compile a deactivated transfer" do
215
+ # Standard Seller:
216
+ Dropzone::Seller.sham!(:build).save! test_privkey
217
+
218
+ # Address 1 closes its account:
219
+ Dropzone::Seller.new( receiver_addr: test_pubkey,
220
+ transfer_pkey: 0 ).save! test_privkey
221
+
222
+ # Address 1 transfers its account:
223
+ Dropzone::Seller.new( receiver_addr: TESTER2_PUBLIC_KEY,
224
+ transfer_pkey: TESTER2_PUBLIC_KEY ).save! test_privkey
225
+
226
+ profile = Dropzone::SellerProfile.new TESTER2_PUBLIC_KEY
227
+
228
+ expect(profile.valid?).to be_falsey
229
+ end
230
+ end
231
+
232
+ describe "validations" do
233
+ after{ clear_blockchain! }
234
+
235
+ it "requires a valid seller message" do
236
+ # No messages have been created here yet:
237
+ profile = Dropzone::SellerProfile.new test_pubkey
238
+
239
+ expect(profile.valid?).to be_falsey
240
+ expect(profile.errors.count).to eq(1)
241
+ expect(profile.errors.on(:addr)).to eq(['profile not found'])
242
+ end
243
+
244
+ it "won't accept a closed account transfer" do
245
+ # Standard Seller:
246
+ Dropzone::Seller.sham!(:build).save! test_privkey
247
+
248
+ # Address 1 closes its account:
249
+ Dropzone::Seller.new( receiver_addr: test_pubkey,
250
+ transfer_pkey: 0 ).save! test_privkey
251
+
252
+ # Address 1 transfers its account:
253
+ Dropzone::Seller.new( receiver_addr: TESTER2_PUBLIC_KEY,
254
+ transfer_pkey: TESTER2_PUBLIC_KEY ).save! test_privkey
255
+
256
+ profile = Dropzone::SellerProfile.new TESTER2_PUBLIC_KEY
257
+ expect(profile.valid?).to be_falsey
258
+ expect(profile.errors.count).to eq(1)
259
+ expect(profile.errors.on(:prior_profile)).to eq(['invalid transfer or closed'])
260
+ end
261
+
262
+ it "won't accept a second transfer out" do
263
+ # Standard Seller:
264
+ Dropzone::Seller.sham!(:build).save! test_privkey
265
+
266
+ # Address 1 transfers to address 2:
267
+ Dropzone::Seller.new( receiver_addr: TESTER2_PUBLIC_KEY,
268
+ transfer_pkey: TESTER2_PUBLIC_KEY ).save! test_privkey
269
+
270
+ # Address 1 transfers to address 3:
271
+ Dropzone::Seller.new( receiver_addr: TESTER3_PUBLIC_KEY,
272
+ transfer_pkey: TESTER3_PUBLIC_KEY ).save! test_privkey
273
+
274
+ profile2 = Dropzone::SellerProfile.new TESTER2_PUBLIC_KEY
275
+ profile3 = Dropzone::SellerProfile.new TESTER3_PUBLIC_KEY
276
+
277
+ expect(profile2.valid?).to be_truthy
278
+ expect(profile2.description).to eq("abc")
279
+ expect(profile2.alias).to eq("Satoshi")
280
+ expect(profile2.communications_pkey).to eq('n3EMs5L3sHcZqRy35cmoPFgw5AzAtWSDUv')
281
+ expect(profile2.addr).to eq(TESTER2_PUBLIC_KEY)
282
+ expect(profile2.active?).to be_truthy
283
+
284
+ expect(profile3.valid?).to be_falsey
285
+ expect(profile3.errors.count).to eq(1)
286
+ expect(profile3.errors.on(:prior_profile)).to eq(['invalid transfer or closed'])
287
+ end
288
+
289
+ end
290
+ end