flow_client 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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +35 -0
  3. data/.gitignore +12 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +20 -0
  6. data/CHANGELOG.md +5 -0
  7. data/CODE_OF_CONDUCT.md +84 -0
  8. data/Gemfile +14 -0
  9. data/Gemfile.lock +115 -0
  10. data/Guardfile +79 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +93 -0
  13. data/Rakefile +12 -0
  14. data/bin/console +15 -0
  15. data/bin/setup +8 -0
  16. data/flow_client.gemspec +44 -0
  17. data/lib/flow/access/access_pb.rb +168 -0
  18. data/lib/flow/access/access_services_pb.rb +96 -0
  19. data/lib/flow/entities/account_pb.rb +30 -0
  20. data/lib/flow/entities/block_header_pb.rb +20 -0
  21. data/lib/flow/entities/block_pb.rb +25 -0
  22. data/lib/flow/entities/block_seal_pb.rb +19 -0
  23. data/lib/flow/entities/collection_pb.rb +23 -0
  24. data/lib/flow/entities/event_pb.rb +20 -0
  25. data/lib/flow/entities/transaction_pb.rb +47 -0
  26. data/lib/flow/execution/execution_pb.rb +65 -0
  27. data/lib/flow/execution/execution_services_pb.rb +43 -0
  28. data/lib/flow/legacy/access/access_pb.rb +157 -0
  29. data/lib/flow/legacy/access/access_services_pb.rb +89 -0
  30. data/lib/flow/legacy/entities/account_pb.rb +28 -0
  31. data/lib/flow/legacy/entities/block_header_pb.rb +20 -0
  32. data/lib/flow/legacy/entities/block_pb.rb +25 -0
  33. data/lib/flow/legacy/entities/block_seal_pb.rb +19 -0
  34. data/lib/flow/legacy/entities/collection_pb.rb +22 -0
  35. data/lib/flow/legacy/entities/event_pb.rb +20 -0
  36. data/lib/flow/legacy/entities/transaction_pb.rb +45 -0
  37. data/lib/flow/legacy/execution/execution_pb.rb +65 -0
  38. data/lib/flow/legacy/execution/execution_services_pb.rb +42 -0
  39. data/lib/flow_client.rb +14 -0
  40. data/lib/flow_client/client.rb +98 -0
  41. data/lib/flow_client/crypto.rb +33 -0
  42. data/lib/flow_client/transaction.rb +147 -0
  43. data/lib/flow_client/utils.rb +38 -0
  44. data/lib/flow_client/version.rb +5 -0
  45. metadata +201 -0
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "flow/entities/transaction_pb"
4
+ require "openssl"
5
+ require "rlp"
6
+
7
+ module FlowClient
8
+ # A Transaction is a full transaction object containing a payload and signatures.
9
+ class Transaction
10
+ TRANSACTION_DOMAIN_TAG = "FLOW-V0.0-transaction"
11
+
12
+ attr_accessor :script,
13
+ :arguments,
14
+ :reference_block_id,
15
+ :gas_limit,
16
+ :proposer_address,
17
+ :proposer_key_index,
18
+ :proposer_key_sequence_number,
19
+ :payer_address,
20
+ :authorizer_addresses,
21
+ :address_aliases
22
+
23
+ attr_reader :envelope_signatures, :payload_signatures
24
+
25
+ def initialize
26
+ @authorizer_addresses = []
27
+ @arguments = []
28
+ @script = ""
29
+ @gas_limit = 0
30
+ @envelope_signatures = []
31
+ @payload_signatures = []
32
+ @proposer_key_index = 0
33
+ @proposer_key_sequence_number = 0
34
+ @address_aliases = {}
35
+ end
36
+
37
+ def self.padded_transaction_domain_tag
38
+ Utils.right_pad_bytes(TRANSACTION_DOMAIN_TAG.bytes, 32).pack("c*")
39
+ end
40
+
41
+ def payload_canonical_form
42
+ [
43
+ resolved_script,
44
+ @arguments,
45
+ [@reference_block_id].pack("H*"),
46
+ @gas_limit,
47
+ padded_address(@proposer_address),
48
+ @proposer_key_index,
49
+ @proposer_key_sequence_number,
50
+ padded_address(@payer_address),
51
+ @authorizer_addresses.map { |address| padded_address(address) }
52
+ ]
53
+ end
54
+
55
+ def payload_message
56
+ payload = payload_canonical_form
57
+
58
+ # example = %w[248 114 176 116 114 97 110 115 97 99 116 105 111 110 32 123 32 101 120 101 99 117 116 101 32 123 32 108 111 103 40 34 72 101 108 108 111 44 32 87 111 114 108 100 33 34 41 32 125 32 125 192 160 72 121 153 246 93 184 142 181 159 21 71 108 105 182 234 79 105 166 51 159 166 79 128 92 248 80 65 251 159 240 90 36 100 136 243 252 210 193 167 143 94 238 128 128 136 243 252 210 193 167 143 94 238 201 136 243 252 210 193 167 143 94 238].map(&:to_i).pack("c*")
59
+ # decoded_example = RLP.decode(example)
60
+ # puts "----------"
61
+ # puts decoded_example.inspect
62
+ # puts "----------"
63
+ # puts RLP.decode(RLP.encode(payload)).inspect
64
+
65
+ # # puts Utils.left_pad_bytes(ref_block_id.bytes, 32).pack('i*').inspect
66
+ # puts RLP.decode(RLP.encode(payload)).inspect
67
+ # ref_block_id = "da8d80c775d75c86064aa0e35a418d02c83cbc198f26d906a4441a90069b63b6"
68
+ # puts [ref_block_id].pack("H*").unpack("C*")
69
+ # puts ["192440c99cb17282"].pack("H*").unpack("C*")
70
+ # # puts RLP.encode(payload).inspect
71
+
72
+ # puts RLP.encode(payload).bytes.inspect
73
+ RLP.encode(payload)
74
+ end
75
+
76
+ def envelope_canonical_form
77
+ # puts "1 !!!!!!!!!!!!!!!!!!!!!!!!!"
78
+ # puts payload_canonical_form.inspect
79
+ # puts "2 !!!!!!!!!!!!!!!!!!!!!!!!!"
80
+ # puts %w[248 117 248 114 176 116 114 97 110 115 97 99 116 105 111 110 32 123 32 101 120 101 99 117 116 101 32 123 32 108 111 103 40 34 72 101 108 108 111 44 32 87 111 114 108 100 33 34 41 32 125 32 125 192 160 72 121 153 246 93 184 142 181 159 21 71 108 105 182 234 79 105 166 51 159 166 79 128 92 248 80 65 251 159 240 90 36 100 136 243 252 210 193 167 143 94 238 128 128 136 243 252 210 193 167 143 94 238 201 136 243 252 210 193 167 143 94 238 192].map(&:to_i).pack("c*").inspect
81
+ # puts "3 !!!!!!!!!!!!!!!!!!!!!!!!!"
82
+ [
83
+ payload_canonical_form,
84
+ []
85
+ ]
86
+ end
87
+
88
+ def envelope_message
89
+ # example = %w[248 117 248 114 176 116 114 97 110 115 97 99 116 105 111 110 32 123 32 101 120 101 99 117 116 101 32 123 32 108 111 103 40 34 72 101 108 108 111 44 32 87 111 114 108 100 33 34 41 32 125 32 125 192 160 191 126 254 24 34 116 225 100 48 61 146 58 249 107 64 242 242 137 30 200 85 212 68 73 165 214 72 89 185 86 47 53 100 136 4 90 23 99 201 48 6 202 128 128 136 4 90 23 99 201 48 6 202 201 136 4 90 23 99 201 48 6 202 192].map(&:to_i).pack("c*")
90
+ # decoded_example = RLP.decode(example)
91
+ # puts "----------"
92
+ # puts decoded_example.inspect
93
+ # puts RLP.decode(RLP.encode(envelope_canonical_form)).inspect
94
+ # puts "----------"
95
+
96
+ # puts "**********"
97
+ # puts "RLP ENCODED ENVELOPE MESSAGE"
98
+ # puts "----------------"
99
+ # puts RLP.encode(envelope_canonical_form).bytes.inspect
100
+ # puts "**********"
101
+ RLP.encode(envelope_canonical_form)
102
+ end
103
+
104
+ def add_envelope_signature(signer_address, key_index, key)
105
+ domain_tagged_payload = (Transaction.padded_transaction_domain_tag.bytes + envelope_message.bytes).pack("C*")
106
+
107
+ @envelope_signatures << Entities::Transaction::Signature.new(
108
+ address: padded_address(signer_address),
109
+ key_id: key_index,
110
+ signature: FlowClient::Crypto.sign(domain_tagged_payload, key)
111
+ )
112
+ end
113
+
114
+ def to_protobuf_message
115
+ payload = payload_canonical_form
116
+ # puts envelope_signature.inspect
117
+ # puts %w[201 159 186 250 20 195 169 176 16 128 200 154 50 249 239 220 221 149 255 210 230 181 237 96 56 158 51 241 110 139 34 201 93 88 248 235 55 206 229 231 39 47 106 31 54 122 59 252 171 165 245 9 112 33 175 6 70 180 157 77 148 130 69 225].map(&:to_i).pack("c*").inspect
118
+
119
+ proposal_key = Entities::Transaction::ProposalKey.new(
120
+ address: payload[4],
121
+ key_id: payload[5],
122
+ sequence_number: payload[6]
123
+ )
124
+
125
+ Entities::Transaction.new(
126
+ script: payload[0],
127
+ arguments: payload[1],
128
+ reference_block_id: payload[2],
129
+ gas_limit: payload[3],
130
+ proposal_key: proposal_key,
131
+ payer: payload[7],
132
+ authorizers: payload[8],
133
+ payload_signatures: [],
134
+ envelope_signatures: @envelope_signatures
135
+ )
136
+ end
137
+
138
+ protected
139
+ def resolved_script
140
+ FlowClient::Utils.substitute_address_aliases(@script, @address_aliases)
141
+ end
142
+
143
+ def padded_address(address_hex_string)
144
+ Utils.left_pad_bytes([address_hex_string].pack("H*").bytes, 8).pack("C*")
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlowClient
4
+ module Utils
5
+ # Left pads a byte array with 0 to length
6
+ def self.left_pad_bytes(byte_array, length)
7
+ required_pad_count = length - byte_array.count
8
+ padding = []
9
+ (1..required_pad_count).each do |_i|
10
+ padding << 0
11
+ end
12
+ padding + byte_array
13
+ end
14
+
15
+ # Right pads a byte array with 0 to length
16
+ def self.right_pad_bytes(byte_array, length)
17
+ required_pad_count = length - byte_array.count
18
+ padding = []
19
+ (1..required_pad_count).each do |_i|
20
+ padding << 0
21
+ end
22
+ byte_array + padding
23
+ end
24
+
25
+ # Substitutes Candence import statements using aliases with addresses
26
+ # e.g. import FungibleToken from 0xFUNGIBLE_TOKEN_ADDRESS.
27
+ #
28
+ # aliases is a hash with aliases as string keys and addresses as values,
29
+ # e.g. { "0xFUNGIBLE_TOKEN_ADDRESS": "0x0" }
30
+ def self.substitute_address_aliases(script_or_transaction, aliases = {})
31
+ new_string = script_or_transaction
32
+ aliases.each do |key, value|
33
+ new_string = new_string.gsub("#{key}", "#{value}")
34
+ end
35
+ new_string
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlowClient
4
+ VERSION = "0.1.0"
5
+ end
metadata ADDED
@@ -0,0 +1,201 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flow_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nico du Plessis
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-08-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: digest-sha3
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ecdsa
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: grpc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: grpc-tools
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: json
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: openssl
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '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'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rlp
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: A Ruby client for the Flow blockchain
126
+ email:
127
+ - nico@glucode.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".github/workflows/ruby.yml"
133
+ - ".gitignore"
134
+ - ".rspec"
135
+ - ".rubocop.yml"
136
+ - CHANGELOG.md
137
+ - CODE_OF_CONDUCT.md
138
+ - Gemfile
139
+ - Gemfile.lock
140
+ - Guardfile
141
+ - LICENSE.txt
142
+ - README.md
143
+ - Rakefile
144
+ - bin/console
145
+ - bin/setup
146
+ - flow_client.gemspec
147
+ - lib/flow/access/access_pb.rb
148
+ - lib/flow/access/access_services_pb.rb
149
+ - lib/flow/entities/account_pb.rb
150
+ - lib/flow/entities/block_header_pb.rb
151
+ - lib/flow/entities/block_pb.rb
152
+ - lib/flow/entities/block_seal_pb.rb
153
+ - lib/flow/entities/collection_pb.rb
154
+ - lib/flow/entities/event_pb.rb
155
+ - lib/flow/entities/transaction_pb.rb
156
+ - lib/flow/execution/execution_pb.rb
157
+ - lib/flow/execution/execution_services_pb.rb
158
+ - lib/flow/legacy/access/access_pb.rb
159
+ - lib/flow/legacy/access/access_services_pb.rb
160
+ - lib/flow/legacy/entities/account_pb.rb
161
+ - lib/flow/legacy/entities/block_header_pb.rb
162
+ - lib/flow/legacy/entities/block_pb.rb
163
+ - lib/flow/legacy/entities/block_seal_pb.rb
164
+ - lib/flow/legacy/entities/collection_pb.rb
165
+ - lib/flow/legacy/entities/event_pb.rb
166
+ - lib/flow/legacy/entities/transaction_pb.rb
167
+ - lib/flow/legacy/execution/execution_pb.rb
168
+ - lib/flow/legacy/execution/execution_services_pb.rb
169
+ - lib/flow_client.rb
170
+ - lib/flow_client/client.rb
171
+ - lib/flow_client/crypto.rb
172
+ - lib/flow_client/transaction.rb
173
+ - lib/flow_client/utils.rb
174
+ - lib/flow_client/version.rb
175
+ homepage: https://github.com/glucode/flow_client
176
+ licenses:
177
+ - MIT
178
+ metadata:
179
+ homepage_uri: https://github.com/glucode/flow_client
180
+ source_code_uri: https://github.com/glucode/flow_client
181
+ changelog_uri: https://github.com/glucode/flow_client
182
+ post_install_message:
183
+ rdoc_options: []
184
+ require_paths:
185
+ - lib
186
+ required_ruby_version: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - ">="
189
+ - !ruby/object:Gem::Version
190
+ version: 2.6.0
191
+ required_rubygems_version: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ requirements: []
197
+ rubygems_version: 3.2.15
198
+ signing_key:
199
+ specification_version: 4
200
+ summary: A Ruby client for the Flow blockchain
201
+ test_files: []