Skip to content

Commit 68fb13b

Browse files
committed
Add MultiSig SC wrapper
1 parent bec5ed5 commit 68fb13b

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

sdk/contracts/MultiSigWrapper.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import sys
2+
import time
3+
from typing import List
4+
5+
from web3 import Web3
6+
7+
from sdk.contracts.base_wrapper import BaseWrapper
8+
from sdk.registry import Registry
9+
10+
11+
# TODO: test when other called SC wrappers will be written and callable
12+
class MultiSig(BaseWrapper):
13+
"""
14+
Contract for handling multisig actions
15+
16+
Attributes:
17+
web3: Web3
18+
Web3 object
19+
registry: Registry
20+
Registry object
21+
address: str
22+
Contract's address
23+
abi: list
24+
Contract's ABI
25+
wallet: Wallet
26+
Wallet object to sign transactions
27+
"""
28+
29+
def __init__(self, web3: Web3, registry: Registry, address: str, abi: list, wallet: 'Wallet' = None):
30+
super().__init__(web3, registry, wallet=wallet)
31+
self.web3 = web3
32+
self.address = address
33+
self._contract = self.web3.eth.contract(self.address, abi=abi)
34+
self.__wallet = wallet
35+
36+
def submit_or_confirm_transaction(self, destination: str, tx_data: str, value: str = '0') -> str:
37+
"""
38+
Allows an owner to submit and confirm a transaction.
39+
If an unexecuted transaction matching `tx_object` exists on the multisig, adds a confirmation to that tx ID.
40+
Otherwise, submits the `tx_object` to the multisig and add confirmation.
41+
42+
Parameters:
43+
destination: str
44+
tx_object: str
45+
Transaction data hex string
46+
value: str
47+
Returns:
48+
str
49+
Transaction hash
50+
"""
51+
# sure that data start with 0x
52+
data = '0x' + tx_data.lstrip('0x')
53+
transaction_count = self._contract.functions.getTransactionCount(
54+
True, True).call()
55+
56+
for tx_id in reversed(range(transaction_count)):
57+
transaction = self._contract.functions.transactions(
58+
tx_id + 1).call()
59+
if transaction[2] == data and transaction[0] == destination and transaction[1] == value and not transaction[3]:
60+
func_call = self._contract.functions.confirmTransaction(
61+
tx_id + 1)
62+
return self.__wallet.send_transaction(func_call)
63+
64+
func_call = self._contract.functions.submitTransaction(
65+
destination, value, tx_data)
66+
67+
return self.__wallet.send_transaction(func_call)
68+
69+
def is_owner(self, owner: str) -> bool:
70+
return self._contract.functions.isOwner(owner).call()
71+
72+
def get_owners(self) -> List[str]:
73+
return self._contract.functions.getOwners().call()
74+
75+
def get_required(self) -> int:
76+
return self._contract.functions.required().call()
77+
78+
def get_internal_required(self) -> int:
79+
return self._contract.functions.internalRequired().call()
80+
81+
def get_transaction_count(self) -> int:
82+
return self._contract.functions.transactionCount().call()
83+
84+
def replace_owner(self, owner: str, new_owner: str) -> str:
85+
func_call = self._contract.functions.replaceOwner(owner, new_owner)
86+
87+
return self.__wallet.send_transaction(func_call)
88+
89+
def get_transaction(self, i: int) -> dict:
90+
destination, value, data, executed = self._contract.functions.transactions(
91+
i).call()
92+
93+
confirmations = []
94+
for owner in self.get_owners():
95+
if self._contract.functions.confirmations(i, owner).call():
96+
confirmations.append(owner)
97+
98+
return {
99+
'destination': destination,
100+
'data': data,
101+
'executed': executed,
102+
'confirmations': confirmations,
103+
'value': value
104+
}
105+
106+
def get_transactions(self) -> List[dict]:
107+
tx_count = self.get_transaction_count()
108+
res = []
109+
for i in range(tx_count):
110+
res.append(self.get_transaction(i))
111+
112+
return res

0 commit comments

Comments
 (0)