Skip to content

Commit fe62656

Browse files
authored
feat(SDK): add Ruffsack class to simplify working with wallet (#13)
1 parent 94fb198 commit fe62656

File tree

8 files changed

+541
-93
lines changed

8 files changed

+541
-93
lines changed

contracts/Ruffsack.vy

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ IMPLEMENTATION: public(address)
3838

3939
# Signer properties
4040
# @dev All current signers (unordered)
41-
signers: public(DynArray[address, 11])
41+
_signers: DynArray[address, 11]
4242

4343
# @dev Number of signers required to execute an action
4444
threshold: public(uint256)
@@ -156,19 +156,25 @@ def initialize(signers: DynArray[address, 11], threshold: uint256):
156156
assert self.threshold == 0 # dev: can only initialize once
157157
assert threshold > 0 and threshold <= len(signers)
158158

159-
self.signers = signers
159+
self._signers = signers
160160
self.threshold = threshold
161161

162162

163+
@view
164+
@external
165+
def signers() -> DynArray[address, 11]:
166+
return self._signers
167+
168+
163169
@external
164170
def set_approval(msghash: bytes32, approved: bool = True):
165-
assert msg.sender in self.signers, "Not a signer"
171+
assert msg.sender in self._signers, "Not a signer"
166172
self.approved[msghash][msg.sender] = approved
167173

168174

169175
def _verify_signatures(msghash: bytes32, signatures: DynArray[Bytes[65], 11]):
170176
approvals_needed: uint256 = self.threshold
171-
signers: DynArray[address, 11] = self.signers
177+
signers: DynArray[address, 11] = self._signers
172178
already_approved: DynArray[address, 11] = []
173179

174180
for signer: address in signers:
@@ -219,7 +225,7 @@ def _rotate_signers(
219225
signers_to_rm: DynArray[address, 11],
220226
threshold: uint256,
221227
):
222-
current_signers: DynArray[address, 11] = self.signers
228+
current_signers: DynArray[address, 11] = self._signers
223229
new_signers: DynArray[address, 11] = []
224230

225231
for signer: address in current_signers:
@@ -237,7 +243,7 @@ def _rotate_signers(
237243
assert threshold <= len(new_signers), "Invalid threshold"
238244
self.threshold = threshold
239245

240-
self.signers = new_signers
246+
self._signers = new_signers
241247

242248
log SignersRotated(
243249
executor=msg.sender,

ruffsack/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from .factory import Factory
2+
from .main import Ruffsack
23
from .packages import PackageType
34

45
__all__ = [
56
Factory.__name__,
67
PackageType.__name__,
8+
Ruffsack.__name__,
79
]

ruffsack/factory.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from ape.utils import ManagerAccessMixin, cached_property
55
from packaging.version import Version
66

7+
from .main import Ruffsack
78
from .packages import MANIFESTS, PackageType
89

910
if TYPE_CHECKING:
@@ -37,14 +38,16 @@ def releases(self) -> dict[Version, "ContractInstance"]:
3738
for log in self.contract.NewRelease.range(
3839
self._last_cached, latest_block + 1
3940
):
41+
# NOTE: Handle dev testing by stripping `+...`
42+
cleaned_version = Version(Version(log.version).public)
4043
self._cached_releases[Version(log.version)] = (
4144
self.chain_manager.contracts.instance_at(
4245
log.implementation,
43-
contract_type=PackageType.SINGLETON(log.version),
46+
contract_type=PackageType.SINGLETON(cleaned_version),
4447
)
4548
)
4649

47-
self._last_cached = latest_block
50+
self._last_cached = latest_block
4851
return self._cached_releases
4952

5053
def new(
@@ -54,7 +57,7 @@ def new(
5457
version: Version | str | None = None,
5558
tag: str | None = None,
5659
**txn_args,
57-
) -> "ContractInstance":
60+
) -> Ruffsack:
5861
if threshold is None:
5962
threshold = len(signers) // 2
6063

@@ -73,9 +76,6 @@ def new(
7376

7477
receipt = self.contract.new(*args, **txn_args)
7578

76-
new_ruffsack_address = receipt.events[0].new_sack
77-
# TODO: Refactor to use SDK internal type? (subclassing `AccountAPI`)
78-
return self.chain_manager.contracts.instance_at(
79-
new_ruffsack_address,
80-
contract_type=PackageType.SINGLETON(version),
79+
return Ruffsack(
80+
address=receipt.events[0].new_sack, version=version, factory=self
8181
)

0 commit comments

Comments
 (0)