@@ -57,10 +57,12 @@ class _ClientCallDetails(
5757 "eth_rpc_endpoint" : "https://kovan.infura.io" ,
5858 "ipfs_rpc_endpoint" : "http://ipfs.singularitynet.io:80" ,
5959 "private_key" : None ,
60+ "signer_private_key" : None ,
6061 "account_index" : 0 ,
6162 "default_gas" : 1000000 ,
6263 "mpe_address" : None ,
63- "token_address" : None
64+ "token_address" : None ,
65+ "allow_transactions" : False
6466}
6567
6668
@@ -73,10 +75,12 @@ def __init__(
7375 eth_rpc_endpoint = snet_sdk_defaults ["eth_rpc_endpoint" ],
7476 ipfs_rpc_endpoint = snet_sdk_defaults ["ipfs_rpc_endpoint" ],
7577 private_key = snet_sdk_defaults ["private_key" ],
78+ signer_private_key = snet_sdk_defaults ["signer_private_key" ],
7679 account_index = snet_sdk_defaults ["account_index" ],
7780 default_gas = snet_sdk_defaults ["default_gas" ],
7881 mpe_address = snet_sdk_defaults ["mpe_address" ],
79- token_address = snet_sdk_defaults ["token_address" ]
82+ token_address = snet_sdk_defaults ["token_address" ],
83+ allow_transactions = snet_sdk_defaults ["allow_transactions" ]
8084 ):
8185 self .libraries_base_path = libraries_base_path
8286 self .default_gas = default_gas
@@ -96,6 +100,19 @@ def __init__(
96100 else : # Working with an unlocked account, for example
97101 self .address = web3 .Web3 .toChecksumAddress (web3 .eth .accounts [account_index ])
98102
103+
104+ if self .private_key is not None and signer_private_key is None :
105+ self .signer_private_key = self .private_key
106+ else :
107+ self .signer_private_key = signer_private_key
108+
109+ signer_public_key = ecdsa .SigningKey .from_string (string = self .private_key ,
110+ curve = ecdsa .SECP256k1 ,
111+ hashfunc = hashlib .sha256 ).get_verifying_key ()
112+
113+ self .signer_address = web3 .Web3 .toChecksumAddress ("0x" + web3 .Web3 .sha3 (hexstr = signer_public_key .to_string ().hex ())[12 :].hex ())
114+
115+
99116 # Instantiate Ethereum client
100117 provider = web3 .HTTPProvider (eth_rpc_endpoint )
101118 self .web3 = web3 .Web3 (provider )
@@ -172,9 +189,9 @@ def _get_channels(self, recipient_address=None):
172189 self .logs = self .web3 .eth .getLogs ({"fromBlock" : self ._get_contract_deployment_block ("MultiPartyEscrow.json" ), "address" : self .mpe_contract .address , "topics" : topics })
173190 event_abi = {'anonymous' : False , 'inputs' : [{'indexed' : False , 'name' : 'channelId' , 'type' : 'uint256' }, {'indexed' : False , 'name' : 'nonce' , 'type' : 'uint256' }, {'indexed' : True , 'name' : 'sender' , 'type' : 'address' }, {'indexed' : False , 'name' : 'signer' , 'type' : 'address' }, {'indexed' : True , 'name' : 'recipient' , 'type' : 'address' }, {'indexed' : True , 'name' : 'groupId' , 'type' : 'bytes32' }, {'indexed' : False , 'name' : 'amount' , 'type' : 'uint256' }, {'indexed' : False , 'name' : 'expiration' , 'type' : 'uint256' }], 'name' : 'ChannelOpen' , 'type' : 'event' }
174191 if recipient_address is None :
175- channels = list (filter (lambda channel : channel .sender == self .address , [web3 .utils .events .get_event_data (event_abi , l )["args" ] for l in self .logs ]))
192+ channels = list (filter (lambda channel : channel .sender == self .address and channel . signer == self . signer_address , [web3 .utils .events .get_event_data (event_abi , l )["args" ] for l in self .logs ]))
176193 else :
177- channels = list (filter (lambda channel : channel .sender == self .address and channel .recipient == recipient_address , [web3 .utils .events .get_event_data (event_abi , l )["args" ] for l in self .logs ]))
194+ channels = list (filter (lambda channel : channel .sender == self .address and channel .signer == self . signer_address and channel . recipient == recipient_address , [web3 .utils .events .get_event_data (event_abi , l )["args" ] for l in self .logs ]))
178195 return channels
179196
180197
@@ -197,13 +214,13 @@ def mpe_withdraw(self, value):
197214
198215
199216 def mpe_open_channel (self , recipient_address , group_id , value , expiration ):
200- receipt = self ._send_transaction (self .mpe_contract .functions .openChannel , self .address , recipient_address , group_id , value , expiration )
217+ receipt = self ._send_transaction (self .mpe_contract .functions .openChannel , self .signer_address , recipient_address , group_id , value , expiration )
201218 return self ._parse_receipt (receipt , self .mpe_contract .events .ChannelOpen , encoder = ChannelOpenEncoder )
202219
203220
204221 def mpe_deposit_and_open_channel (self , recipient_address , group_id , value , expiration ):
205222 self ._token_approve_transfer (value )
206- receipt = self ._send_transaction (self .mpe_contract .functions .depositAndOpenChannel , self .address , recipient_address , group_id , value , expiration )
223+ receipt = self ._send_transaction (self .mpe_contract .functions .depositAndOpenChannel , self .signer_address , recipient_address , group_id , value , expiration )
207224 return self ._parse_receipt (receipt , self .mpe_contract .events .ChannelOpen , encoder = ChannelOpenEncoder )
208225
209226
@@ -279,7 +296,7 @@ def client(self, *args, org_id=None, service_id=None, channel_id=None):
279296 default_group = web3 .utils .datastructures .AttributeDict (client .metadata .groups [0 ])
280297 client .default_payment_address = default_group ["payment_address" ]
281298 default_channel_value = client .metadata .pricing ["price_in_cogs" ]* 100
282- default_channel_expiration = self .web3 .eth .getBlock ("latest" ).number + client .metadata .payment_expiration_threshold + (3600 * 24 * 7 / self .average_block_time )
299+ default_channel_expiration = int ( self .web3 .eth .getBlock ("latest" ).number + client .metadata .payment_expiration_threshold + (3600 * 24 * 7 / self .average_block_time ) )
283300 service_endpoint = None
284301 for endpoint in client .metadata ["endpoints" ]:
285302 if (endpoint ["group_name" ] == default_group ["group_name" ]):
@@ -300,7 +317,7 @@ def client(self, *args, org_id=None, service_id=None, channel_id=None):
300317 def _get_channel_state (channel_id ):
301318 stub = _state_service_pb2_grpc .PaymentChannelStateServiceStub (grpc_channel )
302319 message = web3 .Web3 .soliditySha3 (["uint256" ], [channel_id ])
303- signature = self .web3 .eth .account .signHash (defunct_hash_message (message ), self .private_key ).signature
320+ signature = self .web3 .eth .account .signHash (defunct_hash_message (message ), self .signer_private_key ).signature
304321 request = _state_service_pb2 .ChannelStateRequest (channel_id = web3 .Web3 .toBytes (channel_id ), signature = bytes (signature ))
305322 response = stub .GetChannelState (request )
306323 return {
@@ -315,10 +332,16 @@ def _get_channel_states():
315332
316333 def _get_funded_channel ():
317334 channel_states = _get_channel_states ()
318- if len (channel_states ) != 0 :
319- return next (iter (channel_states ), lambda state : state .initial_amount - state .current_signed_amount >= int (client .metadata .pricing ["price_in_cogs" ]))["channel_id" ]
320- else :
321- raise RuntimeError ("No usable state channel found. Please open a new channel or fund/extend an existing one" )
335+
336+ if len (channel_states ) == 0 :
337+ if allow_transactions is False :
338+ raise RuntimeError ('No state channel found. Please open a new channel or set configuration parameter "allow_transactions=True" when creating Snet class instance' )
339+ else :
340+ _client_open_channel (default_channel_value , default_channel_expiration )
341+ channel_states = _get_channel_states ()
342+
343+ chosen_channel = next (filter (lambda state : state ["initial_amount" ] - state ["current_signed_amount" ] >= int (client .metadata .pricing ["price_in_cogs" ]), iter (channel_states )), None )
344+ return chosen_channel ["channel_id" ]
322345
323346
324347 if _channel_id is None :
@@ -367,7 +390,7 @@ def _get_service_call_metadata(channel_id):
367390 ["address" , "uint256" , "uint256" , "uint256" ],
368391 [self .mpe_contract .address , channel_id , state ["current_nonce" ], amount ]
369392 )
370- signature = bytes (self .web3 .eth .account .signHash (defunct_hash_message (message ), self .private_key ).signature )
393+ signature = bytes (self .web3 .eth .account .signHash (defunct_hash_message (message ), self .signer_private_key ).signature )
371394 metadata = [
372395 ("snet-payment-type" , "escrow" ),
373396 ("snet-payment-channel-id" , str (channel_id )),
0 commit comments