66import asyncio
77import websockets
88import logging
9+ from enum import Enum
10+
11+ class CurrencyFormat (Enum ):
12+ WHOLE = 1
13+ NANO = 2
14+
15+ class CurrencyUnderflow (Exception ):
16+ pass
17+
18+ class Currency ():
19+ @classmethod
20+ def __nanocodas_from_int (_cls , n ):
21+ return n * 1000000000
22+
23+ @classmethod
24+ def __nanocodas_from_string (_cls , s ):
25+ segments = s .split ('.' )
26+ if len (segments ) == 1 :
27+ return int (segments [0 ])
28+ elif len (segments ) == 2 :
29+ [l , r ] = segments
30+ if len (r ) <= 9 :
31+ return int (l + r + ('0' * (9 - len (r ))))
32+ else :
33+ raise Exception ('invalid coda currency format: %s' % s )
34+
35+ def __init__ (self , value , format = CurrencyFormat .WHOLE ):
36+ if format == CurrencyFormat .WHOLE :
37+ if isinstance (value , int ):
38+ self .__nanocodas = Currency .__nanocodas_from_int (value )
39+ elif isinstance (value , float ):
40+ self .__nanocodas = Currency .__nanocodas_from_string (str (value ))
41+ elif isinstance (value , str ):
42+ self .__nanocodas = Currency .__nanocodas_from_string (value )
43+ else :
44+ raise Exception ('cannot construct whole Currency from %s' % type (value ))
45+ elif format == CurrencyFormat .NANO :
46+ if isinstance (value , int ):
47+ self .__nanocodas = value
48+ else :
49+ raise Exception ('cannot construct nano Currency from %s' % type (value ))
50+ else :
51+ raise Exception ('invalid Currency format %s' % format )
52+
53+ def decimal_format (self ):
54+ s = str (self .__nanocodas )
55+ if len (s ) > 9 :
56+ return s [:- 9 ] + '.' + s [- 9 :]
57+ else :
58+ return '0.' + ('0' * (9 - len (s ))) + s
59+
60+ def nanocodas (self ):
61+ return self .__nanocodas
62+
63+ def __str__ (self ):
64+ return self .decimal_format ()
65+
66+ def __repr__ (self ):
67+ return 'Currency(%s)' % self .decimal_format ()
68+
69+ def __add__ (self , other ):
70+ if isinstance (other , Currency ):
71+ return Currency (self .nanocodas () + other .nanocodas (), format = CurrencyFormat .NANO )
72+ else :
73+ raise Exception ('cannot add Currency and %s' % type (other ))
74+
75+ def __sub__ (self , other ):
76+ if isinstance (other , Currency ):
77+ new_value = self .nanocodas () - other .nanocodas ()
78+ if new_value >= 0 :
79+ return Currency (new_value , format = CurrencyFormat .NANO )
80+ else :
81+ raise CurrencyUnderflow ()
82+ else :
83+ raise Exception ('cannot subtract Currency and %s' % type (other ))
84+
85+ def __mul__ (self , other ):
86+ if isinstance (other , int ):
87+ return Currency (self .nanocodas () * other , format = CurrencyFormat .NANO )
88+ elif isinstance (other , Currency ):
89+ return Currency (self .nanocodas () * other .nanocodas (), format = CurrencyFormat .NANO )
90+ else :
91+ raise Exception ('cannot multiply Currency and %s' % type (other ))
992
1093class Client ():
1194 # Implements a GraphQL Client for the Coda Daemon
@@ -386,7 +469,7 @@ def set_current_snark_worker(self, worker_pk: str, fee: str) -> dict:
386469 res = self ._send_mutation (query , variables )
387470 return res ["data" ]
388471
389- def send_payment (self , to_pk : str , from_pk : str , amount : int , fee : int , memo : str ) -> dict :
472+ def send_payment (self , to_pk : str , from_pk : str , amount : Currency , fee : Currency , memo : str ) -> dict :
390473 """Send a payment from the specified wallet to the specified target wallet.
391474
392475 Arguments:
@@ -424,8 +507,8 @@ def send_payment(self, to_pk: str, from_pk: str, amount: int, fee: int, memo: st
424507 variables = {
425508 "from" : from_pk ,
426509 "to" : to_pk ,
427- "amount" : amount ,
428- "fee" : fee ,
510+ "amount" : amount . nanocodas () ,
511+ "fee" : fee . nanocodas () ,
429512 "memo" : memo
430513 }
431514 res = self ._send_mutation (query , variables )
@@ -545,4 +628,4 @@ async def listen_new_blocks(self, callback):
545628 '''
546629 variables = {
547630 }
548- await self ._graphql_subscription (query , variables , callback )
631+ await self ._graphql_subscription (query , variables , callback )
0 commit comments