|
1 | | -from binascii import hexlify, unhexlify |
| 1 | +from typing import Optional |
2 | 2 |
|
3 | | -from crypto.configuration.fee import get_fee |
4 | | -from crypto.constants import TRANSACTION_TYPE_GROUP |
| 3 | +from crypto.configuration.network import get_network |
5 | 4 | from crypto.identity.private_key import PrivateKey |
6 | | -from crypto.identity.public_key import PublicKey |
7 | | -from crypto.transactions.serializer import Serializer |
8 | | -from crypto.transactions.signature import Signature |
9 | | -from crypto.transactions.transaction import Transaction |
10 | | - |
11 | | -class BaseTransactionBuilder(object): |
12 | | - transaction: Transaction |
13 | | - |
14 | | - def __init__(self): |
15 | | - self.transaction = Transaction() |
16 | | - |
17 | | - if hasattr(self, 'transaction_type'): |
18 | | - self.transaction.type = getattr(self, 'transaction_type') |
19 | | - |
20 | | - if hasattr(self, 'transaction_type'): |
21 | | - self.transaction.fee = get_fee(getattr(self, 'transaction_type')) |
22 | | - |
23 | | - if hasattr(self, 'nonce'): |
24 | | - self.transaction.nonce = getattr(self, 'nonce') |
25 | | - |
26 | | - if hasattr(self, 'signatures'): |
27 | | - self.transaction.signatures = getattr(self, 'signatures') |
28 | | - |
29 | | - self.transaction.typeGroup = getattr(self, 'typeGroup', int(TRANSACTION_TYPE_GROUP.CORE)) |
30 | | - self.transaction.version = getattr(self, 'version', 1) |
31 | | - self.transaction.expiration = getattr(self, 'expiration', 0) |
32 | | - if self.transaction.type != 0: |
33 | | - self.transaction.amount = getattr(self, 'amount', 0) |
| 5 | +from crypto.transactions.types.abstract_transaction import AbstractTransaction |
| 6 | + |
| 7 | + |
| 8 | +class AbstractTransactionBuilder: |
| 9 | + def __init__(self, data: Optional[dict] = None): |
| 10 | + default_data = { |
| 11 | + 'value': '0', |
| 12 | + 'senderPublicKey': '', |
| 13 | + 'gasPrice': '5', |
| 14 | + 'nonce': '1', |
| 15 | + 'network': get_network()['version'], |
| 16 | + 'gasLimit': 1_000_000, |
| 17 | + 'data': '', |
| 18 | + } |
| 19 | + self.transaction = self.get_transaction_instance(data or default_data) |
| 20 | + |
| 21 | + def __str__(self): |
| 22 | + return self.to_json() |
| 23 | + |
| 24 | + @classmethod |
| 25 | + def new(cls, data: Optional[dict] = None): |
| 26 | + return cls(data) |
| 27 | + |
| 28 | + def gas_limit(self, gas_limit: int): |
| 29 | + self.transaction.data['gasLimit'] = gas_limit |
| 30 | + return self |
| 31 | + |
| 32 | + def recipient_address(self, recipient_address: str): |
| 33 | + self.transaction.data['recipientAddress'] = recipient_address |
| 34 | + return self |
| 35 | + |
| 36 | + def gas_price(self, gas_price: int): |
| 37 | + self.transaction.data['gasPrice'] = gas_price |
| 38 | + return self |
| 39 | + |
| 40 | + def nonce(self, nonce: str): |
| 41 | + self.transaction.data['nonce'] = nonce |
| 42 | + return self |
| 43 | + |
| 44 | + def network(self, network: int): |
| 45 | + self.transaction.data['network'] = network |
| 46 | + return self |
| 47 | + |
| 48 | + def sign(self, passphrase: str): |
| 49 | + keys = PrivateKey.from_passphrase(passphrase) |
| 50 | + self.transaction.data['senderPublicKey'] = keys.public_key |
| 51 | + self.transaction = self.transaction.sign(keys) |
| 52 | + self.transaction.data['id'] = self.transaction.get_id() |
| 53 | + return self |
| 54 | + |
| 55 | + def verify(self): |
| 56 | + return self.transaction.verify() |
34 | 57 |
|
35 | 58 | def to_dict(self): |
36 | 59 | return self.transaction.to_dict() |
37 | 60 |
|
38 | 61 | def to_json(self): |
39 | 62 | return self.transaction.to_json() |
40 | 63 |
|
41 | | - def sign(self, passphrase): |
42 | | - """Sign the transaction using the given passphrase |
43 | | -
|
44 | | - Args: |
45 | | - passphrase (str): passphrase associated with the account sending this transaction |
46 | | - """ |
47 | | - self.transaction.senderPublicKey = PublicKey.from_passphrase(passphrase) |
48 | | - |
49 | | - msg = self.transaction.to_bytes(False, True, False) |
50 | | - secret = unhexlify(PrivateKey.from_passphrase(passphrase).to_hex()) |
51 | | - self.transaction.signature = Signature.sign(msg, secret) |
52 | | - self.transaction.id = self.transaction.get_id() |
53 | | - |
54 | | - def second_sign(self, passphrase): |
55 | | - """Sign the transaction using the given second passphrase |
56 | | -
|
57 | | - Args: |
58 | | - passphrase (str): 2nd passphrase associated with the account sending this transaction |
59 | | - """ |
60 | | - msg = self.transaction.to_bytes(False, True, False) |
61 | | - secret = unhexlify(PrivateKey.from_passphrase(passphrase).to_hex()) |
62 | | - self.transaction.signSignature = Signature.sign(msg, secret) |
63 | | - self.transaction.id = self.transaction.get_id() |
64 | | - |
65 | | - def multi_sign(self, passphrase, index): |
66 | | - if not self.transaction.signatures: |
67 | | - self.transaction.signatures = [] |
68 | | - |
69 | | - if self.transaction.senderPublicKey is None: |
70 | | - raise Exception('Sender Public Key is required for multi signature') |
71 | | - |
72 | | - index = len(self.transaction.signatures) if index == -1 else index |
73 | | - |
74 | | - msg = self.transaction.to_bytes() |
75 | | - secret = unhexlify(PrivateKey.from_passphrase(passphrase).to_hex()) |
76 | | - signature = Signature.sign(msg, secret) |
77 | | - |
78 | | - index_formatted = hex(index).replace('x', '') |
79 | | - self.transaction.signatures.append(index_formatted + signature) |
80 | | - |
81 | | - def serialize(self, skip_signature=False, skip_second_signature=False, skip_multi_signature=False): |
82 | | - """Perform AIP11 compliant serialization. |
83 | | -
|
84 | | - Args: |
85 | | - skip_signature (bool, optional): do you want to skip the signature |
86 | | - skip_second_signature (bool, optional): do you want to skip the 2nd signature |
87 | | - skip_multi_signature (bool, optional): do you want to skip multi signature |
88 | | -
|
89 | | - Returns: |
90 | | - str: Serialized string |
91 | | - """ |
92 | | - return Serializer(self.to_dict()).serialize(skip_signature, skip_second_signature, skip_multi_signature) |
93 | | - |
94 | | - def schnorr_verify(self): |
95 | | - return self.transaction.verify_schnorr() |
96 | | - |
97 | | - def verify_secondsig_schnorr(self, secondPublicKey): |
98 | | - return self.transaction.verify_secondsig_schnorr(secondPublicKey) |
99 | | - |
100 | | - def verify_multisig_schnorr(self): |
101 | | - return self.transaction.verify_multisig_schnorr() |
102 | | - |
103 | | - def set_nonce(self, nonce): |
104 | | - self.transaction.nonce = nonce |
105 | | - |
106 | | - def set_amount(self, amount: int): |
107 | | - self.transaction.amount = amount |
108 | | - |
109 | | - def set_sender_public_key(self, public_key: str): |
110 | | - self.transaction.senderPublicKey = public_key |
111 | | - |
112 | | - def set_expiration(self, expiration: int): |
113 | | - self.transaction.expiration = expiration |
114 | | - |
115 | | - def set_type_group(self, type_group): |
116 | | - if type(type_group) == int: |
117 | | - self.transaction.typeGroup = type_group |
118 | | - else: |
119 | | - types = {TRANSACTION_TYPE_GROUP.TEST: 0, TRANSACTION_TYPE_GROUP.CORE: 1, TRANSACTION_TYPE_GROUP.RESERVED: 1000} |
120 | | - self.transaction.typeGroup = types[type_group] |
| 64 | + def get_transaction_instance(self, data: dict) -> AbstractTransaction: |
| 65 | + raise NotImplementedError("Subclasses must implement get_transaction_instance()") |
0 commit comments