keoken 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +95 -0
- data/lib/keoken/bitprim/config.yaml +7 -3
- data/lib/keoken/bitprim/transaction.rb +26 -13
- data/lib/keoken/token.rb +8 -8
- data/lib/keoken/transaction/token.rb +4 -4
- data/lib/keoken/version.rb +1 -1
- data/spec/keoken_spec.rb +91 -3
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 782c4d244e16d0450b38609eef276677ab18611484c9d14730e58b86166cdbe5
|
4
|
+
data.tar.gz: aff0fe1e961ad359bc7bc511887def5b64e1730c6d09ac5832d3d99554fca9c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac6cfd0f0f6dcc6c996bee549872a2e45401d4556e24ee9fe82df75da3aafeceaab0fdd50867e6f63475b9262c2f89fac4c40a22ff9aa6117f0572b99f3eb1d7
|
7
|
+
data.tar.gz: 89859960e7cf722382d71117e93e3ed1a20ebfa6ce5a9abc9d32e8f2292a767e4a6ce5e3de8d0ce6d159560969b5bb9a1fbe1568bfcfc82de5493b6253d1cab2
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Keoken
|
2
|
+
|
3
|
+
Creates BCH tokens and send money between them for the Keoken protocol.
|
4
|
+
|
5
|
+
https://www.keoken.io/
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'keoken'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install keoken
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
### Create token and send it to the blockchain
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
# It uses bitcoin-ruby, but you can use Trezor or Electrum, the most important command is the script,
|
29
|
+
# which you can obtain with token.hex,
|
30
|
+
# then you can send it as an output with a scriptPubKey and a value of 0.
|
31
|
+
# In order to crate a token you need two outputs,
|
32
|
+
# the change address with an amount less than original (for fees)
|
33
|
+
# and the other one for the script. To send money you need three outputs,
|
34
|
+
# the change address, the address who owns the recipient token and the script.
|
35
|
+
|
36
|
+
Bitcoin.network = :testnet3
|
37
|
+
token = Keoken::Token.new(name: 'test-keoken')
|
38
|
+
token.create(1_000_000)
|
39
|
+
tx_id = 'aa699dc5ddf598a50dc2cb2cb2729629cb9d2d865df38e4367d13f81ef55f96e'
|
40
|
+
input_script = '76a9147bb97684cc43e2f8ea0ed1d50dddce3ebf80063888ac'
|
41
|
+
position = 0
|
42
|
+
script = token.hex
|
43
|
+
input_amount = 5_0000_0000
|
44
|
+
output_amount = 4_9991_0000
|
45
|
+
key = Bitcoin::Key.from_base58("cShKfHoHVf6iKKZym18ip1MJFQFxJwbcLxW53MQikxdDsGd2oxBU")
|
46
|
+
@transaction_token = Keoken::Transaction::Token.create(tx_id,
|
47
|
+
position,
|
48
|
+
input_script,
|
49
|
+
input_amount,
|
50
|
+
output_amount,
|
51
|
+
key,
|
52
|
+
script)
|
53
|
+
transaction = Keoken::Bitprim::Transaction.new(@transaction_token.raw)
|
54
|
+
transaction.send_tx
|
55
|
+
```
|
56
|
+
|
57
|
+
### Send token money and send transaction to the blockchain
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
Bitcoin.network = :testnet3
|
61
|
+
transaction = Keoken::Bitprim::Transaction.new
|
62
|
+
data = transaction.get_assets_by_address('mro9aqn4xCzXVS7jRFFuzT2ERKonvPdSDAs')
|
63
|
+
token = Keoken::Token.new(id: data[0]['asset_id'])
|
64
|
+
token.send_amount(500_000)
|
65
|
+
tx_id = 'aa699dc5ddf598a50dc2cb2cb2729629cb9d2d865df38e4367d13f81ef55f96e'
|
66
|
+
input_script = '76a9147bb97684cc43e2f8ea0ed1d50dddce3ebf80063888ac'
|
67
|
+
position = 0
|
68
|
+
script = token.hex
|
69
|
+
input_amount = 5_0000_0000
|
70
|
+
output_amount = 4_9991_0000
|
71
|
+
output_amount_address = 20_000
|
72
|
+
output_address = 'mnTd41YZ1e1YqsaPNJh3wkeSUrFvp1guzi'
|
73
|
+
key = Bitcoin::Key.from_base58("cShKfHoHVf6iKKZym18ip1MJFQFxJwbcLxW53MQikxdDsGd2oxBU")
|
74
|
+
@transaction_token = Keoken::Transaction::Token.send_amount(tx_id,
|
75
|
+
position,
|
76
|
+
input_script,
|
77
|
+
input_amount,
|
78
|
+
output_amount,
|
79
|
+
output_amount_address,
|
80
|
+
output_address,
|
81
|
+
key,
|
82
|
+
script)
|
83
|
+
transaction = Keoken::Bitprim::Transaction.new(@transaction_token.raw)
|
84
|
+
transaction.send_tx
|
85
|
+
```
|
86
|
+
|
87
|
+
|
88
|
+
## Contributing
|
89
|
+
|
90
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/bitex-la/keoken-ruby.
|
91
|
+
|
92
|
+
|
93
|
+
## License
|
94
|
+
|
95
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
@@ -1,7 +1,11 @@
|
|
1
1
|
Bitprim:
|
2
2
|
node:
|
3
3
|
testnet:
|
4
|
-
url: https://tbch.blockdozer.com/insight-api
|
4
|
+
url: https://tbch.blockdozer.com/insight-api
|
5
5
|
mainnet:
|
6
|
-
url: https://bch.blockdozer.com/insight-api
|
7
|
-
|
6
|
+
url: https://bch.blockdozer.com/insight-api
|
7
|
+
keoken:
|
8
|
+
testnet:
|
9
|
+
url: https://explorer.testnet.keoken.io/api
|
10
|
+
mainnet:
|
11
|
+
url: https://explorer.keoken.io/api
|
@@ -1,30 +1,34 @@
|
|
1
|
+
require 'json'
|
1
2
|
require 'yaml'
|
2
3
|
require 'net/http'
|
3
4
|
|
4
5
|
module Keoken
|
5
6
|
module Bitprim
|
6
7
|
class Transaction
|
7
|
-
|
8
|
+
def send_tx(raw)
|
9
|
+
uri = URI("#{root_node_url}/tx/send")
|
10
|
+
request = Net::HTTP::Post.new(uri)
|
11
|
+
request.set_form_data(rawtx: raw)
|
8
12
|
|
9
|
-
|
10
|
-
|
13
|
+
response = Net::HTTP.start(uri.hostname, uri.port) do |http|
|
14
|
+
http.request(request)
|
15
|
+
end
|
16
|
+
|
17
|
+
response.value
|
11
18
|
end
|
12
19
|
|
13
|
-
def
|
14
|
-
uri = URI("#{
|
15
|
-
|
16
|
-
|
20
|
+
def get_assets_by_address(address)
|
21
|
+
uri = URI("#{root_keoken_url}/get_assets_by_address")
|
22
|
+
params = { address: address }
|
23
|
+
uri.query = URI.encode_www_form(params)
|
24
|
+
response = Net::HTTP.get_response(uri)
|
17
25
|
|
18
|
-
|
19
|
-
http.request(req)
|
20
|
-
end
|
21
|
-
|
22
|
-
return res.value if res != Net::HTTPSuccess
|
26
|
+
JSON.parse(response.body.tr('\'', '"'))
|
23
27
|
end
|
24
28
|
|
25
29
|
private
|
26
30
|
|
27
|
-
def
|
31
|
+
def root_node_url
|
28
32
|
file = YAML.load_file('lib/keoken/bitprim/config.yaml')
|
29
33
|
if ENV['KEOKEN_NODE'] == 'PRODUCTION'
|
30
34
|
file['Bitprim']['node']['mainnet']['url']
|
@@ -32,6 +36,15 @@ module Keoken
|
|
32
36
|
file['Bitprim']['node']['testnet']['url']
|
33
37
|
end
|
34
38
|
end
|
39
|
+
|
40
|
+
def root_keoken_url
|
41
|
+
file = YAML.load_file('lib/keoken/bitprim/config.yaml')
|
42
|
+
if ENV['KEOKEN_NODE'] == 'PRODUCTION'
|
43
|
+
file['Bitprim']['keoken']['mainnet']['url']
|
44
|
+
else
|
45
|
+
file['Bitprim']['keoken']['testnet']['url']
|
46
|
+
end
|
47
|
+
end
|
35
48
|
end
|
36
49
|
end
|
37
50
|
end
|
data/lib/keoken/token.rb
CHANGED
@@ -11,10 +11,9 @@ module Keoken
|
|
11
11
|
raise Keoken::NameNotFound unless @name
|
12
12
|
data_script =
|
13
13
|
[Keoken::VERSION_NODE,
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
Keoken::TYPE_CREATE_ASSET,
|
15
|
+
name_to_hex(@name),
|
16
|
+
Keoken::PREFIX_BYTE_AMOUNT[0..(Keoken::AMOUNT_SIZE - amount.to_s.length - 1)] + amount.to_s].flatten.join
|
18
17
|
data_length = data_script.htb.bytesize.to_s(16)
|
19
18
|
|
20
19
|
@hex = [Bitcoin::Script::OP_RETURN.to_s(16),
|
@@ -27,10 +26,10 @@ module Keoken
|
|
27
26
|
def send_amount(amount)
|
28
27
|
raise Keoken::IdNotFound unless @id
|
29
28
|
data_script =
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
[Keoken::VERSION_NODE,
|
30
|
+
Keoken::TYPE_SEND_TOKEN,
|
31
|
+
Keoken::PREFIX_BYTE_ASSET_ID[0..(Keoken::ASSET_ID_SIZE - @id.to_s.length - 1)] + @id.to_s,
|
32
|
+
Keoken::PREFIX_BYTE_AMOUNT[0..(Keoken::AMOUNT_SIZE - amount.to_s.length - 1)] + amount.to_s].flatten.join
|
34
33
|
|
35
34
|
data_length = data_script.htb.bytesize.to_s(16)
|
36
35
|
|
@@ -42,6 +41,7 @@ module Keoken
|
|
42
41
|
end
|
43
42
|
|
44
43
|
private
|
44
|
+
|
45
45
|
def name_to_hex(name)
|
46
46
|
asset_bytes = name.bytes.map{|n| n.to_s(16)}
|
47
47
|
asset_bytes + ['00']
|
@@ -27,17 +27,17 @@ module Keoken
|
|
27
27
|
token
|
28
28
|
end
|
29
29
|
|
30
|
-
def self.send_amount(tx_id, position, input_script, input_amount, output_amount, output_amount_to_addr2, key, script)
|
30
|
+
def self.send_amount(tx_id, position, input_script, input_amount, output_amount, output_amount_to_addr2, addr2, key, script)
|
31
31
|
token = self.new
|
32
32
|
tx = build_tx do |t|
|
33
|
-
t.input do |i|
|
34
|
-
i.prev_out(tx_id, position,
|
33
|
+
t.input do |i|
|
34
|
+
i.prev_out(tx_id, position, input_script.htb, input_amount, 0)
|
35
35
|
i.signature_key(key)
|
36
36
|
end
|
37
37
|
t.output do |o|
|
38
38
|
o.value output_amount_to_addr2
|
39
39
|
o.script do |s|
|
40
|
-
s.recipient(
|
40
|
+
s.recipient(addr2)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
t.output do |o|
|
data/lib/keoken/version.rb
CHANGED
data/spec/keoken_spec.rb
CHANGED
@@ -43,7 +43,7 @@ describe Keoken do
|
|
43
43
|
)
|
44
44
|
end
|
45
45
|
|
46
|
-
describe 'creates
|
46
|
+
describe 'creates token' do
|
47
47
|
before(:each) do
|
48
48
|
Bitcoin.network = :testnet3
|
49
49
|
token = Keoken::Token.new(name: 'test-keoken')
|
@@ -93,8 +93,96 @@ describe Keoken do
|
|
93
93
|
'User-Agent' => 'Ruby'
|
94
94
|
})
|
95
95
|
.to_return(status: 200, body: '', headers: {})
|
96
|
-
transaction = Keoken::Bitprim::Transaction.new
|
97
|
-
expect(transaction.send_tx).to be_nil
|
96
|
+
transaction = Keoken::Bitprim::Transaction.new
|
97
|
+
expect(transaction.send_tx(@transaction_token.raw)).to be_nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'send money token' do
|
102
|
+
before(:each) do
|
103
|
+
Bitcoin.network = :testnet3
|
104
|
+
token = Keoken::Token.new(id: 21)
|
105
|
+
token.send_amount(500_000)
|
106
|
+
tx_id = 'aa699dc5ddf598a50dc2cb2cb2729629cb9d2d865df38e4367d13f81ef55f96e'
|
107
|
+
input_script = '76a9147bb97684cc43e2f8ea0ed1d50dddce3ebf80063888ac'
|
108
|
+
position = 0
|
109
|
+
script = token.hex
|
110
|
+
input_amount = 5_0000_0000
|
111
|
+
output_amount = 4_9991_0000
|
112
|
+
output_amount_address = 20_000
|
113
|
+
output_address = 'mnTd41YZ1e1YqsaPNJh3wkeSUrFvp1guzi'
|
114
|
+
key = Bitcoin::Key.from_base58("cShKfHoHVf6iKKZym18ip1MJFQFxJwbcLxW53MQikxdDsGd2oxBU")
|
115
|
+
@transaction_token = Keoken::Transaction::Token.send_amount(tx_id,
|
116
|
+
position,
|
117
|
+
input_script,
|
118
|
+
input_amount,
|
119
|
+
output_amount,
|
120
|
+
output_amount_address,
|
121
|
+
output_address,
|
122
|
+
key,
|
123
|
+
script)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'format to_json' do
|
127
|
+
json = JSON.parse(@transaction_token.to_json)
|
128
|
+
expect(json['out']).to(
|
129
|
+
eq(
|
130
|
+
[
|
131
|
+
{
|
132
|
+
"value" => "0.00020000",
|
133
|
+
"scriptPubKey" => "OP_DUP OP_HASH160 4c2791f07c046ef21d688f12296f91ad7b44d2bb OP_EQUALVERIFY OP_CHECKSIG"
|
134
|
+
},
|
135
|
+
{
|
136
|
+
"value"=>"4.99910000",
|
137
|
+
"scriptPubKey"=> "OP_DUP OP_HASH160 7bb97684cc43e2f8ea0ed1d50dddce3ebf800638 OP_EQUALVERIFY OP_CHECKSIG"
|
138
|
+
},
|
139
|
+
{
|
140
|
+
"value" => "0.00000000",
|
141
|
+
"scriptPubKey" => "OP_RETURN 00004b50 00000001000000210000000000500000"
|
142
|
+
}
|
143
|
+
]
|
144
|
+
)
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'raw transaction' do
|
149
|
+
raw = @transaction_token.raw
|
150
|
+
expect(raw).to start_with('01000000016ef955ef813fd167438ef35d862d9dcb299672b22ccbc20da598f5ddc59d69aa00000000')
|
151
|
+
expect(raw).to end_with('6a0400004b50100000000100000021000000000050000000000000')
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe 'get assets' do
|
156
|
+
before(:each) do
|
157
|
+
Bitcoin.network = :testnet3
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'get assets by address mnTd41YZ1e1YqsaPNJh3wkeSUrFvp1guzi' do
|
161
|
+
body_response = "[{'amount': 100000, 'asset_creator': 'mnTd41YZ1e1YqsaPNJh3wkeSUrFvp1guzi', 'asset_id': 123, 'asset_name': 'keoken-token'}]"
|
162
|
+
stub_request(:get, 'https://explorer.testnet.keoken.io/api/get_assets_by_address?address=mnTd41YZ1e1YqsaPNJh3wkeSUrFvp1guzi')
|
163
|
+
.with(
|
164
|
+
headers: {
|
165
|
+
'Accept' => '*/*',
|
166
|
+
'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
167
|
+
'Host' => 'explorer.testnet.keoken.io',
|
168
|
+
'User-Agent' => 'Ruby'
|
169
|
+
}
|
170
|
+
)
|
171
|
+
.to_return(status: 200, body: body_response, headers: {})
|
172
|
+
|
173
|
+
transaction = Keoken::Bitprim::Transaction.new
|
174
|
+
assets = transaction.get_assets_by_address('mnTd41YZ1e1YqsaPNJh3wkeSUrFvp1guzi')
|
175
|
+
|
176
|
+
expect(assets).to eq(
|
177
|
+
[
|
178
|
+
{
|
179
|
+
'amount' => 100_000,
|
180
|
+
'asset_creator' => 'mnTd41YZ1e1YqsaPNJh3wkeSUrFvp1guzi',
|
181
|
+
'asset_id' => 123,
|
182
|
+
'asset_name' => 'keoken-token'
|
183
|
+
}
|
184
|
+
]
|
185
|
+
)
|
98
186
|
end
|
99
187
|
end
|
100
188
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: keoken
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bitex
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- ".rspec"
|
119
119
|
- Gemfile
|
120
120
|
- Gemfile.lock
|
121
|
+
- README.md
|
121
122
|
- keoken.gemspec
|
122
123
|
- lib/keoken.rb
|
123
124
|
- lib/keoken/bitprim/config.yaml
|