flow_client 0.2.3-arm64-darwin-21

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +37 -0
  3. data/.gitignore +13 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +26 -0
  6. data/CHANGELOG.md +24 -0
  7. data/CODE_OF_CONDUCT.md +84 -0
  8. data/Gemfile +12 -0
  9. data/Gemfile.lock +114 -0
  10. data/Guardfile +79 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +747 -0
  13. data/Rakefile +12 -0
  14. data/bin/console +15 -0
  15. data/bin/setup +8 -0
  16. data/docker-compose.yml +12 -0
  17. data/flow.json +21 -0
  18. data/flow_client.gemspec +44 -0
  19. data/lib/cadence/contracts/NonFungibleToken.cdc +144 -0
  20. data/lib/cadence/templates/add-account-key.cdc +16 -0
  21. data/lib/cadence/templates/add-contract.cdc +5 -0
  22. data/lib/cadence/templates/create-account.cdc +21 -0
  23. data/lib/cadence/templates/remove-contract.cdc +5 -0
  24. data/lib/cadence/templates/update-contract.cdc +5 -0
  25. data/lib/flow/access/access_pb.rb +168 -0
  26. data/lib/flow/access/access_services_pb.rb +96 -0
  27. data/lib/flow/entities/account_pb.rb +30 -0
  28. data/lib/flow/entities/block_header_pb.rb +20 -0
  29. data/lib/flow/entities/block_pb.rb +25 -0
  30. data/lib/flow/entities/block_seal_pb.rb +19 -0
  31. data/lib/flow/entities/collection_pb.rb +23 -0
  32. data/lib/flow/entities/event_pb.rb +20 -0
  33. data/lib/flow/entities/transaction_pb.rb +47 -0
  34. data/lib/flow/execution/execution_pb.rb +65 -0
  35. data/lib/flow/execution/execution_services_pb.rb +43 -0
  36. data/lib/flow/legacy/access/access_pb.rb +157 -0
  37. data/lib/flow/legacy/access/access_services_pb.rb +89 -0
  38. data/lib/flow/legacy/entities/account_pb.rb +28 -0
  39. data/lib/flow/legacy/entities/block_header_pb.rb +20 -0
  40. data/lib/flow/legacy/entities/block_pb.rb +25 -0
  41. data/lib/flow/legacy/entities/block_seal_pb.rb +19 -0
  42. data/lib/flow/legacy/entities/collection_pb.rb +22 -0
  43. data/lib/flow/legacy/entities/event_pb.rb +20 -0
  44. data/lib/flow/legacy/entities/transaction_pb.rb +45 -0
  45. data/lib/flow/legacy/execution/execution_pb.rb +65 -0
  46. data/lib/flow/legacy/execution/execution_services_pb.rb +42 -0
  47. data/lib/flow_client/account.rb +31 -0
  48. data/lib/flow_client/block.rb +81 -0
  49. data/lib/flow_client/cadence_type.rb +185 -0
  50. data/lib/flow_client/client.rb +387 -0
  51. data/lib/flow_client/collection.rb +35 -0
  52. data/lib/flow_client/crypto.rb +62 -0
  53. data/lib/flow_client/event.rb +52 -0
  54. data/lib/flow_client/proposal_key.rb +23 -0
  55. data/lib/flow_client/signature.rb +23 -0
  56. data/lib/flow_client/signer.rb +22 -0
  57. data/lib/flow_client/transaction.rb +190 -0
  58. data/lib/flow_client/utils.rb +67 -0
  59. data/lib/flow_client/version.rb +5 -0
  60. data/lib/flow_client.rb +22 -0
  61. data/logo.svg +121 -0
  62. data/logo@2x.png +0 -0
  63. data/template.md +748 -0
  64. metadata +192 -0
data/README.md ADDED
@@ -0,0 +1,747 @@
1
+ <br />
2
+ <div align="center">
3
+ <a href="">
4
+ <img src="./logo@2x.png" alt="Logo" width="300" height="auto">
5
+ </a>
6
+ <p align="center"> <br />
7
+ <a href=""><strong>View on GitHub »</strong></a> <br /><br />
8
+ <a href="https://docs.onflow.org/sdk-guidelines/">SDK Specifications</a> ·
9
+ <a href="https://github.com/glucode/flow_client">Contribute</a> ·
10
+ <a href="https://github.com/glucode/flow_client">Report a Bug</a>
11
+ </p>
12
+ </div><br />
13
+
14
+ ## Overview
15
+
16
+ This reference documents all the methods available in the SDK, and explains in detail how these methods work.
17
+ SDKs are open source, and you can use them according to the licence.
18
+
19
+ The library client specifications can be found here:
20
+
21
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://github.com/glucode/flow_client)
22
+
23
+
24
+ ## Getting Started
25
+
26
+ ### Installing
27
+
28
+ ```bash
29
+ gem install flow_client
30
+ ```
31
+
32
+ Or using Bundler
33
+
34
+ ```bash
35
+ gem 'flow_client'
36
+ ```
37
+
38
+ ### Importing the Library
39
+
40
+ ```ruby
41
+ require 'flow_client'
42
+ ```
43
+
44
+ ## Connect
45
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://github.com/glucode/flow_client)
46
+
47
+ The library uses gRPC to communicate with the access nodes and it must be configured with correct access node API URL.
48
+
49
+ 📖 **Access API URLs** can be found [here](https://docs.onflow.org/access-api/#flow-access-node-endpoints). An error will be returned if the host is unreachable.
50
+ The Access Nodes APIs hosted by DapperLabs are accessible at:
51
+ - Testnet `access.devnet.nodes.onflow.org:9000`
52
+ - Mainnet `access.mainnet.nodes.onflow.org:9000`
53
+ - Local Emulator `127.0.0.1:3569`
54
+
55
+ Example:
56
+
57
+ ```ruby
58
+ client = FlowClient::Client.new("access.devnet.nodes.onflow.org:9000")
59
+ res = client.ping
60
+ ```
61
+ ## Querying the Flow Network
62
+ After you have established a connection with an access node, you can query the Flow network to retrieve data about blocks, accounts, events and transactions. We will explore how to retrieve each of these entities in the sections below.
63
+
64
+ ### Get Blocks
65
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient/Client)
66
+
67
+ Query the network for block by id, height or get the latest block.
68
+
69
+ 📖 **Block ID** is SHA3-256 hash of the entire block payload. This hash is stored as an ID field on any block response object (ie. response from `GetLatestBlock`).
70
+
71
+ 📖 **Block height** expresses the height of the block on the chain. The latest block height increases by one for every valid block produced.
72
+
73
+ #### Examples
74
+
75
+ This example depicts ways to get the latest block as well as any other block by height or ID:
76
+
77
+ ```ruby
78
+ latest_block = client.get_latest_block
79
+ ```
80
+
81
+ ```ruby
82
+ id = client.get_latest_block.id
83
+ block = client.get_block_by_id(id)
84
+ ```
85
+
86
+ ```ruby
87
+ height = client.get_latest_block.height
88
+ block = client.get_block_by_height(height)
89
+ ```
90
+
91
+ Result output:
92
+ ```ruby
93
+ #<FlowClient::Block:0x00007faf13343928
94
+ @block_seals=[#<FlowClient::BlockSeal:0x00007faf13340b38 @block_id="306155440eabad2296bec00804f896eb29866f6d4a3a508ec08d233b4951f0da", @execution_receipt_id="79f37a11f3cdeb5ad43a014961b0f6411f36ec5e5c8a4ce6a39395dc6e010a7e", @execution_receipt_signatures=[], @result_approval_signatures=[]>],
95
+ @collection_guarantees=
96
+ [#<FlowClient::CollectionGuarantee:0x00007faf13342550 @collection_id="4fad4fd2cce61825102343dfb1d271e1884a72b3a97a01edbcb787b97c82055d", @signatures=["b2a76b5ad5d202438881e3ae5350a037cb1dbc11a2e3c2e359a62e52715685cde99d3635904381db831e471f49abf7a7"]>,
97
+ #<FlowClient::CollectionGuarantee:0x00007faf13341da8 @collection_id="fd414c7466bc72ad7bb62bb94760105d6c5724fe16b0f25de5b38ed80d06b213", @signatures=["801cdac059686a29c4258c004e40c8bbcc88ce6ce626a0e85664cdf3e77ec9d326bdecf734f826ab48409005b8dfda97"]>,
98
+ #<FlowClient::CollectionGuarantee:0x00007faf133415d8 @collection_id="c5482e4162d13308f0603c12924c5fe1efde924ab59bb1fe2bd5d7aaf475bf44", @signatures=["851c5dd521b4567029cfaa9ee3bbc6065ed205ae17ac7480f97887f97dea2fdc176c2acf70f9a97338498ecec07d428c"]>],
99
+ @height=49992170,
100
+ @id="7034b19b6d11b1b078f6d12bba557c923d21681603c0168e9cd32661edb667cb",
101
+ @parent_id="c0cd19c8c6ce5a8170f8a8776dc66c4e697741150115fb4ad0a3b91d8def0672",
102
+ @signatures=["919f93cb66f11f88b86aec9e89cbb66aebe5846a9246f04661cf9094c8bb5e1e7e89da3f0d688b0e27b31cec551f2f89aa755aabed5b44ba0c2cc6e87c72eba2a33d64219df0ee4185ed9ce78f77721d519f3c6bebe0c95bffc9a98ff706001d"],
103
+ @timestamp=2021-11-03 09:00:38.000037 +0200>
104
+ ```
105
+
106
+ ### Get Account
107
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient%2FClient:get_account)
108
+
109
+ Retrieve any account from Flow network's latest block or from a specified block height.
110
+
111
+ 📖 **Account address** is a unique account identifier. Be mindful about the `0x` prefix, you should use the prefix as a default representation but be careful and safely handle user inputs without the prefix.
112
+
113
+ An account includes the following data:
114
+ - Address: the account address.
115
+ - Balance: balance of the account.
116
+ - Contracts: list of contracts deployed to the account.
117
+ - Keys: list of keys associated with the account.
118
+
119
+ #### Examples
120
+ Example depicts ways to get an account at the latest block and at a specific block height:
121
+
122
+ ```ruby
123
+ account = client.get_account("01cf0e2f2f715450")
124
+ ```
125
+ Result output:
126
+ ```ruby
127
+ #<FlowClient::Account:0x00007f84eb281ac8
128
+ @address="01cf0e2f2f715450",
129
+ @balance=0.001,
130
+ @contracts={},
131
+ @keys=[#<FlowClient::AccountKey:0x00007f84eb281848 @hash_algo="SHA3-256", @index=0, @public_key="6f489d349fee5a0436cac0605820429907b05eb772c194ebf429d71caee70d2b2499be9e6c4e17d81f157466ac3d793b217fd091e89a172b11cac81d2378385b", @revoked=false, @sequence_number=0, @weight=1000>]>
132
+ ```
133
+
134
+
135
+ ### Get Transactions
136
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient/Client#get_transaction-instance_method)
137
+
138
+ Retrieve transactions from the network by providing a transaction ID. After a transaction has been submitted, you can also get the transaction result to check the status.
139
+
140
+ 📖 **Transaction ID** is a hash of the encoded transaction payload and can be calculated before submitting the transaction to the network.
141
+
142
+ ⚠️ The transaction ID provided must be from the current spork.
143
+
144
+ 📖 **Transaction status** represents the state of transaction in the blockchain. Status can change until is finalized.
145
+
146
+ | Status | Final | Description |
147
+ | ----------- | ----------- | ----------- |
148
+ | UNKNOWN | ❌ | The transaction has not yet been seen by the network |
149
+ | PENDING | ❌ | The transaction has not yet been included in a block |
150
+ | FINALIZED | ❌ | The transaction has been included in a block |
151
+ | EXECUTED | ❌ | The transaction has been executed but the result has not yet been sealed |
152
+ | SEALED | ✅ | The transaction has been executed and the result is sealed in a block |
153
+ | EXPIRED | ✅ | The transaction reference block is outdated before being executed |
154
+
155
+
156
+ ```ruby
157
+ transaction = client.get_transaction("d46e54de8c34dfe58a22c15d24689d1ad255f67bb9868605fcac28417aa54a37")
158
+ ```
159
+
160
+ Example output:
161
+ ```ruby
162
+ #<FlowClient::Transaction:0x00007fad65ad54e8
163
+ @address_aliases={},
164
+ @arguments=[],
165
+ @authorizer_addresses=["8940baba1178d9ab"],
166
+ @envelope_signatures=[#<FlowClient::Signature:0x00007fad65ad4b10 @address="8940baba1178d9ab", @key_id=0, @signature="36260a6ea5c487c3b68becb6d88e012a8b25b76a0835881281c4ee37a56eeafad7bce02a4bbe8f0123e7a4e6866143aecae348dc5ad7fdebb7cb2a54757ba950">],
167
+ @gas_limit=9999,
168
+ @payer_address="8940baba1178d9ab",
169
+ @payload_signatures=[],
170
+ @proposal_key=#<FlowClient::ProposalKey:0x00007fad65acfd18 @address="8940baba1178d9ab", @key_id=0, @sequence_number=135>,
171
+ @reference_block_id="8f483b7c18ca1f52ee55777b612b61dfbd2f07584db9209b1441d6fbdf31fc51",
172
+ @script=
173
+ "import NonFungibleToken from 0x631e88ae7f1d7c20\nimport SturdyItems from 0xfafb022e4e45634b\n\n// This transaction configures an account to hold Sturdy Items.\n\ntransaction {\n prepare(signer: AuthAccount) {\n \n \t\tlog(\"Hello, World!\")\n log(signer.address)\n // if the account doesn't already have a collection\n if signer.borrow<&SturdyItems.Collection>(from: SturdyItems.CollectionStoragePath) == nil {\n\n // create a new empty collection\n let collection <- SturdyItems.createEmptyCollection()\n \n // save it to the account\n signer.save(<-collection, to: SturdyItems.CollectionStoragePath)\n\n // create a public capability for the collection\n signer.link<&SturdyItems.Collection{NonFungibleToken.CollectionPublic, SturdyItems.SturdyItemsCollectionPublic}>(SturdyItems.CollectionPublicPath, target: SturdyItems.CollectionStoragePath)\n }\n }\n}",
174
+ @signers={}>
175
+ ```
176
+
177
+ ```ruby
178
+ transaction_result = client.get_transaction_result("84c8732a6cef4b66e74cef4492af9fadd3379b9d8a31b97217c5b81640288424")
179
+ ```
180
+
181
+ Example output:
182
+ ```ruby
183
+ #<FlowClient::TransactionResult:0x00007f9bf425f7c8
184
+ @block_id="0000000000000000000000000000000000000000000000000000000000000000",
185
+ @error_message="",
186
+ @events=
187
+ [#<FlowClient::Event:0x00007f9bf425e968
188
+ @event_index=0,
189
+ @payload="{\"type\":\"Event\",\"value\":{\"id\":\"A.0ae53cb6e3f42a79.FlowToken.TokensWithdrawn\",\"fields\":[{\"name\":\"amount\",\"value\":{\"type\":\"UFix64\",\"value\":\"0.00100000\"}},{\"name\":\"from\",\"value\":{\"type\":\"Optional\",\"value\":{\"type\":\"Address\",\"value\":\"0xf8d6e0586b0a20c7\"}}}]}}\n",
190
+ @transaction_id="eee1fe5350ea47f0f88b2b742d9487f48026b97f3983b6fd4c7b03ced888d326",
191
+ @transaction_index=1,
192
+ @type="A.0ae53cb6e3f42a79.FlowToken.TokensWithdrawn">,
193
+ #<FlowClient::Event:0x00007f9bf425e6c0
194
+ @event_index=1,
195
+ @payload="{\"type\":\"Event\",\"value\":{\"id\":\"A.0ae53cb6e3f42a79.FlowToken.TokensWithdrawn\",\"fields\":[{\"name\":\"amount\",\"value\":{\"type\":\"UFix64\",\"value\":\"0.00100000\"}},{\"name\":\"from\",\"value\":{\"type\":\"Optional\",\"value\":null}}]}}\n",
196
+ @transaction_id="eee1fe5350ea47f0f88b2b742d9487f48026b97f3983b6fd4c7b03ced888d326",
197
+ @transaction_index=1,
198
+ @type="A.0ae53cb6e3f42a79.FlowToken.TokensWithdrawn">,
199
+ #<FlowClient::Event:0x00007f9bf425e170
200
+ @event_index=2,
201
+ @payload="{\"type\":\"Event\",\"value\":{\"id\":\"A.0ae53cb6e3f42a79.FlowToken.TokensDeposited\",\"fields\":[{\"name\":\"amount\",\"value\":{\"type\":\"UFix64\",\"value\":\"0.00000000\"}},{\"name\":\"to\",\"value\":{\"type\":\"Optional\",\"value\":{\"type\":\"Address\",\"value\":\"0xe5a8b7f23e8b548f\"}}}]}}\n",
202
+ @transaction_id="eee1fe5350ea47f0f88b2b742d9487f48026b97f3983b6fd4c7b03ced888d326",
203
+ @transaction_index=1,
204
+ @type="A.0ae53cb6e3f42a79.FlowToken.TokensDeposited">,
205
+ #<FlowClient::Event:0x00007f9bf425e080
206
+ @event_index=3,
207
+ @payload="{\"type\":\"Event\",\"value\":{\"id\":\"A.e5a8b7f23e8b548f.FlowFees.TokensDeposited\",\"fields\":[{\"name\":\"amount\",\"value\":{\"type\":\"UFix64\",\"value\":\"0.00000000\"}}]}}\n",
208
+ @transaction_id="eee1fe5350ea47f0f88b2b742d9487f48026b97f3983b6fd4c7b03ced888d326",
209
+ @transaction_index=1,
210
+ @type="A.e5a8b7f23e8b548f.FlowFees.TokensDeposited">,
211
+ #<FlowClient::Event:0x00007f9bf425df68
212
+ @event_index=4,
213
+ @payload="{\"type\":\"Event\",\"value\":{\"id\":\"A.0ae53cb6e3f42a79.FlowToken.TokensDeposited\",\"fields\":[{\"name\":\"amount\",\"value\":{\"type\":\"UFix64\",\"value\":\"0.00100000\"}},{\"name\":\"to\",\"value\":{\"type\":\"Optional\",\"value\":{\"type\":\"Address\",\"value\":\"0x01cf0e2f2f715450\"}}}]}}\n",
214
+ @transaction_id="eee1fe5350ea47f0f88b2b742d9487f48026b97f3983b6fd4c7b03ced888d326",
215
+ @transaction_index=1,
216
+ @type="A.0ae53cb6e3f42a79.FlowToken.TokensDeposited">,
217
+ #<FlowClient::Event:0x00007f9bf425de78
218
+ @event_index=5,
219
+ @payload="{\"type\":\"Event\",\"value\":{\"id\":\"flow.AccountCreated\",\"fields\":[{\"name\":\"address\",\"value\":{\"type\":\"Address\",\"value\":\"0x01cf0e2f2f715450\"}}]}}\n",
220
+ @transaction_id="eee1fe5350ea47f0f88b2b742d9487f48026b97f3983b6fd4c7b03ced888d326",
221
+ @transaction_index=1,
222
+ @type="flow.AccountCreated">,
223
+ #<FlowClient::Event:0x00007f9bf425d950
224
+ @event_index=6,
225
+ @payload=
226
+ "{\"type\":\"Event\",\"value\":{\"id\":\"flow.AccountKeyAdded\",\"fields\":[{\"name\":\"address\",\"value\":{\"type\":\"Address\",\"value\":\"0x01cf0e2f2f715450\"}},{\"name\":\"publicKey\",\"value\":{\"type\":\"Struct\",\"value\":{\"id\":\"PublicKey\",\"fields\":[{\"name\":\"publicKey\",\"value\":{\"type\":\"Array\",\"value\":[{\"type\":\"UInt8\",\"value\":\"111\"},{\"type\":\"UInt8\",\"value\":\"72\"},{\"type\":\"UInt8\",\"value\":\"157\"},{\"type\":\"UInt8\",\"value\":\"52\"},{\"type\":\"UInt8\",\"value\":\"159\"},{\"type\":\"UInt8\",\"value\":\"238\"},{\"type\":\"UInt8\",\"value\":\"90\"},{\"type\":\"UInt8\",\"value\":\"4\"},{\"type\":\"UInt8\",\"value\":\"54\"},{\"type\":\"UInt8\",\"value\":\"202\"},{\"type\":\"UInt8\",\"value\":\"192\"},{\"type\":\"UInt8\",\"value\":\"96\"},{\"type\":\"UInt8\",\"value\":\"88\"},{\"type\":\"UInt8\",\"value\":\"32\"},{\"type\":\"UInt8\",\"value\":\"66\"},{\"type\":\"UInt8\",\"value\":\"153\"},{\"type\":\"UInt8\",\"value\":\"7\"},{\"type\":\"UInt8\",\"value\":\"176\"},{\"type\":\"UInt8\",\"value\":\"94\"},{\"type\":\"UInt8\",\"value\":\"183\"},{\"type\":\"UInt8\",\"value\":\"114\"},{\"type\":\"UInt8\",\"value\":\"193\"},{\"type\":\"UInt8\",\"value\":\"148\"},{\"type\":\"UInt8\",\"value\":\"235\"},{\"type\":\"UInt8\",\"value\":\"244\"},{\"type\":\"UInt8\",\"value\":\"41\"},{\"type\":\"UInt8\",\"value\":\"215\"},{\"type\":\"UInt8\",\"value\":\"28\"},{\"type\":\"UInt8\",\"value\":\"174\"},{\"type\":\"UInt8\",\"value\":\"231\"},{\"type\":\"UInt8\",\"value\":\"13\"},{\"type\":\"UInt8\",\"value\":\"43\"},{\"type\":\"UInt8\",\"value\":\"36\"},{\"type\":\"UInt8\",\"value\":\"153\"},{\"type\":\"UInt8\",\"value\":\"190\"},{\"type\":\"UInt8\",\"value\":\"158\"},{\"type\":\"UInt8\",\"value\":\"108\"},{\"type\":\"UInt8\",\"value\":\"78\"},{\"type\":\"UInt8\",\"value\":\"23\"},{\"type\":\"UInt8\",\"value\":\"216\"},{\"type\":\"UInt8\",\"value\":\"31\"},{\"type\":\"UInt8\",\"value\":\"21\"},{\"type\":\"UInt8\",\"value\":\"116\"},{\"type\":\"UInt8\",\"value\":\"102\"},{\"type\":\"UInt8\",\"value\":\"172\"},{\"type\":\"UInt8\",\"value\":\"61\"},{\"type\":\"UInt8\",\"value\":\"121\"},{\"type\":\"UInt8\",\"value\":\"59\"},{\"type\":\"UInt8\",\"value\":\"33\"},{\"type\":\"UInt8\",\"value\":\"127\"},{\"type\":\"UInt8\",\"value\":\"208\"},{\"type\":\"UInt8\",\"value\":\"145\"},{\"type\":\"UInt8\",\"value\":\"232\"},{\"type\":\"UInt8\",\"value\":\"154\"},{\"type\":\"UInt8\",\"value\":\"23\"},{\"type\":\"UInt8\",\"value\":\"43\"},{\"type\":\"UInt8\",\"value\":\"17\"},{\"type\":\"UInt8\",\"value\":\"202\"},{\"type\":\"UInt8\",\"value\":\"200\"},{\"type\":\"UInt8\",\"value\":\"29\"},{\"type\":\"UInt8\",\"value\":\"35\"},{\"type\":\"UInt8\",\"value\":\"120\"},{\"type\":\"UInt8\",\"value\":\"56\"},{\"type\":\"UInt8\",\"value\":\"91\"}]}},{\"name\":\"signatureAlgorithm\",\"value\":{\"type\":\"Enum\",\"value\":{\"id\":\"SignatureAlgorithm\",\"fields\":[{\"name\":\"rawValue\",\"value\":{\"type\":\"UInt8\",\"value\":\"1\"}}]}}},{\"name\":\"isValid\",\"value\":{\"type\":\"Bool\",\"value\":true}}]}}}]}}\n",
227
+ @transaction_id="eee1fe5350ea47f0f88b2b742d9487f48026b97f3983b6fd4c7b03ced888d326",
228
+ @transaction_index=1,
229
+ @type="flow.AccountKeyAdded">],
230
+ @status=:SEALED,
231
+ @status_code=0>
232
+ ```
233
+
234
+
235
+ ### Get Events
236
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient/Client#get_events-instance_method)
237
+
238
+ Retrieve events by a given type in a specified block height range or through a list of block IDs.
239
+
240
+ 📖 **Event type** is a string that follow a standard format:
241
+ ```
242
+ A.{contract address}.{contract name}.{event name}
243
+ ```
244
+
245
+ Please read more about [events in the documentation](https://docs.onflow.org/core-contracts/flow-token/). The exception to this standard are
246
+ core events, and you should read more about them in [this document](https://docs.onflow.org/cadence/language/core-events/).
247
+
248
+ 📖 **Block height range** expresses the height of the start and end block in the chain.
249
+
250
+ #### Examples
251
+ Example depicts ways to get events within block range or by block IDs:
252
+
253
+ ```ruby
254
+ # get_events(type, start_height, end_height)
255
+ res = client.get_events("A.7e60df042a9c0868.FlowToken.TokensWithdrawn", 50157100, 50157101)
256
+ ```
257
+ Example output:
258
+ ```ruby
259
+ [#<FlowClient::EventsResult:0x00007fad65b8fd98 @block_height=50157100, @block_id="d46e54de8c34dfe58a22c15d24689d1ad255f67bb9868605fcac28417aa54a37", @block_timestamp=2021-11-05 09:56:02.00021 +0200, @events=[]>,
260
+ #<FlowClient::EventsResult:0x00007fad65b8f7f8
261
+ @block_height=50157101,
262
+ @block_id="b0dd0496857b21b22711c623135eb9ebe7640f3dec45ce2a64971ffe03446b5e",
263
+ @block_timestamp=2021-11-05 09:56:03.000031 +0200,
264
+ @events=
265
+ [#<FlowClient::Event:0x00007fad65b8f050
266
+ @event_index=0,
267
+ @payload="{\"type\":\"Event\",\"value\":{\"id\":\"A.7e60df042a9c0868.FlowToken.TokensWithdrawn\",\"fields\":[{\"name\":\"amount\",\"value\":{\"type\":\"UFix64\",\"value\":\"0.00001000\"}},{\"name\":\"from\",\"value\":{\"type\":\"Optional\",\"value\":{\"type\":\"Address\",\"value\":\"0xfafb022e4e45634b\"}}}]}}\n",
268
+ @transaction_id="30c93926fb310c53ab6d29f092fd774c8a3642f6ca018a7ba25dcae553d720b2",
269
+ @transaction_index=0,
270
+ @type="A.7e60df042a9c0868.FlowToken.TokensWithdrawn">,
271
+ #<FlowClient::Event:0x00007fad65b8eba0
272
+ @event_index=2,
273
+ @payload="{\"type\":\"Event\",\"value\":{\"id\":\"A.7e60df042a9c0868.FlowToken.TokensWithdrawn\",\"fields\":[{\"name\":\"amount\",\"value\":{\"type\":\"UFix64\",\"value\":\"0.00001000\"}},{\"name\":\"from\",\"value\":{\"type\":\"Optional\",\"value\":{\"type\":\"Address\",\"value\":\"0x1bc62b2c04dfd147\"}}}]}}\n",
274
+ @transaction_id="5ee3317deb31413135521486a07f040fc34aeba41adf99e6ebd7770716cd6b29",
275
+ @transaction_index=1,
276
+ @type="A.7e60df042a9c0868.FlowToken.TokensWithdrawn">]>]
277
+ ```
278
+
279
+ ### Get Collections
280
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient/Client#get_collection_by_id-instance_method)
281
+
282
+ Retrieve a batch of transactions that have been included in the same block, known as ***collections***.
283
+ Collections are used to improve consensus throughput by increasing the number of transactions per block and they act as a link between a block and a transaction.
284
+
285
+ 📖 **Collection ID** is SHA3-256 hash of the collection payload.
286
+
287
+ Example retrieving a collection:
288
+ ```ruby
289
+ client.get_collection_by_id("f2a15028f4502c088d5460f1f086b65c0a71bb3da44bde6c6c5dcce254ddf849")
290
+ ```
291
+ Example output:
292
+ ```ruby
293
+ #<FlowClient::Collection:0x00007f9bf4239280 @id="f2a15028f4502c088d5460f1f086b65c0a71bb3da44bde6c6c5dcce254ddf849", @transaction_ids=["eee1fe5350ea47f0f88b2b742d9487f48026b97f3983b6fd4c7b03ced888d326"]>
294
+ ```
295
+
296
+ ### Execute Scripts
297
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient/Client#execute_script-instance_method)
298
+
299
+ Scripts allow you to write arbitrary non-mutating Cadence code on the Flow blockchain and return data. You can learn more about [Cadence and scripts here](https://docs.onflow.org/cadence/language/), but we are now only interested in executing the script code and getting back the data.
300
+
301
+ We can execute a script using the latest state of the Flow blockchain or we can choose to execute the script at a specific time in history defined by a block height or block ID.
302
+
303
+ 📖 **Block ID** is SHA3-256 hash of the entire block payload, but you can get that value from the block response properties.
304
+
305
+ 📖 **Block height** expresses the height of the block in the chain.
306
+
307
+ ```ruby
308
+ # Simple script
309
+ script = %{
310
+ pub fun main(a: Int): Int {
311
+ return a + 10
312
+ }
313
+ }
314
+
315
+ args = [FlowClient::CadenceType.Int(1)]
316
+ res = client.execute_script(script, args)
317
+ ```
318
+
319
+ ```ruby
320
+ # Complex script
321
+ script = %{
322
+ pub struct User {
323
+ pub var balance: UFix64
324
+ pub var address: Address
325
+ pub var name: String
326
+
327
+ init(name: String, address: Address, balance: UFix64) {
328
+ self.name = name
329
+ self.address = address
330
+ self.balance = balance
331
+ }
332
+ }
333
+
334
+ pub fun main(name: String): User {
335
+ return User(
336
+ name: name,
337
+ address: 0x1,
338
+ balance: 10.0
339
+ )
340
+ }
341
+ }
342
+
343
+ args = [FlowClient::CadenceType.String("Holy Batman")]
344
+ res = client.execute_script(script, args)
345
+ ```
346
+
347
+ Example output:
348
+ ```ruby
349
+ #<OpenStruct type="Struct", value=#<OpenStruct id="s.a3148d06a181c20c6fb1f92eda0b7b9565386e117d944c2583d0195d56debabf.User", fields=[#<OpenStruct name="balance", value=#<OpenStruct type="UFix64", value="10.00000000">>, #<OpenStruct name="address", value=#<OpenStruct type="Address", value="0x0000000000000001">>, #<OpenStruct name="name", value=#<OpenStruct type="String", value="Holy Batman">>]>>
350
+ ```
351
+
352
+ ## Mutate Flow Network
353
+ Flow, like most blockchains, allows anybody to submit a transaction that mutates the shared global chain state. A transaction is an object that holds a payload, which describes the state mutation, and one or more authorizations that permit the transaction to mutate the state owned by specific accounts.
354
+
355
+ Transaction data is composed and signed with help of the SDK. The signed payload of transaction then gets submitted to the access node API. If a transaction is invalid or the correct number of authorizing signatures are not provided, it gets rejected.
356
+
357
+ Executing a transaction requires couple of steps:
358
+ - [Building a transaction](#build-transactions).
359
+ - [Signing a transaction](#sign-transactions).
360
+ - [Sending a transaction](#send-transactions).
361
+
362
+ ## Transactions
363
+ A transaction is nothing more than a signed set of data that includes script code which are instructions on how to mutate the network state and properties that define and limit it's execution. All these properties are explained bellow.
364
+
365
+ 📖 **Script** field is the portion of the transaction that describes the state mutation logic. On Flow, transaction logic is written in [Cadence](https://docs.onflow.org/cadence/). Here is an example transaction script:
366
+ ```
367
+ transaction(greeting: String) {
368
+ execute {
369
+ log(greeting.concat(", World!"))
370
+ }
371
+ }
372
+ ```
373
+
374
+ 📖 **Arguments**. A transaction can accept zero or more arguments that are passed into the Cadence script. The arguments on the transaction must match the number and order declared in the Cadence script. Sample script from above accepts a single `String` argument.
375
+
376
+ 📖 **[Proposal key](https://docs.onflow.org/concepts/transaction-signing/#proposal-key)** must be provided to act as a sequence number and prevent reply and other potential attacks.
377
+
378
+ Each account key maintains a separate transaction sequence counter; the key that lends its sequence number to a transaction is called the proposal key.
379
+
380
+ A proposal key contains three fields:
381
+ - Account address
382
+ - Key index
383
+ - Sequence number
384
+
385
+ A transaction is only valid if its declared sequence number matches the current on-chain sequence number for that key. The sequence number increments by one after the transaction is executed.
386
+
387
+ 📖 **[Payer](https://docs.onflow.org/concepts/transaction-signing/#signer-roles)** is the account that pays the fees for the transaction. A transaction must specify exactly one payer. The payer is only responsible for paying the network and gas fees; the transaction is not authorized to access resources or code stored in the payer account.
388
+
389
+ 📖 **[Authorizers](https://docs.onflow.org/concepts/transaction-signing/#signer-roles)** are accounts that authorize a transaction to read and mutate their resources. A transaction can specify zero or more authorizers, depending on how many accounts the transaction needs to access.
390
+
391
+ The number of authorizers on the transaction must match the number of AuthAccount parameters declared in the prepare statement of the Cadence script.
392
+
393
+ Example transaction with multiple authorizers:
394
+ ```
395
+ transaction {
396
+ prepare(authorizer1: AuthAccount, authorizer2: AuthAccount) { }
397
+ }
398
+ ```
399
+
400
+ 📖 **Gas limit** is the limit on the amount of computation a transaction requires, and it will abort if it exceeds its gas limit.
401
+ Cadence uses metering to measure the number of operations per transaction. You can read more about it in the [Cadence documentation](/cadence).
402
+
403
+ The gas limit depends on the complexity of the transaction script. Until dedicated gas estimation tooling exists, it's best to use the emulator to test complex transactions and determine a safe limit.
404
+
405
+ 📖 **Reference block** specifies an expiration window (measured in blocks) during which a transaction is considered valid by the network.
406
+ A transaction will be rejected if it is submitted past its expiry block. Flow calculates transaction expiry using the _reference block_ field on a transaction.
407
+ A transaction expires after `600` blocks are committed on top of the reference block, which takes about 10 minutes at average Mainnet block rates.
408
+
409
+ ### Build Transactions
410
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient/Transaction)
411
+
412
+ Building a transaction involves setting the required properties explained above and producing a transaction object.
413
+
414
+ Here we define a simple transaction script that will be used to execute on the network and serve as a good learning example.
415
+
416
+ ```
417
+ transaction(greeting: String) {
418
+
419
+ let guest: Address
420
+
421
+ prepare(authorizer: AuthAccount) {
422
+ self.guest = authorizer.address
423
+ }
424
+
425
+ execute {
426
+ log(greeting.concat(",").concat(guest.toString()))
427
+ }
428
+ }
429
+ ```
430
+
431
+ ```ruby
432
+ cadence = %{
433
+ transaction(greeting: String) {
434
+
435
+ let guest: Address
436
+
437
+ prepare(authorizer: AuthAccount) {
438
+ self.guest = authorizer.address
439
+ }
440
+
441
+ execute {
442
+ log(greeting.concat(",").concat(guest.toString()))
443
+ }
444
+ }
445
+ }
446
+
447
+ arguments = [FlowClient::CadenceType.String("Hello World!")]
448
+
449
+ transaction = FlowClient::Transaction.new
450
+ transaction.script = cadence
451
+ transaction.reference_block_id = client.get_latest_block.id
452
+ transaction.gas_limit = 100
453
+ transaction.arguments = arguments
454
+ ```
455
+
456
+ After you have successfully [built a transaction](#build-transactions) the next step in the process is to sign it.
457
+
458
+ ### Sign Transactions
459
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient/Transaction)
460
+
461
+ Flow introduces new concepts that allow for more flexibility when creating and signing transactions.
462
+ Before trying the examples below, we recommend that you read through the [transaction signature documentation](https://docs.onflow.org/concepts/accounts-and-keys/).
463
+
464
+ After you have successfully [built a transaction](#build-transactions) the next step in the process is to sign it. Flow transactions have envelope and payload signatures, and you should learn about each in the [signature documentation](https://docs.onflow.org/concepts/accounts-and-keys/#anatomy-of-a-transaction).
465
+
466
+ Quick example of building a transaction:
467
+ ```ruby
468
+ arguments = [FlowClient::CadenceType.String("Hello world!")]
469
+
470
+ transaction = FlowClient::Transaction.new
471
+ transaction.script = cadence
472
+ transaction.reference_block_id = client.get_latest_block.id
473
+ transaction.gas_limit = 100
474
+ transaction.arguments = arguments
475
+ ```
476
+
477
+ Signatures can be generated more securely using keys stored in a hardware device such as an [HSM](https://en.wikipedia.org/wiki/Hardware_security_module). The `crypto.Signer` interface is intended to be flexible enough to support a variety of signer implementations and is not limited to in-memory implementations.
478
+
479
+ Simple signature example:
480
+ ```ruby
481
+ account = client.get_account("0x01")
482
+ signer = FlowClient::LocalSigner.new("<private key hex>")
483
+
484
+ transaction.proposer_address = account.address
485
+ transaction.proposer_key_index = account.keys.first.index
486
+ transaction.proposer_key_sequence_number = account.keys.first.sequence_number
487
+ transaction.payer_address = account.address
488
+ transaction.authorizer_addresses = [account.address]
489
+
490
+ transaction.add_envelope_signature(account.address, account.keys.first.index, signer)
491
+ ```
492
+
493
+ Flow supports great flexibility when it comes to transaction signing, we can define multiple authorizers (multi-sig transactions) and have different payer account than proposer. We will explore advanced signing scenarios bellow.
494
+
495
+ ### [Single party, single signature](https://docs.onflow.org/concepts/transaction-signing/#single-party-single-signature)
496
+
497
+ - Proposer, payer and authorizer are the same account (`0x01`).
498
+ - Only the envelope must be signed.
499
+ - Proposal key must have full signing weight.
500
+
501
+ | Account | Key ID | Weight |
502
+ | ------- | ------ | ------ |
503
+ | `0x01` | 1 | 1.0 |
504
+
505
+ ```ruby
506
+ account = client.get_account("0x01")
507
+
508
+ transaction = FlowClient::Transaction.new
509
+ transaction.reference_block_id = client.get_latest_block.id
510
+ transaction.gas_limit = 100
511
+ transaction.proposer_address = account.address
512
+ transaction.proposer_key_index = account.keys.first.index
513
+ transaction.proposer_key_sequence_number = account.keys.first.sequence_number
514
+ transaction.payer_address = account.address
515
+ transaction.authorizer_addresses = [account.address]
516
+
517
+ # Only the envelope needs to be signed in this special case
518
+ signer = FlowClient::LocalSigner.new("<private key hex>")
519
+ transaction.add_envelope_signature(account.address, account.keys.first.index, signer)
520
+ ```
521
+
522
+
523
+ ### [Single party, multiple signatures](https://docs.onflow.org/concepts/transaction-signing/#single-party-multiple-signatures)
524
+
525
+ - Proposer, payer and authorizer are the same account (`0x01`).
526
+ - Only the envelope must be signed.
527
+ - Each key has weight 0.5, so two signatures are required.
528
+
529
+ | Account | Key ID | Weight |
530
+ | ------- | ------ | ------ |
531
+ | `0x01` | 1 | 0.5 |
532
+ | `0x01` | 2 | 0.5 |
533
+
534
+ ```ruby
535
+ account = client.get_account("0x01")
536
+
537
+ transaction = FlowClient::Transaction.new
538
+ transaction.reference_block_id = client.get_latest_block.id
539
+ transaction.gas_limit = 100
540
+ transaction.proposer_address = account.address
541
+ transaction.proposer_key_index = account.keys.first.index
542
+ transaction.proposer_key_sequence_number = account.keys.first.sequence_number
543
+ transaction.payer_address = account.address
544
+ transaction.authorizer_addresses = [account.address]
545
+
546
+ signer = FlowClient::LocalSigner.new("<private key hex>")
547
+ transaction.add_envelope_signature(account.address, account.keys[0].index, signer)
548
+ transaction.add_envelope_signature(account.address, account.keys[1].index, signer)
549
+ ```
550
+
551
+ ### [Multiple parties](https://docs.onflow.org/concepts/transaction-signing/#multiple-parties)
552
+
553
+ - Proposer and authorizer are the same account (`0x01`).
554
+ - Payer is a separate account (`0x02`).
555
+ - Account `0x01` signs the payload.
556
+ - Account `0x02` signs the envelope.
557
+ - Account `0x02` must sign last since it is the payer.
558
+
559
+ | Account | Key ID | Weight |
560
+ | ------- | ------ | ------ |
561
+ | `0x01` | 1 | 1.0 |
562
+ | `0x02` | 3 | 1.0 |
563
+
564
+ ```ruby
565
+ payer_signer = FlowClient::LocalSigner.new("<private key hex>")
566
+ payer_account = client.get_account("0x02")
567
+
568
+ proposer_signer = FlowClient::LocalSigner.new("<private key hex>")
569
+ proposer_account = client.get_account("0x01")
570
+
571
+ @transaction = FlowClient::Transaction.new
572
+ @transaction.reference_block_id = client.get_latest_block.id
573
+ @transaction.gas_limit = gas_limit
574
+
575
+ @transaction.proposer_address = proposer_account.address
576
+ @transaction.proposer_key_index = proposer_account.keys[0].index
577
+ @transaction.proposer_key_sequence_number = proposer_account.keys[0].sequence_number
578
+
579
+ @transaction.payer_address = payer_account.address
580
+ @transaction.authorizer_addresses = [proposer_account.address]
581
+
582
+ @transaction.add_payload_signature(proposer_account.address, proposer_account.keys[0].index, proposer_signer)
583
+ @transaction.add_envelope_signature(payer_account.address, payer_account.keys[2].index, payer_signer)
584
+ ```
585
+
586
+ ### [Multiple parties, two authorizers](https://docs.onflow.org/concepts/transaction-signing/#multiple-parties)
587
+
588
+ - Proposer and authorizer are the same account (`0x01`).
589
+ - Payer is a separate account (`0x02`).
590
+ - Account `0x01` signs the payload.
591
+ - Account `0x02` signs the envelope.
592
+ - Account `0x02` must sign last since it is the payer.
593
+ - Account `0x02` is also an authorizer to show how to include two AuthAccounts into an transaction
594
+
595
+ | Account | Key ID | Weight |
596
+ | ------- | ------ | ------ |
597
+ | `0x01` | 1 | 1.0 |
598
+ | `0x02` | 3 | 1.0 |
599
+
600
+ ```ruby
601
+ payer_signer = FlowClient::LocalSigner.new("<private key hex>")
602
+ payer_account = client.get_account("0x02")
603
+
604
+ proposer_signer = FlowClient::LocalSigner.new("<private key hex>")
605
+ proposer_account = client.get_account("0x01")
606
+
607
+ @transaction = FlowClient::Transaction.new
608
+ @transaction.reference_block_id = client.get_latest_block.id
609
+ @transaction.gas_limit = gas_limit
610
+
611
+ @transaction.proposer_address = proposer_account.address
612
+ @transaction.proposer_key_index = proposer_account.keys[0].index
613
+ @transaction.proposer_key_sequence_number = proposer_account.keys[0].sequence_number
614
+
615
+ @transaction.payer_address = payer_account.address
616
+ @transaction.authorizer_addresses = [proposer_account.address, payer_account.address]
617
+
618
+ @transaction.add_payload_signature(proposer_account.address, proposer_account.keys[0].index, proposer_signer)
619
+ @transaction.add_envelope_signature(payer_account.address, payer_account.keys[2].index, payer_signer)
620
+ ```
621
+
622
+ ### [Multiple parties, multiple signatures](https://docs.onflow.org/concepts/transaction-signing/#multiple-parties)
623
+
624
+ - Proposer and authorizer are the same account (`0x01`).
625
+ - Payer is a separate account (`0x02`).
626
+ - Account `0x01` signs the payload.
627
+ - Account `0x02` signs the envelope.
628
+ - Account `0x02` must sign last since it is the payer.
629
+ - Both accounts must sign twice (once with each of their keys).
630
+
631
+ | Account | Key ID | Weight |
632
+ | ------- | ------ | ------ |
633
+ | `0x01` | 1 | 0.5 |
634
+ | `0x01` | 2 | 0.5 |
635
+ | `0x02` | 3 | 0.5 |
636
+ | `0x02` | 4 | 0.5 |
637
+
638
+ ```ruby
639
+ payer_signer = FlowClient::LocalSigner.new("<private key hex>")
640
+ payer_account = client.get_account("0x02")
641
+
642
+ proposer_signer = FlowClient::LocalSigner.new("<private key hex>")
643
+ proposer_account = client.get_account("0x01")
644
+
645
+ @transaction = FlowClient::Transaction.new
646
+ @transaction.reference_block_id = client.get_latest_block.id
647
+
648
+ @transaction.proposer_address = proposer_account.address
649
+ @transaction.proposer_key_index = proposer_account.keys[0].index
650
+ @transaction.proposer_key_sequence_number = proposer_account.keys[0].sequence_number
651
+
652
+ @transaction.payer_address = payer_account.address
653
+ @transaction.authorizer_addresses = [proposer_account.address]
654
+
655
+ @transaction.add_payload_signature(proposer_account.address, proposer_account.keys[0].index, proposer_signer)
656
+ @transaction.add_payload_signature(proposer_account.address, proposer_account.keys[1].index, proposer_signer)
657
+
658
+ @transaction.add_envelope_signature(payer_account.address, payer_account.keys[2].index, payer_signer)
659
+ @transaction.add_envelope_signature(payer_account.address, payer_account.keys[3].index, payer_signer)
660
+ ```
661
+
662
+
663
+ ### Send Transactions
664
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient/Client#send_transaction-instance_method)
665
+
666
+ After a transaction has been [built](#build-transactions) and [signed](#sign-transactions), it can be sent to the Flow blockchain where it will be executed. If sending was successful you can then [retrieve the transaction result](#get-transactions).
667
+
668
+
669
+ ```ruby
670
+ tx_res = client.send_transaction(@transaction)
671
+ client.wait_for_transaction(tx_res.id) do |response|
672
+ # use response here
673
+ end
674
+ ```
675
+
676
+
677
+ ### Create Accounts
678
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient/Client#create_account-instance_method)
679
+
680
+ On Flow, account creation happens inside a transaction. Because the network allows for a many-to-many relationship between public keys and accounts, it's not possible to derive a new account address from a public key offline.
681
+
682
+ The Flow VM uses a deterministic address generation algorithm to assigen account addresses on chain. You can find more details about address generation in the [accounts & keys documentation](https://docs.onflow.org/concepts/accounts-and-keys/).
683
+
684
+ #### Public Key
685
+ Flow uses ECDSA key pairs to control access to user accounts. Each key pair can be used in combination with the SHA2-256 or SHA3-256 hashing algorithms.
686
+
687
+ ⚠️ You'll need to authorize at least one public key to control your new account.
688
+
689
+ Flow represents ECDSA public keys in raw form without additional metadata. Each key is a single byte slice containing a concatenation of its X and Y components in big-endian byte form.
690
+
691
+ A Flow account can contain zero (not possible to control) or more public keys, referred to as account keys. Read more about [accounts in the documentation](https://docs.onflow.org/concepts/accounts-and-keys/#accounts).
692
+
693
+ An account key contains the following data:
694
+ - Raw public key (described above)
695
+ - Signature algorithm
696
+ - Hash algorithm
697
+ - Weight (integer between 0-1000)
698
+
699
+ Account creation happens inside a transaction, which means that somebody must pay to submit that transaction to the network. We'll call this person the account creator. Make sure you have read [sending a transaction section](#send-transactions) first.
700
+
701
+ ```ruby
702
+ # The account that will pay for the creation of the new account
703
+ payer_account = client.get_account("f8d6e0586b0a20c7")
704
+ # Create an in-memory signer with the payer's private key
705
+ signer = FlowClient::LocalSigner.new("4d9287571c8bff7482ffc27ef68d5b4990f9bd009a1e9fa812aae08ba167d57f")
706
+ # Generate a public key for the new account
707
+ _private_key, public_key = FlowClient::Crypto.generate_key_pair(FlowClient::Crypto::Curves::P256)
708
+ # Create the account
709
+ res = client.create_account([public_key], { "ContractName": "<contract cadence code>" }, payer_account, signer)
710
+ ```
711
+
712
+ ```ruby
713
+ #<FlowClient::Account:0x00007f84eb36b650
714
+ @address="01cf0e2f2f715450",
715
+ @balance=0.001,
716
+ @contracts={},
717
+ @keys=[#<FlowClient::AccountKey:0x00007f84eb36b448 @hash_algo="SHA3-256", @index=0, @public_key="6f489d349fee5a0436cac0605820429907b05eb772c194ebf429d71caee70d2b2499be9e6c4e17d81f157466ac3d793b217fd091e89a172b11cac81d2378385b", @revoked=false, @sequence_number=0, @weight=1000>]>
718
+ ```
719
+
720
+ After the account creation transaction has been submitted you can retrieve the new account address by [getting the transaction result](#get-transactions).
721
+
722
+ The new account address will be emitted in a system-level `flow.AccountCreated` event.
723
+
724
+ ```ruby
725
+ res.address
726
+ ```
727
+
728
+ ### Generate Keys
729
+ [<img src="https://raw.githubusercontent.com/onflow/sdks/main/templates/documentation/ref.svg" width="130">](https://www.rubydoc.info/gems/flow_client/FlowClient/Crypto#generate_key_pair-class_method)
730
+
731
+ Flow uses [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) signatures to control access to user accounts. Each key pair can be used in combination with the `SHA2-256` or `SHA3-256` hashing algorithms.
732
+
733
+ Here's how to generate an ECDSA private key for the P-256 (secp256r1) curve.
734
+
735
+ ```ruby
736
+ # Supported ECC curves are:
737
+ # FlowClient::Crypto::Curves::P256
738
+ # FlowClient::Crypto::Curves::SECP256K1
739
+
740
+ private_key, public_key = FlowClient::Crypto.generate_key_pair(FlowClient::Crypto::Curves::P256)
741
+ ```
742
+
743
+ The example above uses an ECDSA key pair on the P-256 (secp256r1) elliptic curve. Flow also supports the secp256k1 curve used by Bitcoin and Ethereum. Read more about [supported algorithms here](https://docs.onflow.org/concepts/accounts-and-keys/#supported-signature--hash-algorithms).
744
+
745
+ ```ruby
746
+ private_key, public_key = FlowClient::Crypto.generate_key_pair(FlowClient::Crypto::Curves::SECP256K1)
747
+ ```