tierion 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.gitignore +10 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +158 -0
- data/RELEASE.md +98 -0
- data/Rakefile +10 -0
- data/bin/console +10 -0
- data/bin/setup +8 -0
- data/certs/gem-public_cert_grempe.pem +21 -0
- data/exe/tierion +3 -0
- data/lib/tierion.rb +14 -0
- data/lib/tierion/blockchain_receipt.rb +62 -0
- data/lib/tierion/blockchain_receipt_header.rb +11 -0
- data/lib/tierion/blockchain_receipt_target.rb +9 -0
- data/lib/tierion/hashitem.rb +138 -0
- data/lib/tierion/hashitem_receipt.rb +13 -0
- data/lib/tierion/version.rb +3 -0
- data/tierion.gemspec +48 -0
- metadata +189 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c55375f17cd7d97c88eb2121cae9b144d061a48d
|
4
|
+
data.tar.gz: bb6d9e026c6efb40e5d41c801cc8d9a9bbafff81
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 938e14d5a7fb6e19fbc2edeeab3933dc85ea7c67b1718263134fd3767085ae8e221fccceed4cb39ad62cb40dca85ff8e702b97e3cb3f61a28c4f0876440406e1
|
7
|
+
data.tar.gz: 36fd4e48acc7e5efa0cfec1535380ba93e82fc052b391940ac9ea6cad90a8b9a81cfd50a7a02b6114119cf67c0ec605f36ba37545f88fcf7d5a08b03a774e738
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
ADDED
Binary file
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at glenn@rempe.us. All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Glenn Rempe
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
# Tierion
|
2
|
+
|
3
|
+
A simple API client for the [Tierion Hash API](https://tierion.com/docs/hashapi).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'tierion'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install tierion
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Shell commands start with a `$`, Ruby console commands start with `>`.
|
24
|
+
|
25
|
+
Instantiate a new API client
|
26
|
+
|
27
|
+
```
|
28
|
+
> t = Tierion::Hashitem.new('me@example.com', 'mypassword')
|
29
|
+
```
|
30
|
+
|
31
|
+
You can also set the username and password in environment
|
32
|
+
variables.
|
33
|
+
|
34
|
+
```
|
35
|
+
$ export TIERION_USERNAME=me@example.com
|
36
|
+
$ export TIERION_PASSWORD=my_pass
|
37
|
+
```
|
38
|
+
|
39
|
+
```
|
40
|
+
> t = Tierion::Hashitem.new
|
41
|
+
```
|
42
|
+
|
43
|
+
Create the hash you want to record on the blockchain
|
44
|
+
and send it.
|
45
|
+
|
46
|
+
```
|
47
|
+
> my_hash = Digest::SHA256.hexdigest('foo')
|
48
|
+
=> "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae">
|
49
|
+
|
50
|
+
> t.send(my_hash)
|
51
|
+
=> Tierion::HashitemReceipt ...
|
52
|
+
```
|
53
|
+
|
54
|
+
Examine the array of `HashitemReceipt` objects stored in the
|
55
|
+
client. This is the only place to find the hash item
|
56
|
+
ID's. You probably want to store these somewhere in your DB
|
57
|
+
since this client is ephemeral and there is no way to
|
58
|
+
retrieve these ID's later.
|
59
|
+
|
60
|
+
```
|
61
|
+
> t.receipts
|
62
|
+
=> [Tierion::HashitemReceipt..., Tierion::HashitemReceipt ...]
|
63
|
+
```
|
64
|
+
|
65
|
+
Get one HashitemReceipt to work on
|
66
|
+
|
67
|
+
```
|
68
|
+
> h = t.receipts.first
|
69
|
+
```
|
70
|
+
|
71
|
+
For convenience you can use `Hashitem#time` to get
|
72
|
+
the timestamp as a `Time` object (UTC time)
|
73
|
+
|
74
|
+
```
|
75
|
+
> h.time
|
76
|
+
=> 2016-08-01 17:56:11 UTC
|
77
|
+
```
|
78
|
+
|
79
|
+
You can retrieve an individual `BlockchainReceipt` by
|
80
|
+
passing a `HashitemReceipt` as the arg to `Hashitem#blockchain_receipt`
|
81
|
+
|
82
|
+
```
|
83
|
+
> t.blockchain_receipt(h)
|
84
|
+
=> Tierion::BlockchainReceipt ...
|
85
|
+
```
|
86
|
+
|
87
|
+
Or, call `Hashitem#blockchain_receipts` to loop through
|
88
|
+
each `HashitemReceipt` submitted in this session
|
89
|
+
and collect `BlockchainReceipts` for each from the
|
90
|
+
API.
|
91
|
+
|
92
|
+
Remember that these are not available until
|
93
|
+
processed and sent to the blockchain so you may need to
|
94
|
+
call this again later to populate this Array fully.
|
95
|
+
|
96
|
+
```
|
97
|
+
> t.blockchain_receipts
|
98
|
+
=> [Tierion::BlockchainReceipt..., Tierion::BlockchainReceipt ...]
|
99
|
+
```
|
100
|
+
|
101
|
+
Get one `BlockchainReceipt` to work on
|
102
|
+
|
103
|
+
```
|
104
|
+
> b = t.blockchain_receipts.first
|
105
|
+
=> Tierion::BlockchainReceipt ...
|
106
|
+
```
|
107
|
+
|
108
|
+
A `BlockchainReceipt` object has a number of properties
|
109
|
+
which are populated from the API.
|
110
|
+
|
111
|
+
```
|
112
|
+
> b.header
|
113
|
+
> b.target
|
114
|
+
> b.extra
|
115
|
+
|
116
|
+
# The URL's that are generated for confirming this txn on the blockchain.
|
117
|
+
> b.confirmation_url
|
118
|
+
> b.confirmation_url_json
|
119
|
+
```
|
120
|
+
|
121
|
+
You can also query whether the transaction associated
|
122
|
+
with a `BlockchainReceipt` has actually been confirmed on the
|
123
|
+
blockchain. Once confirmed a data structure from the
|
124
|
+
third-party `blockchain.info` API will also be populated
|
125
|
+
with the full transaction data.
|
126
|
+
|
127
|
+
`BlockchainReceipt`s can take quite a while to be confirmed.
|
128
|
+
|
129
|
+
```
|
130
|
+
> b.confirmed?
|
131
|
+
=> true
|
132
|
+
|
133
|
+
# A hash of data from the blockchain.info API
|
134
|
+
> b.blockchain_info_confirmation
|
135
|
+
=> { ... }
|
136
|
+
```
|
137
|
+
|
138
|
+
## Development
|
139
|
+
|
140
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then,
|
141
|
+
run `rake test` to run the tests. You can also run `bin/console` for an
|
142
|
+
interactive prompt that will allow you to experiment.
|
143
|
+
|
144
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
145
|
+
|
146
|
+
You can run the Command Line Interface (CLI) in development
|
147
|
+
with `bundle exec exe/tierion`. (TODO : Implement CLI)
|
148
|
+
|
149
|
+
The formal release process can be found in [RELEASE.md](https://github.com/grempe/tierion/blob/master/RELEASE.md)
|
150
|
+
|
151
|
+
## Contributing
|
152
|
+
|
153
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/grempe/tierion. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
154
|
+
|
155
|
+
|
156
|
+
## License
|
157
|
+
|
158
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/RELEASE.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# Gem Release Process
|
2
|
+
|
3
|
+
Don't use the `bundle exec rake release` task. It is more convenient,
|
4
|
+
but it skips the process of signing the version release task.
|
5
|
+
|
6
|
+
## Run Tests
|
7
|
+
|
8
|
+
```sh
|
9
|
+
$ rake test
|
10
|
+
```
|
11
|
+
|
12
|
+
## Git Push
|
13
|
+
|
14
|
+
```sh
|
15
|
+
$ git push
|
16
|
+
```
|
17
|
+
|
18
|
+
## Bump Version Number and edit CHANGELOG.md
|
19
|
+
|
20
|
+
```sh
|
21
|
+
$ vi lib/tierion/version.rb
|
22
|
+
$ git add lib/tierion/version.rb
|
23
|
+
$ vi CHANGELOG.md
|
24
|
+
$ git add CHANGELOG.md
|
25
|
+
```
|
26
|
+
|
27
|
+
## Local Build and Install w/ Signed Gem
|
28
|
+
|
29
|
+
The `build` step should ask for PEM passphrase to sign gem. If it does
|
30
|
+
not ask it means that the signing cert is not present.
|
31
|
+
|
32
|
+
Build:
|
33
|
+
|
34
|
+
```sh
|
35
|
+
$ rake build
|
36
|
+
Enter PEM pass phrase:
|
37
|
+
tierion 0.1.0 built to pkg/tierion-0.1.0.gem
|
38
|
+
```
|
39
|
+
|
40
|
+
Install locally w/ Cert:
|
41
|
+
|
42
|
+
```sh
|
43
|
+
$ gem uninstall tierion
|
44
|
+
$ rbenv rehash
|
45
|
+
$ gem install pkg/tierion-0.1.0.gem -P MediumSecurity
|
46
|
+
Successfully installed tierion-0.1.0
|
47
|
+
1 gem installed
|
48
|
+
```
|
49
|
+
|
50
|
+
## Git Commit Version and CHANGELOG Changes, Tag and push to Github
|
51
|
+
|
52
|
+
```sh
|
53
|
+
$ git add lib/tierion/version.rb
|
54
|
+
$ git add CHANGELOG.md
|
55
|
+
$ git commit -m 'Bump version v0.1.0'
|
56
|
+
$ git tag -s v0.1.0 -m "v0.1.0" SHA1_OF_COMMIT
|
57
|
+
```
|
58
|
+
|
59
|
+
Verify last commit and last tag are GPG signed:
|
60
|
+
|
61
|
+
```
|
62
|
+
$ git tag -v v0.1.0
|
63
|
+
...
|
64
|
+
gpg: Good signature from "Glenn Rempe (Code Signing Key) <glenn@rempe.us>" [ultimate]
|
65
|
+
...
|
66
|
+
```
|
67
|
+
|
68
|
+
```
|
69
|
+
$ git log --show-signature
|
70
|
+
...
|
71
|
+
gpg: Good signature from "Glenn Rempe (Code Signing Key) <glenn@rempe.us>" [ultimate]
|
72
|
+
...
|
73
|
+
```
|
74
|
+
|
75
|
+
Push code and tags to GitHub:
|
76
|
+
|
77
|
+
```
|
78
|
+
$ git push
|
79
|
+
$ git push --tags
|
80
|
+
```
|
81
|
+
|
82
|
+
## Push gem to Rubygems.org
|
83
|
+
|
84
|
+
```sh
|
85
|
+
$ gem push pkg/tierion-0.1.0.gem
|
86
|
+
```
|
87
|
+
|
88
|
+
Verify Gem Push at [https://rubygems.org/gems/tierion](https://rubygems.org/gems/tierion)
|
89
|
+
|
90
|
+
## Create a GitHub Release
|
91
|
+
|
92
|
+
Specify the tag we just pushed to attach release to. Copy notes from CHANGELOG.md
|
93
|
+
|
94
|
+
[https://github.com/grempe/tierion/releases](https://github.com/grempe/tierion/releases)
|
95
|
+
|
96
|
+
## Announce Release on Twitter
|
97
|
+
|
98
|
+
blah, blah, blah.
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDYDCCAkigAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQ4wDAYDVQQDDAVnbGVu
|
3
|
+
bjEVMBMGCgmSJomT8ixkARkWBXJlbXBlMRIwEAYKCZImiZPyLGQBGRYCdXMwHhcN
|
4
|
+
MTYwNDExMDI0NTU0WhcNMTcwNDExMDI0NTU0WjA7MQ4wDAYDVQQDDAVnbGVubjEV
|
5
|
+
MBMGCgmSJomT8ixkARkWBXJlbXBlMRIwEAYKCZImiZPyLGQBGRYCdXMwggEiMA0G
|
6
|
+
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZqTH5Jf+D/W2B4BIiL49CpHa86rK/
|
7
|
+
oT+v3xZwuEE92lJea+ygn3IAsidVTW47AKE6Lt3UqUkGQGKxsqH/Dhir08BqjLlD
|
8
|
+
gBUozGZpM3B6uWZnD6QXLbOmZeGVDnwB/QDfzaawN1i3smlYxYT+KNLjl80aN3we
|
9
|
+
/cHAWG7JG47AF/S91mYcg1WgZnDgZt9+RyVR1AsfYbM+SidOSoXEOHPCbuUxLKJb
|
10
|
+
gj5ieCFhm5GNWEugvgiX/ruas+VHV0fF3fzjYlU2fZPTuQyB4UD5FWX4UqdsBf3w
|
11
|
+
jB94TDBsJ3FVGPbggEhLGKd8pbQmBIOqXolGaqhs7dnuf5imu5mAXHC1AgMBAAGj
|
12
|
+
bzBtMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBRfxEyosUbKjfFa
|
13
|
+
j+gae2CcT3aFCTAZBgNVHREEEjAQgQ5nbGVubkByZW1wZS51czAZBgNVHRIEEjAQ
|
14
|
+
gQ5nbGVubkByZW1wZS51czANBgkqhkiG9w0BAQUFAAOCAQEAzgK20+MNOknR9Kx6
|
15
|
+
RisI3DsioCADjGldxY+INrwoTfPDVmNm4GdTYC+V+/BvxJw1RqHjEbuXSg0iibQC
|
16
|
+
4vN+th0Km7dnas/td1i+EKfGencfyQyecIaG9l3kbCkCWnldRtZ+BS5EfP2ML2u8
|
17
|
+
fyCtze/Piovu8IwXL1W5kGZMnvzLmWxdqI3VPUou40n8F+EiMMLgd53kpzjtNOau
|
18
|
+
4W+mqVGOwlEGVSgI5+0SIsD8pvc62PlPWTv0kn1bcufKKCZmoVmpfbe3j4JpBInq
|
19
|
+
zieXiXZSAojfFx9g91fKdIrlPbInHU/BaCxXSLBwvOM0drE+c2ue9X8gB55XAhzX
|
20
|
+
37oBiw==
|
21
|
+
-----END CERTIFICATE-----
|
data/exe/tierion
ADDED
data/lib/tierion.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext/object/blank.rb'
|
3
|
+
require 'active_support/core_ext/numeric'
|
4
|
+
require 'active_support/core_ext/integer/time'
|
5
|
+
require 'json'
|
6
|
+
require 'httparty'
|
7
|
+
require 'hashie'
|
8
|
+
|
9
|
+
require 'tierion/version'
|
10
|
+
require 'tierion/hashitem'
|
11
|
+
require 'tierion/hashitem_receipt'
|
12
|
+
require 'tierion/blockchain_receipt'
|
13
|
+
require 'tierion/blockchain_receipt_header'
|
14
|
+
require 'tierion/blockchain_receipt_target'
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Tierion
|
2
|
+
class BlockchainReceipt < Hashie::Dash
|
3
|
+
include Hashie::Extensions::Dash::PropertyTranslation
|
4
|
+
|
5
|
+
property :header, required: true, transform_with: ->(v) {
|
6
|
+
BlockchainReceiptHeader.new(v)
|
7
|
+
}
|
8
|
+
|
9
|
+
property :target, required: true, transform_with: ->(v) {
|
10
|
+
BlockchainReceiptTarget.new(v)
|
11
|
+
}
|
12
|
+
|
13
|
+
property :extra, required: false, default: []
|
14
|
+
|
15
|
+
property :blockchain_info_confirmation, required: false, default: nil
|
16
|
+
|
17
|
+
# Output clean JSON in a format that works with the Blockchain
|
18
|
+
# Receipt validator at https://tierion.com/validate
|
19
|
+
def to_pretty_json
|
20
|
+
puts JSON.pretty_generate(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Recalculate the merkle tree to ensure the receipt is valid
|
24
|
+
def valid?
|
25
|
+
# TODO
|
26
|
+
end
|
27
|
+
|
28
|
+
# Make an API call to check if the tx_id is a confirmed Transaction
|
29
|
+
# on the Blockchain and contains the expected OP_RETURN value with
|
30
|
+
# the merkle_root from this receipt.
|
31
|
+
def confirmed?
|
32
|
+
return false if header.blank? || header.tx_id.blank?
|
33
|
+
return false if header.merkle_root.blank?
|
34
|
+
response = HTTParty.get(confirmation_url_json)
|
35
|
+
|
36
|
+
if response.success? && response['out'].present?
|
37
|
+
# op_return values begin with 0x6a (op_return code) &
|
38
|
+
# 0x20 (hex length in bytes of string)
|
39
|
+
expected_op_return_value = ['6a20', header.merkle_root].join('')
|
40
|
+
confirmed = response['out'].any? do |o|
|
41
|
+
o['script'].present? && o['script'] == expected_op_return_value
|
42
|
+
end
|
43
|
+
|
44
|
+
# store the parsed output from blockchain.info
|
45
|
+
self.blockchain_info_confirmation = response.parsed_response if confirmed
|
46
|
+
return confirmed
|
47
|
+
else
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def confirmation_url
|
53
|
+
return nil if header.blank? || header.tx_id.blank?
|
54
|
+
"https://blockchain.info/tx-index/#{header.tx_id}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def confirmation_url_json
|
58
|
+
return nil if header.blank? || header.tx_id.blank?
|
59
|
+
"#{confirmation_url}?format=json"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Tierion
|
2
|
+
class BlockchainReceiptHeader < Hashie::Dash
|
3
|
+
include Hashie::Extensions::Dash::PropertyTranslation
|
4
|
+
|
5
|
+
property :chainpoint_version, required: true
|
6
|
+
property :hash_type, required: true
|
7
|
+
property :merkle_root, required: true
|
8
|
+
property :tx_id, required: true
|
9
|
+
property :timestamp, required: true
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module Tierion
|
2
|
+
class Hashitem
|
3
|
+
include ::HTTParty
|
4
|
+
base_uri 'https://hashapi.tierion.com/v1'
|
5
|
+
|
6
|
+
default_timeout 5
|
7
|
+
open_timeout 5
|
8
|
+
# debug_output $stdout
|
9
|
+
|
10
|
+
attr_reader :receipts
|
11
|
+
attr_accessor :debug
|
12
|
+
|
13
|
+
def initialize(uname = ENV['TIERION_USERNAME'], pwd = ENV['TIERION_PASSWORD'])
|
14
|
+
@auth = { username: uname, password: pwd }
|
15
|
+
@access_token = nil
|
16
|
+
@expires_at = Time.now.utc - 1
|
17
|
+
@refresh_token = nil
|
18
|
+
@receipts = []
|
19
|
+
auth
|
20
|
+
end
|
21
|
+
|
22
|
+
def auth
|
23
|
+
options = { body: @auth }
|
24
|
+
response = self.class.post('/auth/token', options)
|
25
|
+
|
26
|
+
if response.success?
|
27
|
+
extract_auth_tokens(response)
|
28
|
+
else
|
29
|
+
raise_error(response)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def auth_refresh
|
34
|
+
if expired_auth?
|
35
|
+
options = { body: { 'refreshToken' => @refresh_token } }
|
36
|
+
response = self.class.post('/auth/refresh', options)
|
37
|
+
|
38
|
+
if response.success?
|
39
|
+
extract_auth_tokens(response)
|
40
|
+
else
|
41
|
+
raise_error(response)
|
42
|
+
end
|
43
|
+
else
|
44
|
+
auth
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def send(hash)
|
49
|
+
unless hash =~ /^[a-f0-9]{64}$/
|
50
|
+
raise ArgumentError, 'is not a valid SHA256 hex hash string'
|
51
|
+
end
|
52
|
+
|
53
|
+
auth_refresh unless logged_in?
|
54
|
+
options = {
|
55
|
+
body: { 'hash' => hash },
|
56
|
+
headers: { 'Authorization' => "Bearer #{@access_token}" }
|
57
|
+
}
|
58
|
+
response = self.class.post('/hashitems', options)
|
59
|
+
|
60
|
+
if response.success?
|
61
|
+
parsed = response.parsed_response
|
62
|
+
Hashie.symbolize_keys!(parsed)
|
63
|
+
hir = HashitemReceipt.new(parsed)
|
64
|
+
@receipts << hir
|
65
|
+
return hir
|
66
|
+
else
|
67
|
+
raise_error(response)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Retrieve and store the BlockchainReceipt from the API for each
|
72
|
+
# HashitemReceipt that does not have one.
|
73
|
+
def blockchain_receipts
|
74
|
+
@receipts.each do |hir|
|
75
|
+
next if hir.blockchain_receipt.is_a?(Tierion::BlockchainReceipt)
|
76
|
+
bcr = blockchain_receipt(hir)
|
77
|
+
hir.blockchain_receipt = bcr
|
78
|
+
end
|
79
|
+
|
80
|
+
@receipts.collect(&:blockchain_receipt).compact
|
81
|
+
end
|
82
|
+
|
83
|
+
# Retrieve the blockchain receipt for a specific HashitemReceipt ID
|
84
|
+
def blockchain_receipt(hir)
|
85
|
+
unless hir.is_a?(Tierion::HashitemReceipt)
|
86
|
+
raise ArgumentError, 'is not a HashitemReceipt object'
|
87
|
+
end
|
88
|
+
|
89
|
+
auth_refresh unless logged_in?
|
90
|
+
options = { headers: { 'Authorization' => "Bearer #{@access_token}" } }
|
91
|
+
response = self.class.get("/receipts/#{hir.id}", options)
|
92
|
+
|
93
|
+
if response.success? && response.parsed_response['receipt'].present?
|
94
|
+
receipt = JSON.parse(response.parsed_response['receipt'])
|
95
|
+
Hashie.symbolize_keys!(receipt)
|
96
|
+
BlockchainReceipt.new(receipt)
|
97
|
+
else
|
98
|
+
return nil
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def raise_error(response)
|
105
|
+
if response['error'].present?
|
106
|
+
raise response['error']
|
107
|
+
else
|
108
|
+
raise 'Unknown Fatal Error'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def logged_in?
|
113
|
+
@access_token.present? &&
|
114
|
+
@refresh_token.present? &&
|
115
|
+
@expires_at >= Time.now.utc
|
116
|
+
end
|
117
|
+
|
118
|
+
def expired_auth?
|
119
|
+
@access_token.present? &&
|
120
|
+
@refresh_token.present? &&
|
121
|
+
@expires_at < Time.now.utc
|
122
|
+
end
|
123
|
+
|
124
|
+
def extract_auth_tokens(resp)
|
125
|
+
if resp &&
|
126
|
+
resp.parsed_response &&
|
127
|
+
resp.parsed_response.is_a?(Hash) &&
|
128
|
+
resp.parsed_response.key?('access_token') &&
|
129
|
+
resp.parsed_response.key?('refresh_token') &&
|
130
|
+
resp.parsed_response.key?('expires_in')
|
131
|
+
@access_token = resp.parsed_response['access_token']
|
132
|
+
@refresh_token = resp.parsed_response['refresh_token']
|
133
|
+
@expires_at = Time.now.utc + resp.parsed_response['expires_in']
|
134
|
+
return true
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Tierion
|
2
|
+
class HashitemReceipt < Hashie::Dash
|
3
|
+
include Hashie::Extensions::Dash::PropertyTranslation
|
4
|
+
|
5
|
+
property :id, from: :receiptId, required: true
|
6
|
+
property :timestamp, required: true
|
7
|
+
property :blockchain_receipt, required: false, default: nil
|
8
|
+
|
9
|
+
def time
|
10
|
+
timestamp.is_a?(Integer) ? Time.at(timestamp).utc : nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/tierion.gemspec
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tierion/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'tierion'
|
8
|
+
spec.version = Tierion::VERSION
|
9
|
+
spec.authors = ['Glenn Rempe']
|
10
|
+
spec.email = ['glenn@rempe.us']
|
11
|
+
|
12
|
+
spec.required_ruby_version = '>= 2.1.0'
|
13
|
+
|
14
|
+
cert = File.expand_path('~/.gem-certs/gem-private_key_grempe.pem')
|
15
|
+
if cert && File.exist?(cert)
|
16
|
+
spec.signing_key = cert
|
17
|
+
spec.cert_chain = ['certs/gem-public_cert_grempe.pem']
|
18
|
+
end
|
19
|
+
|
20
|
+
spec.summary = <<-EOF
|
21
|
+
A simple API client for the Tierion Hash API
|
22
|
+
|
23
|
+
https://tierion.com/docs/hashapi
|
24
|
+
EOF
|
25
|
+
|
26
|
+
spec.description = <<-EOF
|
27
|
+
A simple API client for the Tierion Hash API
|
28
|
+
|
29
|
+
https://tierion.com/docs/hashapi
|
30
|
+
EOF
|
31
|
+
|
32
|
+
spec.homepage = 'https://github.com/grempe/tierion'
|
33
|
+
spec.license = 'MIT'
|
34
|
+
|
35
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
36
|
+
# spec.bindir = 'exe'
|
37
|
+
# spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
38
|
+
spec.require_paths = ['lib']
|
39
|
+
|
40
|
+
spec.add_runtime_dependency 'httparty', '~> 0.13'
|
41
|
+
spec.add_runtime_dependency 'activesupport', '~> 5.0'
|
42
|
+
spec.add_runtime_dependency 'hashie', '~> 3.4'
|
43
|
+
|
44
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
45
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
46
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
47
|
+
spec.add_development_dependency 'pry', '~> 0.10'
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tierion
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Glenn Rempe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDYDCCAkigAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQ4wDAYDVQQDDAVnbGVu
|
14
|
+
bjEVMBMGCgmSJomT8ixkARkWBXJlbXBlMRIwEAYKCZImiZPyLGQBGRYCdXMwHhcN
|
15
|
+
MTYwNDExMDI0NTU0WhcNMTcwNDExMDI0NTU0WjA7MQ4wDAYDVQQDDAVnbGVubjEV
|
16
|
+
MBMGCgmSJomT8ixkARkWBXJlbXBlMRIwEAYKCZImiZPyLGQBGRYCdXMwggEiMA0G
|
17
|
+
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZqTH5Jf+D/W2B4BIiL49CpHa86rK/
|
18
|
+
oT+v3xZwuEE92lJea+ygn3IAsidVTW47AKE6Lt3UqUkGQGKxsqH/Dhir08BqjLlD
|
19
|
+
gBUozGZpM3B6uWZnD6QXLbOmZeGVDnwB/QDfzaawN1i3smlYxYT+KNLjl80aN3we
|
20
|
+
/cHAWG7JG47AF/S91mYcg1WgZnDgZt9+RyVR1AsfYbM+SidOSoXEOHPCbuUxLKJb
|
21
|
+
gj5ieCFhm5GNWEugvgiX/ruas+VHV0fF3fzjYlU2fZPTuQyB4UD5FWX4UqdsBf3w
|
22
|
+
jB94TDBsJ3FVGPbggEhLGKd8pbQmBIOqXolGaqhs7dnuf5imu5mAXHC1AgMBAAGj
|
23
|
+
bzBtMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBRfxEyosUbKjfFa
|
24
|
+
j+gae2CcT3aFCTAZBgNVHREEEjAQgQ5nbGVubkByZW1wZS51czAZBgNVHRIEEjAQ
|
25
|
+
gQ5nbGVubkByZW1wZS51czANBgkqhkiG9w0BAQUFAAOCAQEAzgK20+MNOknR9Kx6
|
26
|
+
RisI3DsioCADjGldxY+INrwoTfPDVmNm4GdTYC+V+/BvxJw1RqHjEbuXSg0iibQC
|
27
|
+
4vN+th0Km7dnas/td1i+EKfGencfyQyecIaG9l3kbCkCWnldRtZ+BS5EfP2ML2u8
|
28
|
+
fyCtze/Piovu8IwXL1W5kGZMnvzLmWxdqI3VPUou40n8F+EiMMLgd53kpzjtNOau
|
29
|
+
4W+mqVGOwlEGVSgI5+0SIsD8pvc62PlPWTv0kn1bcufKKCZmoVmpfbe3j4JpBInq
|
30
|
+
zieXiXZSAojfFx9g91fKdIrlPbInHU/BaCxXSLBwvOM0drE+c2ue9X8gB55XAhzX
|
31
|
+
37oBiw==
|
32
|
+
-----END CERTIFICATE-----
|
33
|
+
date: 2016-08-02 00:00:00.000000000 Z
|
34
|
+
dependencies:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: httparty
|
37
|
+
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0.13'
|
42
|
+
type: :runtime
|
43
|
+
prerelease: false
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0.13'
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: activesupport
|
51
|
+
requirement: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '5.0'
|
56
|
+
type: :runtime
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '5.0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: hashie
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '3.4'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '3.4'
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: bundler
|
79
|
+
requirement: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '1.12'
|
84
|
+
type: :development
|
85
|
+
prerelease: false
|
86
|
+
version_requirements: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '1.12'
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rake
|
93
|
+
requirement: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '10.0'
|
98
|
+
type: :development
|
99
|
+
prerelease: false
|
100
|
+
version_requirements: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '10.0'
|
105
|
+
- !ruby/object:Gem::Dependency
|
106
|
+
name: minitest
|
107
|
+
requirement: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '5.0'
|
112
|
+
type: :development
|
113
|
+
prerelease: false
|
114
|
+
version_requirements: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '5.0'
|
119
|
+
- !ruby/object:Gem::Dependency
|
120
|
+
name: pry
|
121
|
+
requirement: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0.10'
|
126
|
+
type: :development
|
127
|
+
prerelease: false
|
128
|
+
version_requirements: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0.10'
|
133
|
+
description: |2
|
134
|
+
A simple API client for the Tierion Hash API
|
135
|
+
|
136
|
+
https://tierion.com/docs/hashapi
|
137
|
+
email:
|
138
|
+
- glenn@rempe.us
|
139
|
+
executables: []
|
140
|
+
extensions: []
|
141
|
+
extra_rdoc_files: []
|
142
|
+
files:
|
143
|
+
- ".gitignore"
|
144
|
+
- ".travis.yml"
|
145
|
+
- CHANGELOG.md
|
146
|
+
- CODE_OF_CONDUCT.md
|
147
|
+
- Gemfile
|
148
|
+
- LICENSE.txt
|
149
|
+
- README.md
|
150
|
+
- RELEASE.md
|
151
|
+
- Rakefile
|
152
|
+
- bin/console
|
153
|
+
- bin/setup
|
154
|
+
- certs/gem-public_cert_grempe.pem
|
155
|
+
- exe/tierion
|
156
|
+
- lib/tierion.rb
|
157
|
+
- lib/tierion/blockchain_receipt.rb
|
158
|
+
- lib/tierion/blockchain_receipt_header.rb
|
159
|
+
- lib/tierion/blockchain_receipt_target.rb
|
160
|
+
- lib/tierion/hashitem.rb
|
161
|
+
- lib/tierion/hashitem_receipt.rb
|
162
|
+
- lib/tierion/version.rb
|
163
|
+
- tierion.gemspec
|
164
|
+
homepage: https://github.com/grempe/tierion
|
165
|
+
licenses:
|
166
|
+
- MIT
|
167
|
+
metadata: {}
|
168
|
+
post_install_message:
|
169
|
+
rdoc_options: []
|
170
|
+
require_paths:
|
171
|
+
- lib
|
172
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: 2.1.0
|
177
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
requirements: []
|
183
|
+
rubyforge_project:
|
184
|
+
rubygems_version: 2.5.1
|
185
|
+
signing_key:
|
186
|
+
specification_version: 4
|
187
|
+
summary: A simple API client for the Tierion Hash API https://tierion.com/docs/hashapi
|
188
|
+
test_files: []
|
189
|
+
has_rdoc:
|
metadata.gz.sig
ADDED
Binary file
|