xgt-ruby 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +56 -0
- data/LICENSE.txt +21 -0
- data/README.md +45 -0
- data/Rakefile +6 -0
- data/bin/.wallet.swp +0 -0
- data/bin/setup +8 -0
- data/bin/wallet +438 -0
- data/examples/api/account_by_key_api/get_key_references.rb +18 -0
- data/examples/api/account_history_api/deprecated/enum_virtual_ops.rb +15 -0
- data/examples/api/account_history_api/deprecated/get_transaction.rb +12 -0
- data/examples/api/account_history_api/get_account_history.rb +16 -0
- data/examples/api/account_history_api/get_ops_in_block.rb +17 -0
- data/examples/api/chain_api/deprecated/dummy_code.rb +65 -0
- data/examples/api/chain_api/deprecated/push_block.rb +20 -0
- data/examples/api/database_api/accounts/find_accounts.rb +16 -0
- data/examples/api/database_api/accounts/list_accounts.rb +18 -0
- data/examples/api/database_api/accounts/not_supported/find_account_recovery_requests.rb +16 -0
- data/examples/api/database_api/accounts/not_supported/find_change_recovery_account_requests.rb +0 -0
- data/examples/api/database_api/accounts/not_supported/find_decline_voting_rights_requests.rb +0 -0
- data/examples/api/database_api/accounts/not_supported/find_escrows.rb +0 -0
- data/examples/api/database_api/accounts/not_supported/find_sbd_conversion_requests.rb +0 -0
- data/examples/api/database_api/accounts/not_supported/find_vesting_delegation_expirations.rb +0 -0
- data/examples/api/database_api/accounts/not_supported/find_vesting_delegations.rb +0 -0
- data/examples/api/database_api/accounts/not_supported/find_withdraw_vesting_routes.rb +18 -0
- data/examples/api/database_api/accounts/not_supported/list_account_recovery_requests.rb +18 -0
- data/examples/api/database_api/accounts/not_supported/list_change_recovery_account_requests.rb +0 -0
- data/examples/api/database_api/accounts/not_supported/list_decline_voting_rights_requests.rb +0 -0
- data/examples/api/database_api/accounts/not_supported/list_escrows.rb +18 -0
- data/examples/api/database_api/accounts/not_supported/list_recovery_histories.rb +17 -0
- data/examples/api/database_api/accounts/not_supported/list_sbd_conversion_requests.rb +0 -0
- data/examples/api/database_api/accounts/not_supported/list_vesting_delegation_expirations.rb +0 -0
- data/examples/api/database_api/accounts/not_supported/list_vesting_delegations.rb +18 -0
- data/examples/api/database_api/accounts/not_supported/list_withdraw_vesting_routes.rb +18 -0
- data/examples/api/database_api/authority/not_supported/find_smt_contributions.rb +0 -0
- data/examples/api/database_api/authority/not_supported/find_smt_token_balances.rb +0 -0
- data/examples/api/database_api/authority/not_supported/find_smt_token_emissions.rb +0 -0
- data/examples/api/database_api/authority/not_supported/find_smt_tokens.rb +0 -0
- data/examples/api/database_api/authority/not_supported/get_nai_pool.rb +0 -0
- data/examples/api/database_api/authority/not_supported/get_potential_signatures.rb +0 -0
- data/examples/api/database_api/authority/not_supported/get_required_signatures.rb +0 -0
- data/examples/api/database_api/authority/not_supported/get_smt_balances.rb +0 -0
- data/examples/api/database_api/authority/not_supported/get_transaction_hex.rb +0 -0
- data/examples/api/database_api/authority/not_supported/list_smt_contributions.rb +0 -0
- data/examples/api/database_api/authority/not_supported/list_smt_token_balances.rb +0 -0
- data/examples/api/database_api/authority/not_supported/list_smt_token_emissions.rb +0 -0
- data/examples/api/database_api/authority/not_supported/list_smt_tokens.rb +0 -0
- data/examples/api/database_api/authority/not_supported/verify_account_authority.rb +0 -0
- data/examples/api/database_api/authority/not_supported/verify_authority.rb +0 -0
- data/examples/api/database_api/authority/not_supported/verify_signatures.rb +0 -0
- data/examples/api/database_api/comments/not_supported/find_comments.rb +0 -0
- data/examples/api/database_api/comments/not_supported/find_votes.rb +0 -0
- data/examples/api/database_api/comments/not_supported/list_comments.rb +0 -0
- data/examples/api/database_api/comments/not_supported/list_votes.rb +0 -0
- data/examples/api/database_api/globals/get_config.rb +14 -0
- data/examples/api/database_api/globals/get_dynamic_global_properties.rb +14 -0
- data/examples/api/database_api/globals/get_hardfork_properties.rb +14 -0
- data/examples/api/database_api/globals/get_reward_funds.rb +14 -0
- data/examples/api/database_api/globals/get_version.rb +15 -0
- data/examples/api/database_api/globals/get_witness_schedule.rb +14 -0
- data/examples/api/database_api/market/not_supported/find_limit_orders.rb +0 -0
- data/examples/api/database_api/market/not_supported/get_order_book.rb +0 -0
- data/examples/api/database_api/market/not_supported/list_limit_orders.rb +0 -0
- data/examples/api/database_api/sps/not_supported/find_proposals.rb +0 -0
- data/examples/api/database_api/sps/not_supported/list_proposal_votes.rb +0 -0
- data/examples/api/database_api/sps/not_supported/list_proposals.rb +0 -0
- data/examples/api/database_api/witnesses/deprecated/get_round.rb +14 -0
- data/examples/api/database_api/witnesses/find_witnesses.rb +16 -0
- data/examples/api/database_api/witnesses/get_active_witnesses.rb +14 -0
- data/examples/api/database_api/witnesses/list_witnesses.rb +17 -0
- data/examples/api/database_api/witnesses/not_supported/list_witness_votes.rb +16 -0
- data/examples/api/extras/get_balance.rb +27 -0
- data/examples/api/network_broadcast_api/broadcast_transaction.rb +16 -0
- data/examples/api/network_broadcast_api/broadcast_transaction_synchronous.rb +15 -0
- data/examples/api/network_broadcast_api/create_wallet.rb +79 -0
- data/examples/api/network_broadcast_api/dummy_code.rb +68 -0
- data/examples/api/network_broadcast_api/get_transaction_hex.rb +17 -0
- data/examples/api/network_broadcast_api/not_supported/broadcast_block.rb +17 -0
- data/examples/api/network_broadcast_api/transfer.rb +45 -0
- data/examples/api/payloads.txt +3580 -0
- data/examples/api/transaction_status_api/find_transaction.rb +16 -0
- data/examples/operations/broadcast_transaction_synchronous.rb +16 -0
- data/examples/operations/completed/account_create.rb +79 -0
- data/examples/operations/completed/account_witness_proxy.rb +29 -0
- data/examples/operations/completed/account_witness_vote.rb +31 -0
- data/examples/operations/completed/claim_account.rb +33 -0
- data/examples/operations/completed/create_claimed_account.rb +62 -0
- data/examples/operations/completed/custom.rb +31 -0
- data/examples/operations/completed/custom_json.rb +32 -0
- data/examples/operations/completed/decline_voting_rights.rb +30 -0
- data/examples/operations/completed/delegate_some_vesting_shares.rb +32 -0
- data/examples/operations/completed/set_withdraw_vesting_route.rb +32 -0
- data/examples/operations/completed/transfer.rb +44 -0
- data/examples/operations/completed/transfer_to_vesting.rb +32 -0
- data/examples/operations/completed/update_proposal_votes.rb +31 -0
- data/examples/operations/completed/withdraw_vesting.rb +30 -0
- data/examples/operations/completed/witness_update.rb +64 -0
- data/examples/operations/deprecated/account_update.rb +44 -0
- data/examples/operations/deprecated/cancel_transfer_from_savings.rb +30 -0
- data/examples/operations/deprecated/challenge_authority.rb +28 -0
- data/examples/operations/deprecated/claim_reward_balance.rb +35 -0
- data/examples/operations/deprecated/convert.rb +38 -0
- data/examples/operations/deprecated/custom_binary.rb +31 -0
- data/examples/operations/deprecated/feed_publish.rb +33 -0
- data/examples/operations/do_later/change_recovery_account.rb +31 -0
- data/examples/operations/do_later/claim_reward_balance2.rb +37 -0
- data/examples/operations/do_later/remove_proposal_votes.rb +0 -0
- data/examples/operations/in_progress/create_proposal.rb +40 -0
- data/examples/operations/in_progress/escrow_approve.rb +36 -0
- data/examples/operations/in_progress/witness_set_properties.rb +62 -0
- data/lib/xgt/.ruby.rb.swp +0 -0
- data/lib/xgt/ruby.rb +200 -0
- data/lib/xgt/ruby/version.rb +5 -0
- data/payloads.txt +461 -0
- data/sample.rb +41 -0
- data/sample2.rb +104 -0
- data/xgt-ruby.gemspec +31 -0
- metadata +262 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5f8d69d052511822395feefa32e8458e6aca8a0068fb6f49a4f6a54e8591ae92
|
4
|
+
data.tar.gz: abdd0974944764969e3cbdfd68daf4f902dec7b16e792bda0842f8c82f53b0b4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a9e39d1fbcfe97f675ce932886c53733a1785be0baf8fcc9b533c35419e1a2c4c6a30a016fed35b7e7f46967745d74fa11da1c00824c6fbf84019ec3d8c3a5bb
|
7
|
+
data.tar.gz: 7561a1e4349f988590944d1307fd0bc504397694bb4abc1cced45652af915c073bc15548ab263ba52ab8479a5bfc6dd062dc545bc30554da42be0e153d4ecaa8
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at roger@thefifthcircuit.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
xgt-ruby (0.1.0)
|
5
|
+
base58 (~> 0.2.3)
|
6
|
+
bitcoin-ruby (~> 0.0.19)
|
7
|
+
faraday (~> 0.15.4)
|
8
|
+
faraday_middleware (~> 0.13.1)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
base58 (0.2.3)
|
14
|
+
bitcoin-ruby (0.0.20)
|
15
|
+
eventmachine
|
16
|
+
ffi
|
17
|
+
scrypt
|
18
|
+
diff-lcs (1.3)
|
19
|
+
eventmachine (1.2.7)
|
20
|
+
faraday (0.15.4)
|
21
|
+
multipart-post (>= 1.2, < 3)
|
22
|
+
faraday_middleware (0.13.1)
|
23
|
+
faraday (>= 0.7.4, < 1.0)
|
24
|
+
ffi (1.15.0)
|
25
|
+
ffi-compiler (1.0.1)
|
26
|
+
ffi (>= 1.0.0)
|
27
|
+
rake
|
28
|
+
multipart-post (2.0.0)
|
29
|
+
rake (10.5.0)
|
30
|
+
rspec (3.8.0)
|
31
|
+
rspec-core (~> 3.8.0)
|
32
|
+
rspec-expectations (~> 3.8.0)
|
33
|
+
rspec-mocks (~> 3.8.0)
|
34
|
+
rspec-core (3.8.0)
|
35
|
+
rspec-support (~> 3.8.0)
|
36
|
+
rspec-expectations (3.8.3)
|
37
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
+
rspec-support (~> 3.8.0)
|
39
|
+
rspec-mocks (3.8.0)
|
40
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
+
rspec-support (~> 3.8.0)
|
42
|
+
rspec-support (3.8.0)
|
43
|
+
scrypt (3.0.7)
|
44
|
+
ffi-compiler (>= 1.0, < 2.0)
|
45
|
+
|
46
|
+
PLATFORMS
|
47
|
+
ruby
|
48
|
+
|
49
|
+
DEPENDENCIES
|
50
|
+
bundler (~> 2.0)
|
51
|
+
rake (~> 10.0)
|
52
|
+
rspec (~> 3.0)
|
53
|
+
xgt-ruby!
|
54
|
+
|
55
|
+
BUNDLED WITH
|
56
|
+
2.1.4
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 Roger Jungemann
|
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,45 @@
|
|
1
|
+
# Xgt::Ruby
|
2
|
+
|
3
|
+
XGT client library for Ruby
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'xgt/ruby'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install xgt-ruby
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
View `sample.rb` in the repo for an example. It will require a local testnet to run.
|
24
|
+
|
25
|
+
```sh
|
26
|
+
bundle exec ruby sample.rb
|
27
|
+
```
|
28
|
+
|
29
|
+
## Development
|
30
|
+
|
31
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
32
|
+
|
33
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
34
|
+
|
35
|
+
## Contributing
|
36
|
+
|
37
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/rjungemann/xgt-ruby. 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.
|
38
|
+
|
39
|
+
## License
|
40
|
+
|
41
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
42
|
+
|
43
|
+
## Code of Conduct
|
44
|
+
|
45
|
+
Everyone interacting in the Xgt::Ruby project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/rjungemann/xgt-ruby/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
ADDED
data/bin/.wallet.swp
ADDED
Binary file
|
data/bin/setup
ADDED
data/bin/wallet
ADDED
@@ -0,0 +1,438 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'xgt/ruby'
|
6
|
+
require 'bigdecimal'
|
7
|
+
|
8
|
+
# ------
|
9
|
+
# Config
|
10
|
+
# ------
|
11
|
+
|
12
|
+
# TODO: Validate
|
13
|
+
@host = ENV['XGT_HOST'] || 'http://localhost:8751'
|
14
|
+
@current_name = ENV['XGT_NAME'] || 'XGT0000000000000000000000000000000000000000'
|
15
|
+
default_wifs = {
|
16
|
+
'XGT0000000000000000000000000000000000000000' => [
|
17
|
+
'5JNHfZYKGaomSFvd4NUdQ9qMcEAC43kujbfjueTHpVapX1Kzq2n'
|
18
|
+
]
|
19
|
+
}
|
20
|
+
@wifs = ENV['XGT_WIFS'] \
|
21
|
+
&.split(';') \
|
22
|
+
&.map { |pair| pair.split(':') } \
|
23
|
+
&.map { |pair| [pair[0], pair[1].split(',')] } \
|
24
|
+
&.to_h \
|
25
|
+
|| default_wifs
|
26
|
+
@logger = Logger.new($stdout)
|
27
|
+
@last_result = nil
|
28
|
+
@last_output = StringIO.new
|
29
|
+
|
30
|
+
# -------
|
31
|
+
# Helpers
|
32
|
+
# -------
|
33
|
+
|
34
|
+
def current_name
|
35
|
+
@current_name
|
36
|
+
end
|
37
|
+
|
38
|
+
def current_wifs
|
39
|
+
@wifs[current_name] || []
|
40
|
+
end
|
41
|
+
|
42
|
+
def logger
|
43
|
+
@logger
|
44
|
+
end
|
45
|
+
|
46
|
+
def last_result
|
47
|
+
@last_result
|
48
|
+
end
|
49
|
+
|
50
|
+
def last_output
|
51
|
+
@last_output
|
52
|
+
end
|
53
|
+
|
54
|
+
COLORS = {
|
55
|
+
yellow: 33,
|
56
|
+
magenta: 35,
|
57
|
+
cyan: 36,
|
58
|
+
}
|
59
|
+
|
60
|
+
def colorize(color, msg)
|
61
|
+
%(\033[#{COLORS[color]}m#{msg}\033[0m)
|
62
|
+
end
|
63
|
+
|
64
|
+
def logo
|
65
|
+
[
|
66
|
+
colorize(:magenta, ' _'), "\n",
|
67
|
+
colorize(:magenta, '__ ____ _| |_ '), colorize(:yellow, ' _ _ _'), "\n",
|
68
|
+
colorize(:magenta, '\ \/ / _` | __|'), colorize(:yellow, ' __ __ ____ _| | |___| |_'), "\n",
|
69
|
+
colorize(:magenta, ' > < (_| | |_ '), colorize(:yellow, ' \ V V / _` | | / -_) _|'), "\n",
|
70
|
+
colorize(:magenta, '/_/\_\__, |\__|'), colorize(:yellow, ' \_/\_/\__,_|_|_\___|\__|'), "\n",
|
71
|
+
colorize(:magenta, ' |___/'), "\n",
|
72
|
+
"\n",
|
73
|
+
%(Type in "info" and hit enter for a list of commands.), "\n",
|
74
|
+
"\n",
|
75
|
+
].join('')
|
76
|
+
end
|
77
|
+
|
78
|
+
def output_pair(key, value, indent_level)
|
79
|
+
@last_output << %( ) * (4 * indent_level)
|
80
|
+
@last_output << key if key
|
81
|
+
@last_output << %( #{value}) if value
|
82
|
+
@last_output << %(\n)
|
83
|
+
$stdout << %( ) * (4 * indent_level)
|
84
|
+
$stdout << colorize(:cyan, key) if key
|
85
|
+
$stdout << %( #{value}) if value
|
86
|
+
$stdout << %(\n)
|
87
|
+
end
|
88
|
+
|
89
|
+
def output_item(key, value, indent_level)
|
90
|
+
if value.respond_to?(:keys) || value.respond_to?(:each)
|
91
|
+
output_pair(key, nil, indent_level)
|
92
|
+
output_subresult(value, indent_level + 1)
|
93
|
+
else
|
94
|
+
output_pair(key, value, indent_level)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def output_subresult(item, indent_level=0)
|
99
|
+
if item.respond_to?(:keys)
|
100
|
+
item.each do |(key, value)|
|
101
|
+
output_item(key, value, indent_level)
|
102
|
+
end
|
103
|
+
elsif item.respond_to?(:each)
|
104
|
+
item.each.with_index do |value, i|
|
105
|
+
output_item(i, value, indent_level)
|
106
|
+
end
|
107
|
+
else
|
108
|
+
output_item(nil, value, indent_level)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def output_result(item)
|
113
|
+
@last_output = StringIO.new
|
114
|
+
output_subresult(item)
|
115
|
+
@last_output.rewind
|
116
|
+
nil
|
117
|
+
end
|
118
|
+
|
119
|
+
def rpc
|
120
|
+
Xgt::Ruby::Rpc.new(@host)
|
121
|
+
end
|
122
|
+
|
123
|
+
def chain_properties
|
124
|
+
return @chain_properties if @chain_properties
|
125
|
+
witness_schedule = rpc.call('database_api.get_witness_schedule', {}) || {}
|
126
|
+
@chain_properties = witness_schedule['median_props']
|
127
|
+
@chain_properties
|
128
|
+
end
|
129
|
+
|
130
|
+
def config
|
131
|
+
return @config if @config
|
132
|
+
@config = rpc.call('database_api.get_config', {})
|
133
|
+
@config
|
134
|
+
end
|
135
|
+
|
136
|
+
def address_prefix
|
137
|
+
return @address_prefix if @address_prefix
|
138
|
+
@address_prefix = config['XGT_ADDRESS_PREFIX']
|
139
|
+
logger.info(%(Retrieved address prefix... #{@address_prefix}))
|
140
|
+
@address_prefix
|
141
|
+
end
|
142
|
+
|
143
|
+
def chain_id
|
144
|
+
return @chain_id if @chain_id
|
145
|
+
@chain_id = config['XGT_CHAIN_ID']
|
146
|
+
logger.info(%(Retrieved chain ID... #{@chain_id}))
|
147
|
+
@chain_id
|
148
|
+
end
|
149
|
+
|
150
|
+
def precision
|
151
|
+
8 # TODO: Make dynamic
|
152
|
+
end
|
153
|
+
|
154
|
+
def fee
|
155
|
+
(chain_properties['account_creation_fee'] || {})['amount']
|
156
|
+
end
|
157
|
+
|
158
|
+
def currency_symbol
|
159
|
+
config['XGT_SYMBOL_STR']
|
160
|
+
end
|
161
|
+
|
162
|
+
# --------
|
163
|
+
# Commands
|
164
|
+
# --------
|
165
|
+
|
166
|
+
def info
|
167
|
+
print(%(\n))
|
168
|
+
puts(colorize(:yellow, %(-----)))
|
169
|
+
puts(colorize(:yellow, %(USAGE)))
|
170
|
+
puts(colorize(:yellow, %(-----)))
|
171
|
+
print(%(\n))
|
172
|
+
puts(%(#{colorize(:cyan, 'info')} view this info message))
|
173
|
+
puts(%(#{colorize(:cyan, 'switch_wallet NAME')} switch to another wallet))
|
174
|
+
puts(%(#{colorize(:cyan, 'create_wallet')} create a new XGT wallet))
|
175
|
+
puts(%(#{colorize(:cyan, 'list_wallets')} stream a full list of wallets))
|
176
|
+
puts(%(#{colorize(:cyan, 'list_wallets NAME')} stream a full list of wallets, starting with NAME))
|
177
|
+
puts(%(#{colorize(:cyan, 'get_wallet')} look up your wallet info))
|
178
|
+
puts(%(#{colorize(:cyan, 'get_wallet NAME')} look up another user's wallet info))
|
179
|
+
puts(%(#{colorize(:cyan, 'transfer TO, AMOUNT')} transfer money to another wallet))
|
180
|
+
print(%(\n))
|
181
|
+
puts(colorize(:yellow, %(---------------------)))
|
182
|
+
puts(colorize(:yellow, %(ENVIRONMENT VARIABLES)))
|
183
|
+
puts(colorize(:yellow, %(---------------------)))
|
184
|
+
print(%(\n))
|
185
|
+
puts(%(#{colorize(:cyan, 'XGT_HOST')} a hostname of a valid superproducer))
|
186
|
+
puts(%(#{colorize(:cyan, 'XGT_NAME')} the wallet name to use by default))
|
187
|
+
puts(%(#{colorize(:cyan, 'XGT_WIFS')} mapping of names to WIFs, like `foo:123,234;bar:345`))
|
188
|
+
print(%(\n))
|
189
|
+
puts(colorize(:yellow, %(-----)))
|
190
|
+
puts(colorize(:yellow, %(NOTES)))
|
191
|
+
puts(colorize(:yellow, %(-----)))
|
192
|
+
print(%(\n))
|
193
|
+
puts(%(A prettified form of the last result of every call is stored in `last_result`.))
|
194
|
+
print(%(\n))
|
195
|
+
puts(%(An IO containing the raw body of the last result of every call is stored in `last_output`.))
|
196
|
+
print(%(\n))
|
197
|
+
puts(%(You can get an Xgt::Ruby::Rpc instance via `rpc`.))
|
198
|
+
print(%(\n))
|
199
|
+
puts(%(Any method in `bin/wallet` is available from this CLI, so take a look!))
|
200
|
+
print(%(\n))
|
201
|
+
true
|
202
|
+
end
|
203
|
+
|
204
|
+
def switch_wallet(name)
|
205
|
+
@current_name = name
|
206
|
+
end
|
207
|
+
|
208
|
+
def fetch_wallet_name(public_key)
|
209
|
+
result = rpc.call('wallet_by_key_api.get_key_references', { 'keys' => [public_key] })
|
210
|
+
result&.fetch('wallets', [])&.first&.first
|
211
|
+
end
|
212
|
+
|
213
|
+
def generate_keys(from_wallet_name=current_name, master_key=current_wifs.first)
|
214
|
+
ks = { 'master' => master_key }
|
215
|
+
%w(recovery money social memo).each do |role|
|
216
|
+
private_key = Xgt::Ruby::Auth.generate_wif(from_wallet_name, master_key, role)
|
217
|
+
public_key = Xgt::Ruby::Auth.wif_to_public_key(private_key, address_prefix)
|
218
|
+
ks["#{role}_private"] = private_key
|
219
|
+
ks["#{role}_public"] = public_key
|
220
|
+
end
|
221
|
+
ks['wallet_name'] = Xgt::Ruby::Auth.generate_wallet_name(ks['recovery_public'])
|
222
|
+
ks
|
223
|
+
end
|
224
|
+
|
225
|
+
def create_wallet
|
226
|
+
keys = generate_keys
|
227
|
+
txn = {
|
228
|
+
'operations' => [{
|
229
|
+
'type' => 'wallet_create_operation',
|
230
|
+
'value' => {
|
231
|
+
'fee' => {
|
232
|
+
'amount' => fee,
|
233
|
+
'precision' => precision,
|
234
|
+
'nai' => '@@000000021'
|
235
|
+
},
|
236
|
+
'creator' => keys['wallet_name'],
|
237
|
+
'recovery' => {
|
238
|
+
'weight_threshold' => 1,
|
239
|
+
'account_auths' => [],
|
240
|
+
'key_auths' => [[keys['recovery_public'], 1]]
|
241
|
+
},
|
242
|
+
'money' => {
|
243
|
+
'weight_threshold' => 1,
|
244
|
+
'account_auths' => [],
|
245
|
+
'key_auths' => [[keys['money_public'], 1]]
|
246
|
+
},
|
247
|
+
'social' => {
|
248
|
+
'weight_threshold' => 1,
|
249
|
+
'account_auths' => [],
|
250
|
+
'key_auths' => [[keys['social_public'], 1]]
|
251
|
+
},
|
252
|
+
'memo_key' => keys['memo_public'],
|
253
|
+
'json_metadata' => '',
|
254
|
+
}
|
255
|
+
}]
|
256
|
+
}
|
257
|
+
|
258
|
+
id = rpc.broadcast_transaction(txn, current_wifs, chain_id)
|
259
|
+
(puts 'Waiting...' or sleep 1) until fetch_wallet_name(current_name)
|
260
|
+
|
261
|
+
response = keys
|
262
|
+
|
263
|
+
output_result(response)
|
264
|
+
@last_result = response
|
265
|
+
true
|
266
|
+
end
|
267
|
+
|
268
|
+
def list_wallets(name=nil)
|
269
|
+
enumerator = Enumerator.new do |yielder|
|
270
|
+
last_name = name
|
271
|
+
loop do
|
272
|
+
subresponse = rpc.call('database_api.list_wallets', {
|
273
|
+
'start' => last_name,
|
274
|
+
'limit' => 2,
|
275
|
+
'order' => 'by_name'
|
276
|
+
})
|
277
|
+
wallets = subresponse['wallets']
|
278
|
+
break if wallets.last['name'] == last_name
|
279
|
+
wallets.each do |wallet|
|
280
|
+
next if wallet['name'] == last_name
|
281
|
+
yielder.yield(wallet)
|
282
|
+
end
|
283
|
+
last_name = wallets.last['name']
|
284
|
+
end
|
285
|
+
end
|
286
|
+
response = { 'wallets' => enumerator }
|
287
|
+
output_result(response)
|
288
|
+
@last_result = response
|
289
|
+
true
|
290
|
+
end
|
291
|
+
|
292
|
+
def get_wallet(name=current_name)
|
293
|
+
response = rpc.call('database_api.find_wallets', { 'wallets' => [name] })
|
294
|
+
wallet = response['wallets'][0]
|
295
|
+
wallet.keys.each do |key|
|
296
|
+
wallet.delete(key) if key.match(/withdraw/)
|
297
|
+
wallet.delete(key) if key.match(/vest/)
|
298
|
+
wallet.delete(key) if key.match(/sbd/)
|
299
|
+
wallet.delete(key) if key.match(/saving/)
|
300
|
+
wallet.delete(key) if key.match(/comment/)
|
301
|
+
wallet.delete(key) if key.match(/reward/)
|
302
|
+
wallet.delete(key) if key.match(/proxy/)
|
303
|
+
wallet.delete(key) if key.match(/proxied/)
|
304
|
+
wallet.delete(key) if key.match(/lifetime/)
|
305
|
+
wallet.delete(key) if key.match(/social/)
|
306
|
+
wallet.delete(key) if key.match(/mined/)
|
307
|
+
end
|
308
|
+
output_result(wallet)
|
309
|
+
@last_result = response
|
310
|
+
true
|
311
|
+
end
|
312
|
+
|
313
|
+
def transfer(to, amount)
|
314
|
+
txn = {
|
315
|
+
'operations' => [{
|
316
|
+
'type' => 'transfer_operation',
|
317
|
+
'value' => {
|
318
|
+
'amount' => {
|
319
|
+
'amount' => ( amount * (10 ** precision) ).to_i.to_s,
|
320
|
+
'precision' => precision,
|
321
|
+
'nai' => '@@000000021'
|
322
|
+
},
|
323
|
+
'from' => current_name,
|
324
|
+
'to' => to,
|
325
|
+
'json_metadata' => '',
|
326
|
+
}
|
327
|
+
}]
|
328
|
+
}
|
329
|
+
|
330
|
+
logger.info(%(Transferring #{amount} to "#{to}"))
|
331
|
+
id = rpc.broadcast_transaction(txn, current_wifs, chain_id)
|
332
|
+
(puts 'Waiting...' or sleep 1) until rpc.transaction_ready?(id)
|
333
|
+
response = {} # TODO
|
334
|
+
output_result(response)
|
335
|
+
@last_result = response
|
336
|
+
true
|
337
|
+
end
|
338
|
+
|
339
|
+
def fetch_wallet_name(public_key)
|
340
|
+
result = rpc.call('wallet_by_key_api.get_key_references', { 'keys' => [public_key] })
|
341
|
+
result&.fetch('wallets', [])&.first&.first
|
342
|
+
end
|
343
|
+
|
344
|
+
def lazy_create(recovery_public)
|
345
|
+
keys = generate_keys(current_name, recovery_public)
|
346
|
+
transfer(keys['wallet_name'], BigDecimal('0.00000001'))
|
347
|
+
|
348
|
+
response = keys
|
349
|
+
output_result(response)
|
350
|
+
@last_result = response
|
351
|
+
true
|
352
|
+
end
|
353
|
+
|
354
|
+
def lazy_redeem(recovery_private)
|
355
|
+
recovery_public = Xgt::Ruby::Auth.wif_to_public_key(recovery_private, address_prefix)
|
356
|
+
wallet_name = Xgt::Ruby::Auth.generate_wallet_name(recovery_public)
|
357
|
+
keys = generate_keys(current_name, recovery_public).merge('wallet_name' => wallet_name)
|
358
|
+
txn = {
|
359
|
+
'operations' => [{
|
360
|
+
'type' => 'wallet_update_operation',
|
361
|
+
'value' => {
|
362
|
+
'wallet' => wallet_name,
|
363
|
+
'recovery' => {
|
364
|
+
'weight_threshold' => 1,
|
365
|
+
'account_auths' => [],
|
366
|
+
'key_auths' => [[keys['recovery_public'], 1]]
|
367
|
+
},
|
368
|
+
'money' => {
|
369
|
+
'weight_threshold' => 1,
|
370
|
+
'account_auths' => [],
|
371
|
+
'key_auths' => [[keys['money_public'], 1]]
|
372
|
+
},
|
373
|
+
'social' => {
|
374
|
+
'weight_threshold' => 1,
|
375
|
+
'account_auths' => [],
|
376
|
+
'key_auths' => [[keys['social_public'], 1]]
|
377
|
+
},
|
378
|
+
'memo_key' => keys['memo_public'],
|
379
|
+
'json_metadata' => '',
|
380
|
+
}
|
381
|
+
}]
|
382
|
+
}
|
383
|
+
logger.info(%(Redeeming #{wallet_name}"))
|
384
|
+
id = rpc.broadcast_transaction(txn, [recovery_private], chain_id)
|
385
|
+
#(puts 'Waiting...' or sleep 1) until rpc.transaction_ready?(id)
|
386
|
+
(puts 'Waiting...' or sleep 1) until fetch_wallet_name(keys['recovery_public'])
|
387
|
+
response = {} # TODO
|
388
|
+
output_result(response)
|
389
|
+
@last_result = response
|
390
|
+
true
|
391
|
+
end
|
392
|
+
|
393
|
+
# ----
|
394
|
+
# Main
|
395
|
+
# ----
|
396
|
+
|
397
|
+
def start_console
|
398
|
+
require 'irb'
|
399
|
+
ARGV.clear
|
400
|
+
IRB.setup nil
|
401
|
+
|
402
|
+
IRB.conf[:PROMPT] = {}
|
403
|
+
IRB.conf[:IRB_NAME] = 'wallet'
|
404
|
+
IRB.conf[:PROMPT][:WALLET] = {
|
405
|
+
:PROMPT_I => '%N>> ',
|
406
|
+
:PROMPT_N => '%N>> ',
|
407
|
+
:PROMPT_S => '%N%l> ',
|
408
|
+
:PROMPT_C => '%N*> ',
|
409
|
+
:RETURN => "#=> %s\n"
|
410
|
+
}
|
411
|
+
IRB.conf[:PROMPT_MODE] = :WALLET
|
412
|
+
IRB.conf[:RC] = false
|
413
|
+
|
414
|
+
require 'irb/completion'
|
415
|
+
require 'irb/ext/save-history'
|
416
|
+
IRB.conf[:READLINE] = true
|
417
|
+
|
418
|
+
irb = IRB::Irb.new(IRB::WorkSpace.new(self))
|
419
|
+
IRB.conf[:MAIN_CONTEXT] = irb.context
|
420
|
+
|
421
|
+
trap('SIGINT') do
|
422
|
+
IRB.irb.signal_handle
|
423
|
+
end
|
424
|
+
|
425
|
+
begin
|
426
|
+
catch(:IRB_EXIT) do
|
427
|
+
irb.eval_input
|
428
|
+
end
|
429
|
+
ensure
|
430
|
+
IRB.irb_at_exit
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
# Allows for this file to be run as a script or loaded as a library.
|
435
|
+
if __FILE__ == $0
|
436
|
+
puts logo
|
437
|
+
start_console
|
438
|
+
end
|