dao-treasury 0.0.10__cp310-cp310-win32.whl → 0.0.70__cp310-cp310-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dao_treasury/.grafana/provisioning/dashboards/breakdowns/Expenses.json +551 -0
- dao_treasury/.grafana/provisioning/dashboards/breakdowns/Revenue.json +551 -0
- dao_treasury/.grafana/provisioning/dashboards/dashboards.yaml +7 -7
- dao_treasury/.grafana/provisioning/dashboards/streams/LlamaPay.json +220 -0
- dao_treasury/.grafana/provisioning/dashboards/summary/Monthly.json +153 -29
- dao_treasury/.grafana/provisioning/dashboards/transactions/Treasury Transactions.json +181 -29
- dao_treasury/.grafana/provisioning/dashboards/treasury/Cashflow (Including Unsorted).json +808 -0
- dao_treasury/.grafana/provisioning/dashboards/treasury/Cashflow.json +602 -0
- dao_treasury/.grafana/provisioning/dashboards/treasury/Current Treasury Assets.json +981 -0
- dao_treasury/.grafana/provisioning/dashboards/treasury/Historical Treasury Balances.json +2989 -0
- dao_treasury/.grafana/provisioning/dashboards/treasury/Operating Cashflow.json +478 -0
- dao_treasury/.grafana/provisioning/datasources/datasources.yaml +17 -0
- dao_treasury/ENVIRONMENT_VARIABLES.py +20 -0
- dao_treasury/__init__.py +36 -10
- dao_treasury/_docker.cp310-win32.pyd +0 -0
- dao_treasury/_docker.py +169 -37
- dao_treasury/_nicknames.cp310-win32.pyd +0 -0
- dao_treasury/_nicknames.py +32 -0
- dao_treasury/_wallet.cp310-win32.pyd +0 -0
- dao_treasury/_wallet.py +164 -12
- dao_treasury/constants.cp310-win32.pyd +0 -0
- dao_treasury/constants.py +39 -0
- dao_treasury/db.py +925 -150
- dao_treasury/docker-compose.yaml +6 -5
- dao_treasury/main.py +238 -28
- dao_treasury/sorting/__init__.cp310-win32.pyd +0 -0
- dao_treasury/sorting/__init__.py +219 -115
- dao_treasury/sorting/_matchers.cp310-win32.pyd +0 -0
- dao_treasury/sorting/_matchers.py +261 -17
- dao_treasury/sorting/_rules.cp310-win32.pyd +0 -0
- dao_treasury/sorting/_rules.py +166 -21
- dao_treasury/sorting/factory.cp310-win32.pyd +0 -0
- dao_treasury/sorting/factory.py +245 -37
- dao_treasury/sorting/rule.cp310-win32.pyd +0 -0
- dao_treasury/sorting/rule.py +228 -46
- dao_treasury/sorting/rules/__init__.cp310-win32.pyd +0 -0
- dao_treasury/sorting/rules/__init__.py +1 -0
- dao_treasury/sorting/rules/ignore/__init__.cp310-win32.pyd +0 -0
- dao_treasury/sorting/rules/ignore/__init__.py +1 -0
- dao_treasury/sorting/rules/ignore/llamapay.cp310-win32.pyd +0 -0
- dao_treasury/sorting/rules/ignore/llamapay.py +20 -0
- dao_treasury/streams/__init__.cp310-win32.pyd +0 -0
- dao_treasury/streams/__init__.py +0 -0
- dao_treasury/streams/llamapay.cp310-win32.pyd +0 -0
- dao_treasury/streams/llamapay.py +388 -0
- dao_treasury/treasury.py +118 -25
- dao_treasury/types.cp310-win32.pyd +0 -0
- dao_treasury/types.py +104 -7
- dao_treasury-0.0.70.dist-info/METADATA +134 -0
- dao_treasury-0.0.70.dist-info/RECORD +54 -0
- dao_treasury-0.0.70.dist-info/top_level.txt +2 -0
- dao_treasury__mypyc.cp310-win32.pyd +0 -0
- a743a720bbc4482d330e__mypyc.cp310-win32.pyd +0 -0
- dao_treasury/.grafana/provisioning/datasources/sqlite.yaml +0 -10
- dao_treasury-0.0.10.dist-info/METADATA +0 -36
- dao_treasury-0.0.10.dist-info/RECORD +0 -28
- dao_treasury-0.0.10.dist-info/top_level.txt +0 -2
- {dao_treasury-0.0.10.dist-info → dao_treasury-0.0.70.dist-info}/WHEEL +0 -0
dao_treasury/sorting/__init__.py
CHANGED
|
@@ -1,16 +1,47 @@
|
|
|
1
1
|
"""
|
|
2
|
-
This module
|
|
2
|
+
This module provides the core logic for sorting DAO Treasury transactions into transaction groups (categories).
|
|
3
|
+
|
|
4
|
+
Sorting enables comprehensive financial reporting and categorization tailored for on-chain organizations.
|
|
5
|
+
Transactions are matched against either statically defined rules or more advanced dynamic rules based on user-defined matching functions.
|
|
6
|
+
|
|
7
|
+
Sorting works by attempting matches in this order:
|
|
8
|
+
1. Check if the transaction is an internal transfer (within treasury wallets).
|
|
9
|
+
2. Check if the transaction is "Out of Range" (neither sender nor receiver was a treasury wallet at the time of the tx).
|
|
10
|
+
3. Match by transaction hash using registered HashMatchers.
|
|
11
|
+
4. Match by sender address using registered FromAddressMatchers.
|
|
12
|
+
5. Match by recipient address using registered ToAddressMatchers.
|
|
13
|
+
6. Assign "Must Sort Inbound" or "Must Sort Outbound" groups if part of treasury.
|
|
14
|
+
7. Raise an error if no match is found (unexpected case).
|
|
15
|
+
|
|
16
|
+
See the complete [sort rules documentation](https://bobthebuidler.github.io/dao-treasury/sort_rules.html) for detailed explanations
|
|
17
|
+
and examples on defining and registering sort rules.
|
|
18
|
+
|
|
19
|
+
See Also:
|
|
20
|
+
:func:`dao_treasury.sorting.sort_basic`
|
|
21
|
+
:func:`dao_treasury.sorting.sort_basic_entity`
|
|
22
|
+
:func:`dao_treasury.sorting.sort_advanced`
|
|
23
|
+
:class:`dao_treasury.sorting.HashMatcher`
|
|
24
|
+
:class:`dao_treasury.sorting.FromAddressMatcher`
|
|
25
|
+
:class:`dao_treasury.sorting.ToAddressMatcher`
|
|
3
26
|
"""
|
|
27
|
+
|
|
4
28
|
from logging import getLogger
|
|
5
29
|
from typing import Final, Optional
|
|
6
30
|
|
|
7
31
|
from eth_portfolio.structs import LedgerEntry
|
|
8
32
|
from evmspec.data import TransactionHash
|
|
33
|
+
from y.exceptions import ContractNotVerified
|
|
9
34
|
|
|
10
|
-
from dao_treasury import db
|
|
35
|
+
from dao_treasury import constants, db
|
|
11
36
|
from dao_treasury._wallet import TreasuryWallet
|
|
12
|
-
from dao_treasury.sorting._matchers import
|
|
37
|
+
from dao_treasury.sorting._matchers import (
|
|
38
|
+
_Matcher,
|
|
39
|
+
FromAddressMatcher,
|
|
40
|
+
HashMatcher,
|
|
41
|
+
ToAddressMatcher,
|
|
42
|
+
)
|
|
13
43
|
from dao_treasury.sorting.factory import (
|
|
44
|
+
SortRuleFactory,
|
|
14
45
|
cost_of_revenue,
|
|
15
46
|
expense,
|
|
16
47
|
ignore,
|
|
@@ -20,13 +51,14 @@ from dao_treasury.sorting.factory import (
|
|
|
20
51
|
)
|
|
21
52
|
from dao_treasury.sorting.rule import (
|
|
22
53
|
SORT_RULES,
|
|
23
|
-
CostOfRevenueSortRule,
|
|
24
|
-
ExpenseSortRule,
|
|
25
|
-
IgnoreSortRule,
|
|
26
|
-
OtherExpenseSortRule,
|
|
27
|
-
OtherIncomeSortRule,
|
|
54
|
+
CostOfRevenueSortRule,
|
|
55
|
+
ExpenseSortRule,
|
|
56
|
+
IgnoreSortRule,
|
|
57
|
+
OtherExpenseSortRule,
|
|
58
|
+
OtherIncomeSortRule,
|
|
28
59
|
RevenueSortRule,
|
|
29
60
|
)
|
|
61
|
+
from dao_treasury.sorting.rules import *
|
|
30
62
|
from dao_treasury.types import TxGroupDbid
|
|
31
63
|
|
|
32
64
|
|
|
@@ -34,11 +66,11 @@ logger: Final = getLogger("dao_treasury.sorting")
|
|
|
34
66
|
|
|
35
67
|
|
|
36
68
|
__all__ = [
|
|
37
|
-
"CostOfRevenueSortRule",
|
|
38
|
-
"ExpenseSortRule",
|
|
39
|
-
"IgnoreSortRule",
|
|
40
|
-
"OtherExpenseSortRule",
|
|
41
|
-
"OtherIncomeSortRule",
|
|
69
|
+
"CostOfRevenueSortRule",
|
|
70
|
+
"ExpenseSortRule",
|
|
71
|
+
"IgnoreSortRule",
|
|
72
|
+
"OtherExpenseSortRule",
|
|
73
|
+
"OtherIncomeSortRule",
|
|
42
74
|
"RevenueSortRule",
|
|
43
75
|
"cost_of_revenue",
|
|
44
76
|
"expense",
|
|
@@ -46,40 +78,81 @@ __all__ = [
|
|
|
46
78
|
"other_expense",
|
|
47
79
|
"other_income",
|
|
48
80
|
"revenue",
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
81
|
+
"SortRuleFactory",
|
|
82
|
+
"HashMatcher",
|
|
83
|
+
"FromAddressMatcher",
|
|
84
|
+
"ToAddressMatcher",
|
|
52
85
|
"SORT_RULES",
|
|
53
86
|
"_Matcher",
|
|
54
87
|
]
|
|
55
88
|
|
|
56
89
|
# C constants
|
|
57
90
|
TxGroup: Final = db.TxGroup
|
|
58
|
-
|
|
59
|
-
|
|
91
|
+
MUST_SORT_INBOUND_TXGROUP_DBID: Final = db.must_sort_inbound_txgroup_dbid
|
|
92
|
+
MUST_SORT_OUTBOUND_TXGROUP_DBID: Final = db.must_sort_outbound_txgroup_dbid
|
|
93
|
+
|
|
94
|
+
INTERNAL_TRANSFER_TXGROUP_DBID: Final = TxGroup.get_dbid(
|
|
95
|
+
name="Internal Transfer",
|
|
96
|
+
parent=TxGroup.get_dbid("Ignore"),
|
|
97
|
+
)
|
|
98
|
+
"""Database ID for the 'Internal Transfer' transaction group.
|
|
99
|
+
|
|
100
|
+
This group represents transactions that occur internally between treasury-owned wallets.
|
|
101
|
+
Such internal movements of funds within the DAO's treasury do not require separate handling or reporting.
|
|
102
|
+
|
|
103
|
+
See Also:
|
|
104
|
+
:class:`dao_treasury.db.TxGroup`
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
OUT_OF_RANGE_TXGROUP_DBID = TxGroup.get_dbid(
|
|
108
|
+
name="Out of Range", parent=TxGroup.get_dbid("Ignore")
|
|
109
|
+
)
|
|
110
|
+
"""Database ID for the 'Out of Range' transaction group.
|
|
111
|
+
|
|
112
|
+
This category is assigned to transactions where neither the sender nor the recipient
|
|
113
|
+
wallet are members of the treasury at the time of the transaction.
|
|
114
|
+
|
|
115
|
+
See Also:
|
|
116
|
+
:class:`dao_treasury.db.TxGroup`
|
|
117
|
+
"""
|
|
60
118
|
|
|
61
119
|
|
|
62
120
|
def sort_basic(entry: LedgerEntry) -> TxGroupDbid:
|
|
121
|
+
"""Determine the transaction group ID for a basic ledger entry using static matching.
|
|
122
|
+
|
|
123
|
+
The function attempts to categorize the transaction by testing:
|
|
124
|
+
- If both 'from' and 'to' addresses are treasury wallets (internal transfer).
|
|
125
|
+
- If neither ‘to’ address is a treasury wallet at the time of the transaction (out of range).
|
|
126
|
+
- If the transaction hash matches a known HashMatcher.
|
|
127
|
+
- If the 'from' address matches a FromAddressMatcher.
|
|
128
|
+
- If the 'to' address matches a ToAddressMatcher.
|
|
129
|
+
- Assignment to 'Must Sort Outbound' or 'Must Sort Inbound' groups if applicable.
|
|
130
|
+
- Raises `NotImplementedError` if none of the above conditions are met (should not happen).
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
entry: A ledger entry representing a blockchain transaction.
|
|
134
|
+
|
|
135
|
+
Examples:
|
|
136
|
+
>>> from eth_portfolio.structs import Transaction
|
|
137
|
+
>>> entry = Transaction(from_address="0xabc...", to_address="0xdef...", block_number=1234567)
|
|
138
|
+
>>> group_id = sort_basic(entry)
|
|
139
|
+
>>> print(group_id)
|
|
140
|
+
|
|
141
|
+
See Also:
|
|
142
|
+
:func:`sort_basic_entity`
|
|
143
|
+
:func:`sort_advanced`
|
|
144
|
+
:class:`dao_treasury.sorting.HashMatcher`
|
|
145
|
+
"""
|
|
146
|
+
from_address = entry.from_address
|
|
147
|
+
to_address = entry.to_address
|
|
148
|
+
block = entry.block_number
|
|
149
|
+
|
|
63
150
|
txgroup_dbid: Optional[TxGroupDbid] = None
|
|
64
|
-
if
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
start_block_for_wallet <= entry.block_number
|
|
70
|
-
and (end_block_for_wallet is None or entry.block_number <= end_block_for_wallet)
|
|
71
|
-
):
|
|
72
|
-
if to_wallet := TreasuryWallet._get_instance(entry.to_address):
|
|
73
|
-
start_block_for_wallet = to_wallet._start_block
|
|
74
|
-
end_block_for_wallet = to_wallet._end_block
|
|
75
|
-
if (
|
|
76
|
-
start_block_for_wallet <= entry.block_number
|
|
77
|
-
and (end_block_for_wallet is None or entry.block_number <= end_block_for_wallet)
|
|
78
|
-
):
|
|
79
|
-
txgroup_dbid = TxGroup.get_dbid(
|
|
80
|
-
name="Internal Transfer",
|
|
81
|
-
parent=TxGroup.get_dbid("Ignore"),
|
|
82
|
-
)
|
|
151
|
+
if TreasuryWallet.check_membership(from_address, block):
|
|
152
|
+
if TreasuryWallet.check_membership(to_address, block):
|
|
153
|
+
txgroup_dbid = INTERNAL_TRANSFER_TXGROUP_DBID
|
|
154
|
+
elif not TreasuryWallet.check_membership(to_address, block):
|
|
155
|
+
txgroup_dbid = OUT_OF_RANGE_TXGROUP_DBID
|
|
83
156
|
|
|
84
157
|
if txgroup_dbid is None:
|
|
85
158
|
if isinstance(txhash := entry.hash, TransactionHash):
|
|
@@ -87,105 +160,136 @@ def sort_basic(entry: LedgerEntry) -> TxGroupDbid:
|
|
|
87
160
|
txgroup_dbid = HashMatcher.match(txhash)
|
|
88
161
|
|
|
89
162
|
if txgroup_dbid is None:
|
|
90
|
-
txgroup_dbid = FromAddressMatcher.match(
|
|
163
|
+
txgroup_dbid = FromAddressMatcher.match(from_address)
|
|
91
164
|
|
|
92
165
|
if txgroup_dbid is None:
|
|
93
|
-
txgroup_dbid = ToAddressMatcher.match(
|
|
94
|
-
|
|
166
|
+
txgroup_dbid = ToAddressMatcher.match(to_address)
|
|
167
|
+
|
|
95
168
|
if txgroup_dbid is None:
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
):
|
|
103
|
-
txgroup_dbid = must_sort_outbound_txgroup_dbid
|
|
104
|
-
|
|
105
|
-
elif (
|
|
106
|
-
entry.to_address
|
|
107
|
-
and (to_wallet := TreasuryWallet._get_instance(entry.to_address))
|
|
108
|
-
and to_wallet._start_block <= entry.block_number
|
|
109
|
-
and to_wallet._end_block is None or entry.block_number <= to_wallet._end_block # type: ignore [union-attr, operator]
|
|
110
|
-
):
|
|
111
|
-
txgroup_dbid = must_sort_inbound_txgroup_dbid
|
|
112
|
-
|
|
169
|
+
if TreasuryWallet.check_membership(from_address, block):
|
|
170
|
+
txgroup_dbid = MUST_SORT_OUTBOUND_TXGROUP_DBID
|
|
171
|
+
|
|
172
|
+
elif TreasuryWallet.check_membership(to_address, block):
|
|
173
|
+
txgroup_dbid = MUST_SORT_INBOUND_TXGROUP_DBID
|
|
174
|
+
|
|
113
175
|
else:
|
|
114
176
|
raise NotImplementedError("this isnt supposed to happen")
|
|
115
177
|
return txgroup_dbid # type: ignore [no-any-return]
|
|
116
178
|
|
|
117
179
|
|
|
118
|
-
def sort_basic_entity(
|
|
180
|
+
def sort_basic_entity(tx: db.TreasuryTx) -> TxGroupDbid:
|
|
181
|
+
"""Determine the transaction group ID for a TreasuryTx database entity using static matching.
|
|
182
|
+
|
|
183
|
+
Similar to :func:`sort_basic` but operates on a TreasuryTx entity from the database.
|
|
184
|
+
It considers additional constants such as `DISPERSE_APP` when determining whether
|
|
185
|
+
a transaction is out of range.
|
|
186
|
+
|
|
187
|
+
Args:
|
|
188
|
+
tx: A TreasuryTx database entity representing a treasury transaction.
|
|
189
|
+
|
|
190
|
+
Examples:
|
|
191
|
+
>>> from dao_treasury.db import TreasuryTx
|
|
192
|
+
>>> tx = TreasuryTx[123]
|
|
193
|
+
>>> group_id = sort_basic_entity(tx)
|
|
194
|
+
>>> print(group_id)
|
|
195
|
+
|
|
196
|
+
See Also:
|
|
197
|
+
:func:`sort_basic`
|
|
198
|
+
:func:`sort_advanced`
|
|
199
|
+
"""
|
|
200
|
+
from_address = tx.from_address.address
|
|
201
|
+
to_address = tx.to_address
|
|
202
|
+
block = tx.block
|
|
203
|
+
|
|
119
204
|
txgroup_dbid: Optional[TxGroupDbid] = None
|
|
120
|
-
if
|
|
121
|
-
if
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
and entry.to_address
|
|
129
|
-
):
|
|
130
|
-
if to_wallet := TreasuryWallet._get_instance(entry.to_address.address):
|
|
131
|
-
start_block_for_wallet = to_wallet._start_block
|
|
132
|
-
end_block_for_wallet = to_wallet._end_block
|
|
133
|
-
if (
|
|
134
|
-
start_block_for_wallet <= entry.block
|
|
135
|
-
and (end_block_for_wallet is None or entry.block <= end_block_for_wallet)
|
|
136
|
-
):
|
|
137
|
-
txgroup_dbid = TxGroup.get_dbid(
|
|
138
|
-
name="Internal Transfer",
|
|
139
|
-
parent=TxGroup.get_dbid("Ignore"),
|
|
140
|
-
)
|
|
205
|
+
if TreasuryWallet.check_membership(from_address, block):
|
|
206
|
+
if TreasuryWallet.check_membership(tx.to_address.address, block):
|
|
207
|
+
txgroup_dbid = INTERNAL_TRANSFER_TXGROUP_DBID
|
|
208
|
+
elif not (
|
|
209
|
+
TreasuryWallet.check_membership(tx.to_address.address, tx.block)
|
|
210
|
+
or from_address in constants.DISPERSE_APP
|
|
211
|
+
):
|
|
212
|
+
txgroup_dbid = OUT_OF_RANGE_TXGROUP_DBID
|
|
141
213
|
|
|
142
214
|
if txgroup_dbid is None:
|
|
143
|
-
txgroup_dbid = HashMatcher.match(
|
|
144
|
-
|
|
215
|
+
txgroup_dbid = HashMatcher.match(tx.hash)
|
|
216
|
+
|
|
145
217
|
if txgroup_dbid is None:
|
|
146
|
-
txgroup_dbid = FromAddressMatcher.match(
|
|
218
|
+
txgroup_dbid = FromAddressMatcher.match(from_address)
|
|
147
219
|
|
|
148
|
-
if txgroup_dbid is None and
|
|
149
|
-
txgroup_dbid = ToAddressMatcher.match(
|
|
220
|
+
if txgroup_dbid is None and to_address:
|
|
221
|
+
txgroup_dbid = ToAddressMatcher.match(to_address.address)
|
|
150
222
|
|
|
151
223
|
if txgroup_dbid is None:
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
txgroup_dbid =
|
|
160
|
-
|
|
161
|
-
elif
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
and to_wallet._start_block <= entry.block
|
|
165
|
-
and to_wallet._end_block is None or entry.block <= to_wallet._end_block # type: ignore [union-attr, operator]
|
|
166
|
-
):
|
|
167
|
-
txgroup_dbid = must_sort_inbound_txgroup_dbid
|
|
168
|
-
|
|
224
|
+
if TreasuryWallet.check_membership(from_address, block):
|
|
225
|
+
txgroup_dbid = MUST_SORT_OUTBOUND_TXGROUP_DBID
|
|
226
|
+
|
|
227
|
+
elif TreasuryWallet.check_membership(to_address.address, block):
|
|
228
|
+
txgroup_dbid = MUST_SORT_INBOUND_TXGROUP_DBID
|
|
229
|
+
|
|
230
|
+
elif from_address in constants.DISPERSE_APP:
|
|
231
|
+
txgroup_dbid = MUST_SORT_OUTBOUND_TXGROUP_DBID
|
|
232
|
+
|
|
233
|
+
elif from_address in constants.DISPERSE_APP:
|
|
234
|
+
txgroup_dbid = MUST_SORT_OUTBOUND_TXGROUP_DBID
|
|
235
|
+
|
|
169
236
|
else:
|
|
170
237
|
raise NotImplementedError("this isnt supposed to happen")
|
|
171
|
-
|
|
172
|
-
if txgroup_dbid not in (
|
|
173
|
-
|
|
174
|
-
|
|
238
|
+
|
|
239
|
+
if txgroup_dbid not in (
|
|
240
|
+
MUST_SORT_INBOUND_TXGROUP_DBID,
|
|
241
|
+
MUST_SORT_OUTBOUND_TXGROUP_DBID,
|
|
242
|
+
):
|
|
243
|
+
logger.info("Sorted %s to %s", tx, TxGroup.get_fullname(txgroup_dbid))
|
|
244
|
+
|
|
175
245
|
return txgroup_dbid # type: ignore [no-any-return]
|
|
176
246
|
|
|
177
247
|
|
|
178
248
|
async def sort_advanced(entry: db.TreasuryTx) -> TxGroupDbid:
|
|
249
|
+
"""Determine the transaction group ID for a TreasuryTx entity using advanced dynamic rules.
|
|
250
|
+
|
|
251
|
+
Starts with the result of static matching via :func:`sort_basic_entity`, then
|
|
252
|
+
applies advanced asynchronous matching rules registered under :data:`SORT_RULES`.
|
|
253
|
+
Applies rules sequentially until a match is found or all rules are exhausted.
|
|
254
|
+
|
|
255
|
+
If a rule's match attempt raises a `ContractNotVerified` exception, the rule is skipped.
|
|
256
|
+
|
|
257
|
+
Updates the TreasuryTx entity's transaction group in the database when a match
|
|
258
|
+
other than 'Must Sort Inbound/Outbound' is found.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
entry: A TreasuryTx database entity representing a treasury transaction.
|
|
262
|
+
|
|
263
|
+
Examples:
|
|
264
|
+
>>> from dao_treasury.db import TreasuryTx
|
|
265
|
+
>>> import asyncio
|
|
266
|
+
>>> tx = TreasuryTx[123]
|
|
267
|
+
>>> group_id = asyncio.run(sort_advanced(tx))
|
|
268
|
+
>>> print(group_id)
|
|
269
|
+
|
|
270
|
+
See Also:
|
|
271
|
+
:func:`sort_basic_entity`
|
|
272
|
+
:data:`SORT_RULES`
|
|
273
|
+
"""
|
|
179
274
|
txgroup_dbid = sort_basic_entity(entry)
|
|
180
275
|
|
|
181
|
-
if txgroup_dbid in (
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
276
|
+
if txgroup_dbid in (
|
|
277
|
+
MUST_SORT_INBOUND_TXGROUP_DBID,
|
|
278
|
+
MUST_SORT_OUTBOUND_TXGROUP_DBID,
|
|
279
|
+
):
|
|
280
|
+
for rules in SORT_RULES.values():
|
|
281
|
+
for rule in rules:
|
|
282
|
+
try:
|
|
283
|
+
if await rule.match(entry):
|
|
284
|
+
txgroup_dbid = rule.txgroup_dbid
|
|
285
|
+
break
|
|
286
|
+
except ContractNotVerified:
|
|
287
|
+
continue
|
|
288
|
+
if txgroup_dbid not in (
|
|
289
|
+
MUST_SORT_INBOUND_TXGROUP_DBID,
|
|
290
|
+
MUST_SORT_OUTBOUND_TXGROUP_DBID,
|
|
291
|
+
):
|
|
292
|
+
logger.info("Sorted %s to %s", entry, TxGroup.get_fullname(txgroup_dbid))
|
|
293
|
+
await entry._set_txgroup(txgroup_dbid)
|
|
294
|
+
|
|
191
295
|
return txgroup_dbid # type: ignore [no-any-return]
|
|
Binary file
|