yearn-treasury 0.0.39__tar.gz → 0.0.45__tar.gz
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.
Potentially problematic release.
This version of yearn-treasury might be problematic. Click here for more details.
- {yearn_treasury-0.0.39/yearn_treasury.egg-info → yearn_treasury-0.0.45}/PKG-INFO +2 -3
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/pyproject.toml +6 -6
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/setup.py +4 -2
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/_logging.py +2 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/address_labels.yaml +6 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/main.py +43 -22
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/__init__.py +1 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/aave.py +15 -8
- yearn_treasury-0.0.45/yearn_treasury/rules/ignore/swaps/auctions.py +31 -0
- yearn_treasury-0.0.45/yearn_treasury/rules/ignore/swaps/compound.py +58 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/cowswap.py +16 -13
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/curve.py +40 -12
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/uniswap.py +26 -6
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/yfi.py +2 -1
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_income/misc.py +1 -1
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/shitcoins.py +7 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/vaults.py +3 -4
- yearn_treasury-0.0.45/yearn_treasury/yteams.py +208 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45/yearn_treasury.egg-info}/PKG-INFO +2 -3
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury.egg-info/SOURCES.txt +2 -0
- yearn_treasury-0.0.45/yearn_treasury.egg-info/requires.txt +2 -0
- yearn_treasury-0.0.39/yearn_treasury/rules/ignore/swaps/compound.py +0 -48
- yearn_treasury-0.0.39/yearn_treasury.egg-info/requires.txt +0 -3
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/MANIFEST.in +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/README.md +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/setup.cfg +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/__init__.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/_db.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/_ens.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/budget/__init__.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/budget/_request.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/budget/_requests.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/constants.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/py.typed +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/__init__.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/constants.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/cost_of_revenue/__init__.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/cost_of_revenue/gas.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/cost_of_revenue/match_on_hash.yaml +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/expense/__init__.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/expense/general.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/expense/infrastructure.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/expense/match_on_hash.yaml +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/expense/match_on_to_address.yaml +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/expense/people.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/expense/security.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/__init__.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/general.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/maker.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/passthru.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/staking.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/_skip_tokens.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/conversion_factory.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/gearbox.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/iearn.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/otc.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/pooltogether.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/synthetix.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/unwrapper.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/vaults.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/woofy.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/yla.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/unit.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/weth.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/ygov.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/__init__.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/boost.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/bugs.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/donations.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/dyfi.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/events.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/match_on_hash.yaml +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/match_on_to_address.yaml +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/misc.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/revshare.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_income/__init__.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_income/airdrops.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_income/match_on_hash.yaml +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/revenue/__init__.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/revenue/bribes.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/revenue/farming.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/revenue/keepcoins.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/revenue/match_on_hash.yaml +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/revenue/seasolver.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/revenue/vaults.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/revenue/yteams.py +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/wallets.yaml +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury.egg-info/dependency_links.txt +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury.egg-info/entry_points.txt +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury.egg-info/not-zip-safe +0 -0
- {yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: yearn_treasury
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.45
|
|
4
4
|
Summary: This WIP library runs the eth-portfolio and dao-treasury exporters for the Yearn Finance treasury.
|
|
5
5
|
Classifier: Development Status :: 3 - Alpha
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -15,8 +15,7 @@ Classifier: Operating System :: OS Independent
|
|
|
15
15
|
Classifier: Topic :: Software Development :: Libraries
|
|
16
16
|
Requires-Python: >=3.10,<3.13
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: dao-treasury
|
|
19
|
-
Requires-Dist: eth-brownie<1.23,>=1.21.0
|
|
18
|
+
Requires-Dist: dao-treasury==0.0.67
|
|
20
19
|
Requires-Dist: faster-async-lru<3,>=2.0.5
|
|
21
20
|
Dynamic: classifier
|
|
22
21
|
Dynamic: description
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "yearn-treasury"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.45"
|
|
4
4
|
description = "This WIP library runs the eth-portfolio and dao-treasury exporters for the Yearn Finance treasury."
|
|
5
5
|
authors = ["Bob The Buidler <you@example.com>"]
|
|
6
6
|
packages = [{ include = "yearn_treasury/*" }]
|
|
@@ -12,8 +12,9 @@ requires = [
|
|
|
12
12
|
"mypy[mypyc]==1.18.2",
|
|
13
13
|
"tomli>=2.0.0; python_version < '3.11'",
|
|
14
14
|
"types-requests",
|
|
15
|
-
"dao-treasury
|
|
16
|
-
"eth-
|
|
15
|
+
"dao-treasury==0.0.66; platform_system == 'Linux'",
|
|
16
|
+
"eth-brownie==1.22.0.dev0; platform_system == 'Linux'",
|
|
17
|
+
"eth-typing==5.2.1",
|
|
17
18
|
]
|
|
18
19
|
build-backend = "setuptools.build_meta"
|
|
19
20
|
|
|
@@ -22,12 +23,11 @@ yearn-treasury = "yearn_treasury.main:main"
|
|
|
22
23
|
|
|
23
24
|
[tool.poetry.dependencies]
|
|
24
25
|
python = ">=3.10,<3.13"
|
|
25
|
-
dao-treasury = "
|
|
26
|
-
eth-brownie = ">=1.21.0,<1.23"
|
|
26
|
+
dao-treasury = "==0.0.67"
|
|
27
27
|
faster-async-lru = ">=2.0.5,<3"
|
|
28
28
|
|
|
29
29
|
[tool.poetry.group.dev.dependencies]
|
|
30
|
-
mypy = "
|
|
30
|
+
mypy = "1.18.2"
|
|
31
31
|
types-requests = "*"
|
|
32
32
|
|
|
33
33
|
[tool.poetry.group.docs.dependencies]
|
|
@@ -14,6 +14,7 @@ else:
|
|
|
14
14
|
"yearn_treasury/rules/expense",
|
|
15
15
|
# "yearn_treasury/rules/ignore",
|
|
16
16
|
"yearn_treasury/rules/ignore/swaps/conversion_factory.py",
|
|
17
|
+
"yearn_treasury/rules/ignore/swaps/auctions.py",
|
|
17
18
|
# "yearn_treasury/rules/ignore/swaps/curve.py", enable with brownie 1.22.0
|
|
18
19
|
"yearn_treasury/rules/ignore/swaps/gearbox.py",
|
|
19
20
|
"yearn_treasury/rules/ignore/swaps/iearn.py",
|
|
@@ -23,7 +24,7 @@ else:
|
|
|
23
24
|
"yearn_treasury/rules/ignore/swaps/unwrapper.py",
|
|
24
25
|
"yearn_treasury/rules/ignore/swaps/vaults.py",
|
|
25
26
|
"yearn_treasury/rules/ignore/swaps/woofy.py",
|
|
26
|
-
|
|
27
|
+
"yearn_treasury/rules/ignore/swaps/yfi.py",
|
|
27
28
|
"yearn_treasury/rules/ignore/swaps/yla.py",
|
|
28
29
|
"yearn_treasury/rules/ignore/general.py",
|
|
29
30
|
"yearn_treasury/rules/ignore/unit.py",
|
|
@@ -40,7 +41,7 @@ else:
|
|
|
40
41
|
"yearn_treasury/_db.py",
|
|
41
42
|
"yearn_treasury/_ens.py",
|
|
42
43
|
"yearn_treasury/_logging.py",
|
|
43
|
-
|
|
44
|
+
"yearn_treasury/vaults.py",
|
|
44
45
|
"--strict",
|
|
45
46
|
"--pretty",
|
|
46
47
|
"--disable-error-code=unused-ignore",
|
|
@@ -48,6 +49,7 @@ else:
|
|
|
48
49
|
"--disable-error-code=no-any-return",
|
|
49
50
|
"--disable-error-code=misc", # TODO: drop support for 32bit systems
|
|
50
51
|
],
|
|
52
|
+
group_name="yearn_treasury",
|
|
51
53
|
)
|
|
52
54
|
|
|
53
55
|
|
|
@@ -25,6 +25,8 @@ suppress_logs_for: Final[Dict[Network, List[HexAddress]]] = {
|
|
|
25
25
|
"0xBF7AA989192b020a8d3e1C65a558e123834325cA", # unpriceable yvWBTC - This vault had a bug and does not have a pricePerShare
|
|
26
26
|
"0x5aFE3855358E112B5647B952709E6165e1c1eEEe", # SAFE - This was not tradeable at the time of the first airdrops
|
|
27
27
|
"0x718AbE90777F5B778B52D553a5aBaa148DD0dc5D", # yvCurve-alETH - The underlying curve pool had an issue and is unpriceable
|
|
28
|
+
"0x3819f64f282bf135d62168C1e513280dAF905e06", # HDRN
|
|
29
|
+
"0x5fAa989Af96Af85384b8a938c2EdE4A7378D9875", # GAL
|
|
28
30
|
],
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -28,6 +28,12 @@
|
|
|
28
28
|
- "0xC564EE9f21Ed8A2d8E7e76c085740d5e4c5FaFbE"
|
|
29
29
|
yLockers Multisig:
|
|
30
30
|
- "0x4444AAAACDBa5580282365e25b16309Bd770ce4a"
|
|
31
|
+
yRoboTreasury Treasury Contract:
|
|
32
|
+
- "0xEf77cc176c748d291EfB6CdC982c5744fC7211c8"
|
|
33
|
+
yRoboTreasury Stables Reserve:
|
|
34
|
+
- "0x278374fFb10B7D16E7633444c13e6E565EA57c28"
|
|
35
|
+
yearn.fi Dutch Auctions:
|
|
36
|
+
- "0x861fE45742f70054917B65bE18904662bD0dBd30"
|
|
31
37
|
250:
|
|
32
38
|
Yearn Strategist Multisig:
|
|
33
39
|
- "0x72a34AbafAB09b15E7191822A679f28E067C4a16"
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Command-line interface for the Yearn Treasury exporter.
|
|
3
3
|
|
|
4
4
|
This module provides the `yearn-treasury` CLI, which connects to a Brownie network
|
|
5
|
-
based on the `--network` option
|
|
6
|
-
periodically snapshots treasury
|
|
7
|
-
|
|
5
|
+
(based on the `--network` option or the `BROWNIE_NETWORK_ID` environment variable),
|
|
6
|
+
periodically snapshots treasury metrics, and pushes them to Victoria Metrics.
|
|
7
|
+
It also launches Yearn Treasury's Grafana dashboard and an optional renderer for visual reports.
|
|
8
8
|
|
|
9
9
|
Example:
|
|
10
10
|
Run export every 12 hours on mainnet:
|
|
@@ -12,15 +12,24 @@ Example:
|
|
|
12
12
|
.. code-block:: bash
|
|
13
13
|
|
|
14
14
|
yearn-treasury run --network mainnet --interval 12h
|
|
15
|
+
|
|
16
|
+
CLI Options:
|
|
17
|
+
--network Brownie network identifier (default: mainnet)
|
|
18
|
+
--interval Time interval between datapoints (default: 12h)
|
|
19
|
+
--concurrency Max number of historical blocks to export concurrently (default: 30)
|
|
20
|
+
--daemon Run as a background daemon (currently unsupported)
|
|
21
|
+
--grafana-port Port for the Grafana dashboard (default: 3004)
|
|
22
|
+
--victoria-port Port for the Victoria metrics endpoint (default: 8430)
|
|
23
|
+
--start-renderer Start the Grafana renderer container for dashboard image export
|
|
24
|
+
--renderer-port Port for the renderer service (default: 8080)
|
|
15
25
|
"""
|
|
16
26
|
|
|
17
27
|
import asyncio
|
|
18
28
|
import os
|
|
19
29
|
from argparse import ArgumentParser
|
|
20
|
-
from pathlib import Path
|
|
21
30
|
from typing import Final, final
|
|
22
31
|
|
|
23
|
-
from
|
|
32
|
+
from yearn_treasury import yteams
|
|
24
33
|
|
|
25
34
|
|
|
26
35
|
parser = ArgumentParser(description="Treasury CLI")
|
|
@@ -42,8 +51,8 @@ run_parser.add_argument(
|
|
|
42
51
|
run_parser.add_argument(
|
|
43
52
|
"--concurrency",
|
|
44
53
|
type=int,
|
|
45
|
-
help="The max number of historical blocks to export concurrently. default:
|
|
46
|
-
default=
|
|
54
|
+
help="The max number of historical blocks to export concurrently. default: 30",
|
|
55
|
+
default=30,
|
|
47
56
|
)
|
|
48
57
|
run_parser.add_argument(
|
|
49
58
|
"--daemon",
|
|
@@ -83,23 +92,19 @@ BROWNIE_NETWORK = os.environ["BROWNIE_NETWORK_ID"]
|
|
|
83
92
|
# TODO: run forever arg
|
|
84
93
|
def main() -> None:
|
|
85
94
|
"""
|
|
86
|
-
Connect to the configured Brownie network and start the export loop.
|
|
95
|
+
Connect to the configured Brownie network, clean up the database, and start the export loop.
|
|
87
96
|
|
|
88
97
|
This function is registered as a console script entrypoint under
|
|
89
|
-
``yearn-treasury
|
|
90
|
-
|
|
91
|
-
Steps:
|
|
98
|
+
``yearn-treasury``. It performs the following steps:
|
|
92
99
|
1. Reads the ``BROWNIE_NETWORK_ID`` environment variable (populated from
|
|
93
100
|
the ``--network`` option or existing env var).
|
|
94
|
-
2. Connects to
|
|
95
|
-
3.
|
|
96
|
-
4.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
6.
|
|
100
|
-
|
|
101
|
-
Raises:
|
|
102
|
-
RuntimeError: If the Brownie network cannot be determined.
|
|
101
|
+
2. Connects to the specified Brownie network.
|
|
102
|
+
3. Merges local SHITCOINS into eth_portfolio's config to skip tokens we don't care about.
|
|
103
|
+
4. Drops any shitcoin transactions that might be in the database.
|
|
104
|
+
5. Constructs an immutable Args subclass to pass CLI parameters to
|
|
105
|
+
:func:`dao_treasury.main.export`.
|
|
106
|
+
6. Exports ports for external services into environment variables.
|
|
107
|
+
7. Runs both the DAO Treasury export and Yearn team revenue/expenses calculation concurrently under asyncio.
|
|
103
108
|
"""
|
|
104
109
|
import dao_treasury.db
|
|
105
110
|
import eth_portfolio
|
|
@@ -115,7 +120,10 @@ def main() -> None:
|
|
|
115
120
|
@final
|
|
116
121
|
class Args(constants.Args):
|
|
117
122
|
"""
|
|
118
|
-
Immutable container of CLI arguments for
|
|
123
|
+
Immutable container of CLI arguments for export and dashboard/renderer configuration.
|
|
124
|
+
|
|
125
|
+
Inherits from DAO Treasury's :class:`constants.Args` and is used to pass runtime
|
|
126
|
+
parameters to the DAO Treasury export and related services.
|
|
119
127
|
"""
|
|
120
128
|
|
|
121
129
|
network: Final[str] = args.network
|
|
@@ -149,7 +157,20 @@ def main() -> None:
|
|
|
149
157
|
os.environ["DAO_TREASURY_RENDERER_PORT"] = str(Args.renderer_port)
|
|
150
158
|
os.environ["VICTORIA_PORT"] = str(Args.victoria_port)
|
|
151
159
|
|
|
160
|
+
async def yearn_wrapper():
|
|
161
|
+
"""
|
|
162
|
+
Run the DAO Treasury export and Yearn team revenue/expenses calculation concurrently.
|
|
163
|
+
|
|
164
|
+
This coroutine gathers:
|
|
165
|
+
- The main DAO Treasury export process (dao_treasury.main.export)
|
|
166
|
+
- The Yearn teams' revenue and expenses calculation (yteams.calculate_teams_revenue_expenses)
|
|
167
|
+
"""
|
|
168
|
+
return await asyncio.gather(
|
|
169
|
+
dao_treasury.main.export(Args),
|
|
170
|
+
yteams.calculate_teams_revenue_expenses(),
|
|
171
|
+
)
|
|
172
|
+
|
|
152
173
|
# Start the balance export routine
|
|
153
|
-
asyncio.get_event_loop().run_until_complete(
|
|
174
|
+
asyncio.get_event_loop().run_until_complete(yearn_wrapper())
|
|
154
175
|
|
|
155
176
|
rules # I just put this here so the import isn't flagged as unused
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/__init__.py
RENAMED
|
@@ -7,6 +7,7 @@ swaps: Final[SortRuleFactory[IgnoreSortRule]] = ignore("Swaps")
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
from yearn_treasury.rules.ignore.swaps.aave import *
|
|
10
|
+
from yearn_treasury.rules.ignore.swaps.auctions import *
|
|
10
11
|
from yearn_treasury.rules.ignore.swaps.compound import *
|
|
11
12
|
from yearn_treasury.rules.ignore.swaps.conversion_factory import *
|
|
12
13
|
from yearn_treasury.rules.ignore.swaps.cowswap import *
|
|
@@ -43,20 +43,27 @@ async def is_aave_withdrawal(tx: TreasuryTx) -> bool:
|
|
|
43
43
|
if (
|
|
44
44
|
from_address == event["_user"]
|
|
45
45
|
and await token.contract.underlyingAssetAddress == event["_reserve"]
|
|
46
|
-
and token.scale_value(event["_amount"]) == tx.amount
|
|
47
46
|
):
|
|
48
|
-
|
|
47
|
+
# TODO get rid of this rounding when we migrate the db to postgres
|
|
48
|
+
event_amount = round(token.scale_value(event["_amount"]), 11)
|
|
49
|
+
if event_amount == round(tx.amount, 11):
|
|
50
|
+
return True
|
|
51
|
+
print(
|
|
52
|
+
f"Aave Withdrawal atoken side does not match: {round(tx.amount, 14)} {event_amount}"
|
|
53
|
+
)
|
|
49
54
|
|
|
50
55
|
# Underlying side
|
|
51
56
|
if TreasuryWallet.check_membership(tx.to_address.address, tx.block): # type: ignore [union-attr, arg-type]
|
|
52
57
|
token = tx.token
|
|
53
58
|
for event in await tx.get_events("RedeemUnderlying", sync=False):
|
|
54
|
-
if
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
if token == event["_reserve"] and to_address == event["_user"]:
|
|
60
|
+
# TODO get rid of this rounding when we migrate the db to postgres
|
|
61
|
+
event_amount = round(token.scale_value(event["_amount"]), 11)
|
|
62
|
+
if event_amount == round(tx.amount, 11):
|
|
63
|
+
return True
|
|
64
|
+
print(
|
|
65
|
+
f"Aave Withdrawal underlying side does not match: {round(tx.amount, 14)} {event_amount}"
|
|
66
|
+
)
|
|
60
67
|
|
|
61
68
|
# TODO: If these end up becoming more frequent, figure out sorting hueristics.
|
|
62
69
|
return tx.hash == "0x36ee5631859a15f57b44e41b8590023cf6f0c7b12d28ea760e9d8f8003f4fc50"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from typing import Final
|
|
2
|
+
|
|
3
|
+
from dao_treasury import TreasuryTx
|
|
4
|
+
from y import Network
|
|
5
|
+
|
|
6
|
+
from yearn_treasury.rules.ignore.swaps import swaps
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
auctions: Final = swaps("Auctions")
|
|
10
|
+
|
|
11
|
+
YEARNFI_DUTCH_AUCTIONS: Final = "0x861fE45742f70054917B65bE18904662bD0dBd30"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@auctions("Auction Proceeds", Network.Mainnet)
|
|
15
|
+
async def is_auction_proceeds(tx: TreasuryTx) -> bool:
|
|
16
|
+
# NOTE: the other side of these swaps is currently recorded under
|
|
17
|
+
# 'Ignore:Internal Transfer' when it goes to the Generic bucket contract
|
|
18
|
+
if tx.from_nickname != "Contract: GPv2Settlement":
|
|
19
|
+
return False
|
|
20
|
+
|
|
21
|
+
for trade in await tx.get_events("Trade", sync=False):
|
|
22
|
+
if trade["owner"] != YEARNFI_DUTCH_AUCTIONS or tx.token != trade["buyToken"]:
|
|
23
|
+
continue
|
|
24
|
+
buy_amount = tx.token.scale_value(trade["buyAmount"])
|
|
25
|
+
if round(buy_amount, 14) == round(tx.amount, 14):
|
|
26
|
+
return True
|
|
27
|
+
print(
|
|
28
|
+
f"auction proceeds amount does not match: {round(buy_amount, 14)} {round(tx.amount, 14)}"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return False
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from typing import Final
|
|
2
|
+
|
|
3
|
+
from dao_treasury import TreasuryTx
|
|
4
|
+
|
|
5
|
+
from yearn_treasury.rules.ignore.swaps import swaps
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
compound: Final = swaps("Compound")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@compound("Deposit")
|
|
12
|
+
async def is_compound_deposit(tx: TreasuryTx) -> bool:
|
|
13
|
+
for event in await tx.get_events("Mint", sync=False):
|
|
14
|
+
if all(arg in event for arg in ("minter", "mintTokens", "mintAmount")):
|
|
15
|
+
minter = event["minter"]
|
|
16
|
+
minted = tx.token.scale_value(event["mintTokens"])
|
|
17
|
+
# cToken side
|
|
18
|
+
if tx.token == tx.from_address == event.address and tx.to_address == minter:
|
|
19
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
20
|
+
if round(minted, 14) == round(tx.amount, 14):
|
|
21
|
+
return True
|
|
22
|
+
print(
|
|
23
|
+
f"Compound deposit ctoken side does not match: {round(minted, 14)} {round(tx.amount, 14)}"
|
|
24
|
+
)
|
|
25
|
+
# underlying side
|
|
26
|
+
elif tx.to_address == event.address and tx.from_address == minter:
|
|
27
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
28
|
+
if round(minted, 14) == round(tx.amount, 14):
|
|
29
|
+
return True
|
|
30
|
+
print(
|
|
31
|
+
f"Compound deposit underlying side does not match: {round(minted, 14)} {round(tx.amount, 14)}"
|
|
32
|
+
)
|
|
33
|
+
return False
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@compound("Withdrawal")
|
|
37
|
+
async def is_compound_withdrawal(tx: TreasuryTx) -> bool:
|
|
38
|
+
for event in await tx.get_events("Redeem", sync=False):
|
|
39
|
+
if all(arg in event for arg in ("redeemer", "redeemTokens", "redeemAmount")):
|
|
40
|
+
redeemer = event["redeemer"]
|
|
41
|
+
redeemed = tx.token.scale_value(event["redeemTokens"])
|
|
42
|
+
# cToken side
|
|
43
|
+
if tx.token == event.address and tx.from_address == redeemer:
|
|
44
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
45
|
+
if round(redeemed, 7) == round(tx.amount, 7):
|
|
46
|
+
return True
|
|
47
|
+
print(
|
|
48
|
+
f"Compound withdrawal ctoken side does not match: {round(redeemed, 7)} {round(tx.amount, 7)}"
|
|
49
|
+
)
|
|
50
|
+
# underlying side
|
|
51
|
+
elif tx.to_address == redeemer and tx.from_address == event.address:
|
|
52
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
53
|
+
if round(redeemed, 14) == round(tx.amount, 14):
|
|
54
|
+
return True
|
|
55
|
+
print(
|
|
56
|
+
f"Compound withdrawal underlying side does not match: {round(redeemed, 14)} {round(tx.amount, 14)}"
|
|
57
|
+
)
|
|
58
|
+
return False
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/cowswap.py
RENAMED
|
@@ -10,7 +10,7 @@ from yearn_treasury.rules.ignore.swaps import swaps
|
|
|
10
10
|
from yearn_treasury.rules.ignore.swaps._skip_tokens import SKIP_TOKENS
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
COWSWAP: Final = "0x9008D19f58AAbD9eD0D60971565AA8510560ab41"
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@swaps("Cowswap", Network.Mainnet)
|
|
@@ -34,23 +34,26 @@ def is_cowswap_swap(tx: TreasuryTx) -> bool:
|
|
|
34
34
|
|
|
35
35
|
for trade in tx.events["Trade"]:
|
|
36
36
|
if (
|
|
37
|
-
trade.address ==
|
|
37
|
+
trade.address == COWSWAP
|
|
38
38
|
and TreasuryWallet.check_membership(trade["owner"], block)
|
|
39
39
|
and trade["buyToken"] not in SKIP_TOKENS
|
|
40
40
|
):
|
|
41
41
|
# buy side
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
and TreasuryWallet.check_membership(tx.to_address.address, block) # type: ignore [union-attr, arg-type]
|
|
45
|
-
and amount == token.scale_value(trade["buyAmount"])
|
|
42
|
+
if token_address == trade["buyToken"] and TreasuryWallet.check_membership(
|
|
43
|
+
tx.to_address.address, block # type: ignore [union-attr, arg-type]
|
|
46
44
|
):
|
|
47
|
-
|
|
45
|
+
# TODO get rid of this rounding when we move to postgres
|
|
46
|
+
buy_amount = round(token.scale_value(trade["buyAmount"]), 8)
|
|
47
|
+
if round(amount, 8) == buy_amount:
|
|
48
|
+
return True
|
|
49
|
+
print(f"Cowswap buy amount does not match: {round(amount, 8)} {buy_amount}")
|
|
48
50
|
# sell side
|
|
49
|
-
elif
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
elif token_address == trade["sellToken"] and tx.from_address == trade["owner"]:
|
|
52
|
+
# TODO get rid of this rounding when we move to postgres
|
|
53
|
+
sell_amount = round(token.scale_value(trade["sellAmount"]), 8)
|
|
54
|
+
if round(amount, 8) != sell_amount:
|
|
55
|
+
print(f"Cowswap sell amount does not match: {round(amount, 8)} {sell_amount}")
|
|
56
|
+
continue
|
|
54
57
|
# Did Yearn actually receive the other side of the trade?
|
|
55
58
|
for address in TREASURY_WALLETS:
|
|
56
59
|
if TreasuryWallet.check_membership(address, block):
|
|
@@ -59,7 +62,7 @@ def is_cowswap_swap(tx: TreasuryTx) -> bool:
|
|
|
59
62
|
for t in TreasuryTx # type: ignore [attr-defined]
|
|
60
63
|
if t.hash == tx.hash
|
|
61
64
|
and t.token.address.address == trade["buyToken"]
|
|
62
|
-
and t.from_address.address ==
|
|
65
|
+
and t.from_address.address == COWSWAP
|
|
63
66
|
and t.to_address.address == address
|
|
64
67
|
)
|
|
65
68
|
|
|
@@ -50,11 +50,19 @@ async def is_curve_deposit(tx: TreasuryTx) -> bool:
|
|
|
50
50
|
# Tokens sent
|
|
51
51
|
elif tx.to_address == event.address:
|
|
52
52
|
try:
|
|
53
|
+
tx_amount = round(tx.amount, 8)
|
|
53
54
|
for i, amount in enumerate(event["token_amounts"]):
|
|
54
|
-
|
|
55
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
56
|
+
event_amount = round(tx.token.scale_value(amount), 8)
|
|
57
|
+
if tx_amount == event_amount:
|
|
55
58
|
pool = await Contract.coroutine(event.address) # type: ignore [assignment]
|
|
56
59
|
if tx.token == await _get_coin_at_index(pool, i):
|
|
57
60
|
return True
|
|
61
|
+
return True
|
|
62
|
+
else:
|
|
63
|
+
print(
|
|
64
|
+
f"Curve AddLiquidity sent amount does not match: {tx_amount} {event_amount}"
|
|
65
|
+
)
|
|
58
66
|
except EventLookupError:
|
|
59
67
|
pass
|
|
60
68
|
|
|
@@ -67,10 +75,16 @@ async def is_curve_deposit(tx: TreasuryTx) -> bool:
|
|
|
67
75
|
print(f"AddLiquidity-3crv: {event}")
|
|
68
76
|
token = tx.token
|
|
69
77
|
for i, amount in enumerate(event["token_amounts"]):
|
|
70
|
-
|
|
78
|
+
event_amount = token.scale_value(amount)
|
|
79
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
80
|
+
if round(tx.amount, 14) == round(event_amount, 14):
|
|
71
81
|
pool = await Contract.coroutine(event.address) # type: ignore [assignment]
|
|
72
82
|
if token == await _get_coin_at_index(pool, i):
|
|
73
83
|
return True
|
|
84
|
+
else:
|
|
85
|
+
print(
|
|
86
|
+
f"AddLiquidity-3crv amount does not match: {round(tx.amount, 14)} {round(event_amount)}"
|
|
87
|
+
)
|
|
74
88
|
|
|
75
89
|
# TODO: see if we can remove these with latest hueristics
|
|
76
90
|
return CHAINID == Network.Mainnet and tx.hash in (
|
|
@@ -98,17 +112,24 @@ async def is_curve_withdrawal(tx: TreasuryTx) -> bool:
|
|
|
98
112
|
def _is_curve_withdrawal_one(tx: TreasuryTx) -> bool:
|
|
99
113
|
for event in tx.get_events("RemoveLiquidityOne"):
|
|
100
114
|
# LP Token Side
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
115
|
+
if tx.to_address == ZERO_ADDRESS and _token_is_curvey(tx):
|
|
116
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
117
|
+
event_amount = round(tx.token.scale_value(event["token_amount"]), 9)
|
|
118
|
+
if round(tx.amount, 9) == event_amount:
|
|
119
|
+
return True
|
|
120
|
+
print(
|
|
121
|
+
f"Curve withdrawal one curvey amount does not match: {round(tx.amount, 9)} {event_amount}"
|
|
122
|
+
)
|
|
107
123
|
# Tokens rec'd
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
124
|
+
if tx.from_address != event.address:
|
|
125
|
+
continue
|
|
126
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
127
|
+
event_amount = tx.token.scale_value(event["coin_amount"])
|
|
128
|
+
if round(tx.amount, 9) == round(event_amount, 9):
|
|
111
129
|
return True
|
|
130
|
+
print(
|
|
131
|
+
f"Curve withdrawal one amount does not match: {round(tx.amount, 9)} {round(event_amount, 9)}"
|
|
132
|
+
)
|
|
112
133
|
return False
|
|
113
134
|
|
|
114
135
|
|
|
@@ -127,15 +148,22 @@ async def _is_curve_withdrawal_multi(tx: TreasuryTx) -> bool:
|
|
|
127
148
|
elif tx.from_address == event.address and TreasuryWallet.check_membership(
|
|
128
149
|
tx.to_address.address, tx.block # type: ignore [union-attr, arg-type]
|
|
129
150
|
):
|
|
151
|
+
tx_amount = round(tx.amount, 7)
|
|
130
152
|
try:
|
|
131
153
|
for i, amount in enumerate(event["token_amounts"]):
|
|
132
|
-
|
|
154
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
155
|
+
event_amount = round(tx.token.scale_value(amount), 7)
|
|
156
|
+
if tx_amount == event_amount:
|
|
133
157
|
pool = await Contract.coroutine(event.address) # type: ignore [assignment]
|
|
134
158
|
if hasattr(pool, "underlying_coins"):
|
|
135
159
|
coin: ChecksumAddress = await pool.underlying_coins.coroutine(i)
|
|
136
160
|
return tx.token == coin
|
|
137
161
|
else:
|
|
138
162
|
return tx.token == await _get_coin_at_index(pool, i)
|
|
163
|
+
else:
|
|
164
|
+
print(
|
|
165
|
+
f"Curve withdrawal multi amount does not match: {tx_amount} {event_amount}"
|
|
166
|
+
)
|
|
139
167
|
except EventLookupError:
|
|
140
168
|
# some other event has different keys, maybe we need to implement logic to capture these. time will tell.
|
|
141
169
|
pass
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/uniswap.py
RENAMED
|
@@ -57,7 +57,7 @@ async def is_uniswap_deposit(tx: TreasuryTx) -> bool:
|
|
|
57
57
|
if any(
|
|
58
58
|
tokens[1] == transfer.address
|
|
59
59
|
and tx.to_address
|
|
60
|
-
== transfer.values()[:1]
|
|
60
|
+
== transfer.values()[:1] # type: ignore [index]
|
|
61
61
|
== [mint["sender"], mint.address]
|
|
62
62
|
for transfer in transfers
|
|
63
63
|
):
|
|
@@ -78,7 +78,7 @@ async def is_uniswap_deposit(tx: TreasuryTx) -> bool:
|
|
|
78
78
|
if any(
|
|
79
79
|
tokens[0] == transfer.address
|
|
80
80
|
and tx.to_address
|
|
81
|
-
== transfer.values()[:1]
|
|
81
|
+
== transfer.values()[:1] # type: ignore [index]
|
|
82
82
|
== [mint["sender"], mint.address]
|
|
83
83
|
for transfer in transfers
|
|
84
84
|
):
|
|
@@ -243,11 +243,21 @@ async def is_uniswap_swap(tx: TreasuryTx) -> bool:
|
|
|
243
243
|
continue
|
|
244
244
|
|
|
245
245
|
if tx.token == token0:
|
|
246
|
-
|
|
246
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
247
|
+
event_amount = round(tx.token.scale_value(swap["amount0In"]), 10)
|
|
248
|
+
if event_amount == round(tx.amount, 10):
|
|
247
249
|
return True
|
|
250
|
+
print(
|
|
251
|
+
f"Uniswap sell token0 amount does not match: {round(tx.amount, 10)} {event_amount}"
|
|
252
|
+
)
|
|
248
253
|
elif tx.token == token1:
|
|
249
|
-
|
|
254
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
255
|
+
event_amount = round(tx.token.scale_value(swap["amount1In"]), 10)
|
|
256
|
+
if event_amount == round(tx.amount, 10):
|
|
250
257
|
return True
|
|
258
|
+
print(
|
|
259
|
+
f"Uniswap sell token1 amount does not match: {round(tx.amount, 10)} {event_amount}"
|
|
260
|
+
)
|
|
251
261
|
|
|
252
262
|
# Buy side
|
|
253
263
|
elif tx.from_address == swap.address and TreasuryWallet._get_instance(
|
|
@@ -262,11 +272,21 @@ async def is_uniswap_swap(tx: TreasuryTx) -> bool:
|
|
|
262
272
|
# This will be recorded elsewhere
|
|
263
273
|
continue
|
|
264
274
|
if "amount0Out" in swap and tx.token == token0:
|
|
265
|
-
|
|
275
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
276
|
+
event_amount = round(tx.token.scale_value(swap["amount0Out"]), 9)
|
|
277
|
+
if event_amount == round(tx.amount, 9):
|
|
266
278
|
return True
|
|
279
|
+
print(
|
|
280
|
+
f"Uniswap buy token0 amount does not match: {round(tx.amount, 9)} {event_amount}"
|
|
281
|
+
)
|
|
267
282
|
elif "amount1Out" in swap and tx.token == token1:
|
|
268
|
-
|
|
283
|
+
# TODO: get rid of this rounding when we migrate to postgres
|
|
284
|
+
event_amount = round(tx.token.scale_value(swap["amount1Out"]), 10)
|
|
285
|
+
if event_amount == round(tx.amount, 10):
|
|
269
286
|
return True
|
|
287
|
+
print(
|
|
288
|
+
f"Uniswap buy token1 amount does not match: {round(tx.amount, 10)} {event_amount}"
|
|
289
|
+
)
|
|
270
290
|
return False
|
|
271
291
|
|
|
272
292
|
|
|
@@ -104,7 +104,8 @@ def is_buying_with_auction(tx: TreasuryTx) -> bool:
|
|
|
104
104
|
if tx.from_address != receiver:
|
|
105
105
|
print(f"Transfer does not match auction taker: taker={tx.from_address.address} transfer={receiver}") # type: ignore [union-attr]
|
|
106
106
|
continue
|
|
107
|
-
|
|
107
|
+
# TODO get rid of this rounding once we've swapped out sqlite for postgres
|
|
108
|
+
if round(amount, 14) == round(event["taken"], 14): # type: ignore [call-overload]
|
|
108
109
|
return True
|
|
109
110
|
print(f"AuctionTaken: {event} amount does not match Transfer: {transfer}")
|
|
110
111
|
return False
|
|
@@ -54,6 +54,9 @@ _SHITCOINS: Final = {
|
|
|
54
54
|
"0xe2549E429B78458fa60BC7B1b284d4411E1D5105",
|
|
55
55
|
"0xCfdD747d041397bcE08B0Fe6ebF7Ef65E9F46795",
|
|
56
56
|
"0x9745969171a38B40db05c506fe2DA2C36f317627",
|
|
57
|
+
"0x6051C1354Ccc51b4d561e43b02735DEaE64768B8",
|
|
58
|
+
"0xf0814d0E47F2390a8082C4a1BD819FDDe50f9bFc",
|
|
59
|
+
"0x2DBd330bC9B7f3A822a9173aB52172BdDDcAcE2A",
|
|
57
60
|
# just andre tinkering
|
|
58
61
|
"0x5cB5e2d7Ab9Fd32021dF8F1D3E5269bD437Ec3Bf",
|
|
59
62
|
# these arent shitcoins per se but we can't price them and dont expect to in the future, lets save cpu cycles
|
|
@@ -80,6 +83,8 @@ _SHITCOINS: Final = {
|
|
|
80
83
|
"0xdE56173463d6461001B0891bC90DB224965f5762", # MAGNUS
|
|
81
84
|
"0x922824A5b3B3D5f4485fF52F4Ab7Cba5eA491874", # POSEIDON
|
|
82
85
|
"0x84F7D2f6FB447Bb11d3E7Ce64D83e1c02c2F3078", # VIRTUAL
|
|
86
|
+
"0x5C6Ed14E1017cf75C237A4A4b93Ce1D2f83EB002", # GRVT
|
|
87
|
+
"0xf76E6eFf109258fd5F52823d9F9feE7c90C97251", # wkeyDAO
|
|
83
88
|
# test token?
|
|
84
89
|
"0x372d5d02c6b4075bd58892f80300cA590e92d29E", # tOUSG
|
|
85
90
|
# dETH? don't think this is needed
|
|
@@ -106,6 +111,8 @@ _SHITCOINS: Final = {
|
|
|
106
111
|
"0xc83377b9eE3CEe4Cc03CCd58AfdE1FB12864aEE3", # E AI
|
|
107
112
|
"0x927402ab67c0CDA3c187E9DFE34554AC581441f2", # SAITABIT
|
|
108
113
|
"0x691539810DF6e879A377C24CfEE130BBE92708d8", # NVIDIA AI
|
|
114
|
+
"0xdC82aC0A89197854cb2240FaBF7E7760a4fF4d9e", # NVIDIA
|
|
115
|
+
"0x5Fba8ea5A559CF5c99BA6dd884Ae17C1d621fE5B", # OSCAR AI
|
|
109
116
|
# matt furry spam
|
|
110
117
|
"0x73228b3D33cC71cB721Fc62950577bE63bd9c8C9", # Maskman by Matt Furie
|
|
111
118
|
"0x7c28e66436C93BB9F657dDF2BA0eeeCf61369b92", # Bloodboy by Matt Furie
|
|
@@ -12,7 +12,7 @@ Key Responsibilities:
|
|
|
12
12
|
- Provide lookup tables for use in vault deposit/withdrawal sort rules.
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
from typing import Dict, Final
|
|
15
|
+
from typing import Dict, Final
|
|
16
16
|
|
|
17
17
|
from brownie import chain
|
|
18
18
|
from eth_typing import ChecksumAddress
|
|
@@ -41,11 +41,10 @@ if chain.id == Network.Mainnet:
|
|
|
41
41
|
|
|
42
42
|
# TODO: make resolve_ens util in eth-port and refactor this out
|
|
43
43
|
v2_registries = [
|
|
44
|
-
event["newAddress"].hex()
|
|
45
|
-
for event in Events(addresses=resolver, topics=topics).events(now)
|
|
44
|
+
event["newAddress"].hex() for event in Events(addresses=resolver, topics=topics).events(now)
|
|
46
45
|
]
|
|
47
46
|
|
|
48
47
|
for event in Events(addresses=list(map(str, v2_registries))).events(now):
|
|
49
48
|
if event.name == "NewVault":
|
|
50
49
|
vault_address = event["vault"]
|
|
51
|
-
v2[vault_address] = Contract(vault_address)
|
|
50
|
+
v2[vault_address] = Contract(vault_address)
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# This is a loose copy of an old script and will not likely be refactored into something pretty
|
|
2
|
+
import os
|
|
3
|
+
from datetime import datetime, timedelta, timezone
|
|
4
|
+
from decimal import Decimal
|
|
5
|
+
from functools import lru_cache
|
|
6
|
+
from logging import getLogger
|
|
7
|
+
from typing import Any, Dict, Final, List, Set, Tuple
|
|
8
|
+
|
|
9
|
+
import a_sync
|
|
10
|
+
from brownie import chain
|
|
11
|
+
from eth_portfolio.structs import TokenTransfer
|
|
12
|
+
from eth_portfolio._ydb.token_transfers import InboundTokenTransfers
|
|
13
|
+
from pandas import DataFrame, MultiIndex
|
|
14
|
+
from y import Contract, Network, get_block_at_timestamp
|
|
15
|
+
from y.exceptions import ContractNotVerified
|
|
16
|
+
|
|
17
|
+
from yearn_treasury.constants import ZERO_ADDRESS
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
DATA_FOLDER: Final = os.path.join(".", "data")
|
|
21
|
+
OUTPUT_FILE: Final = os.path.join(DATA_FOLDER, f"teams_revenue_{chain.id}.csv")
|
|
22
|
+
NUMBER_OF_MONTHS_TO_INCLUDE_IN_REPORT: Final = 36
|
|
23
|
+
|
|
24
|
+
if not os.path.exists(DATA_FOLDER):
|
|
25
|
+
os.makedirs(DATA_FOLDER)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# TODO: maybe move this into constants for reuse
|
|
29
|
+
yteams_addresses = {
|
|
30
|
+
Network.Mainnet: {
|
|
31
|
+
"v3": {
|
|
32
|
+
"ms": "0x33333333D5eFb92f19a5F94a43456b3cec2797AE",
|
|
33
|
+
"splits": {"0x2A12CAA2c13Af03c117D836CA3811a5Ca946133B": 12.5},
|
|
34
|
+
},
|
|
35
|
+
"dinobots": {
|
|
36
|
+
"ms": "0x2C01B4AD51a67E2d8F02208F54dF9aC4c0B778B6",
|
|
37
|
+
"splits": {"0xC4f238633A85A854C4702d2c66264771D1fa7904": 17.5},
|
|
38
|
+
},
|
|
39
|
+
"ylockers": {
|
|
40
|
+
"ms": "0x4444AAAACDBa5580282365e25b16309Bd770ce4a",
|
|
41
|
+
"splits": {
|
|
42
|
+
"0xac580302548FCCBBf00020de20C3A8AA516821AD": 2.5,
|
|
43
|
+
"0x794f80E899c772de9E326eC83cCfD8D94e208B49": 6.25,
|
|
44
|
+
"0x5FF0f87b05806ce89967638CA727Af8309d92A89": 12.5,
|
|
45
|
+
"0x5A7575368797695BefD785f546C6b8B7e9D37f8c": 15.625,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
# "ylockers others": {"ms": "0x4444AAAACDBa5580282365e25b16309Bd770ce4a","splits":{"0x5FF0f87b05806ce89967638CA727Af8309d92A89":12.5, "0x5A7575368797695BefD785f546C6b8B7e9D37f8c":15.625}},
|
|
49
|
+
"yaudit": {
|
|
50
|
+
"ms": "0x8973B848775a87a0D5bcf262C555859b87E6F7dA",
|
|
51
|
+
"splits": {
|
|
52
|
+
"0xd7A1DBe236A38528D54317415a530b2326068373": 35,
|
|
53
|
+
"0xF104F38592287e25868BD8C3dcCCa1a311916f88": 35,
|
|
54
|
+
"0x1a9D272C3b7fE427639702A332D51348213B0bC1": 20,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
"yeth": {
|
|
58
|
+
"ms": "0xeEEEEeeeEe274C3CCe13f77C85d8eBd9F7fd4479",
|
|
59
|
+
"splits": {"0x14EFe6390C6758E3fE4379A14e3B329274b1b072": 25},
|
|
60
|
+
},
|
|
61
|
+
"yfarm": {
|
|
62
|
+
"ms": "0x55157997cb324a374cCd7c40914ff879Fd9D515C",
|
|
63
|
+
"splits": {"0x0B3cCe59E038373F6008D9266B6D6eB4d21689b1": 50},
|
|
64
|
+
},
|
|
65
|
+
"sms": {
|
|
66
|
+
"ms": "0x16388463d60FFE0661Cf7F1f31a7D658aC790ff7",
|
|
67
|
+
"splits": {"0xd6748776CF06a80EbE36cd83D325B31bb916bf54": 25},
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
}[Network(chain.id)]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
logger: Final = getLogger(__name__)
|
|
74
|
+
|
|
75
|
+
_not_verified: Final[Set[str]] = set()
|
|
76
|
+
_warned: Final[Set[TokenTransfer]] = set()
|
|
77
|
+
|
|
78
|
+
_known_tokens_without_prices: Final = frozenset({"SAFE", "vCOW"})
|
|
79
|
+
"""When there is a PriceError for these tokens, no logs will be emitted."""
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@lru_cache(maxsize=None)
|
|
83
|
+
def transfers_for(wallet: str) -> InboundTokenTransfers:
|
|
84
|
+
return InboundTokenTransfers(wallet, 0, load_prices=True) # type: ignore [arg-type]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
async def calculate_teams_revenue_expenses() -> None:
|
|
88
|
+
logger.info("Starting process to calculate teams revenues and expenses")
|
|
89
|
+
timestamps = get_timestamps_for_report()
|
|
90
|
+
|
|
91
|
+
async def get_coros_for_timestamp(dt: datetime) -> Dict[str, Dict[str, Decimal]]:
|
|
92
|
+
return await a_sync.gather(
|
|
93
|
+
{
|
|
94
|
+
label: total(label, wallet_info, dt)
|
|
95
|
+
for label, wallet_info in yteams_addresses.items()
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
all_data = await a_sync.gather({dt: get_coros_for_timestamp(dt) for dt in timestamps})
|
|
100
|
+
|
|
101
|
+
result = {
|
|
102
|
+
(dt, teams, movement): values
|
|
103
|
+
for dt, data in all_data.items()
|
|
104
|
+
for teams, info in data.items()
|
|
105
|
+
for movement, values in info.items()
|
|
106
|
+
}
|
|
107
|
+
df = DataFrame.from_dict(result, orient="index")
|
|
108
|
+
print("------------")
|
|
109
|
+
# print(df.index)
|
|
110
|
+
# print(df.head(10))
|
|
111
|
+
df.index = MultiIndex.from_tuples(df.index)
|
|
112
|
+
print("********")
|
|
113
|
+
# print(df.index)
|
|
114
|
+
df.reset_index(inplace=True)
|
|
115
|
+
df.columns = ["datetime", "team", "label", "value"]
|
|
116
|
+
df.to_csv(OUTPUT_FILE)
|
|
117
|
+
logger.info(
|
|
118
|
+
f"Finished processing yteams calculations and saved file to {os.path.abspath(OUTPUT_FILE)}"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def get_timestamps_for_report() -> List[datetime]:
|
|
123
|
+
now = datetime.now(tz=timezone.utc)
|
|
124
|
+
prev_month_end = datetime(
|
|
125
|
+
year=now.year,
|
|
126
|
+
month=now.month,
|
|
127
|
+
day=1,
|
|
128
|
+
hour=0,
|
|
129
|
+
minute=0,
|
|
130
|
+
second=0,
|
|
131
|
+
microsecond=0,
|
|
132
|
+
tzinfo=timezone.utc,
|
|
133
|
+
) - timedelta(microseconds=1)
|
|
134
|
+
datetimes = []
|
|
135
|
+
print("Exporting report for timestamps:")
|
|
136
|
+
for _ in range(NUMBER_OF_MONTHS_TO_INCLUDE_IN_REPORT):
|
|
137
|
+
print(f" - {prev_month_end}")
|
|
138
|
+
datetimes.append(prev_month_end)
|
|
139
|
+
prev_month_end -= timedelta(days=prev_month_end.day)
|
|
140
|
+
return datetimes
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
async def total(label: str, wallet_info: Dict[str, Any], timestamp: datetime) -> Dict[str, Decimal]:
|
|
144
|
+
rev = await sum_revenue_transfers.sum(wallet_info["splits"].items(), timestamp=timestamp)
|
|
145
|
+
grants = await sum_grants_received(wallet_info["ms"], timestamp)
|
|
146
|
+
if rev > 10_000_000:
|
|
147
|
+
raise ValueError(rev)
|
|
148
|
+
if grants > 10_000_000:
|
|
149
|
+
raise ValueError(grants)
|
|
150
|
+
net = rev - grants
|
|
151
|
+
if label == "yaudit":
|
|
152
|
+
logger.info("--- %s thru %s ---", label, timestamp)
|
|
153
|
+
logger.info("inbound %s", rev)
|
|
154
|
+
logger.info("grants -%s", grants)
|
|
155
|
+
logger.info("net %s", net)
|
|
156
|
+
return {"revenue": rev, "grants": grants, "total": net}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@a_sync.a_sync(default="async")
|
|
160
|
+
async def sum_revenue_transfers(params: Tuple[str, Decimal], timestamp: datetime) -> Decimal:
|
|
161
|
+
wallet, rev_share = params
|
|
162
|
+
block = await get_block_at_timestamp(timestamp)
|
|
163
|
+
total = Decimal(0)
|
|
164
|
+
async for transfer in transfers_for(wallet).yield_thru_block(block):
|
|
165
|
+
transfer = await transfer
|
|
166
|
+
if transfer is None:
|
|
167
|
+
# failed to decode, probably shitcoin
|
|
168
|
+
continue
|
|
169
|
+
if not transfer.value:
|
|
170
|
+
# zero value transfer
|
|
171
|
+
continue
|
|
172
|
+
if transfer.price:
|
|
173
|
+
total += transfer.value * transfer.price
|
|
174
|
+
elif transfer not in _warned and transfer.token not in _known_tokens_without_prices:
|
|
175
|
+
logger.warning(f"BAD: {transfer}")
|
|
176
|
+
_warned.add(transfer)
|
|
177
|
+
return round(total * Decimal((100 - rev_share) / 100), 8)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
async def sum_grants_received(wallet: str, timestamp: datetime) -> Decimal:
|
|
181
|
+
grants = Decimal(0)
|
|
182
|
+
block = await get_block_at_timestamp(timestamp)
|
|
183
|
+
async for transfer in transfers_for(wallet).yield_thru_block(block):
|
|
184
|
+
transfer = await transfer
|
|
185
|
+
if transfer is None:
|
|
186
|
+
# failed to decode, probably shitcoin
|
|
187
|
+
continue
|
|
188
|
+
if not transfer.value:
|
|
189
|
+
# zero value transfer
|
|
190
|
+
continue
|
|
191
|
+
if transfer.price:
|
|
192
|
+
if transfer.from_address != ZERO_ADDRESS:
|
|
193
|
+
try:
|
|
194
|
+
contract = await Contract.coroutine(transfer.from_address)
|
|
195
|
+
if (
|
|
196
|
+
hasattr(contract, "recipient") and await contract.recipient == wallet
|
|
197
|
+
) or transfer.from_address == "0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52":
|
|
198
|
+
grants += transfer.value * transfer.price
|
|
199
|
+
except ContractNotVerified as e:
|
|
200
|
+
if str(e) not in _not_verified:
|
|
201
|
+
_not_verified.add(str(e))
|
|
202
|
+
logger.debug(f"{e.__class__.__name__}: {e}")
|
|
203
|
+
except Exception as e:
|
|
204
|
+
logger.warning(f"{e.__class__.__name__}: {e}")
|
|
205
|
+
elif transfer not in _warned and transfer.token not in _known_tokens_without_prices:
|
|
206
|
+
logger.warning(f"BAD: {transfer}")
|
|
207
|
+
_warned.add(transfer)
|
|
208
|
+
return round(grants, 8)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: yearn_treasury
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.45
|
|
4
4
|
Summary: This WIP library runs the eth-portfolio and dao-treasury exporters for the Yearn Finance treasury.
|
|
5
5
|
Classifier: Development Status :: 3 - Alpha
|
|
6
6
|
Classifier: Intended Audience :: Developers
|
|
@@ -15,8 +15,7 @@ Classifier: Operating System :: OS Independent
|
|
|
15
15
|
Classifier: Topic :: Software Development :: Libraries
|
|
16
16
|
Requires-Python: >=3.10,<3.13
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: dao-treasury
|
|
19
|
-
Requires-Dist: eth-brownie<1.23,>=1.21.0
|
|
18
|
+
Requires-Dist: dao-treasury==0.0.67
|
|
20
19
|
Requires-Dist: faster-async-lru<3,>=2.0.5
|
|
21
20
|
Dynamic: classifier
|
|
22
21
|
Dynamic: description
|
|
@@ -13,6 +13,7 @@ yearn_treasury/py.typed
|
|
|
13
13
|
yearn_treasury/shitcoins.py
|
|
14
14
|
yearn_treasury/vaults.py
|
|
15
15
|
yearn_treasury/wallets.yaml
|
|
16
|
+
yearn_treasury/yteams.py
|
|
16
17
|
yearn_treasury.egg-info/PKG-INFO
|
|
17
18
|
yearn_treasury.egg-info/SOURCES.txt
|
|
18
19
|
yearn_treasury.egg-info/dependency_links.txt
|
|
@@ -46,6 +47,7 @@ yearn_treasury/rules/ignore/ygov.py
|
|
|
46
47
|
yearn_treasury/rules/ignore/swaps/__init__.py
|
|
47
48
|
yearn_treasury/rules/ignore/swaps/_skip_tokens.py
|
|
48
49
|
yearn_treasury/rules/ignore/swaps/aave.py
|
|
50
|
+
yearn_treasury/rules/ignore/swaps/auctions.py
|
|
49
51
|
yearn_treasury/rules/ignore/swaps/compound.py
|
|
50
52
|
yearn_treasury/rules/ignore/swaps/conversion_factory.py
|
|
51
53
|
yearn_treasury/rules/ignore/swaps/cowswap.py
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
from typing import Final
|
|
2
|
-
|
|
3
|
-
from dao_treasury import TreasuryTx
|
|
4
|
-
|
|
5
|
-
from yearn_treasury.rules.ignore.swaps import swaps
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
compound: Final = swaps("Compound")
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@compound("Deposit")
|
|
12
|
-
async def is_compound_deposit(tx: TreasuryTx) -> bool:
|
|
13
|
-
for event in await tx.get_events("Mint", sync=False):
|
|
14
|
-
if all(arg in event for arg in ("minter", "mintTokens", "mintAmount")):
|
|
15
|
-
minter = event["minter"]
|
|
16
|
-
minted = tx.token.scale_value(event["mintTokens"])
|
|
17
|
-
# cToken side
|
|
18
|
-
if (
|
|
19
|
-
tx.token == tx.from_address == event.address
|
|
20
|
-
and tx.to_address == minter
|
|
21
|
-
and minted == tx.amount
|
|
22
|
-
):
|
|
23
|
-
return True
|
|
24
|
-
# underlying side
|
|
25
|
-
elif (
|
|
26
|
-
tx.to_address == event.address and tx.from_address == minter and minted == tx.amount
|
|
27
|
-
):
|
|
28
|
-
return True
|
|
29
|
-
return False
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@compound("Withdrawal")
|
|
33
|
-
async def is_compound_withdrawal(tx: TreasuryTx) -> bool:
|
|
34
|
-
for event in await tx.get_events("Redeem", sync=False):
|
|
35
|
-
if all(arg in event for arg in ("redeemer", "redeemTokens", "redeemAmount")):
|
|
36
|
-
redeemer = event["redeemer"]
|
|
37
|
-
redeemed = tx.token.scale_value(event["redeemTokens"])
|
|
38
|
-
# cToken side
|
|
39
|
-
if tx.token == event.address and tx.from_address == redeemer and redeemed == tx.amount:
|
|
40
|
-
return True
|
|
41
|
-
# underlying side
|
|
42
|
-
elif (
|
|
43
|
-
tx.to_address == redeemer
|
|
44
|
-
and tx.from_address == event.address
|
|
45
|
-
and redeemed == tx.amount
|
|
46
|
-
):
|
|
47
|
-
return True
|
|
48
|
-
return False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/cost_of_revenue/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/expense/infrastructure.py
RENAMED
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/expense/match_on_hash.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/_skip_tokens.py
RENAMED
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/gearbox.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/pooltogether.py
RENAMED
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/synthetix.py
RENAMED
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/ignore/swaps/unwrapper.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/donations.py
RENAMED
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/events.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_expense/revshare.py
RENAMED
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_income/__init__.py
RENAMED
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_income/airdrops.py
RENAMED
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/other_income/match_on_hash.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury/rules/revenue/match_on_hash.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{yearn_treasury-0.0.39 → yearn_treasury-0.0.45}/yearn_treasury.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|