fabric-gateway 0.0.2 → 0.4.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +3 -0
  3. data/.github/workflows/codeql-analysis.yml +71 -0
  4. data/.github/workflows/rspec.yml +37 -0
  5. data/.github/workflows/rubocop.yml +28 -0
  6. data/.github/workflows/todo.yml +10 -0
  7. data/.github/workflows/yardoc.yml +28 -0
  8. data/.gitignore +1 -0
  9. data/.rubocop.yml +23 -0
  10. data/.ruby-version +1 -0
  11. data/.vscode/settings.json +7 -0
  12. data/.yardopts +8 -0
  13. data/CODE_OF_CONDUCT.md +105 -46
  14. data/Gemfile +5 -3
  15. data/LICENSE.txt +1 -1
  16. data/README.md +123 -12
  17. data/Rakefile +6 -3
  18. data/bin/console +4 -3
  19. data/bin/regenerate +1 -0
  20. data/bin/release +5 -0
  21. data/fabric-gateway.gemspec +31 -17
  22. data/lib/fabric/accessors/contract.rb +51 -0
  23. data/lib/fabric/accessors/gateway.rb +33 -0
  24. data/lib/fabric/accessors/network.rb +40 -0
  25. data/lib/fabric/client.rb +199 -0
  26. data/lib/fabric/constants.rb +8 -0
  27. data/lib/fabric/contract.rb +178 -0
  28. data/lib/fabric/ec_crypto_suite.rb +199 -0
  29. data/lib/fabric/entities/chaincode_events_requests.rb +166 -0
  30. data/lib/fabric/entities/envelope.rb +158 -0
  31. data/lib/fabric/entities/identity.rb +87 -0
  32. data/lib/fabric/entities/proposal.rb +189 -0
  33. data/lib/fabric/entities/proposed_transaction.rb +163 -0
  34. data/lib/fabric/entities/status.rb +32 -0
  35. data/lib/fabric/entities/transaction.rb +247 -0
  36. data/lib/fabric/gateway.rb +31 -6
  37. data/lib/fabric/network.rb +70 -0
  38. data/lib/fabric/version.rb +5 -0
  39. data/lib/fabric.rb +59 -0
  40. data/lib/msp/identities_pb.rb +25 -0
  41. metadata +162 -13
  42. data/Gemfile.lock +0 -42
  43. data/lib/fabric/gateway/version.rb +0 -5
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "fabric/gateway"
4
+ require 'bundler/setup'
5
+ require 'fabric'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "fabric/gateway"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
data/bin/regenerate CHANGED
@@ -16,3 +16,4 @@ grpc_tools_ruby_protoc -I ./fabric-protos --ruby_out=./lib --grpc_out=./lib ./fa
16
16
  grpc_tools_ruby_protoc -I ./fabric-protos --ruby_out=./lib --grpc_out=./lib ./fabric-protos/orderer/ab.proto
17
17
  grpc_tools_ruby_protoc -I ./fabric-protos --ruby_out=./lib --grpc_out=./lib ./fabric-protos/gossip/message.proto
18
18
  grpc_tools_ruby_protoc -I ./fabric-protos --ruby_out=./lib --grpc_out=./lib ./fabric-protos/msp/msp_principal.proto
19
+ grpc_tools_ruby_protoc -I ./fabric-protos --ruby_out=./lib --grpc_out=./lib ./fabric-protos/msp/identities.proto
data/bin/release ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+
3
+ # Requires gem install gem-release
4
+ # usage: bin/relase -v minor|major|etc.
5
+ gem bump --file lib/fabric/version.rb -t -r $@
@@ -1,31 +1,45 @@
1
- require_relative 'lib/fabric/gateway/version'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/fabric/version'
2
4
 
3
5
  Gem::Specification.new do |spec|
4
- spec.name = "fabric-gateway"
5
- spec.version = Fabric::Gateway::VERSION
6
- spec.authors = ["Jonathan Chan"]
7
- spec.email = ["jonathan.chan@ethicalidentity.com"]
6
+ spec.name = 'fabric-gateway'
7
+ spec.version = Fabric::VERSION
8
+ spec.authors = ['Jonathan Chan']
9
+ spec.email = ['jonathan.chan@ethicalidentity.com']
8
10
 
9
- spec.summary = %q{Hyperledger Fabric Gateway gRPC SDK}
10
- spec.description = %q{Hyperledger Fabric Gateway gRPC SDK generated directly from protos found at: https://github.com/hyperledger/fabric-protos.}
11
- spec.homepage = "https://github.com/ethicalidentity/fabric-gateway-ruby"
12
- spec.license = "MIT"
13
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
11
+ spec.summary = 'Hyperledger Fabric Gateway SDK'
12
+ spec.description = 'Ruby port of the Hyperledger Fabric Gateway SDK'
13
+ spec.homepage = 'https://github.com/ethicalidentity/fabric-gateway-ruby'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0')
14
16
 
15
- spec.metadata["allowed_push_host"] = 'https://rubygems.org'
17
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
16
18
 
17
- spec.metadata["homepage_uri"] = spec.homepage
18
- spec.metadata["source_code_uri"] = "https://github.com/ethicalidentity/fabric-gateway-ruby"
19
- spec.metadata["changelog_uri"] = "https://github.com/EthicalIdentity/fabric-gateway-ruby/blob/master/CHANGELOG.md"
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = 'https://github.com/ethicalidentity/fabric-gateway-ruby'
21
+ spec.metadata['changelog_uri'] = 'https://github.com/EthicalIdentity/fabric-gateway-ruby/blob/master/CHANGELOG.md'
20
22
 
21
23
  # Specify which files should be added to the gem when it is released.
22
24
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
25
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
26
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
27
  end
26
- spec.bindir = "exe"
28
+ spec.bindir = 'exe'
27
29
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
- spec.require_paths = ["lib"]
30
+ spec.require_paths = ['lib']
29
31
  spec.add_dependency('google-protobuf', '>= 3.19.1')
30
32
  spec.add_dependency('grpc', '~> 1.42')
33
+ spec.add_development_dependency('codecov', '~> 0.6.0')
34
+ spec.add_development_dependency('factory_bot', '~> 6.2.0')
35
+ spec.add_development_dependency('grpc-tools', '~> 1.42')
36
+ spec.add_development_dependency('rake-notes', '~> 0.2.0')
37
+ spec.add_development_dependency('rubocop', '~> 1.23.0')
38
+ spec.add_development_dependency('rubocop-rspec', '~> 2.6.0')
39
+ spec.add_development_dependency('simplecov', '~> 0.21.2')
40
+ spec.add_development_dependency('timecop', '~> 0.9.4')
41
+ spec.add_development_dependency('yard', '~> 0.9.27')
42
+ spec.metadata = {
43
+ 'rubygems_mfa_required' => 'true'
44
+ }
31
45
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ module Accessors
5
+ #
6
+ # Add accessor methods to the given class.
7
+ #
8
+ # Usage: make sure the class has a contract accessor method
9
+ # and then `include Fabric::Accessors::Contract`
10
+ #
11
+ module Contract
12
+ # @!visibility private
13
+ def self.included(base)
14
+ base.send :include, Fabric::Accessors::Network
15
+ end
16
+
17
+ # @!parse include Fabric::Accessors::Network
18
+ # @!parse include Fabric::Accessors::Gateway
19
+
20
+ #
21
+ # Returns the network instance
22
+ #
23
+ # @return [Fabric::Network] network
24
+ # @!parse attr_reader :network
25
+ #
26
+ def network
27
+ contract.network
28
+ end
29
+
30
+ #
31
+ # Returns the contract name
32
+ #
33
+ # @return [String] contract name
34
+ # @!parse attr_reader :contract_name
35
+ #
36
+ def contract_name
37
+ contract.contract_name
38
+ end
39
+
40
+ #
41
+ # Returns the chaincode name
42
+ #
43
+ # @return [String] chaincode name
44
+ # @!parse attr_reader :chaincode_name
45
+ #
46
+ def chaincode_name
47
+ contract.chaincode_name
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ module Accessors
5
+ #
6
+ # Add accessor methods to the given class.
7
+ #
8
+ # Usage: make sure the class has a gateway accessor method
9
+ # and then `include Fabric::Accessors::Gateway`
10
+ #
11
+ module Gateway
12
+ #
13
+ # Returns the client instance
14
+ #
15
+ # @return [Fabric::Client] client
16
+ # @!parse attr_reader :client
17
+ #
18
+ def client
19
+ gateway.client
20
+ end
21
+
22
+ #
23
+ # Returns the signer identity instance
24
+ #
25
+ # @return [Fabric::Identity] signer
26
+ # @!parse attr_reader :signer
27
+ #
28
+ def signer
29
+ gateway.signer
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ module Accessors
5
+ #
6
+ # Add accessor methods to the given class.
7
+ #
8
+ # Usage: make sure the class has a network accessor method
9
+ # and then `include Fabric::Accessors::Network`
10
+ #
11
+ module Network
12
+ # @!visibility private
13
+ def self.included(base)
14
+ base.send :include, Fabric::Accessors::Gateway
15
+ end
16
+
17
+ # @!parse include Fabric::Accessors::Gateway
18
+
19
+ #
20
+ # Returns the gateway instance
21
+ #
22
+ # @return [Fabric::Gateway] gateway
23
+ # @!parse attr_reader :gateway
24
+ #
25
+ def gateway
26
+ network.gateway
27
+ end
28
+
29
+ #
30
+ # Network name or the channel name or channel id
31
+ #
32
+ # @return [String] network name
33
+ # @!parse attr_reader :network_name
34
+ #
35
+ def network_name
36
+ network.name
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ #
5
+ # Gateway Client represents the connection to a Hyperledger Fabric Gateway.
6
+ #
7
+ class Client
8
+ attr_reader :grpc_client, :default_call_options
9
+
10
+ #
11
+ # Initializes a client
12
+ #
13
+ #
14
+ # @overload initialize(grpc_client: client, default_call_options: {}, **client_opts)
15
+ # Initializes a client from a gRPC Gateway client stub
16
+ # @param [Gateway::Gateway::Stub] grpc_client grpc gateway client stub
17
+ # @param [Hash] default_call_options call options to use by default for different operations
18
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response Keyword Argument call options for
19
+ # *_options default_call_options
20
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:initialize Keyword arguments for **client_opts
21
+ # @option default_call_options [Hash] :endorse_options default options for endorse call
22
+ # @option default_call_options [Hash] :evaluate_options default options for evaluate call
23
+ # @option default_call_options [Hash] :submit_options default options for submit call
24
+ # @option default_call_options [Hash] :commit_status_options default options for commit_status call
25
+ # @option default_call_options [Hash] :chaincode_events_options default options for chaincode_events call
26
+ # @param [Hash] **client_opts client initialization options
27
+ # @overload initialize(host: host, creds: creds, default_call_options: {}, **client_opts)
28
+ # Instantiates a new gRPC Gateway client stub from the parameters
29
+ # @param [string] host hostname and port of the gateway
30
+ # @param [GRPC::Core::ChannelCredentials|GRPC::Core::XdsChannelCredentials|Symbol] creds channel credentials
31
+ # (usually the CA certificate)
32
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response Keyword Argument call options for
33
+ # *_options default_call_options
34
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:initialize Keyword arguments for **client_opts
35
+ # @option default_call_options [Hash] :endorse_options default options for endorse call
36
+ # @option default_call_options [Hash] :evaluate_options default options for evaluate call
37
+ # @option default_call_options [Hash] :submit_options default options for submit call
38
+ # @option default_call_options [Hash] :commit_status_options default options for commit_status call
39
+ # @option default_call_options [Hash] :chaincode_events_options default options for chaincode_events call
40
+ # @param [Hash] **client_opts client initialization options
41
+ #
42
+ def initialize(grpc_client: nil, host: nil, creds: nil, default_call_options: {}, **client_opts)
43
+ if grpc_client
44
+ init_stub grpc_client
45
+ elsif host && creds
46
+ init_grpc_args(host, creds, **client_opts)
47
+ else
48
+ raise InvalidArgument, 'Must pass a Gateway::Gateway::Stub or <host>, <creds>, <client_opts>'
49
+ end
50
+ init_call_options(default_call_options)
51
+ end
52
+
53
+ #
54
+ # Submits an evaluate_request to the gateway to be evaluted.
55
+ #
56
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response Call options for options parameter
57
+ # @param [Gateway::EvaluateRequest] evaluate_request
58
+ # @param [Hash] options gRPC call options (merged with default_call_options from initializer)
59
+ #
60
+ # @return [Gateway::EvaluateResponse] evaluate_response
61
+ #
62
+ def evaluate(evaluate_request, options = {})
63
+ @grpc_client.evaluate(evaluate_request, @default_call_options[:evaluate_options].merge(options))
64
+ end
65
+
66
+ #
67
+ # Submits an endorse_request to the gateway to be evaluted.
68
+ #
69
+ # @param [Gateway::EndorseRequest] endorse_request
70
+ # @param [Hash] options gRPC call options (merged with default options) @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
71
+ #
72
+ # @return [Gateway::EndorseResponse] endorse_response
73
+ #
74
+ def endorse(endorse_request, options = {})
75
+ @grpc_client.endorse(endorse_request, @default_call_options[:endorse_options].merge(options))
76
+ end
77
+
78
+ #
79
+ # Submits an submit_request to the gateway to be evaluted.
80
+ #
81
+ # @param [Gateway::SubmitRequest] submit_request
82
+ # @param [Hash] options gRPC call options (merged with default options) @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
83
+ #
84
+ # @return [Gateway::SubmitResponse] submit_response
85
+ #
86
+ def submit(submit_request, options = {})
87
+ @grpc_client.submit(submit_request, @default_call_options[:submit_options].merge(options))
88
+ end
89
+
90
+ #
91
+ # Submits an commit_status_request to the gateway to be evaluted.
92
+ #
93
+ # @param [Gateway::CommitStatusRequest] commit_status_request
94
+ # @param [Hash] options gRPC call options (merged with default options) @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
95
+ #
96
+ # Returns an enum or if you pass a block, use the block.
97
+ # @return [Gateway::CommitStatusResponse] commit_status_response
98
+ #
99
+ def commit_status(commit_status_request, options = {})
100
+ @grpc_client.commit_status(commit_status_request, @default_call_options[:commit_status_options].merge(options))
101
+ end
102
+
103
+ #
104
+ # Subscribe to chaincode events
105
+ #
106
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:server_streamer GRPC::ClientStub#server_streamer
107
+ # - gRPC Underlying Call Reference
108
+ #
109
+ #
110
+ # @overload chaincode_events(chaincode_events_request)
111
+ # @example Utilizing Blocking Enumerator
112
+ # call = client.chaincode_events(chaincode_events_request)
113
+ # call.each do |event|
114
+ # pp event
115
+ # end
116
+ # @param [Gateway::ChaincodeEventsRequest] chaincode_events_request
117
+ # @param [Hash] options gRPC call options (merged with default options)
118
+ # @return [Enumerator] enumerator with Gateway::ChaincodeEventsResponse objects
119
+ # @overload chaincode_events(chaincode_events_request)
120
+ # @example Utilizing a blocking block
121
+ # client.chaincode_events(chaincode_events_request) do |event|
122
+ # pp event
123
+ # end
124
+ # @param [Gateway::ChaincodeEventsRequest] chaincode_events_request
125
+ # @param [Hash] options gRPC call options (merged with default options)
126
+ # @yield [event] Blocking call that yields Gateway::ChaincodeEventsResponse objects when received from the server
127
+ # @yieldparam event [Gateway::ChaincodeEventsResponse] chaincode event
128
+ # @return [nil]
129
+ # @overload chaincode_events(chaincode_events_request, {return_op: true})
130
+ # @example Utilizing an operation control object and a enumerator
131
+ # op = client.chaincode_events(chaincode_events_request, {return_op: true})
132
+ #
133
+ # t = Thread.new do
134
+ # call = op.execute
135
+ # call.each do |event|
136
+ # pp event
137
+ # end
138
+ # end
139
+ #
140
+ # op.status
141
+ # op.cancelled?
142
+ # op.cancel
143
+ # @param [Gateway::ChaincodeEventsRequest] chaincode_events_request
144
+ # @param [Hash] options gRPC call options (merged with default options)
145
+ # @return [GRPC::ActiveCall::Operation]
146
+ # @overload chaincode_events(chaincode_events_request, {return_op: true})
147
+ # @example Utilizing an operation control object and a block
148
+ # op = client.chaincode_events(chaincode_events_request, {return_op: true}) do |event|
149
+ # pp event
150
+ # end
151
+ #
152
+ # t = Thread.new do
153
+ # call = op.execute
154
+ # end
155
+ #
156
+ # op.status
157
+ # op.cancelled?
158
+ # op.cancel
159
+ # @param [Gateway::ChaincodeEventsRequest] chaincode_events_request
160
+ # @param [Hash] options gRPC call options (merged with default options)
161
+ # @yield [event] Blocking call that yields Gateway::ChaincodeEventsResponse objects when received from the server
162
+ # @yieldparam event [Gateway::ChaincodeEventsResponse] chaincode event
163
+ # @return [GRPC::ActiveCall::Operation]
164
+ #
165
+ def chaincode_events(chaincode_events_request, options = {}, &block)
166
+ @grpc_client.chaincode_events(chaincode_events_request,
167
+ @default_call_options[:chaincode_events_options].merge(options), &block)
168
+ end
169
+
170
+ private
171
+
172
+ def init_stub(stub)
173
+ unless stub.is_a? ::Gateway::Gateway::Stub
174
+ raise InvalidArgument, 'Must pass a Gateway::Gateway::Stub or <host>, <creds>, <client_opts>'
175
+ end
176
+
177
+ @grpc_client = stub
178
+ end
179
+
180
+ def init_grpc_args(host, creds, **client_opts)
181
+ unless creds.is_a?(GRPC::Core::ChannelCredentials) ||
182
+ creds.is_a?(GRPC::Core::XdsChannelCredentials) ||
183
+ creds.is_a?(Symbol)
184
+ raise InvalidArgument, 'creds is not a ChannelCredentials, XdsChannelCredentials, or Symbol'
185
+ end
186
+
187
+ @grpc_client = ::Gateway::Gateway::Stub.new(host, creds, **client_opts)
188
+ end
189
+
190
+ def init_call_options(call_options)
191
+ @default_call_options = call_options
192
+ @default_call_options[:endorse_options] ||= {}
193
+ @default_call_options[:evaluate_options] ||= {}
194
+ @default_call_options[:submit_options] ||= {}
195
+ @default_call_options[:commit_status_options] ||= {}
196
+ @default_call_options[:chaincode_events_options] ||= {}
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ module Constants
5
+ ## Variables
6
+ CHANNEL_HEADER_VERSION = 1
7
+ end
8
+ end
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ #
5
+ # Contract represents a smart contract, and allows applications to:
6
+ #
7
+ # - Evaluate transactions that query state from the ledger using the EvaluateTransaction() method.
8
+ #
9
+ # - Submit transactions that store state to the ledger using the SubmitTransaction() method.
10
+ #
11
+ # For more complex transaction invocations, such as including transient data, transactions can be evaluated or
12
+ # submitted using the Evaluate() or Submit() methods respectively. The result of a submitted transaction can be
13
+ # accessed prior to its commit to the ledger using SubmitAsync().
14
+ #
15
+ # By default, proposal, transaction and commit status messages will be signed using the signing implementation
16
+ # specified when connecting the Gateway. In cases where an external client holds the signing credentials, a signing
17
+ # implementation can be omitted when connecting the Gateway and off-line signing can be carried out by:
18
+ #
19
+ # 1. Returning the serialized proposal, transaction or commit status along with its digest to the client for
20
+ # them to generate a signature.
21
+ #
22
+ # 2. With the serialized message and signature received from the client to create a signed proposal, transaction or
23
+ # commit using the Gateway's NewSignedProposal(), NewSignedTransaction() or NewSignedCommit() methods respectively.
24
+ #
25
+ class Contract
26
+ attr_reader :network, :chaincode_name, :contract_name
27
+
28
+ # @!parse include Fabric::Accessors::Network
29
+ # @!parse include Fabric::Accessors::Gateway
30
+ include Fabric::Accessors::Network
31
+
32
+ def initialize(network, chaincode_name, contract_name = '')
33
+ @network = network
34
+ @chaincode_name = chaincode_name
35
+ @contract_name = contract_name
36
+ end
37
+
38
+ #
39
+ # Evaluate a transaction function and return its results. A transaction proposal will be evaluated on endorsing
40
+ # peers but the transaction will not be sent to the ordering service and so will not be committed to the ledger.
41
+ # This can be used for querying the world state.
42
+ #
43
+ # @param [String] transaction_name
44
+ # @param [Array] arguments array of arguments to pass to the transaction
45
+ #
46
+ # @return [String] raw payload of the transaction response
47
+ #
48
+ def evaluate_transaction(transaction_name, arguments = [])
49
+ evaluate(transaction_name, { arguments: arguments })
50
+ end
51
+
52
+ #
53
+ # Submit a transaction to the ledger and return its result only after it is committed to the ledger. The
54
+ # transaction function will be evaluated on endorsing peers and then submitted to the ordering service to be
55
+ # committed to the ledger.
56
+ #
57
+ #
58
+ # @param [String] transaction_name
59
+ # @param [Array] arguments array of arguments to pass to the transaction
60
+ #
61
+ # @return [String] raw payload of the transaction response
62
+ #
63
+ def submit_transaction(transaction_name, arguments = [])
64
+ submit(transaction_name, { arguments: arguments })
65
+ end
66
+
67
+ #
68
+ # Evaluate a transaction function and return its result. This method provides greater control over the transaction
69
+ # proposal content and the endorsing peers on which it is evaluated. This allows transaction functions to be
70
+ # evaluated where the proposal must include transient data, or that will access ledger data with key-based
71
+ # endorsement policies.
72
+ #
73
+ # @param [String] transaction_name
74
+ # @param [Hash] proposal_options
75
+ # @option proposal_options [Array] :arguments array of arguments to pass to the transaction
76
+ # @option proposal_options [Hash] :transient_data Private data passed to the transaction function but not recorded
77
+ # on the ledger.
78
+ # @option proposal_options [Array] :endorsing_organizations Specifies the set of organizations that will attempt to
79
+ # endorse the proposal.
80
+ #
81
+ # @return [String] Raw evaluation response payload
82
+ #
83
+ def evaluate(transaction_name, proposal_options = {})
84
+ new_proposal(transaction_name, **proposal_options).evaluate
85
+ end
86
+
87
+ #
88
+ # Submit a transaction to the ledger and return its result only after it is committed to the ledger. The
89
+ # transaction function will be evaluated on endorsing peers and then submitted to the ordering service to be
90
+ # committed to the ledger.
91
+ #
92
+ # @param [String] transaction_name
93
+ # @param [Hash] proposal_options
94
+ # @option proposal_options [Array] :arguments array of arguments to pass to the transaction
95
+ # @option proposal_options [Hash] :transient_data Private data passed to the transaction function but not recorded
96
+ # on the ledger.
97
+ # @option proposal_options [Array] :endorsing_organizations Specifies the set of organizations that will attempt to
98
+ # endorse the proposal.
99
+ #
100
+ # @return [String] Raw evaluation response payload
101
+ #
102
+ def submit(transaction_name, proposal_options = {})
103
+ transaction = new_proposal(transaction_name, **proposal_options).endorse
104
+ transaction.submit
105
+
106
+ transaction.result
107
+ end
108
+
109
+ #
110
+ # @todo unimplemented, not sure if this can be implemented because
111
+ # the official grpc ruby client does not support non-blocking async
112
+ # calls (https://github.com/grpc/grpc/issues/10973)
113
+ #
114
+ # not 100% sure if grpc support is necessary for this.
115
+ #
116
+ def submit_async
117
+ raise NotYetImplemented
118
+ end
119
+
120
+ #
121
+ # Get chaincode events emitted by transaction functions of the chaincode.
122
+ #
123
+ # @see Fabric::Client#chaincode_events Fabric::Client#chaincode_events - explanation of the different return types
124
+ # and example usage.
125
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:server_streamer Call options for options parameter
126
+ #
127
+ # @param [Integer] start_block Block number at which to start reading chaincode events.
128
+ # @param [Hash] call_options gRPC call options (merged with default_call_options from initializer)
129
+ # @yield [chaincode_event] loops through the chaincode events
130
+ # @yieldparam [Gateway::ChaincodeEventsResponse] chaincode_event the chaincode event
131
+ #
132
+ # @return [Enumerator|GRPC::ActiveCall::Operation|nil] Dependent on parameters passed;
133
+ # please see Fabric::Client#get_chaincode_events
134
+ #
135
+ def chaincode_events(start_block: nil, call_options: {}, &block)
136
+ network.chaincode_events(
137
+ self,
138
+ start_block: start_block,
139
+ call_options: call_options,
140
+ &block
141
+ )
142
+ end
143
+
144
+ #
145
+ # Creates a transaction proposal that can be evaluated or endorsed. Supports off-line signing flow.
146
+ #
147
+ # @param [String] transaction_name transaction name (first argument unshifted into the argument array)
148
+ # @param [Array<String>] arguments array of arguments to pass to the transaction
149
+ # @param [Hash] transient_data Private data passed to the transaction function but not recorded on the ledger.
150
+ # @param [Array] endorsing_organizations Specifies the set of organizations that will attempt to endorse the
151
+ # proposal.
152
+ #
153
+ # @return [Fabric::Proposal] signed unexecuted proposal
154
+ #
155
+ def new_proposal(transaction_name, arguments: [], transient_data: {}, endorsing_organizations: [])
156
+ proposed_transaction = ProposedTransaction.new(
157
+ self,
158
+ qualified_transaction_name(transaction_name),
159
+ arguments: arguments,
160
+ transient_data: transient_data,
161
+ endorsing_organizations: endorsing_organizations
162
+ )
163
+ Proposal.new(proposed_transaction)
164
+ end
165
+
166
+ #
167
+ # Generates the qualified transaction name for the contract. (prepends the contract name to the transaction name if
168
+ # contract name is set)
169
+ #
170
+ # @param [string] transaction_name
171
+ #
172
+ # @return [string] qualified transaction name
173
+ #
174
+ def qualified_transaction_name(transaction_name)
175
+ contract_name.nil? || contract_name.empty? ? transaction_name : "#{contract_name}:#{transaction_name}"
176
+ end
177
+ end
178
+ end