flow-ruby 0.2.1
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
- data/.github/workflows/test.yml +23 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +26 -0
- data/CHANGELOG.md +10 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +59 -0
- data/LICENSE.txt +21 -0
- data/README.md +58 -0
- data/Rakefile +16 -0
- data/bin/console +11 -0
- data/bin/setup +6 -0
- data/flow-ruby.gemspec +38 -0
- data/lib/flow.rb +11 -0
- data/lib/flow/access/access_pb.rb +169 -0
- data/lib/flow/access/access_services_pb.rb +87 -0
- data/lib/flow/client.rb +358 -0
- data/lib/flow/entities/account_pb.rb +32 -0
- data/lib/flow/entities/block_header_pb.rb +22 -0
- data/lib/flow/entities/block_pb.rb +27 -0
- data/lib/flow/entities/block_seal_pb.rb +21 -0
- data/lib/flow/entities/collection_pb.rb +24 -0
- data/lib/flow/entities/event_pb.rb +22 -0
- data/lib/flow/entities/transaction_pb.rb +47 -0
- data/lib/flow/execution/execution_pb.rb +67 -0
- data/lib/flow/execution/execution_services_pb.rb +42 -0
- data/lib/flow/version.rb +5 -0
- metadata +180 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# Source: flow/access/access.proto for package 'flow.access'
|
3
|
+
|
4
|
+
require 'grpc'
|
5
|
+
require 'flow/access/access_pb'
|
6
|
+
|
7
|
+
module Flow
|
8
|
+
module Access
|
9
|
+
module AccessAPI
|
10
|
+
# AccessAPI is the public-facing API provided by access nodes.
|
11
|
+
class Service
|
12
|
+
|
13
|
+
include GRPC::GenericService
|
14
|
+
|
15
|
+
self.marshal_class_method = :encode
|
16
|
+
self.unmarshal_class_method = :decode
|
17
|
+
self.service_name = 'flow.access.AccessAPI'
|
18
|
+
|
19
|
+
# Ping is used to check if the access node is alive and healthy.
|
20
|
+
rpc :Ping, ::Flow::Access::PingRequest, ::Flow::Access::PingResponse
|
21
|
+
# Block Headers
|
22
|
+
#
|
23
|
+
# GetLatestBlockHeader gets the latest sealed or unsealed block header.
|
24
|
+
rpc :GetLatestBlockHeader, ::Flow::Access::GetLatestBlockHeaderRequest, ::Flow::Access::BlockHeaderResponse
|
25
|
+
# GetBlockHeaderByID gets a block header by ID.
|
26
|
+
rpc :GetBlockHeaderByID, ::Flow::Access::GetBlockHeaderByIDRequest, ::Flow::Access::BlockHeaderResponse
|
27
|
+
# GetBlockHeaderByHeight gets a block header by height.
|
28
|
+
rpc :GetBlockHeaderByHeight, ::Flow::Access::GetBlockHeaderByHeightRequest, ::Flow::Access::BlockHeaderResponse
|
29
|
+
# Blocks
|
30
|
+
#
|
31
|
+
# GetLatestBlock gets the full payload of the latest sealed or unsealed block.
|
32
|
+
rpc :GetLatestBlock, ::Flow::Access::GetLatestBlockRequest, ::Flow::Access::BlockResponse
|
33
|
+
# GetBlockByID gets a full block by ID.
|
34
|
+
rpc :GetBlockByID, ::Flow::Access::GetBlockByIDRequest, ::Flow::Access::BlockResponse
|
35
|
+
# GetBlockByHeight gets a full block by height.
|
36
|
+
rpc :GetBlockByHeight, ::Flow::Access::GetBlockByHeightRequest, ::Flow::Access::BlockResponse
|
37
|
+
# Collections
|
38
|
+
#
|
39
|
+
# GetCollectionByID gets a collection by ID.
|
40
|
+
rpc :GetCollectionByID, ::Flow::Access::GetCollectionByIDRequest, ::Flow::Access::CollectionResponse
|
41
|
+
# Transactions
|
42
|
+
#
|
43
|
+
# SendTransaction submits a transaction to the network.
|
44
|
+
rpc :SendTransaction, ::Flow::Access::SendTransactionRequest, ::Flow::Access::SendTransactionResponse
|
45
|
+
# GetTransaction gets a transaction by ID.
|
46
|
+
rpc :GetTransaction, ::Flow::Access::GetTransactionRequest, ::Flow::Access::TransactionResponse
|
47
|
+
# GetTransactionResult gets the result of a transaction.
|
48
|
+
rpc :GetTransactionResult, ::Flow::Access::GetTransactionRequest, ::Flow::Access::TransactionResultResponse
|
49
|
+
# Accounts
|
50
|
+
#
|
51
|
+
# GetAccount is an alias for GetAccountAtLatestBlock.
|
52
|
+
#
|
53
|
+
# Warning: this function is deprecated. It behaves identically to GetAccountAtLatestBlock and will be removed in a future version.
|
54
|
+
rpc :GetAccount, ::Flow::Access::GetAccountRequest, ::Flow::Access::GetAccountResponse
|
55
|
+
# GetAccountAtLatestBlock gets an account by address from the latest sealed execution state.
|
56
|
+
rpc :GetAccountAtLatestBlock, ::Flow::Access::GetAccountAtLatestBlockRequest, ::Flow::Access::AccountResponse
|
57
|
+
# GetAccountAtBlockHeight gets an account by address at the given block height
|
58
|
+
rpc :GetAccountAtBlockHeight, ::Flow::Access::GetAccountAtBlockHeightRequest, ::Flow::Access::AccountResponse
|
59
|
+
# Scripts
|
60
|
+
#
|
61
|
+
# ExecuteScriptAtLatestBlock executes a read-only Cadence script against the latest sealed execution state.
|
62
|
+
rpc :ExecuteScriptAtLatestBlock, ::Flow::Access::ExecuteScriptAtLatestBlockRequest, ::Flow::Access::ExecuteScriptResponse
|
63
|
+
# ExecuteScriptAtBlockID executes a ready-only Cadence script against the execution state at the block with the given ID.
|
64
|
+
rpc :ExecuteScriptAtBlockID, ::Flow::Access::ExecuteScriptAtBlockIDRequest, ::Flow::Access::ExecuteScriptResponse
|
65
|
+
# ExecuteScriptAtBlockHeight executes a ready-only Cadence script against the execution state at the given block height.
|
66
|
+
rpc :ExecuteScriptAtBlockHeight, ::Flow::Access::ExecuteScriptAtBlockHeightRequest, ::Flow::Access::ExecuteScriptResponse
|
67
|
+
# Events
|
68
|
+
#
|
69
|
+
# GetEventsForHeightRange retrieves events emitted within the specified block range.
|
70
|
+
rpc :GetEventsForHeightRange, ::Flow::Access::GetEventsForHeightRangeRequest, ::Flow::Access::EventsResponse
|
71
|
+
# GetEventsForBlockIDs retrieves events for the specified block IDs and event type.
|
72
|
+
rpc :GetEventsForBlockIDs, ::Flow::Access::GetEventsForBlockIDsRequest, ::Flow::Access::EventsResponse
|
73
|
+
# NetworkParameters
|
74
|
+
#
|
75
|
+
# GetNetworkParameters retrieves the Flow network details
|
76
|
+
rpc :GetNetworkParameters, ::Flow::Access::GetNetworkParametersRequest, ::Flow::Access::GetNetworkParametersResponse
|
77
|
+
# ProtocolState
|
78
|
+
#
|
79
|
+
# GetLatestProtocolStateSnapshot retrieves the latest sealed protocol state snapshot.
|
80
|
+
# Used by Flow nodes joining the network to bootstrap a space-efficient local state.
|
81
|
+
rpc :GetLatestProtocolStateSnapshot, ::Flow::Access::GetLatestProtocolStateSnapshotRequest, ::Flow::Access::ProtocolStateSnapshotResponse
|
82
|
+
end
|
83
|
+
|
84
|
+
Stub = Service.rpc_stub_class
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/flow/client.rb
ADDED
@@ -0,0 +1,358 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Flow
|
4
|
+
#
|
5
|
+
# The client class is used to access the Flow API
|
6
|
+
#
|
7
|
+
class Client
|
8
|
+
NODES = {
|
9
|
+
mainnet: "access.mainnet.nodes.onflow.org:9000",
|
10
|
+
testnet: "access.devnet.nodes.onflow.org:9000",
|
11
|
+
canarynet: "access.canary.nodes.onflow.org:9000"
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
#
|
15
|
+
# @param node [Symbol, String] the node address used in the stub
|
16
|
+
#
|
17
|
+
def initialize(node: :mainnet)
|
18
|
+
@stub = Access::AccessAPI::Stub.new(detect_node(node), :this_channel_is_insecure)
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Check if the Access API is ready and available
|
23
|
+
#
|
24
|
+
# @return [Flow::Access::PingResponse]
|
25
|
+
#
|
26
|
+
def ping
|
27
|
+
@stub.ping(Access::PingRequest.new)
|
28
|
+
end
|
29
|
+
|
30
|
+
####
|
31
|
+
# Block Headers
|
32
|
+
#
|
33
|
+
# The following methods query information about block headers
|
34
|
+
####
|
35
|
+
|
36
|
+
#
|
37
|
+
# Get the latest sealed or unsealed block header
|
38
|
+
#
|
39
|
+
# @param is_sealed [Boolean]
|
40
|
+
#
|
41
|
+
# @return [Flow::Entities::BlockHeader]
|
42
|
+
#
|
43
|
+
def get_latest_block_header(is_sealed: false)
|
44
|
+
req = Access::GetLatestBlockHeaderRequest.new(is_sealed: is_sealed)
|
45
|
+
res = @stub.get_latest_block_header(req)
|
46
|
+
res.block
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Get a block header by ID
|
51
|
+
#
|
52
|
+
# @todo The ID should be +bytes+ or it should be formatted automatically
|
53
|
+
#
|
54
|
+
# @param id [String]
|
55
|
+
#
|
56
|
+
# @return [Flow::Entities::BlockHeader]
|
57
|
+
#
|
58
|
+
def get_block_header_by_id(id)
|
59
|
+
req = Access::GetBlockHeaderByIDRequest.new(id: id)
|
60
|
+
res = @stub.get_block_header_by_id(req)
|
61
|
+
res.block
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Get a block header by height
|
66
|
+
#
|
67
|
+
# @param height [uint64]
|
68
|
+
#
|
69
|
+
# @return [Flow::Entities::BlockHeader]
|
70
|
+
#
|
71
|
+
def get_block_header_by_height(height)
|
72
|
+
req = Access::GetBlockHeaderByHeightRequest.new(height: height)
|
73
|
+
res = @stub.get_block_header_by_height(req)
|
74
|
+
res.block
|
75
|
+
end
|
76
|
+
|
77
|
+
####
|
78
|
+
# Blocks
|
79
|
+
#
|
80
|
+
# The following methods query information about full blocks
|
81
|
+
####
|
82
|
+
|
83
|
+
#
|
84
|
+
# Get the full payload of the latest sealed or unsealed block
|
85
|
+
#
|
86
|
+
# @param is_sealed [Boolean]
|
87
|
+
#
|
88
|
+
# @return [Flow::Entities::Block]
|
89
|
+
#
|
90
|
+
def get_latest_block(is_sealed: false)
|
91
|
+
req = Access::GetLatestBlockRequest.new(is_sealed: is_sealed)
|
92
|
+
res = @stub.get_latest_block(req)
|
93
|
+
res.block
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Get a full block by ID
|
98
|
+
#
|
99
|
+
# @todo The ID should be +bytes+ or it should be formatted automatically
|
100
|
+
#
|
101
|
+
# @param id [String]
|
102
|
+
#
|
103
|
+
# @return [Flow::Entities::Block]
|
104
|
+
#
|
105
|
+
def get_block_by_id(id)
|
106
|
+
req = Access::GetBlockByIDRequest.new(id: id)
|
107
|
+
res = @stub.get_block_by_id(req)
|
108
|
+
res.block
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Get a full block by height
|
113
|
+
#
|
114
|
+
# @param height [uint64]
|
115
|
+
#
|
116
|
+
# @return [Flow::Entities::Block]
|
117
|
+
#
|
118
|
+
def get_block_by_height(height)
|
119
|
+
req = Access::GetBlockByHeightRequest.new(height: height)
|
120
|
+
res = @stub.get_block_by_height(req)
|
121
|
+
res.block
|
122
|
+
end
|
123
|
+
|
124
|
+
####
|
125
|
+
# Collections
|
126
|
+
#
|
127
|
+
# The following methods query information about collections
|
128
|
+
####
|
129
|
+
|
130
|
+
#
|
131
|
+
# Gets a collection by ID
|
132
|
+
#
|
133
|
+
# @todo The ID should be +bytes+ or it should be formatted automatically
|
134
|
+
#
|
135
|
+
# @param id [String]
|
136
|
+
#
|
137
|
+
# @return [Flow::Entities::Collection]
|
138
|
+
#
|
139
|
+
def get_collection_by_id(id)
|
140
|
+
req = Access::GetCollectionByIDRequest.new(id: id)
|
141
|
+
res = @stub.get_collection_by_id(req)
|
142
|
+
res.collection
|
143
|
+
end
|
144
|
+
|
145
|
+
####
|
146
|
+
# Transactions
|
147
|
+
#
|
148
|
+
# The following methods can be used to submit transactions and fetch their results
|
149
|
+
####
|
150
|
+
|
151
|
+
#
|
152
|
+
# Submit a transaction to the network
|
153
|
+
#
|
154
|
+
#
|
155
|
+
#
|
156
|
+
#
|
157
|
+
# def send_transaction()
|
158
|
+
# # TODO: build and sign transaction here
|
159
|
+
# # req = Access::SendTransactionRequest.new()
|
160
|
+
# # @stub.send_transaction(req)
|
161
|
+
# end
|
162
|
+
|
163
|
+
#
|
164
|
+
# Get a transaction by ID
|
165
|
+
#
|
166
|
+
# @todo The ID should be +bytes+ or it should be formatted automatically
|
167
|
+
#
|
168
|
+
# @param id [String]
|
169
|
+
#
|
170
|
+
# @return [Flow::Entities::Transaction]
|
171
|
+
#
|
172
|
+
def get_transaction(id)
|
173
|
+
req = Access::GetTransactionRequest.new(id: id)
|
174
|
+
res = @stub.get_transaction(req)
|
175
|
+
res.transaction
|
176
|
+
end
|
177
|
+
|
178
|
+
#
|
179
|
+
# Get the execution result of a transaction
|
180
|
+
#
|
181
|
+
# @todo The ID should be +bytes+ or it should be formatted automatically
|
182
|
+
# @todo We might want to change the return value here, TransactionReturnResponse has
|
183
|
+
# these available keys: status, status_code, error_message, events
|
184
|
+
#
|
185
|
+
# @param id [String]
|
186
|
+
#
|
187
|
+
# @return [Flow::Access::TransactionResultResponse]
|
188
|
+
#
|
189
|
+
def get_transaction_result(id)
|
190
|
+
req = Access::GetTransactionRequest.new(id: id)
|
191
|
+
@stub.get_transaction_result(req)
|
192
|
+
end
|
193
|
+
|
194
|
+
####
|
195
|
+
# Accounts
|
196
|
+
####
|
197
|
+
|
198
|
+
#
|
199
|
+
# Get an account by address
|
200
|
+
#
|
201
|
+
# @param address [String]
|
202
|
+
#
|
203
|
+
# @return [Flow::Entities::Account]
|
204
|
+
#
|
205
|
+
def get_account_at_latest_block(address)
|
206
|
+
req = Access::GetAccountAtLatestBlockRequest.new(address: to_bytes(address))
|
207
|
+
res = @stub.get_account_at_latest_block(req)
|
208
|
+
res.account
|
209
|
+
end
|
210
|
+
|
211
|
+
#
|
212
|
+
# Get an account by address at the given block height
|
213
|
+
#
|
214
|
+
# @param address [String]
|
215
|
+
# @param block_height [uint64]
|
216
|
+
#
|
217
|
+
# @return [Flow::Entities::Account]
|
218
|
+
#
|
219
|
+
def get_account_at_block_height(address, block_height)
|
220
|
+
req = Access::GetAccountAtBlockHeightRequest.new(
|
221
|
+
address: to_bytes(address),
|
222
|
+
block_height: block_height
|
223
|
+
)
|
224
|
+
|
225
|
+
res = @stub.get_account_at_latest_block(req)
|
226
|
+
res.account
|
227
|
+
end
|
228
|
+
|
229
|
+
####
|
230
|
+
# Scripts
|
231
|
+
####
|
232
|
+
|
233
|
+
#
|
234
|
+
# Execute a read-only Cadence script against the latest sealed execution state
|
235
|
+
#
|
236
|
+
# @param script [String] cadence script
|
237
|
+
# @param args [Array] array of args
|
238
|
+
#
|
239
|
+
# @return [OpenStruct]
|
240
|
+
#
|
241
|
+
def execute_script(script, args = [])
|
242
|
+
req = Access::ExecuteScriptAtLatestBlockRequest.new(
|
243
|
+
script: script,
|
244
|
+
arguments: args
|
245
|
+
)
|
246
|
+
|
247
|
+
res = @stub.execute_script_at_latest_block(req)
|
248
|
+
parse_json(res.value)
|
249
|
+
end
|
250
|
+
|
251
|
+
####
|
252
|
+
# Events
|
253
|
+
#
|
254
|
+
# The following methods can be used to query for on-chain events
|
255
|
+
####
|
256
|
+
|
257
|
+
#
|
258
|
+
# Retrieve events emitted within the specified block range
|
259
|
+
#
|
260
|
+
# @todo Scope the response further
|
261
|
+
#
|
262
|
+
# @param type [String]
|
263
|
+
# @param start_height [uint64]
|
264
|
+
# @param end_height [uint64]
|
265
|
+
#
|
266
|
+
# @return [EventsResponse]
|
267
|
+
#
|
268
|
+
def get_events_for_height_range(type, start_height: 2, end_height: 3)
|
269
|
+
req = Access::GetEventsForHeightRangeRequest.new(
|
270
|
+
type: type,
|
271
|
+
start_height: start_height,
|
272
|
+
end_height: end_height
|
273
|
+
)
|
274
|
+
|
275
|
+
@stub.get_events_for_height_range(req)
|
276
|
+
end
|
277
|
+
|
278
|
+
#
|
279
|
+
# Retrieve events for the specified block IDs and event type
|
280
|
+
#
|
281
|
+
# @todo Scope the response further
|
282
|
+
#
|
283
|
+
# @param type [String]
|
284
|
+
# @param block_ids [Array]
|
285
|
+
#
|
286
|
+
# @return [EventsResponse]
|
287
|
+
#
|
288
|
+
def get_events_for_block_ids(type, block_ids = [])
|
289
|
+
req = Access::GetEventsForBlockIDsRequest.new(
|
290
|
+
type: type,
|
291
|
+
block_ids: block_ids
|
292
|
+
)
|
293
|
+
|
294
|
+
@stub.get_events_for_block_ids(req)
|
295
|
+
end
|
296
|
+
|
297
|
+
####
|
298
|
+
# Network Parameters
|
299
|
+
#
|
300
|
+
# Network parameters provide information about the Flow network.
|
301
|
+
# Currently, it only includes the chain ID.
|
302
|
+
# The following method can be used to query for network parameters
|
303
|
+
####
|
304
|
+
|
305
|
+
#
|
306
|
+
# Retrieve the network parameters
|
307
|
+
#
|
308
|
+
# @return [Hash]
|
309
|
+
#
|
310
|
+
def get_network_parameters
|
311
|
+
req = Access::GetNetworkParametersRequest.new
|
312
|
+
res = @stub.get_network_parameters(req)
|
313
|
+
res.to_h
|
314
|
+
end
|
315
|
+
|
316
|
+
####
|
317
|
+
# Protocol state snapshot
|
318
|
+
#
|
319
|
+
# The following method can be used to query the latest protocol state snapshot
|
320
|
+
####
|
321
|
+
|
322
|
+
#
|
323
|
+
# Retrieve the latest Protocol state snapshot serialized as a byte array.
|
324
|
+
# It is used by Flow nodes joining the network to bootstrap a space-efficient local state
|
325
|
+
#
|
326
|
+
# @todo Fix. This currently fails with unimplemented_error
|
327
|
+
#
|
328
|
+
# @return
|
329
|
+
#
|
330
|
+
def get_latest_protocol_state_snapshot
|
331
|
+
req = Access::GetLatestProtocolStateSnapshotRequest.new
|
332
|
+
@stub.get_latest_protocol_state_snapshot(req)
|
333
|
+
end
|
334
|
+
|
335
|
+
private
|
336
|
+
|
337
|
+
def detect_node(node)
|
338
|
+
case node.to_sym
|
339
|
+
when :mainnet then NODES[:mainnet]
|
340
|
+
when :testnet then NODES[:testnet]
|
341
|
+
when :canarynet then NODES[:canarynet]
|
342
|
+
else node
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
def parse_json(event_payload)
|
347
|
+
JSON.parse(event_payload, object_class: OpenStruct)
|
348
|
+
end
|
349
|
+
|
350
|
+
def to_bytes(string)
|
351
|
+
[string].pack("H*")
|
352
|
+
end
|
353
|
+
|
354
|
+
def to_string(bytes)
|
355
|
+
bytes.unpack1("H*")
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: flow/entities/account.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
7
|
+
add_file("flow/entities/account.proto", :syntax => :proto3) do
|
8
|
+
add_message "flow.entities.Account" do
|
9
|
+
optional :address, :bytes, 1
|
10
|
+
optional :balance, :uint64, 2
|
11
|
+
optional :code, :bytes, 3
|
12
|
+
repeated :keys, :message, 4, "flow.entities.AccountKey"
|
13
|
+
map :contracts, :string, :bytes, 5
|
14
|
+
end
|
15
|
+
add_message "flow.entities.AccountKey" do
|
16
|
+
optional :index, :uint32, 1
|
17
|
+
optional :public_key, :bytes, 2
|
18
|
+
optional :sign_algo, :uint32, 3
|
19
|
+
optional :hash_algo, :uint32, 4
|
20
|
+
optional :weight, :uint32, 5
|
21
|
+
optional :sequence_number, :uint32, 6
|
22
|
+
optional :revoked, :bool, 7
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Flow
|
28
|
+
module Entities
|
29
|
+
Account = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flow.entities.Account").msgclass
|
30
|
+
AccountKey = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flow.entities.AccountKey").msgclass
|
31
|
+
end
|
32
|
+
end
|