1
- import asyncio
2
1
from typing import List , Any , Union
3
2
from ain .provider import Provider
4
3
from ain .net import Network
5
4
from ain .wallet import Wallet
6
5
from ain .types import AinOptions , TransactionInput , TransactionBody , ValueOnlyTransactionInput
7
6
from ain .db import Database
7
+ from ain .signer import Signer
8
+ from ain .signer .default_signer import DefaultSigner
8
9
from ain .utils import getTimestamp , toChecksumAddress
9
10
10
11
class Ain :
@@ -28,6 +29,8 @@ class Ain:
28
29
"""The `Network` instance."""
29
30
wallet : Wallet
30
31
"""The `Wallet` instance."""
32
+ signer : Signer
33
+ """The `Signer` instance."""
31
34
32
35
def __init__ (self , providerUrl : str , chainId : int = 0 , ainOptions : AinOptions = AinOptions ()):
33
36
self .provider = Provider (self , providerUrl )
@@ -36,6 +39,7 @@ def __init__(self, providerUrl: str, chainId: int = 0, ainOptions: AinOptions =
36
39
self .net = Network (self .provider )
37
40
self .wallet = Wallet (self , self .chainId )
38
41
self .db = Database (self , self .provider )
42
+ self .signer = DefaultSigner (self .wallet , self .provider )
39
43
40
44
def setProvider (self , providerUrl : str , chainId : int = 0 ):
41
45
"""Sets a new provider
@@ -50,6 +54,14 @@ def setProvider(self, providerUrl: str, chainId: int = 0):
50
54
self .wallet .chainId = chainId
51
55
self .db = Database (self , self .provider )
52
56
57
+ def setSigner (self , signer : Signer ):
58
+ """Sets a new signer
59
+
60
+ Args:
61
+ signer (Signer): The signer to set.
62
+ """
63
+ self .signer = signer
64
+
53
65
# TODO(kriii): Return objects typing.
54
66
55
67
async def getBlock (
@@ -141,9 +153,7 @@ async def getTransaction(self, transactionHash: str) -> Any:
141
153
Returns:
142
154
The transaction with the given transaction hash.
143
155
"""
144
- return await self .provider .send (
145
- "ain_getTransactionByHash" , {"hash" : transactionHash }
146
- )
156
+ return await self .provider .send ("ain_getTransactionByHash" , {"hash" : transactionHash })
147
157
148
158
async def getStateUsage (self , appName : str ) -> Any :
149
159
"""Gets a state usage with the given app name.
@@ -154,9 +164,7 @@ async def getStateUsage(self, appName: str) -> Any:
154
164
Returns:
155
165
The state usage with the given app name.
156
166
"""
157
- return await self .provider .send (
158
- "ain_getStateUsage" , {"app_name" : appName }
159
- )
167
+ return await self .provider .send ("ain_getStateUsage" , {"app_name" : appName })
160
168
161
169
async def validateAppName (self , appName : str ) -> Any :
162
170
"""Validate a given app name.
@@ -167,56 +175,43 @@ async def validateAppName(self, appName: str) -> Any:
167
175
Returns:
168
176
The validity of the given app name.
169
177
"""
170
- return await self .provider .send (
171
- "ain_validateAppName" , {"app_name" : appName }
172
- )
178
+ return await self .provider .send ("ain_validateAppName" , {"app_name" : appName })
173
179
174
- async def sendTransaction (self , transactionObject : TransactionInput ) -> Any :
175
- """Signs and sends the transaction to the network.
180
+ async def sendTransaction (self , transactionObject : TransactionInput , isDryrun = False ) -> Any :
181
+ """Signs and sends a transaction to the network.
176
182
177
183
Args:
178
- transactionObject (TransactionInput): The transaction.
184
+ transactionObject (TransactionInput): The transaction input object.
185
+ isDryrun (bool): The dryrun option.
179
186
180
187
Returns:
181
- The transaction result .
188
+ The return value of the blockchain API .
182
189
"""
183
- txBody = await self .buildTransactionBody (transactionObject )
184
- signature = self .wallet .signTransaction (
185
- txBody , getattr (transactionObject , "address" , None )
186
- )
187
- return await self .sendSignedTransaction (signature , txBody )
190
+ return await self .signer .sendTransaction (transactionObject , isDryrun )
188
191
189
- async def sendSignedTransaction (self , signature : str , txBody : TransactionBody ) -> Any :
192
+ async def sendSignedTransaction (self , signature : str , txBody : TransactionBody , isDryrun = False ) -> Any :
190
193
"""Sends a signed transaction to the network.
191
194
192
195
Args:
193
- signature (str): The signature of the transaction .
196
+ signature (str): The signature.
194
197
txBody (TransactionBody): The transaction body.
198
+ isDryrun (bool): The dryrun option.
195
199
196
200
Returns:
197
- The transaction result .
201
+ The return value of the blockchain API .
198
202
"""
199
- return await self .provider .send (
200
- "ain_sendSignedTransaction" , {"signature" : signature , "tx_body" : txBody }
201
- )
203
+ return await self .signer .sendSignedTransaction (signature , txBody , isDryrun )
202
204
203
205
async def sendTransactionBatch (self , transactionObjects : List [TransactionInput ]) -> List [Any ]:
204
- """Sends a signed transactions to the network.
206
+ """Signs and sends multiple transactions in a batch to the network.
205
207
206
208
Args:
207
- transactionObjects (List[TransactionInput]): The list of the transactions .
209
+ transactionObjects (List[TransactionInput]): The list of the transaction input objects .
208
210
209
211
Returns:
210
- The transaction results .
212
+ The return value of the blockchain API .
211
213
"""
212
- txListCoroutines = []
213
- for txInput in transactionObjects :
214
- txListCoroutines .append (self .__buildSignedTransaction (txInput ))
215
-
216
- txList = await asyncio .gather (* txListCoroutines )
217
- return await self .provider .send (
218
- "ain_sendSignedTransactionBatch" , {"tx_list" : txList }
219
- )
214
+ return await self .signer .sendTransactionBatch (transactionObjects )
220
215
221
216
def depositConsensusStake (self , input : ValueOnlyTransactionInput ) -> Any :
222
217
"""Sends a transaction that deposits AIN for consensus staking.
@@ -251,69 +246,11 @@ async def getConsensusStakeAmount(self, account: str = None) -> Any:
251
246
The amount of the AIN of that address.
252
247
"""
253
248
if account is None :
254
- address = self .wallet . getImpliedAddress ()
249
+ address = self .signer . getAddress ()
255
250
else :
256
251
address = toChecksumAddress (account )
257
252
return await self .db .ref (f"/deposit_accounts/consensus/{ address } " ).getValue ()
258
253
259
- async def getNonce (self , args : dict ) -> Any :
260
- """Gets a current transaction count of account, which is the nonce of the account.
261
-
262
- Args:
263
- args (dict): May contain a string 'address' and a string 'from' values.
264
- The 'address' indicates the address of the account to get the
265
- nonce of, and the 'from' indicates where to get the nonce from.
266
- It could be either the pending transaction pool ("pending") or
267
- the committed blocks ("committed"). The default value is "committed".
268
-
269
- Returns:
270
- The nonce of the account.
271
- """
272
- params = dict (args )
273
- if "address" in args :
274
- params ["address" ] = toChecksumAddress (args ["address" ])
275
- else :
276
- params ["address" ] = self .wallet .getImpliedAddress ()
277
-
278
- if "from" in args :
279
- if args ["from" ] != "pending" and args ["from" ] != "committed" :
280
- raise ValueError ("'from' should be either 'pending' or 'committed'" )
281
-
282
- ret = await self .provider .send ("ain_getNonce" , params )
283
- return ret
284
-
285
- async def buildTransactionBody (
286
- self , transactionInput : TransactionInput
287
- ) -> TransactionBody :
288
- """Builds a transaction body from the transaction input.
289
-
290
- Args:
291
- transactionInput (TransactionInput): The transaction input.
292
-
293
- Returns:
294
- TransactionBody: The builded transaction body.
295
- """
296
- address = self .wallet .getImpliedAddress (
297
- getattr (transactionInput , "address" , None )
298
- )
299
- operation = transactionInput .operation
300
- parent_tx_hash = getattr (transactionInput , "parent_tx_hash" , None )
301
- nonce = getattr (transactionInput , "nonce" , None )
302
- if nonce is None :
303
- nonce = await self .getNonce ({"address" : address , "from" : "pending" })
304
- timestamp = getattr (transactionInput , "timestamp" , getTimestamp ())
305
- gas_price = getattr (transactionInput , "gas_price" , 0 )
306
- billing = getattr (transactionInput , "billing" , None )
307
-
308
- return TransactionBody (
309
- operation = operation ,
310
- parent_tx_hash = parent_tx_hash ,
311
- nonce = nonce ,
312
- timestamp = timestamp ,
313
- gas_price = gas_price ,
314
- billing = billing ,
315
- )
316
-
317
254
def __stakeFunction (self , path : str , input : ValueOnlyTransactionInput ) -> Any :
318
255
"""A base function for all staking related database changes. It builds a
319
256
deposit/withdraw transaction and sends the transaction by calling sendTransaction().
@@ -322,20 +259,7 @@ def __stakeFunction(self, path: str, input: ValueOnlyTransactionInput) -> Any:
322
259
raise ValueError ("a value should be specified." )
323
260
if type (input .value ) is not int :
324
261
raise ValueError ("value has to be a int." )
325
- input .address = self .wallet . getImpliedAddress (getattr (input , "address" , None ))
262
+ input .address = self .signer . getAddress (getattr (input , "address" , None ))
326
263
ref = self .db .ref (f'{ path } /{ input .address } ' ).push ()
327
264
input .ref = "value"
328
265
return ref .setValue (input )
329
-
330
- async def __buildSignedTransaction (self , transactionObject : TransactionInput ) -> dict :
331
- """Returns a builded transaction with the signature"""
332
- txBody = await self .buildTransactionBody (transactionObject )
333
- if not hasattr (transactionObject , "nonce" ):
334
- # Batch transactions' nonces should be specified.
335
- # If they're not, they default to un-nonced (nonce = -1).
336
- txBody .nonce = - 1
337
-
338
- signature = self .wallet .signTransaction (
339
- txBody , getattr (transactionObject , "address" , None )
340
- )
341
- return {"signature" : signature , "tx_body" : txBody }
0 commit comments