libra_client 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -0
  3. data/.travis.yml +0 -0
  4. data/CODE_OF_CONDUCT.md +0 -0
  5. data/Gemfile +0 -0
  6. data/Gemfile.lock +24 -2
  7. data/LICENSE.txt +0 -0
  8. data/README.md +8 -12
  9. data/Rakefile +0 -0
  10. data/bin/console +2 -0
  11. data/bin/setup +0 -0
  12. data/gen_proto.sh +0 -0
  13. data/lib/libra/access_path.rb +51 -0
  14. data/lib/libra/account_address.rb +29 -0
  15. data/lib/libra/account_config.rb +57 -0
  16. data/lib/libra/account_resource.rb +38 -0
  17. data/lib/libra/mnemonic.rb +147 -0
  18. data/lib/libra/version.rb +3 -0
  19. data/lib/libra_client.rb +143 -57
  20. data/libra_client.gemspec +7 -2
  21. data/libra_client.sublime-project +16 -0
  22. data/proto-lib/access_path_pb.rb +0 -0
  23. data/proto-lib/account_state_blob_pb.rb +0 -0
  24. data/proto-lib/admission_control_pb.rb +0 -0
  25. data/proto-lib/admission_control_services_pb.rb +0 -0
  26. data/proto-lib/events_pb.rb +0 -0
  27. data/proto-lib/get_with_proof_pb.rb +0 -0
  28. data/proto-lib/ledger_info_pb.rb +0 -0
  29. data/proto-lib/mempool_status_pb.rb +0 -0
  30. data/proto-lib/proof_pb.rb +0 -0
  31. data/proto-lib/transaction_info_pb.rb +0 -0
  32. data/proto-lib/transaction_pb.rb +0 -0
  33. data/proto-lib/validator_change_pb.rb +0 -0
  34. data/proto-lib/vm_errors_pb.rb +0 -0
  35. data/protos/access_path.proto +0 -0
  36. data/protos/account_state_blob.proto +0 -0
  37. data/protos/admission_control.proto +0 -0
  38. data/protos/events.proto +0 -0
  39. data/protos/get_with_proof.proto +0 -0
  40. data/protos/ledger_info.proto +0 -0
  41. data/protos/mempool_status.proto +0 -0
  42. data/protos/proof.proto +0 -0
  43. data/protos/transaction.proto +0 -0
  44. data/protos/transaction_info.proto +0 -0
  45. data/protos/validator_change.proto +0 -0
  46. data/protos/vm_errors.proto +0 -0
  47. metadata +52 -5
  48. data/lib/libra_client/version.rb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ee0031b3c2294d7aa714045e404828a129d3141f51bd1e71fcdf61c5f085b9b
4
- data.tar.gz: f25cfe316bedb6904b6e87c321c56d2e116b63381fe874f30d4df8e5f324a1c3
3
+ metadata.gz: f758e04df55fe337f1c56b5fe70d037c86e109440690f22638dc135521d7c0a6
4
+ data.tar.gz: 130f1edfeccc99b78345c22276b5623707e98b848c25f7548c8795f5bba699bc
5
5
  SHA512:
6
- metadata.gz: 7b860682cb2b2c5c5c59971eedbe091698adbe457ee670eed30adf0c605142078128bd8077b74db9df322ca0698c15c354ea95601c54a78d3615f4224ec9b07a
7
- data.tar.gz: 568504cec1ae771f1d536e0454a1bcd64806461cfbe321823d2bbd1205997e708f675dd7696dacd250f43777e94e921fcbf8c8025307505097b1071460c80256
6
+ metadata.gz: 4f5973fd755d991dd2abf802372924432d27bf72ef65d2dfadc4487f924eb5c397147fcfecc52e5ce7f7f375718d72aada400504e630894a5f9e470014d62d76
7
+ data.tar.gz: 97e574d53dda8187837a5102e09c2d902b6d82b7ecd7c85bbd18d2853e3fb1830cb881edde8333fa189afe359262350bbdd03ef1b235c97b1216c345bb9def5e
data/.gitignore CHANGED
@@ -6,3 +6,9 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ .DS_Store
10
+ Thumbs.db
11
+ *.sublime-workspace
12
+ .byebug_history
13
+ .idea
14
+
File without changes
File without changes
data/Gemfile CHANGED
File without changes
@@ -1,29 +1,51 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- libra_client (0.1.0)
4
+ libra_client (0.1.2)
5
+ canoser (~> 0.1.0)
5
6
  grpc (~> 1.23)
7
+ rest-client (~> 2.0)
6
8
 
7
9
  GEM
8
10
  remote: https://rubygems.org/
9
11
  specs:
12
+ byebug (11.0.1)
13
+ canoser (0.1.1)
14
+ domain_name (0.5.20190701)
15
+ unf (>= 0.0.5, < 1.0.0)
10
16
  google-protobuf (3.9.1)
11
17
  googleapis-common-protos-types (1.0.4)
12
18
  google-protobuf (~> 3.0)
13
19
  grpc (1.23.0)
14
20
  google-protobuf (~> 3.8)
15
21
  googleapis-common-protos-types (~> 1.0)
22
+ http-accept (1.7.0)
23
+ http-cookie (1.0.3)
24
+ domain_name (~> 0.5)
25
+ mime-types (3.2.2)
26
+ mime-types-data (~> 3.2015)
27
+ mime-types-data (3.2019.0331)
16
28
  minitest (5.11.3)
29
+ netrc (0.11.0)
17
30
  rake (10.5.0)
31
+ rest-client (2.1.0)
32
+ http-accept (>= 1.7.0, < 2.0)
33
+ http-cookie (>= 1.0.2, < 2.0)
34
+ mime-types (>= 1.16, < 4.0)
35
+ netrc (~> 0.8)
36
+ unf (0.1.4)
37
+ unf_ext
38
+ unf_ext (0.0.7.6)
18
39
 
19
40
  PLATFORMS
20
41
  ruby
21
42
 
22
43
  DEPENDENCIES
23
44
  bundler (~> 2.0)
45
+ byebug (~> 11.0)
24
46
  libra_client!
25
47
  minitest (~> 5.0)
26
48
  rake (~> 10.0)
27
49
 
28
50
  BUNDLED WITH
29
- 2.0.1
51
+ 2.0.2
File without changes
data/README.md CHANGED
@@ -1,8 +1,7 @@
1
1
  # LibraClient
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/libra_client`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ LibraClient is an unofficial client for [Libra blockchain](http://libra.org). The library allows Ruby program to interact with Libra nodes with [protobuf](https://developers.google.com/protocol-buffers/) message through [grpc](https://grpc.io/).
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
6
5
 
7
6
  ## Installation
8
7
 
@@ -25,12 +24,13 @@ Or install it yourself as:
25
24
 
26
25
  ```ruby
27
26
  require 'libra_client'
28
- LibraClient.get_transaction(0) #get the genesis transaction
29
- LibraClient.get_transaction(1) #get the first transaction
30
- version = LibraClient.get_latest_transaction_version
31
- LibraClient.get_transaction(version) #get the latest transaction
27
+ client = Libra::Client.new(:testnet)
28
+ client.get_transaction(0) #get the genesis transaction
29
+ client.get_transaction(1) #get the first transaction
30
+ version = client.get_latest_transaction_version
31
+ client.get_transaction(version) #get the latest transaction
32
32
 
33
- LibraClient.get_account_state(ASSOCIATION_ADDRESS)
33
+ client.get_account_state(ASSOCIATION_ADDRESS)
34
34
  ```
35
35
 
36
36
  ## Development
@@ -41,12 +41,8 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
41
41
 
42
42
  ## Contributing
43
43
 
44
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/libra_client. 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.
44
+ Bug reports and pull requests are welcome on GitHub at https://github.com/yuanxinyu/libra_client. 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.
45
45
 
46
46
  ## License
47
47
 
48
48
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
49
-
50
- ## Code of Conduct
51
-
52
- Everyone interacting in the LibraClient project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/libra_client/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile CHANGED
File without changes
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "bundler/setup"
4
4
  require "libra_client"
5
+ #require 'byebug'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -11,4 +12,5 @@ require "libra_client"
11
12
  # Pry.start
12
13
 
13
14
  require "irb"
15
+ require 'irb/completion'
14
16
  IRB.start(__FILE__)
data/bin/setup CHANGED
File without changes
File without changes
@@ -0,0 +1,51 @@
1
+ # Suppose we have the following data structure in a smart contract:
2
+ #
3
+ # struct B {
4
+ # Map<String, String> mymap;
5
+ # }
6
+ #
7
+ # struct A {
8
+ # B b;
9
+ # int my_int;
10
+ # }
11
+ #
12
+ # struct C {
13
+ # List<int> mylist;
14
+ # }
15
+ #
16
+ # A a;
17
+ # C c;
18
+ #
19
+ # and the data belongs to Alice. Then an access to `a.b.mymap` would be translated to an access
20
+ # to an entry in key-value store whose key is `<Alice>/a/b/mymap`. In the same way, the access to
21
+ # `c.mylist` would need to query `<Alice>/c/mylist`.
22
+ #
23
+ # So an account stores its data in a directory structure, for example:
24
+ # <Alice>/balance: 10
25
+ # <Alice>/a/b/mymap: {"Bob" => "abcd", "Carol" => "efgh"}
26
+ # <Alice>/a/myint: 20
27
+ # <Alice>/c/mylist: [3, 5, 7, 9]
28
+ #
29
+ # If someone needs to query the map above and find out what value associated with "Bob" is,
30
+ # `address` will be set to Alice and `path` will be set to "/a/b/mymap/Bob".
31
+ #
32
+ # On the other hand, if you want to query only <Alice>/a/*, `address` will be set to Alice and
33
+ # `path` will be set to "/a" and use the `get_prefix()` method from statedb
34
+
35
+
36
+ module Libra
37
+ class AccessPath
38
+ attr_accessor :address
39
+ attr_accessor :path
40
+
41
+ def initialize(address_hex, path)
42
+ @address = AccountAddress.new(address_hex)
43
+ @path = path
44
+ end
45
+
46
+ def to_proto
47
+ Types::AccessPath.new(address: address.addr, path: path)
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,29 @@
1
+ # A struct that represents an account address.
2
+ # Currently Public Key is used.
3
+
4
+ module Libra
5
+ class AccountAddress
6
+ ADDRESS_LENGTH = 32;
7
+
8
+ SHORT_STRING_LENGTH = 4;
9
+
10
+ LIBRA_NETWORK_ID_SHORT = "lb";
11
+
12
+ attr_accessor :addr
13
+ attr_accessor :hex
14
+
15
+ def initialize(hex_literal)
16
+ @hex = hex_literal
17
+ @addr = [hex_literal].pack('H*')
18
+ end
19
+
20
+ def self.hex_to_bytes(hex_literal)
21
+ [hex_literal].pack('H*')
22
+ end
23
+
24
+ def self.from_public_key
25
+ #TODO
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,57 @@
1
+
2
+ module Libra
3
+ class AccountConfig
4
+ # LibraCoin
5
+ COIN_MODULE_NAME = "LibraCoin";
6
+ COIN_STRUCT_NAME = "T";
7
+
8
+ # Account
9
+ ACCOUNT_MODULE_NAME = "LibraAccount";
10
+ ACCOUNT_STRUCT_NAME = "T";
11
+
12
+ # Hash
13
+ HASH_MODULE_NAME = "Hash";
14
+
15
+ # pub fn resource_access_vec(tag: &StructTag, accesses: &Accesses) -> Vec<u8> {
16
+ # let mut key = vec![];
17
+ # key.push(Self::RESOURCE_TAG);
18
+
19
+ # key.append(&mut tag.hash().to_vec());
20
+
21
+ # // We don't need accesses in production right now. Accesses are appended here just for
22
+ # // passing the old tests.
23
+ # key.append(&mut accesses.as_separated_string().into_bytes());
24
+ # key
25
+ # }
26
+
27
+ # /// Return the path to the Account resource. It can be used to create an AccessPath for an
28
+ # /// Account resource.
29
+ # pub fn account_resource_path() -> Vec<u8> {
30
+ # AccessPath::resource_access_vec(
31
+ # &StructTag {
32
+ # address: core_code_address(),
33
+ # module: ACCOUNT_MODULE_NAME.to_string(),
34
+ # name: ACCOUNT_STRUCT_NAME.to_string(),
35
+ # type_params: vec![],
36
+ # },
37
+ # &Accesses::empty(),
38
+ # )
39
+ # }
40
+ ACCOUNT_RESOURCE_PATH = [1, 33, 125, 166, 198, 179, 225, 159, 24, 37, 207, 178, 103, 109, 174, 204, 227, 191, 61, 224, 60, 242, 102, 71, 199, 141, 240, 11, 55, 27, 37, 204, 151]
41
+
42
+ def self.account_sent_event_path
43
+ path = ACCOUNT_RESOURCE_PATH + "/sent_events_count/".bytes
44
+ path.pack('C*')
45
+ end
46
+
47
+ def self.account_received_event_path
48
+ path = ACCOUNT_RESOURCE_PATH + "/received_events_count/".bytes
49
+ path.pack('C*')
50
+ end
51
+
52
+ def self.association_address
53
+ AccountAddress.new("000000000000000000000000000000000000000000000000000000000a550c18")
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,38 @@
1
+
2
+ module Libra
3
+ class AccountState < Canoser::Struct
4
+ define_field :blob, {}
5
+ end
6
+
7
+ # pub struct AccountResource {
8
+ # balance: u64,
9
+ # sequence_number: u64,
10
+ # authentication_key: ByteArray,
11
+ # delegated_withdrawal_capability: bool,
12
+ # sent_events: EventHandle,
13
+ # received_events: EventHandle,
14
+ # }
15
+
16
+ # impl CanonicalSerialize for AccountResource {
17
+ # fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> Result<()> {
18
+ # // TODO(drussi): the order in which these fields are serialized depends on some
19
+ # // implementation details in the VM.
20
+ # serializer
21
+ # .encode_struct(&self.authentication_key)?
22
+ # .encode_u64(self.balance)?
23
+ # .encode_bool(self.delegated_withdrawal_capability)?
24
+ # .encode_struct(&self.received_events)?
25
+ # .encode_struct(&self.sent_events)?
26
+ # .encode_u64(self.sequence_number)?;
27
+ # Ok(())
28
+ # }
29
+ # }
30
+ class AccountResource < Canoser::Struct
31
+ define_field :authentication_key, [Canoser::Uint8]
32
+ define_field :balance, Canoser::Uint64
33
+ define_field :delegated_withdrawal_capability, Canoser::Bool
34
+ define_field :received_events_count, Canoser::Uint64
35
+ define_field :sent_events_count, Canoser::Uint64
36
+ define_field :sequence_number, Canoser::Uint64
37
+ end
38
+ end
@@ -0,0 +1,147 @@
1
+
2
+ require 'openssl'
3
+ require 'securerandom'
4
+ require 'digest'
5
+
6
+ module Libra
7
+
8
+ MNEMONIC_SALT_PREFIX = "LIBRA WALLET: mnemonic salt prefix$"
9
+ MASTER_KEY_SALT = "LIBRA WALLET: master key salt$"
10
+ INFO_PREFIX = "LIBRA WALLET: derived key$"
11
+
12
+ class Mnemonic
13
+ def self.to_seed(mnemonic, passphrase = 'LIBRA')
14
+ seed = OpenSSL::PKCS5.pbkdf2_hmac(
15
+ mnemonic, MNEMONIC_SALT_PREFIX + passphrase, 2048, 64, OpenSSL::Digest::SHA512.new
16
+ ) # how to support SHA3_256 in ruby?
17
+ seed.unpack('H*')[0].first
18
+ end
19
+
20
+ def self.generate(strength_bits = 256)
21
+ if (strength_bits % 32) > 0
22
+ raise ArgumentError, format(
23
+ 'Strength should be divisible by 32, but it is not (%<strength_bits>d)',
24
+ strength_bits: strength_bits
25
+ )
26
+ end
27
+ data = SecureRandom.random_bytes((strength_bits / 8).floor)
28
+ to_mnemonic(data)
29
+ end
30
+
31
+ def self.wordlist
32
+ @wordlist ||= nil
33
+ return @wordlist if @wordlist
34
+ @wordlist = WORDLIST_ENGLISH.split(/[ \n]/).map(&:strip).reject(&:empty?)
35
+ if @wordlist.size != (radix = 2048)
36
+ raise ArgumentError, format(
37
+ 'Wordlist should contain %<radix>d words, but it contains %<count>d words.',
38
+ radix: radix, count: wordlist.size
39
+ )
40
+ end
41
+ @wordlist
42
+ end
43
+
44
+ def self.to_mnemonic(data)
45
+ if (data.bytesize % 4) > 0
46
+ raise ArgumentError, format(
47
+ 'Data length in bits should be divisible by 32, ' \
48
+ 'but it is not (%<count>d bytes = %<bits_count>d bits).',
49
+ count: data.bytesize, bits_count: data.bytesize * 8
50
+ )
51
+ end
52
+ b = data.unpack('B*')[0] +
53
+ Digest::SHA256.digest(data).unpack('B*')[0]
54
+ .ljust(256, '0')[0...(data.bytesize * 8 / 32)]
55
+
56
+ (0...(b.bytesize / 11)).map do |i|
57
+ idx = b[(i * 11)...((i + 1) * 11)].to_i(2)
58
+ wordlist[idx]
59
+ end.join(' ')
60
+ end
61
+
62
+ WORDLIST_ENGLISH = <<-TEXT.freeze
63
+ abandon ability able about above absent absorb abstract absurd abuse access accident account accuse achieve acid acoustic acquire across act action actor actress actual adapt
64
+ add addict address adjust admit adult advance advice aerobic affair afford afraid again age agent agree ahead aim air airport aisle alarm album alcohol alert
65
+ alien all alley allow almost alone alpha already also alter always amateur amazing among amount amused analyst anchor ancient anger angle angry animal ankle announce
66
+ annual another answer antenna antique anxiety any apart apology appear apple approve april arch arctic area arena argue arm armed armor army around arrange arrest
67
+ arrive arrow art artefact artist artwork ask aspect assault asset assist assume asthma athlete atom attack attend attitude attract auction audit august aunt author auto
68
+ autumn average avocado avoid awake aware away awesome awful awkward axis baby bachelor bacon badge bag balance balcony ball bamboo banana banner bar barely bargain
69
+ barrel base basic basket battle beach bean beauty because become beef before begin behave behind believe below belt bench benefit best betray better between beyond
70
+ bicycle bid bike bind biology bird birth bitter black blade blame blanket blast bleak bless blind blood blossom blouse blue blur blush board boat body
71
+ boil bomb bone bonus book boost border boring borrow boss bottom bounce box boy bracket brain brand brass brave bread breeze brick bridge brief bright
72
+ bring brisk broccoli broken bronze broom brother brown brush bubble buddy budget buffalo build bulb bulk bullet bundle bunker burden burger burst bus business busy
73
+ butter buyer buzz cabbage cabin cable cactus cage cake call calm camera camp can canal cancel candy cannon canoe canvas canyon capable capital captain car
74
+ carbon card cargo carpet carry cart case cash casino castle casual cat catalog catch category cattle caught cause caution cave ceiling celery cement census century
75
+ cereal certain chair chalk champion change chaos chapter charge chase chat cheap check cheese chef cherry chest chicken chief child chimney choice choose chronic chuckle
76
+ chunk churn cigar cinnamon circle citizen city civil claim clap clarify claw clay clean clerk clever click client cliff climb clinic clip clock clog close
77
+ cloth cloud clown club clump cluster clutch coach coast coconut code coffee coil coin collect color column combine come comfort comic common company concert conduct
78
+ confirm congress connect consider control convince cook cool copper copy coral core corn correct cost cotton couch country couple course cousin cover coyote crack cradle
79
+ craft cram crane crash crater crawl crazy cream credit creek crew cricket crime crisp critic crop cross crouch crowd crucial cruel cruise crumble crunch crush
80
+ cry crystal cube culture cup cupboard curious current curtain curve cushion custom cute cycle dad damage damp dance danger daring dash daughter dawn day deal
81
+ debate debris decade december decide decline decorate decrease deer defense define defy degree delay deliver demand demise denial dentist deny depart depend deposit depth deputy
82
+ derive describe desert design desk despair destroy detail detect develop device devote diagram dial diamond diary dice diesel diet differ digital dignity dilemma dinner dinosaur
83
+ direct dirt disagree discover disease dish dismiss disorder display distance divert divide divorce dizzy doctor document dog doll dolphin domain donate donkey donor door dose
84
+ double dove draft dragon drama drastic draw dream dress drift drill drink drip drive drop drum dry duck dumb dune during dust dutch duty dwarf
85
+ dynamic eager eagle early earn earth easily east easy echo ecology economy edge edit educate effort egg eight either elbow elder electric elegant element elephant
86
+ elevator elite else embark embody embrace emerge emotion employ empower empty enable enact end endless endorse enemy energy enforce engage engine enhance enjoy enlist enough
87
+ enrich enroll ensure enter entire entry envelope episode equal equip era erase erode erosion error erupt escape essay essence estate eternal ethics evidence evil evoke
88
+ evolve exact example excess exchange excite exclude excuse execute exercise exhaust exhibit exile exist exit exotic expand expect expire explain expose express extend extra eye
89
+ eyebrow fabric face faculty fade faint faith fall false fame family famous fan fancy fantasy farm fashion fat fatal father fatigue fault favorite feature february
90
+ federal fee feed feel female fence festival fetch fever few fiber fiction field figure file film filter final find fine finger finish fire firm first
91
+ fiscal fish fit fitness fix flag flame flash flat flavor flee flight flip float flock floor flower fluid flush fly foam focus fog foil fold
92
+ follow food foot force forest forget fork fortune forum forward fossil foster found fox fragile frame frequent fresh friend fringe frog front frost frown frozen
93
+ fruit fuel fun funny furnace fury future gadget gain galaxy gallery game gap garage garbage garden garlic garment gas gasp gate gather gauge gaze general
94
+ genius genre gentle genuine gesture ghost giant gift giggle ginger giraffe girl give glad glance glare glass glide glimpse globe gloom glory glove glow glue
95
+ goat goddess gold good goose gorilla gospel gossip govern gown grab grace grain grant grape grass gravity great green grid grief grit grocery group grow
96
+ grunt guard guess guide guilt guitar gun gym habit hair half hammer hamster hand happy harbor hard harsh harvest hat have hawk hazard head health
97
+ heart heavy hedgehog height hello helmet help hen hero hidden high hill hint hip hire history hobby hockey hold hole holiday hollow home honey hood
98
+ hope horn horror horse hospital host hotel hour hover hub huge human humble humor hundred hungry hunt hurdle hurry hurt husband hybrid ice icon idea
99
+ identify idle ignore ill illegal illness image imitate immense immune impact impose improve impulse inch include income increase index indicate indoor industry infant inflict inform
100
+ inhale inherit initial inject injury inmate inner innocent input inquiry insane insect inside inspire install intact interest into invest invite involve iron island isolate issue
101
+ item ivory jacket jaguar jar jazz jealous jeans jelly jewel job join joke journey joy judge juice jump jungle junior junk just kangaroo keen keep
102
+ ketchup key kick kid kidney kind kingdom kiss kit kitchen kite kitten kiwi knee knife knock know lab label labor ladder lady lake lamp language
103
+ laptop large later latin laugh laundry lava law lawn lawsuit layer lazy leader leaf learn leave lecture left leg legal legend leisure lemon lend length
104
+ lens leopard lesson letter level liar liberty library license life lift light like limb limit link lion liquid list little live lizard load loan lobster
105
+ local lock logic lonely long loop lottery loud lounge love loyal lucky luggage lumber lunar lunch luxury lyrics machine mad magic magnet maid mail main
106
+ major make mammal man manage mandate mango mansion manual maple marble march margin marine market marriage mask mass master match material math matrix matter maximum
107
+ maze meadow mean measure meat mechanic medal media melody melt member memory mention menu mercy merge merit merry mesh message metal method middle midnight milk
108
+ million mimic mind minimum minor minute miracle mirror misery miss mistake mix mixed mixture mobile model modify mom moment monitor monkey monster month moon moral
109
+ more morning mosquito mother motion motor mountain mouse move movie much muffin mule multiply muscle museum mushroom music must mutual myself mystery myth naive name
110
+ napkin narrow nasty nation nature near neck need negative neglect neither nephew nerve nest net network neutral never news next nice night noble noise nominee
111
+ noodle normal north nose notable note nothing notice novel now nuclear number nurse nut oak obey object oblige obscure observe obtain obvious occur ocean october
112
+ odor off offer office often oil okay old olive olympic omit once one onion online only open opera opinion oppose option orange orbit orchard order
113
+ ordinary organ orient original orphan ostrich other outdoor outer output outside oval oven over own owner oxygen oyster ozone pact paddle page pair palace palm
114
+ panda panel panic panther paper parade parent park parrot party pass patch path patient patrol pattern pause pave payment peace peanut pear peasant pelican pen
115
+ penalty pencil people pepper perfect permit person pet phone photo phrase physical piano picnic picture piece pig pigeon pill pilot pink pioneer pipe pistol pitch
116
+ pizza place planet plastic plate play please pledge pluck plug plunge poem poet point polar pole police pond pony pool popular portion position possible post
117
+ potato pottery poverty powder power practice praise predict prefer prepare present pretty prevent price pride primary print priority prison private prize problem process produce profit
118
+ program project promote proof property prosper protect proud provide public pudding pull pulp pulse pumpkin punch pupil puppy purchase purity purpose purse push put puzzle
119
+ pyramid quality quantum quarter question quick quit quiz quote rabbit raccoon race rack radar radio rail rain raise rally ramp ranch random range rapid rare
120
+ rate rather raven raw razor ready real reason rebel rebuild recall receive recipe record recycle reduce reflect reform refuse region regret regular reject relax release
121
+ relief rely remain remember remind remove render renew rent reopen repair repeat replace report require rescue resemble resist resource response result retire retreat return reunion
122
+ reveal review reward rhythm rib ribbon rice rich ride ridge rifle right rigid ring riot ripple risk ritual rival river road roast robot robust rocket
123
+ romance roof rookie room rose rotate rough round route royal rubber rude rug rule run runway rural sad saddle sadness safe sail salad salmon salon
124
+ salt salute same sample sand satisfy satoshi sauce sausage save say scale scan scare scatter scene scheme school science scissors scorpion scout scrap screen script
125
+ scrub sea search season seat second secret section security seed seek segment select sell seminar senior sense sentence series service session settle setup seven shadow
126
+ shaft shallow share shed shell sheriff shield shift shine ship shiver shock shoe shoot shop short shoulder shove shrimp shrug shuffle shy sibling sick side
127
+ siege sight sign silent silk silly silver similar simple since sing siren sister situate six size skate sketch ski skill skin skirt skull slab slam
128
+ sleep slender slice slide slight slim slogan slot slow slush small smart smile smoke smooth snack snake snap sniff snow soap soccer social sock soda
129
+ soft solar soldier solid solution solve someone song soon sorry sort soul sound soup source south space spare spatial spawn speak special speed spell spend
130
+ sphere spice spider spike spin spirit split spoil sponsor spoon sport spot spray spread spring spy square squeeze squirrel stable stadium staff stage stairs stamp
131
+ stand start state stay steak steel stem step stereo stick still sting stock stomach stone stool story stove strategy street strike strong struggle student stuff
132
+ stumble style subject submit subway success such sudden suffer sugar suggest suit summer sun sunny sunset super supply supreme sure surface surge surprise surround survey
133
+ suspect sustain swallow swamp swap swarm swear sweet swift swim swing switch sword symbol symptom syrup system table tackle tag tail talent talk tank tape
134
+ target task taste tattoo taxi teach team tell ten tenant tennis tent term test text thank that theme then theory there they thing this thought
135
+ three thrive throw thumb thunder ticket tide tiger tilt timber time tiny tip tired tissue title toast tobacco today toddler toe together toilet token tomato
136
+ tomorrow tone tongue tonight tool tooth top topic topple torch tornado tortoise toss total tourist toward tower town toy track trade traffic tragic train transfer
137
+ trap trash travel tray treat tree trend trial tribe trick trigger trim trip trophy trouble truck true truly trumpet trust truth try tube tuition tumble
138
+ tuna tunnel turkey turn turtle twelve twenty twice twin twist two type typical ugly umbrella unable unaware uncle uncover under undo unfair unfold unhappy uniform
139
+ unique unit universe unknown unlock until unusual unveil update upgrade uphold upon upper upset urban urge usage use used useful useless usual utility vacant vacuum
140
+ vague valid valley valve van vanish vapor various vast vault vehicle velvet vendor venture venue verb verify version very vessel veteran viable vibrant vicious victory
141
+ video view village vintage violin virtual virus visa visit visual vital vivid vocal voice void volcano volume vote voyage wage wagon wait walk wall walnut
142
+ want warfare warm warrior wash wasp waste water wave way wealth weapon wear weasel weather web wedding weekend weird welcome west wet whale what wheat
143
+ wheel when where whip whisper wide width wife wild will win window wine wing wink winner winter wire wisdom wise wish witness wolf woman wonder
144
+ wood wool word work world worry worth wrap wreck wrestle wrist write wrong yard year yellow you young youth zebra zero zone zoo
145
+ TEXT
146
+ end
147
+ end
@@ -0,0 +1,3 @@
1
+ module Libra
2
+ VERSION = "0.1.2"
3
+ end
@@ -3,74 +3,160 @@ $LOAD_PATH.unshift(protolib) if File.directory?(protolib) && !$LOAD_PATH.include
3
3
 
4
4
  require 'grpc'
5
5
  require 'admission_control_services_pb'
6
+ require 'canoser'
7
+ require 'rest_client'
6
8
 
7
- LIBRA_TESTNET_HOST = "ac.testnet.libra.org:8000"
8
- FAUCET_HOST = "http://faucet.testnet.libra.org"
9
- #ACCOUNT_STATE_PATH = bytes.fromhex("01217da6c6b3e19f1825cfb2676daecce3bf3de03cf26647c78df00b371b25cc97")
9
+ require "libra/version"
10
+ require 'libra/account_address'
11
+ require 'libra/account_config'
12
+ require 'libra/access_path'
13
+ require 'libra/account_resource'
14
+ require 'libra/mnemonic'
10
15
 
11
- ACCOUNT_RESOURCE_PATH = [1, 33, 125, 166, 198, 179, 225, 159, 24, 37, 207, 178, 103, 109, 174, 204, 227, 191, 61, 224, 60, 242, 102, 71, 199, 141, 240, 11, 55, 27, 37, 204, 151]
12
- ACCOUNT_SENT_EVENT_PATH = [1, 33, 125, 166, 198, 179, 225, 159, 24, 37, 207, 178, 103, 109, 174, 204, 227, 191, 61, 224, 60, 242, 102, 71, 199, 141, 240, 11, 55, 27, 37, 204, 151, 47, 115, 101, 110, 116, 95, 101, 118, 101, 110, 116, 115, 95, 99, 111, 117, 110, 116, 47]
13
- ASSOCIATION_ADDRESS = "000000000000000000000000000000000000000000000000000000000a550c18"
14
16
 
17
+ module Libra
18
+ class LibraError < StandardError; end
15
19
 
16
- module LibraClient
20
+ NETWORKS = {
21
+ testnet:{
22
+ host: "ac.testnet.libra.org:8000",
23
+ faucet_host: "faucet.testnet.libra.org"
24
+ }
25
+ }
17
26
 
18
- def self.get_latest_transaction_version
19
- stub = AdmissionControl::AdmissionControl::Stub.new("ac.testnet.libra.org:8000",:this_channel_is_insecure)
20
- resp = stub.update_to_latest_ledger(Types::UpdateToLatestLedgerRequest.new())
21
- resp.ledger_info_with_sigs.ledger_info.version
22
- end
23
27
 
24
- def self.update_to_latest_ledger(requested_items)
25
- request = Types::UpdateToLatestLedgerRequest.new(client_known_version: 3747, requested_items: requested_items)
26
- stub = AdmissionControl::AdmissionControl::Stub.new("ac.testnet.libra.org:8000",:this_channel_is_insecure)
27
- response = stub.update_to_latest_ledger(request)
28
- # [:response_items, :ledger_info_with_sigs, :validator_change_events]
29
- response
30
- end
28
+ class Client
31
29
 
32
- def self.get_account_state(address)
33
- address = [address].pack('H*')
34
- query = Types::GetAccountStateRequest.new(address: address)
35
- item = Types::RequestItem.new(get_account_state_request: query)
36
- resp = update_to_latest_ledger([item])
37
- state = resp.response_items[0].get_account_state_response.account_state_with_proof
38
- state
39
- end
30
+ def initialize(network="testnet")
31
+ raise LibraError.new("only support testnet now.") unless network.to_s == "testnet"
32
+ @host = NETWORKS[network.to_sym][:host]
33
+ @faucet_host = NETWORKS[network.to_sym][:faucet_host]
34
+ end
40
35
 
41
- def self.get_transactions(start_version, limit=1, fetch_events=false)
42
- query = Types::GetTransactionsRequest.new(start_version: start_version, limit: limit, fetch_events: fetch_events)
43
- item = Types::RequestItem.new(get_transactions_request: query)
44
- resp = update_to_latest_ledger([item])
45
- txn_list_with_proof = resp.response_items[0].get_transactions_response.txn_list_with_proof
46
- #[:transactions, :infos, :events_for_versions, :first_transaction_version, :proof_of_first_transaction, :proof_of_last_transaction]
47
- txn_list_with_proof.transactions
48
- end
36
+ def get_latest_transaction_version
37
+ stub = AdmissionControl::AdmissionControl::Stub.new(@host,:this_channel_is_insecure)
38
+ resp = stub.update_to_latest_ledger(Types::UpdateToLatestLedgerRequest.new())
39
+ resp.ledger_info_with_sigs.ledger_info.version
40
+ end
49
41
 
50
- def self.get_transaction(start_version)
51
- #Types::SignedTransaction [:raw_txn_bytes, :sender_public_key, :sender_signature]
52
- get_transactions(start_version)[0]
53
- end
42
+ def update_to_latest_ledger(requested_items)
43
+ request = Types::UpdateToLatestLedgerRequest.new(client_known_version: 0, requested_items: requested_items)
44
+ stub = AdmissionControl::AdmissionControl::Stub.new(@host,:this_channel_is_insecure)
45
+ response = stub.update_to_latest_ledger(request)
46
+ # [:response_items, :ledger_info_with_sigs, :validator_change_events]
47
+ response
48
+ end
54
49
 
55
- def self.get_account_transaction(address, sequence_number, fetch_events=true)
56
- address = [address].pack('H*')
57
- query = Types::GetAccountTransactionBySequenceNumberRequest.new(account: address, sequence_number: sequence_number, fetch_events: fetch_events)
58
- item = Types::RequestItem.new(get_account_transaction_by_sequence_number_request: query)
59
- resp = update_to_latest_ledger([item])
60
- transaction = resp.response_items[0].get_account_transaction_by_sequence_number_response.signed_transaction_with_proof
61
- #Types::SignedTransactionWithProof [:version, :signed_transaction, :proof, :events]
62
- transaction
63
- end
50
+ def get_sequence_number(address)
51
+ state = get_account_state(address)
52
+ state["sequence_number"]
53
+ end
64
54
 
65
- def self.get_events(address, start_sequence_number, ascending=true, limit=1)
66
- address = [address].pack('H*')
67
- path = ACCOUNT_SENT_EVENT_PATH.map{|x| x.chr}.join("")
68
- access_path = Types::AccessPath.new(address: address, path: path)
69
- query = Types::GetEventsByEventAccessPathRequest.new(access_path: access_path, start_event_seq_num: start_sequence_number, ascending: ascending, limit: limit)
70
- item = Types::RequestItem.new(get_events_by_event_access_path_request: query)
71
- resp = update_to_latest_ledger([item])
72
- resp.response_items[0].get_events_by_event_access_path_response.events_with_proof
73
- end
55
+ def get_balance(address)
56
+ state = get_account_state(address)
57
+ state["balance"]
58
+ end
59
+
60
+ def get_account_state(address)
61
+ query = Types::GetAccountStateRequest.new(address: AccountAddress.hex_to_bytes(address))
62
+ item = Types::RequestItem.new(get_account_state_request: query)
63
+ resp = update_to_latest_ledger([item])
64
+ state = resp.response_items[0].get_account_state_response.account_state_with_proof
65
+ map = Libra::AccountState.deserialize(state.blob.blob)["blob"]
66
+ resource = map[AccountConfig::ACCOUNT_RESOURCE_PATH]
67
+ Libra::AccountResource.deserialize(resource.pack('C*'))
68
+ end
69
+
70
+ def get_transactions(start_version, limit=1, fetch_events=false)
71
+ query = Types::GetTransactionsRequest.new(start_version: start_version, limit: limit, fetch_events: fetch_events)
72
+ item = Types::RequestItem.new(get_transactions_request: query)
73
+ resp = update_to_latest_ledger([item])
74
+ txn_list_with_proof = resp.response_items[0].get_transactions_response.txn_list_with_proof
75
+ #[:transactions, :infos, :events_for_versions, :first_transaction_version, :proof_of_first_transaction, :proof_of_last_transaction]
76
+ txn_list_with_proof.transactions
77
+ end
78
+
79
+ def get_transaction(start_version)
80
+ #Types::SignedTransaction [:raw_txn_bytes, :sender_public_key, :sender_signature]
81
+ get_transactions(start_version)[0]
82
+ end
83
+
84
+ def get_account_transaction(address, sequence_number, fetch_events=true)
85
+ addr = AccountAddress.hex_to_bytes(address)
86
+ query = Types::GetAccountTransactionBySequenceNumberRequest.new(account: addr, sequence_number: sequence_number, fetch_events: fetch_events)
87
+ item = Types::RequestItem.new(get_account_transaction_by_sequence_number_request: query)
88
+ resp = update_to_latest_ledger([item])
89
+ transaction = resp.response_items[0].get_account_transaction_by_sequence_number_response.signed_transaction_with_proof
90
+ #Types::SignedTransactionWithProof [:version, :signed_transaction, :proof, :events]
91
+ transaction
92
+ end
93
+
94
+ # Returns events specified by `access_path` with sequence number in range designated by
95
+ # `start_seq_num`, `ascending` and `limit`. If ascending is true this query will return up to
96
+ # `limit` events that were emitted after `start_event_seq_num`. Otherwise it will return up to
97
+ # `limit` events in the reverse order. Both cases are inclusive.
98
+ def get_events(address_hex, path, start_sequence_number, ascending=true, limit=1)
99
+ access_path = AccessPath.new(address_hex, path).to_proto
100
+ query = Types::GetEventsByEventAccessPathRequest.new(access_path: access_path, start_event_seq_num: start_sequence_number, ascending: ascending, limit: limit)
101
+ item = Types::RequestItem.new(get_events_by_event_access_path_request: query)
102
+ resp = update_to_latest_ledger([item])
103
+ resp.response_items[0].get_events_by_event_access_path_response.events_with_proof
104
+ end
105
+
106
+ def get_events_sent(address_hex, start_sequence_number, ascending=true, limit=1)
107
+ path = AccountConfig.account_sent_event_path
108
+ get_events(address_hex, path, start_sequence_number, ascending, limit)
109
+ end
110
+
111
+ def get_events_received(address_hex, start_sequence_number, ascending=true, limit=1)
112
+ path = AccountConfig.account_received_event_path
113
+ get_events(address_hex, path, start_sequence_number, ascending, limit)
114
+ end
115
+
116
+ def get_latest_events_sent(address_hex, limit=1)
117
+ get_events_sent(address_hex, 2**64-1, false, limit)
118
+ end
119
+
120
+ def get_latest_events_received(address_hex, limit=1)
121
+ get_events_received(address_hex, 2**64-1, false, limit)
122
+ end
123
+
124
+ def mint_coins_with_local_faucet_account
125
+ end
126
+
127
+ def mint_coins_with_faucet_service(receiver, num_coins, is_blocking)
128
+ resp = RestClient.post "http://#{@faucet_host}?amount=#{num_coins}&address=#{receiver}", {}
129
+ if resp.code != 200
130
+ raise LibraError.new("Failed to query remote faucet server[status=#{resp.code}]: #{resp.body}")
131
+ end
132
+ sequence_number = resp.body.to_i
133
+ if is_blocking
134
+ puts AccountConfig.association_address.hex
135
+ self.wait_for_transaction(AccountConfig.association_address.hex, sequence_number);
136
+ end
137
+ end
138
+
139
+ def wait_for_transaction(account, sequence_number)
140
+ max_iterations = 500
141
+ puts("waiting ")
142
+ while (max_iterations > 0 )do
143
+ $stdout.flush
144
+ max_iterations -= 1;
145
+ transaction = get_account_transaction(account, sequence_number - 1, true)
146
+ if transaction && transaction.events
147
+ puts "transaction is stored!"
148
+ if transaction.events.events.size == 0
149
+ puts "no events emitted"
150
+ end
151
+ return
152
+ else
153
+ print(".")
154
+ sleep(0.01)
155
+ end
156
+ end
157
+ puts "wait_for_transaction timeout"
158
+ end
74
159
 
160
+ end
75
161
 
76
162
  end
@@ -1,11 +1,11 @@
1
1
 
2
2
  lib = File.expand_path("../lib", __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "libra_client/version"
4
+ require "libra/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "libra_client"
8
- spec.version = LibraClient::VERSION
8
+ spec.version = Libra::VERSION
9
9
  spec.authors = ["yuan xinyu"]
10
10
  spec.email = ["yuanxinyu.hangzhou@gmail.com"]
11
11
 
@@ -39,6 +39,11 @@ Gem::Specification.new do |spec|
39
39
  spec.add_development_dependency "bundler", "~> 2.0"
40
40
  spec.add_development_dependency "rake", "~> 10.0"
41
41
  spec.add_development_dependency "minitest", "~> 5.0"
42
+ spec.add_development_dependency "byebug", "~> 11.0"
42
43
 
43
44
  spec.add_dependency "grpc", "~> 1.23"
45
+ spec.add_dependency "canoser", "~> 0.1.0"
46
+ spec.add_dependency "rest-client", "~> 2.0"
47
+ #spec.add_dependency "openssl", "~> 2.1.3"
48
+
44
49
  end
@@ -0,0 +1,16 @@
1
+ {
2
+ "folders":
3
+ [
4
+ {
5
+ "path": ".",
6
+ "folder_exclude_patterns": [".bundle",".idea","certs","coverage","tmp","log","pkg"],
7
+ "file_exclude_patterns": ["*.sublime-workspace","*.sqlite3","spec/examples.txt",".byebug_history",".DS_Store"]
8
+ }
9
+ ],
10
+ "settings":
11
+ {
12
+ "translate_tabs_to_spaces": true,
13
+ "trim_trailing_white_space_on_save": true,
14
+ "tab_size": 2
15
+ }
16
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libra_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - yuan xinyu
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-22 00:00:00.000000000 Z
11
+ date: 2019-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '11.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '11.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: grpc
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,34 @@ dependencies:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: '1.23'
83
+ - !ruby/object:Gem::Dependency
84
+ name: canoser
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.1.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.1.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: rest-client
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.0'
69
111
  description: A ruby client for Libra network.
70
112
  email:
71
113
  - yuanxinyu.hangzhou@gmail.com
@@ -84,9 +126,15 @@ files:
84
126
  - bin/console
85
127
  - bin/setup
86
128
  - gen_proto.sh
129
+ - lib/libra/access_path.rb
130
+ - lib/libra/account_address.rb
131
+ - lib/libra/account_config.rb
132
+ - lib/libra/account_resource.rb
133
+ - lib/libra/mnemonic.rb
134
+ - lib/libra/version.rb
87
135
  - lib/libra_client.rb
88
- - lib/libra_client/version.rb
89
136
  - libra_client.gemspec
137
+ - libra_client.sublime-project
90
138
  - proto-lib/access_path_pb.rb
91
139
  - proto-lib/account_state_blob_pb.rb
92
140
  - proto-lib/admission_control_pb.rb
@@ -135,8 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
183
  - !ruby/object:Gem::Version
136
184
  version: '0'
137
185
  requirements: []
138
- rubyforge_project:
139
- rubygems_version: 2.7.7
186
+ rubygems_version: 3.0.1
140
187
  signing_key:
141
188
  specification_version: 4
142
189
  summary: A ruby client for Libra network.
@@ -1,3 +0,0 @@
1
- module LibraClient
2
- VERSION = "0.1.1"
3
- end