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.
- checksums.yaml +7 -0
- data/.github/workflows/ruby.yml +35 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +20 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +115 -0
- data/Guardfile +79 -0
- data/LICENSE.txt +21 -0
- data/README.md +93 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/flow_client.gemspec +44 -0
- data/lib/flow/access/access_pb.rb +168 -0
- data/lib/flow/access/access_services_pb.rb +96 -0
- data/lib/flow/entities/account_pb.rb +30 -0
- data/lib/flow/entities/block_header_pb.rb +20 -0
- data/lib/flow/entities/block_pb.rb +25 -0
- data/lib/flow/entities/block_seal_pb.rb +19 -0
- data/lib/flow/entities/collection_pb.rb +23 -0
- data/lib/flow/entities/event_pb.rb +20 -0
- data/lib/flow/entities/transaction_pb.rb +47 -0
- data/lib/flow/execution/execution_pb.rb +65 -0
- data/lib/flow/execution/execution_services_pb.rb +43 -0
- data/lib/flow/legacy/access/access_pb.rb +157 -0
- data/lib/flow/legacy/access/access_services_pb.rb +89 -0
- data/lib/flow/legacy/entities/account_pb.rb +28 -0
- data/lib/flow/legacy/entities/block_header_pb.rb +20 -0
- data/lib/flow/legacy/entities/block_pb.rb +25 -0
- data/lib/flow/legacy/entities/block_seal_pb.rb +19 -0
- data/lib/flow/legacy/entities/collection_pb.rb +22 -0
- data/lib/flow/legacy/entities/event_pb.rb +20 -0
- data/lib/flow/legacy/entities/transaction_pb.rb +45 -0
- data/lib/flow/legacy/execution/execution_pb.rb +65 -0
- data/lib/flow/legacy/execution/execution_services_pb.rb +42 -0
- data/lib/flow_client.rb +14 -0
- data/lib/flow_client/client.rb +98 -0
- data/lib/flow_client/crypto.rb +33 -0
- data/lib/flow_client/transaction.rb +147 -0
- data/lib/flow_client/utils.rb +38 -0
- data/lib/flow_client/version.rb +5 -0
- metadata +201 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: flow/legacy/entities/account.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
7
|
+
add_file("flow/legacy/entities/account.proto", :syntax => :proto3) do
|
8
|
+
add_message "entities.Account" do
|
9
|
+
optional :address, :bytes, 1
|
10
|
+
optional :balance, :uint64, 2
|
11
|
+
optional :code, :bytes, 3
|
12
|
+
repeated :keys, :message, 4, "entities.AccountKey"
|
13
|
+
end
|
14
|
+
add_message "entities.AccountKey" do
|
15
|
+
optional :index, :uint32, 1
|
16
|
+
optional :public_key, :bytes, 2
|
17
|
+
optional :sign_algo, :uint32, 3
|
18
|
+
optional :hash_algo, :uint32, 4
|
19
|
+
optional :weight, :uint32, 5
|
20
|
+
optional :sequence_number, :uint32, 6
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module Entities
|
26
|
+
Account = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.Account").msgclass
|
27
|
+
AccountKey = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.AccountKey").msgclass
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: flow/legacy/entities/block_header.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
require 'google/protobuf/timestamp_pb'
|
7
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
8
|
+
add_file("flow/legacy/entities/block_header.proto", :syntax => :proto3) do
|
9
|
+
add_message "entities.BlockHeader" do
|
10
|
+
optional :id, :bytes, 1
|
11
|
+
optional :parent_id, :bytes, 2
|
12
|
+
optional :height, :uint64, 3
|
13
|
+
optional :timestamp, :message, 4, "google.protobuf.Timestamp"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Entities
|
19
|
+
BlockHeader = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.BlockHeader").msgclass
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: flow/legacy/entities/block.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
require 'google/protobuf/timestamp_pb'
|
7
|
+
require 'flow/legacy/entities/collection_pb'
|
8
|
+
require 'flow/legacy/entities/block_seal_pb'
|
9
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
10
|
+
add_file("flow/legacy/entities/block.proto", :syntax => :proto3) do
|
11
|
+
add_message "entities.Block" do
|
12
|
+
optional :id, :bytes, 1
|
13
|
+
optional :parent_id, :bytes, 2
|
14
|
+
optional :height, :uint64, 3
|
15
|
+
optional :timestamp, :message, 4, "google.protobuf.Timestamp"
|
16
|
+
repeated :collection_guarantees, :message, 5, "entities.CollectionGuarantee"
|
17
|
+
repeated :block_seals, :message, 6, "entities.BlockSeal"
|
18
|
+
repeated :signatures, :bytes, 7
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Entities
|
24
|
+
Block = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.Block").msgclass
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: flow/legacy/entities/block_seal.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
7
|
+
add_file("flow/legacy/entities/block_seal.proto", :syntax => :proto3) do
|
8
|
+
add_message "entities.BlockSeal" do
|
9
|
+
optional :block_id, :bytes, 1
|
10
|
+
optional :execution_receipt_id, :bytes, 2
|
11
|
+
repeated :execution_receipt_signatures, :bytes, 3
|
12
|
+
repeated :result_approval_signatures, :bytes, 4
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Entities
|
18
|
+
BlockSeal = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.BlockSeal").msgclass
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: flow/legacy/entities/collection.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
7
|
+
add_file("flow/legacy/entities/collection.proto", :syntax => :proto3) do
|
8
|
+
add_message "entities.Collection" do
|
9
|
+
optional :id, :bytes, 1
|
10
|
+
repeated :transaction_ids, :bytes, 2
|
11
|
+
end
|
12
|
+
add_message "entities.CollectionGuarantee" do
|
13
|
+
optional :collection_id, :bytes, 1
|
14
|
+
repeated :signatures, :bytes, 2
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Entities
|
20
|
+
Collection = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.Collection").msgclass
|
21
|
+
CollectionGuarantee = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.CollectionGuarantee").msgclass
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: flow/legacy/entities/event.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
7
|
+
add_file("flow/legacy/entities/event.proto", :syntax => :proto3) do
|
8
|
+
add_message "entities.Event" do
|
9
|
+
optional :type, :string, 1
|
10
|
+
optional :transaction_id, :bytes, 2
|
11
|
+
optional :transaction_index, :uint32, 3
|
12
|
+
optional :event_index, :uint32, 4
|
13
|
+
optional :payload, :bytes, 5
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Entities
|
19
|
+
Event = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.Event").msgclass
|
20
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: flow/legacy/entities/transaction.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
7
|
+
add_file("flow/legacy/entities/transaction.proto", :syntax => :proto3) do
|
8
|
+
add_message "entities.Transaction" do
|
9
|
+
optional :script, :bytes, 1
|
10
|
+
repeated :arguments, :bytes, 2
|
11
|
+
optional :reference_block_id, :bytes, 3
|
12
|
+
optional :gas_limit, :uint64, 4
|
13
|
+
optional :proposal_key, :message, 5, "entities.Transaction.ProposalKey"
|
14
|
+
optional :payer, :bytes, 6
|
15
|
+
repeated :authorizers, :bytes, 7
|
16
|
+
repeated :payload_signatures, :message, 8, "entities.Transaction.Signature"
|
17
|
+
repeated :envelope_signatures, :message, 9, "entities.Transaction.Signature"
|
18
|
+
end
|
19
|
+
add_message "entities.Transaction.ProposalKey" do
|
20
|
+
optional :address, :bytes, 1
|
21
|
+
optional :key_id, :uint32, 2
|
22
|
+
optional :sequence_number, :uint64, 3
|
23
|
+
end
|
24
|
+
add_message "entities.Transaction.Signature" do
|
25
|
+
optional :address, :bytes, 1
|
26
|
+
optional :key_id, :uint32, 2
|
27
|
+
optional :signature, :bytes, 3
|
28
|
+
end
|
29
|
+
add_enum "entities.TransactionStatus" do
|
30
|
+
value :UNKNOWN, 0
|
31
|
+
value :PENDING, 1
|
32
|
+
value :FINALIZED, 2
|
33
|
+
value :EXECUTED, 3
|
34
|
+
value :SEALED, 4
|
35
|
+
value :EXPIRED, 5
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module Entities
|
41
|
+
Transaction = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.Transaction").msgclass
|
42
|
+
Transaction::ProposalKey = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.Transaction.ProposalKey").msgclass
|
43
|
+
Transaction::Signature = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.Transaction.Signature").msgclass
|
44
|
+
TransactionStatus = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("entities.TransactionStatus").enummodule
|
45
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# source: flow/legacy/execution/execution.proto
|
3
|
+
|
4
|
+
require 'google/protobuf'
|
5
|
+
|
6
|
+
require 'flow/legacy/entities/account_pb'
|
7
|
+
require 'flow/legacy/entities/event_pb'
|
8
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
9
|
+
add_file("flow/legacy/execution/execution.proto", :syntax => :proto3) do
|
10
|
+
add_message "execution.PingRequest" do
|
11
|
+
end
|
12
|
+
add_message "execution.PingResponse" do
|
13
|
+
end
|
14
|
+
add_message "execution.GetAccountAtBlockIDRequest" do
|
15
|
+
optional :block_id, :bytes, 1
|
16
|
+
optional :address, :bytes, 2
|
17
|
+
end
|
18
|
+
add_message "execution.GetAccountAtBlockIDResponse" do
|
19
|
+
optional :account, :message, 1, "entities.Account"
|
20
|
+
end
|
21
|
+
add_message "execution.ExecuteScriptAtBlockIDRequest" do
|
22
|
+
optional :block_id, :bytes, 1
|
23
|
+
optional :script, :bytes, 2
|
24
|
+
repeated :arguments, :bytes, 3
|
25
|
+
end
|
26
|
+
add_message "execution.ExecuteScriptAtBlockIDResponse" do
|
27
|
+
optional :value, :bytes, 1
|
28
|
+
end
|
29
|
+
add_message "execution.GetEventsForBlockIDsResponse" do
|
30
|
+
repeated :results, :message, 1, "execution.GetEventsForBlockIDsResponse.Result"
|
31
|
+
end
|
32
|
+
add_message "execution.GetEventsForBlockIDsResponse.Result" do
|
33
|
+
optional :block_id, :bytes, 1
|
34
|
+
optional :block_height, :uint64, 2
|
35
|
+
repeated :events, :message, 3, "entities.Event"
|
36
|
+
end
|
37
|
+
add_message "execution.GetEventsForBlockIDsRequest" do
|
38
|
+
optional :type, :string, 1
|
39
|
+
repeated :block_ids, :bytes, 2
|
40
|
+
end
|
41
|
+
add_message "execution.GetTransactionResultRequest" do
|
42
|
+
optional :block_id, :bytes, 1
|
43
|
+
optional :transaction_id, :bytes, 2
|
44
|
+
end
|
45
|
+
add_message "execution.GetTransactionResultResponse" do
|
46
|
+
optional :status_code, :uint32, 1
|
47
|
+
optional :error_message, :string, 2
|
48
|
+
repeated :events, :message, 3, "entities.Event"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module Execution
|
54
|
+
PingRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.PingRequest").msgclass
|
55
|
+
PingResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.PingResponse").msgclass
|
56
|
+
GetAccountAtBlockIDRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.GetAccountAtBlockIDRequest").msgclass
|
57
|
+
GetAccountAtBlockIDResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.GetAccountAtBlockIDResponse").msgclass
|
58
|
+
ExecuteScriptAtBlockIDRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.ExecuteScriptAtBlockIDRequest").msgclass
|
59
|
+
ExecuteScriptAtBlockIDResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.ExecuteScriptAtBlockIDResponse").msgclass
|
60
|
+
GetEventsForBlockIDsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.GetEventsForBlockIDsResponse").msgclass
|
61
|
+
GetEventsForBlockIDsResponse::Result = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.GetEventsForBlockIDsResponse.Result").msgclass
|
62
|
+
GetEventsForBlockIDsRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.GetEventsForBlockIDsRequest").msgclass
|
63
|
+
GetTransactionResultRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.GetTransactionResultRequest").msgclass
|
64
|
+
GetTransactionResultResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("execution.GetTransactionResultResponse").msgclass
|
65
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# Source: flow/legacy/execution/execution.proto for package 'execution'
|
3
|
+
|
4
|
+
require 'grpc'
|
5
|
+
require 'flow/legacy/execution/execution_pb'
|
6
|
+
|
7
|
+
module Execution
|
8
|
+
module ExecutionAPI
|
9
|
+
# ExecutionAPI is the API provided by the execution nodes.
|
10
|
+
class Service
|
11
|
+
|
12
|
+
include ::GRPC::GenericService
|
13
|
+
|
14
|
+
self.marshal_class_method = :encode
|
15
|
+
self.unmarshal_class_method = :decode
|
16
|
+
self.service_name = 'execution.ExecutionAPI'
|
17
|
+
|
18
|
+
# Ping is used to check if the access node is alive and healthy.
|
19
|
+
rpc :Ping, ::Execution::PingRequest, ::Execution::PingResponse
|
20
|
+
# Accounts
|
21
|
+
#
|
22
|
+
# GetAccountAtBlockID gets an account by address at the given block ID
|
23
|
+
rpc :GetAccountAtBlockID, ::Execution::GetAccountAtBlockIDRequest, ::Execution::GetAccountAtBlockIDResponse
|
24
|
+
# Scripts
|
25
|
+
#
|
26
|
+
# ExecuteScriptAtBlockID executes a ready-only Cadence script against the
|
27
|
+
# execution state at the block with the given ID.
|
28
|
+
rpc :ExecuteScriptAtBlockID, ::Execution::ExecuteScriptAtBlockIDRequest, ::Execution::ExecuteScriptAtBlockIDResponse
|
29
|
+
# Events
|
30
|
+
#
|
31
|
+
# GetEventsForBlockIDs retrieves events for all the specified block IDs that
|
32
|
+
# have the given type
|
33
|
+
rpc :GetEventsForBlockIDs, ::Execution::GetEventsForBlockIDsRequest, ::Execution::GetEventsForBlockIDsResponse
|
34
|
+
# Transaction
|
35
|
+
#
|
36
|
+
# GetTransactionResult gets the result of a transaction.
|
37
|
+
rpc :GetTransactionResult, ::Execution::GetTransactionResultRequest, ::Execution::GetTransactionResultResponse
|
38
|
+
end
|
39
|
+
|
40
|
+
Stub = Service.rpc_stub_class
|
41
|
+
end
|
42
|
+
end
|
data/lib/flow_client.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "flow_client/version"
|
4
|
+
require "openssl"
|
5
|
+
require "rlp"
|
6
|
+
|
7
|
+
# Collection of classes to interact with the Flow blockchain
|
8
|
+
module FlowClient
|
9
|
+
class Error < StandardError; end
|
10
|
+
require "flow_client/crypto"
|
11
|
+
require "flow_client/utils"
|
12
|
+
require "flow_client/client"
|
13
|
+
require "flow_client/transaction"
|
14
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "flow/access/access_services_pb"
|
4
|
+
require "flow/execution/execution_services_pb"
|
5
|
+
require "json"
|
6
|
+
|
7
|
+
# Collection of classes to interact with the Flow blockchain
|
8
|
+
module FlowClient
|
9
|
+
# Flow client
|
10
|
+
class Client
|
11
|
+
attr_accessor :address_aliases
|
12
|
+
|
13
|
+
def initialize(node_address)
|
14
|
+
@stub = Access::AccessAPI::Stub.new(node_address, :this_channel_is_insecure)
|
15
|
+
@address_aliases = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def ping
|
19
|
+
req = Access::PingRequest.new
|
20
|
+
@stub.ping(req)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Accounts
|
24
|
+
def get_account(address)
|
25
|
+
req = Access::GetAccountAtLatestBlockRequest.new(address: to_bytes(address))
|
26
|
+
res = @stub.get_account_at_latest_block(req)
|
27
|
+
res.account
|
28
|
+
end
|
29
|
+
|
30
|
+
# Scripts
|
31
|
+
def execute_script(script, args = [])
|
32
|
+
req = Access::ExecuteScriptAtLatestBlockRequest.new(
|
33
|
+
script: FlowClient::Utils.substitute_address_aliases(script, @address_aliases),
|
34
|
+
arguments: args
|
35
|
+
)
|
36
|
+
res = @stub.execute_script_at_latest_block(req)
|
37
|
+
parse_json(res.value)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Blocks
|
41
|
+
def get_latest_block(is_sealed: true)
|
42
|
+
req = Access::GetLatestBlockRequest.new(
|
43
|
+
is_sealed: is_sealed
|
44
|
+
)
|
45
|
+
|
46
|
+
@stub.get_latest_block(req)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Events
|
50
|
+
def get_events(type, start_height, end_height)
|
51
|
+
req = Access::GetEventsForHeightRangeRequest.new(
|
52
|
+
type: type,
|
53
|
+
start_height: start_height,
|
54
|
+
end_height: end_height
|
55
|
+
)
|
56
|
+
@stub.get_events_for_height_range(req)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Transactions
|
60
|
+
|
61
|
+
# Send a FlowClient::Transaction transaction to the blockchain
|
62
|
+
def send_transaction(transaction)
|
63
|
+
transaction.address_aliases = @address_aliases
|
64
|
+
req = Access::SendTransactionRequest.new(
|
65
|
+
transaction: transaction.message
|
66
|
+
)
|
67
|
+
@stub.send_transaction(req)
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_transaction(transaction_id)
|
71
|
+
req = Access::GetTransactionRequest.new(
|
72
|
+
id: to_bytes(transaction_id)
|
73
|
+
)
|
74
|
+
@stub.get_transaction(req)
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_transaction_result(transaction_id)
|
78
|
+
req = Access::GetTransactionRequest.new(
|
79
|
+
id: to_bytes(transaction_id)
|
80
|
+
)
|
81
|
+
@stub.get_transaction_result(req)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def parse_json(event_payload)
|
87
|
+
JSON.parse(event_payload, object_class: OpenStruct)
|
88
|
+
end
|
89
|
+
|
90
|
+
def to_bytes(string)
|
91
|
+
[string].pack("H*")
|
92
|
+
end
|
93
|
+
|
94
|
+
def to_string(bytes)
|
95
|
+
bytes.unpack1("H*")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "openssl"
|
4
|
+
|
5
|
+
module FlowClient
|
6
|
+
class Crypto
|
7
|
+
def self.sign(data, key)
|
8
|
+
digest = OpenSSL::Digest.digest("SHA3-256", data)
|
9
|
+
asn = key.dsa_sign_asn1(digest)
|
10
|
+
asn1 = OpenSSL::ASN1.decode(asn)
|
11
|
+
r, s = asn1.value
|
12
|
+
combined_bytes = Utils.left_pad_bytes([r.value.to_s(16)].pack("H*").unpack("C*"), 32) +
|
13
|
+
Utils.left_pad_bytes([s.value.to_s(16)].pack("H*").unpack("C*"), 32)
|
14
|
+
combined_bytes.pack("C*")
|
15
|
+
end
|
16
|
+
|
17
|
+
# TODO: Handle both sig algos here
|
18
|
+
# secp256k1
|
19
|
+
# prime256v1
|
20
|
+
def self.key_from_hex_keys(private_hex, public_hex)
|
21
|
+
asn1 = OpenSSL::ASN1::Sequence(
|
22
|
+
[
|
23
|
+
OpenSSL::ASN1::Integer(1),
|
24
|
+
OpenSSL::ASN1::OctetString([private_hex].pack("H*")),
|
25
|
+
OpenSSL::ASN1::ObjectId("prime256v1", 0, :EXPLICIT),
|
26
|
+
OpenSSL::ASN1::BitString([public_hex].pack("H*"), 1, :EXPLICIT)
|
27
|
+
]
|
28
|
+
)
|
29
|
+
|
30
|
+
OpenSSL::PKey::EC.new(asn1.to_der)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|