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
@@ -0,0 +1,189 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ #
5
+ # Proposal represents a transaction proposal that can be sent to peers for endorsement or evaluated as a query.
6
+ #
7
+ # Combined ProposalBuilder with Proposal. Utilizing instance variables and functions in proposal seem adaquate enough
8
+ # to fully create the proposal. ProposalBuilder did not seem like a native ruby design pattern.
9
+ class Proposal
10
+ attr_reader :proposed_transaction
11
+
12
+ #
13
+ # Instantiates a new Proposal
14
+ #
15
+ # @param [Fabric::ProposedTransaction] proposed_transaction ProposedTransaction container class
16
+ #
17
+ def initialize(proposed_transaction)
18
+ @proposed_transaction = proposed_transaction
19
+ end
20
+
21
+ def contract
22
+ @proposed_transaction.contract
23
+ end
24
+
25
+ include Fabric::Accessors::Contract
26
+
27
+ def transaction_id
28
+ proposed_transaction.transaction_id
29
+ end
30
+
31
+ #
32
+ # Returns the proposal message as a protobuf Message object.
33
+ #
34
+ # @return [Protos::Proposal|nil] Proposal message
35
+ #
36
+ def proposal
37
+ proposed_transaction.proposal
38
+ end
39
+
40
+ #
41
+ # Returns the signed proposal
42
+ #
43
+ # <rant>
44
+ # Fabric message naming scheme is a mess:
45
+ # ProposedTransaction has a Proposal which is a SignedProposal
46
+ # which has a Proposal which is a Proposal
47
+ # so.... which proposal do you want to access? Adding this function for clarity
48
+ # </rant>
49
+ #
50
+ # @return [Protos::SignedProposal|nil] SignedProposal message
51
+ #
52
+ def signed_proposal
53
+ proposed_transaction.proposed_transaction.proposal
54
+ end
55
+
56
+ #
57
+ # Serialized bytes of the proposal message in proto3 format.
58
+ #
59
+ # @return [String] Binary representation of the proposal message.
60
+ #
61
+ def to_proto
62
+ proposed_transaction.to_proto
63
+ end
64
+
65
+ #
66
+ # Proposal digest which can be utilized for offline signing.
67
+ # If signing offline, call signature= to set signature once
68
+ # computed.
69
+ #
70
+ # @return [String] raw binary digest of the proposal message.
71
+ #
72
+ def digest
73
+ Fabric.crypto_suite.digest(proposal.to_proto)
74
+ end
75
+
76
+ #
77
+ # Sets the signature of the signed proposal in the proposed transaction
78
+ #
79
+ # @param [String] signature raw byte string signature of the proposal message
80
+ # (should be the signature of the proposed message digest)
81
+ #
82
+ def signature=(signature)
83
+ proposed_transaction.signed_proposal.signature = signature
84
+ end
85
+
86
+ #
87
+ # Returns the signed proposal signature
88
+ #
89
+ # @return [String] Raw byte string signature
90
+ #
91
+ def signature
92
+ proposed_transaction.signed_proposal.signature
93
+ end
94
+
95
+ #
96
+ # Returns true if the signed proposal has a signature
97
+ #
98
+ # @return [Boolean] true|false
99
+ #
100
+ def signed?
101
+ # signature cannot be nil because google protobuf won't let it
102
+ !proposed_transaction.signed_proposal.signature.empty?
103
+ end
104
+
105
+ #
106
+ # Utilizes the signer to sign the proposal message if it has not been signed yet.
107
+ #
108
+ def sign
109
+ return if signed?
110
+
111
+ self.signature = signer.sign proposal.to_proto
112
+ end
113
+
114
+ #
115
+ # Evaluate the transaction proposal and obtain its result, without updating the ledger. This runs the transaction
116
+ # on a peer to obtain a transaction result, but does not submit the endorsed transaction to the orderer to be
117
+ # committed to the ledger.
118
+ #
119
+ # @param [Hash] options gRPC call options @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
120
+ #
121
+ # @return [String] The result returned by the transaction function
122
+ #
123
+ def evaluate(options = {})
124
+ sign
125
+
126
+ evaluate_response = client.evaluate(new_evaluate_request, options)
127
+ evaluate_response.result.payload
128
+ end
129
+
130
+ #
131
+ # Obtain endorsement for the transaction proposal from sufficient peers to allow it to be committed to the ledger.
132
+ #
133
+ # @param [Hash] options gRPC call options @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
134
+ #
135
+ # @return [Fabric::Transaction] An endorsed transaction that can be submitted to the ledger.
136
+ #
137
+ def endorse(options = {})
138
+ sign
139
+ endorse_response = client.endorse(new_endorse_request, options)
140
+
141
+ raise Fabric::Error, 'Missing transaction envelope' if endorse_response.prepared_transaction.nil?
142
+
143
+ prepared_transaction = new_prepared_transaction(endorse_response.prepared_transaction)
144
+
145
+ Fabric::Transaction.new(network, prepared_transaction)
146
+ end
147
+
148
+ #
149
+ # Generates an evaluate request from this proposal.
150
+ #
151
+ # @return [Gateway::EvaluateRequest] evaluation request with the current proposal
152
+ #
153
+ def new_evaluate_request
154
+ ::Gateway::EvaluateRequest.new(
155
+ channel_id: network_name,
156
+ proposed_transaction: signed_proposal,
157
+ target_organizations: proposed_transaction.endorsing_organizations
158
+ )
159
+ end
160
+
161
+ #
162
+ # Creates a new endorse request from this proposal.
163
+ #
164
+ # @return [Gateway::EndorseRequest] EndorseRequest protobuf message
165
+ #
166
+ def new_endorse_request
167
+ ::Gateway::EndorseRequest.new(
168
+ transaction_id: transaction_id,
169
+ channel_id: network_name,
170
+ proposed_transaction: signed_proposal,
171
+ endorsing_organizations: proposed_transaction.endorsing_organizations
172
+ )
173
+ end
174
+
175
+ #
176
+ # Creates a new prepared transaction from a transaction envelope.
177
+ #
178
+ # @param [Common::Envelope] envelope transaction envelope
179
+ #
180
+ # @return [Gateway::PreparedTransaction] prepared transaction protobuf message
181
+ #
182
+ def new_prepared_transaction(envelope)
183
+ ::Gateway::PreparedTransaction.new(
184
+ transaction_id: transaction_id,
185
+ envelope: envelope
186
+ )
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ #
5
+ # Manages the instantiation and creation of the Gateway::ProposedTransaction Protobuf Message.
6
+ #
7
+ # Adapted from official fabric-gateway SDK ProposalBuilder and hyperledger-fabric-sdk:
8
+ # https://github.com/hyperledger/fabric-gateway/blob/1518e03ed3d6db1b6809e23e61a92744fd18e724/node/src/proposalbuilder.ts
9
+ # https://github.com/kirshin/hyperledger-fabric-sdk/blob/95a5a1a37001852312df25946e960a9ff149207e/lib/fabric/proposal.rb
10
+ class ProposedTransaction
11
+ attr_reader :contract,
12
+ :transaction_name,
13
+ :transient_data,
14
+ :arguments,
15
+ :proposed_transaction
16
+
17
+ # Specifies the set of organizations that will attempt to endorse the proposal.
18
+ # No other organizations' peers will be sent this proposal.
19
+ # This is usually used in conjunction with transientData for private data scenarios.
20
+ attr_reader :endorsing_organizations
21
+
22
+ # @!parse include Fabric::Accessors::Network
23
+ # @!parse include Fabric::Accessors::Gateway
24
+ include Fabric::Accessors::Contract
25
+
26
+ def initialize(contract, transaction_name, arguments: [], transient_data: {}, endorsing_organizations: [])
27
+ @contract = contract
28
+ @transaction_name = transaction_name
29
+ @arguments = arguments
30
+ @transient_data = transient_data
31
+ @endorsing_organizations = endorsing_organizations
32
+
33
+ generate_proposed_transaction
34
+ end
35
+
36
+ #
37
+ # Builds the proposed transaction protobuf message
38
+ #
39
+ # @return [Gateway::ProposedTransaction]
40
+ #
41
+ def generate_proposed_transaction
42
+ @proposed_transaction = ::Gateway::ProposedTransaction.new(
43
+ transaction_id: transaction_id,
44
+ proposal: signed_proposal,
45
+ endorsing_organizations: endorsing_organizations
46
+ )
47
+ end
48
+
49
+ def signed_proposal
50
+ @signed_proposal ||= Protos::SignedProposal.new(
51
+ proposal_bytes: proposal.to_proto
52
+ )
53
+ end
54
+
55
+ def proposal
56
+ @proposal ||= Protos::Proposal.new header: header.to_proto,
57
+ payload: chaincode_proposal_payload.to_proto
58
+ end
59
+
60
+ def header
61
+ Common::Header.new channel_header: channel_header.to_proto,
62
+ signature_header: signature_header.to_proto
63
+ end
64
+
65
+ def channel_header
66
+ Common::ChannelHeader.new type: Common::HeaderType::ENDORSER_TRANSACTION,
67
+ channel_id: network_name, tx_id: transaction_id,
68
+ extension: channel_header_extension.to_proto,
69
+ timestamp: timestamp, epoch: 0
70
+ # version: Constants::CHANNEL_HEADER_VERSION # official SDK does not send this.
71
+ end
72
+
73
+ def channel_header_extension
74
+ Protos::ChaincodeHeaderExtension.new chaincode_id: chaincode_id
75
+ end
76
+
77
+ def chaincode_id
78
+ Protos::ChaincodeID.new name: chaincode_name
79
+ end
80
+
81
+ def chaincode_proposal_payload
82
+ chaincode_input = Protos::ChaincodeInput.new args: [transaction_name] + arguments
83
+ chaincode_spec = Protos::ChaincodeSpec.new type: Protos::ChaincodeSpec::Type::NODE,
84
+ chaincode_id: chaincode_id,
85
+ input: chaincode_input
86
+ input = Protos::ChaincodeInvocationSpec.new chaincode_spec: chaincode_spec
87
+
88
+ Protos::ChaincodeProposalPayload.new input: input.to_proto, TransientMap: transient_data
89
+ end
90
+
91
+ #
92
+ # Returns the current timestamp
93
+ #
94
+ # @return [Google::Protobuf::Timestamp] gRPC timestamp
95
+ #
96
+ def timestamp
97
+ now = Time.now
98
+
99
+ @timestamp ||= Google::Protobuf::Timestamp.new seconds: now.to_i, nanos: now.nsec
100
+ end
101
+
102
+ #
103
+ # Generates a random nonce
104
+ #
105
+ # @return [String] random nonce
106
+ #
107
+ def nonce
108
+ @nonce ||= signer.crypto_suite.generate_nonce
109
+ end
110
+
111
+ #
112
+ # Generates a unique transaction ID for the transaction based on a random number and the signer
113
+ # or returns the existing transaction ID if it has already been generated.
114
+ #
115
+ # @return [String] transaction ID
116
+ #
117
+ def transaction_id
118
+ @transaction_id ||= signer.crypto_suite.hexdigest(nonce + signer.to_proto)
119
+ end
120
+
121
+ #
122
+ # Generates a SignatureHeader protobuf message from the signer and nonce
123
+ #
124
+ # @return [Common::SignatureHeader] signature header protobuf message instance
125
+ #
126
+ def signature_header
127
+ Common::SignatureHeader.new creator: signer.to_proto, nonce: nonce
128
+ end
129
+
130
+ # Dev note: if we have more classes that encapsulate protobuffer messages, consider
131
+ # creating an EncapsulatedPBMessage to hold the message and expose the following methods
132
+ # as common interface.
133
+
134
+ #
135
+ # Returns the protobuf message instance
136
+ #
137
+ # @return [Gateway::ProposedTransaction] protobuf message instance
138
+ #
139
+ def as_proto
140
+ proposed_transaction
141
+ end
142
+
143
+ #
144
+ # Returns the serialized Protobuf binary form of the proposed transaction
145
+ #
146
+ # @return [String] serialized Protobuf binary form of the proposed transaction
147
+ #
148
+ def to_proto
149
+ proposed_transaction.to_proto
150
+ end
151
+
152
+ #
153
+ # Returns the serialized JSON form of the proposed transaction
154
+ #
155
+ # @param [Hash] options JSON serialization options @see https://ruby-doc.org/stdlib-2.6.3/libdoc/json/rdoc/JSON.html#method-i-generate
156
+ #
157
+ # @return [String] serialized JSON form of the proposed transaction
158
+ #
159
+ def to_json(options = {})
160
+ proposed_transaction.to_json(options)
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ #
5
+ # Status of a transaction that is to be committed to the ledger.
6
+ #
7
+ class Status
8
+ TRANSACTION_STATUSES = ::Protos::TxValidationCode.constants.map(&::Protos::TxValidationCode.method(:const_get))
9
+ .collect do |i|
10
+ [::Protos::TxValidationCode.lookup(i), i]
11
+ end.to_h
12
+
13
+ # @return [Integer] Block number in which the transaction committed.
14
+ attr_reader :block_number
15
+
16
+ # @return [Integer] Transaction status
17
+ attr_reader :code
18
+
19
+ # @return [Boolean] `true` if the transaction committed successfully; otherwise `false`.
20
+ attr_reader :successful
21
+
22
+ # @return [String] The ID of the transaction.
23
+ attr_reader :transaction_id
24
+
25
+ def initialize(transaction_id, block_number, code)
26
+ @transaction_id = transaction_id
27
+ @block_number = block_number
28
+ @code = code
29
+ @successful = @code == TRANSACTION_STATUSES[:VALID]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,247 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Fabric
4
+ #
5
+ # Represents an endorsed transaction that can be submitted to the orderer for commit to the ledger,
6
+ # query the transaction results and its commit status.
7
+ #
8
+ class Transaction
9
+ attr_reader :network
10
+
11
+ include Fabric::Accessors::Network
12
+
13
+ # @return [Gateway::PreparedTransaction] Prepared Transaction
14
+ attr_reader :prepared_transaction
15
+
16
+ # @return [Fabric::Envelope]
17
+ attr_reader :envelope
18
+
19
+ #
20
+ # Creates a new Transaction instance.
21
+ #
22
+ # @param [Fabric::Network] network
23
+ # @param [Gateway::PreparedTransaction] prepared_transaction
24
+ #
25
+ def initialize(network, prepared_transaction)
26
+ @network = network
27
+ @prepared_transaction = prepared_transaction
28
+ @envelope = Envelope.new(prepared_transaction.envelope)
29
+ end
30
+
31
+ #
32
+ # Get the transaction result. This is obtained during the endorsement process when the transaction proposal is
33
+ # run on endorsing peers.
34
+ #
35
+ # @param [boolean] check_status set to true to raise exception if transaction has not yet been committed
36
+ #
37
+ # @return [String] Raw transaction result
38
+ #
39
+ def result(check_status: true)
40
+ raise Fabric::CommitError, status if check_status && !status.successful
41
+
42
+ envelope.result
43
+ end
44
+
45
+ #
46
+ # Returns the transaction ID from the prepared transaction.
47
+ #
48
+ # @return [String] transaction_id
49
+ #
50
+ def transaction_id
51
+ prepared_transaction.transaction_id
52
+ end
53
+
54
+ #
55
+ # Submit the transaction to the orderer to be committed to the ledger.
56
+ #
57
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
58
+ #
59
+ # @param [Hash] options gRPC call options
60
+ #
61
+ # @return [Fabric::Transaction] self
62
+ def submit(options = {})
63
+ sign_submit_request
64
+
65
+ client.submit(new_submit_request, options)
66
+
67
+ self
68
+ end
69
+
70
+ #
71
+ # Sign the transaction envelope.
72
+ #
73
+ # @return [void]
74
+ def sign_submit_request
75
+ return if submit_request_signed?
76
+
77
+ signature = signer.sign(envelope.payload_bytes)
78
+ self.submit_request_signature = signature
79
+ end
80
+
81
+ #
82
+ # Returns true if the transaction envelope has been signed.
83
+ #
84
+ # @return [Boolean] true if signed; false otherwise
85
+ #
86
+ def submit_request_signed?
87
+ @envelope.signed?
88
+ end
89
+
90
+ #
91
+ # Digest to be signed to support offline signing of the submit request
92
+ #
93
+ # @return [String] digest of the submit request
94
+ #
95
+ def submit_request_digest
96
+ envelope.payload_digest
97
+ end
98
+
99
+ #
100
+ # Sets the submit request signature. This is used to support offline signing of the submit request.
101
+ #
102
+ # @param [String] signature
103
+ #
104
+ # @return [void]
105
+ #
106
+ def submit_request_signature=(signature)
107
+ envelope.signature = signature
108
+ end
109
+
110
+ #
111
+ # Get status of the committed transaction. If the transaction has not yet committed, this method blocks until the
112
+ # commit occurs. If status is already queried, this returns status from cache and does not make additional queries.
113
+ #
114
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
115
+ #
116
+ # @param [Hash] options gRPC call options
117
+ #
118
+ # @return [Fabric::Status] status of the committed transaction
119
+ #
120
+ def status(options = {})
121
+ @status ||= query_status(options)
122
+ end
123
+
124
+ #
125
+ # Digest to be signed to support offline signing of the commit status request
126
+ #
127
+ # @return [String] digest of the commit status request
128
+ #
129
+ def status_request_digest
130
+ Fabric.crypto_suite.digest(signed_commit_status_request.request)
131
+ end
132
+
133
+ #
134
+ # Sets the status request signature. This is used to support offline signing of the commit status request.
135
+ #
136
+ # @param [String] signature
137
+ #
138
+ # @return [void]
139
+ #
140
+ def status_request_signature=(signature)
141
+ signed_commit_status_request.signature = signature
142
+ end
143
+
144
+ #
145
+ # Returns true if the signed commit status request has been signed.
146
+ #
147
+ # @return [Boolean] true if signed; false otherwise
148
+ #
149
+ def status_request_signed?
150
+ !signed_commit_status_request.signature.empty?
151
+ end
152
+
153
+ #
154
+ # Sign the signed commit status request
155
+ #
156
+ # @return [Fabric::Transaction] self
157
+ #
158
+ def sign_status_request
159
+ return if status_request_signed?
160
+
161
+ signature = signer.sign(signed_commit_status_request.request)
162
+ signed_commit_status_request.signature = signature
163
+
164
+ self
165
+ end
166
+
167
+ #
168
+ # Returns the current instance of the signed commit status request. Necessary so we can keep the state of the
169
+ # signature in the transaction object.
170
+ #
171
+ # @return [Gateway::SignedCommitStatusRequest] signed commit status request
172
+ #
173
+ def signed_commit_status_request
174
+ @signed_commit_status_request ||= new_signed_commit_status_request
175
+ end
176
+
177
+ private
178
+
179
+ #
180
+ # Actual status query call used by status method.
181
+ #
182
+ # @see https://www.rubydoc.info/gems/grpc/GRPC%2FClientStub:request_response
183
+ #
184
+ # @param [Hash] options gRPC call options
185
+ #
186
+ # @return [Fabric::Status] status of the committed transaction
187
+ #
188
+ def query_status(options = {})
189
+ sign_status_request
190
+
191
+ commit_status_response = client.commit_status(signed_commit_status_request, options)
192
+ new_status(commit_status_response)
193
+ end
194
+
195
+ #
196
+ # Generates a new signed commit status request
197
+ #
198
+ # @return [Gateway::SignedCommitStatusRequest] signed commit status request protobuf message
199
+ #
200
+ def new_signed_commit_status_request
201
+ ::Gateway::SignedCommitStatusRequest.new(
202
+ request: new_commit_status_request.to_proto
203
+ )
204
+ end
205
+
206
+ #
207
+ # Generates a new commit status request
208
+ #
209
+ # @return [Gateway::CommitStatusRequest] commit status request protobuf message
210
+ #
211
+ def new_commit_status_request
212
+ ::Gateway::CommitStatusRequest.new(
213
+ channel_id: network_name,
214
+ transaction_id: transaction_id,
215
+ identity: signer.to_proto
216
+ )
217
+ end
218
+
219
+ #
220
+ # Generates a new submit request.
221
+ #
222
+ # @return [Gateway::SubmitRequest] submit request protobuf message
223
+ #
224
+ def new_submit_request
225
+ ::Gateway::SubmitRequest.new(
226
+ transaction_id: transaction_id,
227
+ channel_id: network_name,
228
+ prepared_transaction: envelope.envelope
229
+ )
230
+ end
231
+
232
+ #
233
+ # New Status from CommitStatusResponse
234
+ #
235
+ # @param [Gateway::CommitStatusResponse] response commit status response
236
+ #
237
+ # @return [Fabric::Status] transaction status
238
+ #
239
+ def new_status(response)
240
+ Fabric::Status.new(
241
+ transaction_id,
242
+ response.block_number,
243
+ Fabric::Status::TRANSACTION_STATUSES[response.result]
244
+ )
245
+ end
246
+ end
247
+ end
@@ -1,10 +1,35 @@
1
- require "fabric/gateway/version"
2
- require "gateway/gateway_pb"
3
- require "gateway/gateway_services_pb"
1
+ # frozen_string_literal: true
4
2
 
5
3
  module Fabric
6
- module Gateway
7
- class Error < StandardError; end
8
- # Your code goes here...
4
+ #
5
+ # Gateway represents the connection of a specific client identity to a Fabric Gateway.
6
+ #
7
+ class Gateway
8
+ attr_reader :signer, :client
9
+
10
+ #
11
+ # Initialize a new Gateway
12
+ #
13
+ # @param [Fabric::Identity] signer identity utilized to sign transactions
14
+ # @param [Fabric::Client] client Gateway Client
15
+ #
16
+ def initialize(signer, client)
17
+ raise InvalidArgument, 'signer must be Fabric::Identity' unless signer.is_a? Fabric::Identity
18
+ raise InvalidArgument, 'client must be Fabric::Client' unless client.is_a? Fabric::Client
19
+
20
+ @signer = signer
21
+ @client = client
22
+ end
23
+
24
+ #
25
+ # Initialize new network from the Gateway
26
+ #
27
+ # @param [string] name channel name
28
+ #
29
+ # @return [Fabric::Network] returns a new network
30
+ #
31
+ def new_network(name)
32
+ Network.new(self, name)
33
+ end
9
34
  end
10
35
  end