dao-treasury 0.0.30__cp312-cp312-win32.whl → 0.0.32__cp312-cp312-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.
Files changed (34) hide show
  1. bf2b4fe1f86ad2ea158b__mypyc.cp312-win32.pyd +0 -0
  2. dao_treasury/.grafana/provisioning/dashboards/dashboards.yaml +8 -0
  3. dao_treasury/.grafana/provisioning/dashboards/streams/LlamaPay.json +116 -0
  4. dao_treasury/.grafana/provisioning/dashboards/treasury/Cashflow.json +22 -22
  5. dao_treasury/_docker.cp312-win32.pyd +0 -0
  6. dao_treasury/_nicknames.cp312-win32.pyd +0 -0
  7. dao_treasury/_wallet.cp312-win32.pyd +0 -0
  8. dao_treasury/constants.cp312-win32.pyd +0 -0
  9. dao_treasury/db.py +172 -16
  10. dao_treasury/sorting/__init__.cp312-win32.pyd +0 -0
  11. dao_treasury/sorting/__init__.py +1 -0
  12. dao_treasury/sorting/_matchers.cp312-win32.pyd +0 -0
  13. dao_treasury/sorting/_rules.cp312-win32.pyd +0 -0
  14. dao_treasury/sorting/factory.cp312-win32.pyd +0 -0
  15. dao_treasury/sorting/rule.cp312-win32.pyd +0 -0
  16. dao_treasury/sorting/rules/__init__.cp312-win32.pyd +0 -0
  17. dao_treasury/sorting/rules/__init__.py +1 -0
  18. dao_treasury/sorting/rules/ignore/__init__.cp312-win32.pyd +0 -0
  19. dao_treasury/sorting/rules/ignore/__init__.py +1 -0
  20. dao_treasury/sorting/rules/ignore/llamapay.cp312-win32.pyd +0 -0
  21. dao_treasury/sorting/rules/ignore/llamapay.py +20 -0
  22. dao_treasury/streams/__init__.cp312-win32.pyd +0 -0
  23. dao_treasury/streams/__init__.py +0 -0
  24. dao_treasury/streams/llamapay.cp312-win32.pyd +0 -0
  25. dao_treasury/streams/llamapay.py +376 -0
  26. dao_treasury/treasury.py +22 -4
  27. dao_treasury/types.cp312-win32.pyd +0 -0
  28. {dao_treasury-0.0.30.dist-info → dao_treasury-0.0.32.dist-info}/METADATA +2 -2
  29. dao_treasury-0.0.32.dist-info/RECORD +49 -0
  30. dao_treasury-0.0.32.dist-info/top_level.txt +2 -0
  31. 3619d39567c7fe330ece__mypyc.cp312-win32.pyd +0 -0
  32. dao_treasury-0.0.30.dist-info/RECORD +0 -38
  33. dao_treasury-0.0.30.dist-info/top_level.txt +0 -2
  34. {dao_treasury-0.0.30.dist-info → dao_treasury-0.0.32.dist-info}/WHEEL +0 -0
@@ -24,3 +24,11 @@ providers:
24
24
  editable: false
25
25
  options:
26
26
  path: /etc/grafana/provisioning/dashboards/transactions
27
+
28
+ - name: 'LlamaPay Streams'
29
+ folder: 'streams'
30
+ type: file
31
+ disableDeletion: true
32
+ editable: false
33
+ options:
34
+ path: /etc/grafana/provisioning/dashboards/streams
@@ -0,0 +1,116 @@
1
+ {
2
+ "annotations": {
3
+ "list": [
4
+ {
5
+ "builtIn": 1,
6
+ "datasource": {
7
+ "type": "grafana",
8
+ "uid": "-- Grafana --"
9
+ },
10
+ "enable": true,
11
+ "hide": true,
12
+ "iconColor": "rgba(0, 211, 255, 1)",
13
+ "name": "Annotations & Alerts",
14
+ "type": "dashboard"
15
+ }
16
+ ]
17
+ },
18
+ "editable": true,
19
+ "fiscalYearStartMonth": 0,
20
+ "graphTooltip": 0,
21
+ "id": 7,
22
+ "links": [],
23
+ "liveNow": false,
24
+ "panels": [
25
+ {
26
+ "datasource": {
27
+ "type": "frser-sqlite-datasource",
28
+ "uid": "P2D2EEF3E092AF52B"
29
+ },
30
+ "description": "",
31
+ "fieldConfig": {
32
+ "defaults": {
33
+ "color": {
34
+ "mode": "thresholds"
35
+ },
36
+ "custom": {
37
+ "align": "auto",
38
+ "cellOptions": {
39
+ "type": "auto"
40
+ },
41
+ "inspect": false
42
+ },
43
+ "mappings": [],
44
+ "thresholds": {
45
+ "mode": "absolute",
46
+ "steps": [
47
+ {
48
+ "color": "green",
49
+ "value": null
50
+ },
51
+ {
52
+ "color": "red",
53
+ "value": 80
54
+ }
55
+ ]
56
+ }
57
+ },
58
+ "overrides": []
59
+ },
60
+ "gridPos": {
61
+ "h": 19,
62
+ "w": 24,
63
+ "x": 0,
64
+ "y": 0
65
+ },
66
+ "id": 1,
67
+ "options": {
68
+ "cellHeight": "sm",
69
+ "footer": {
70
+ "countRows": false,
71
+ "fields": "",
72
+ "reducer": [
73
+ "sum"
74
+ ],
75
+ "show": false
76
+ },
77
+ "showHeader": true
78
+ },
79
+ "pluginVersion": "10.2.0",
80
+ "targets": [
81
+ {
82
+ "datasource": {
83
+ "type": "frser-sqlite-datasource",
84
+ "uid": "P2D2EEF3E092AF52B"
85
+ },
86
+ "queryText": "select stream_id as \"Stream ID\", b.address as \"Factory\", start_block as \"Start Block\", end_block as \"End Block\", c.symbol as \"Token\", d.address as \"From\", e.address as \"To\", reason as \"Reason\", amount_per_second as \"Amount Per Second\", status as \"Status\", txgroup as \"TxGroup\"\nfrom streams a\nleft join addresses b on a.contract = b.address_id\nleft join tokens c on a.token = c.token_id\nleft join addresses d on a.from_address = d.address_id\nleft join addresses e on a.to_address = e.address_id",
87
+ "queryType": "table",
88
+ "rawQueryText": "select stream_id as \"Stream ID\", b.address as \"Factory\", start_block as \"Start Block\", end_block as \"End Block\", c.symbol as \"Token\", d.address as \"From\", e.address as \"To\", reason as \"Reason\", amount_per_second as \"Amount Per Second\", status as \"Status\", txgroup as \"TxGroup\"\nfrom streams a\nleft join addresses b on a.contract = b.address_id\nleft join tokens c on a.token = c.token_id\nleft join addresses d on a.from_address = d.address_id\nleft join addresses e on a.to_address = e.address_id",
89
+ "refId": "A",
90
+ "timeColumns": [
91
+ "time",
92
+ "ts"
93
+ ]
94
+ }
95
+ ],
96
+ "title": "LlamaPay Streams",
97
+ "type": "table"
98
+ }
99
+ ],
100
+ "refresh": "",
101
+ "schemaVersion": 38,
102
+ "tags": [],
103
+ "templating": {
104
+ "list": []
105
+ },
106
+ "time": {
107
+ "from": "now-6h",
108
+ "to": "now"
109
+ },
110
+ "timepicker": {},
111
+ "timezone": "",
112
+ "title": "LlamaPay",
113
+ "uid": "aa4d62a2-9e52-4acc-8f38-a96c77810aca",
114
+ "version": 1,
115
+ "weekStart": ""
116
+ }
@@ -71,9 +71,9 @@
71
71
  "targets": [
72
72
  {
73
73
  "datasource": "SQLite",
74
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Revenue'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
74
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Revenue'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
75
75
  "queryType": "table",
76
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Revenue'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
76
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Revenue'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
77
77
  "refId": "A",
78
78
  "timeColumns": [
79
79
  "time",
@@ -133,9 +133,9 @@
133
133
  "targets": [
134
134
  {
135
135
  "datasource": "SQLite",
136
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Expenses'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
136
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Expenses'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
137
137
  "queryType": "table",
138
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Expenses'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
138
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Expenses'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
139
139
  "refId": "A",
140
140
  "timeColumns": [
141
141
  "time",
@@ -195,9 +195,9 @@
195
195
  "targets": [
196
196
  {
197
197
  "datasource": "SQLite",
198
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Cost of Revenue'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
198
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Cost of Revenue'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
199
199
  "queryType": "table",
200
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Cost of Revenue'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
200
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Cost of Revenue'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
201
201
  "refId": "A",
202
202
  "timeColumns": [
203
203
  "time",
@@ -257,9 +257,9 @@
257
257
  "targets": [
258
258
  {
259
259
  "datasource": "SQLite",
260
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Other Income'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
260
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Other Income'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
261
261
  "queryType": "table",
262
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Other Income'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
262
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Other Income'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
263
263
  "refId": "A",
264
264
  "timeColumns": [
265
265
  "time",
@@ -319,9 +319,9 @@
319
319
  "targets": [
320
320
  {
321
321
  "datasource": "SQLite",
322
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Other Expenses'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
322
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Other Expenses'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
323
323
  "queryType": "table",
324
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Other Expenses'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
324
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Other Expenses'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
325
325
  "refId": "A",
326
326
  "timeColumns": [
327
327
  "time",
@@ -382,9 +382,9 @@
382
382
  "targets": [
383
383
  {
384
384
  "datasource": "SQLite",
385
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n (\n -- Revenue\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END)\n -- Cost of Revenue\n - SUM(CASE WHEN gh.top_category = 'Cost of Revenue' THEN t.value_usd ELSE 0 END)\n -- Expenses\n - SUM(CASE WHEN gh.top_category = 'Expenses' THEN t.value_usd ELSE 0 END)\n -- Other Income\n + SUM(CASE WHEN gh.top_category = 'Other Income' THEN t.value_usd ELSE 0 END)\n -- Other Expenses\n - SUM(CASE WHEN gh.top_category = 'Other Expenses' THEN t.value_usd ELSE 0 END)\n ) AS total_net\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000",
385
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n (\n -- Revenue\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END)\n -- Cost of Revenue\n - SUM(CASE WHEN gh.top_category = 'Cost of Revenue' THEN t.value_usd ELSE 0 END)\n -- Expenses\n - SUM(CASE WHEN gh.top_category = 'Expenses' THEN t.value_usd ELSE 0 END)\n -- Other Income\n + SUM(CASE WHEN gh.top_category = 'Other Income' THEN t.value_usd ELSE 0 END)\n -- Other Expenses\n - SUM(CASE WHEN gh.top_category = 'Other Expenses' THEN t.value_usd ELSE 0 END)\n ) AS total_net\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000",
386
386
  "queryType": "table",
387
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n (\n -- Revenue\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END)\n -- Cost of Revenue\n - SUM(CASE WHEN gh.top_category = 'Cost of Revenue' THEN t.value_usd ELSE 0 END)\n -- Expenses\n - SUM(CASE WHEN gh.top_category = 'Expenses' THEN t.value_usd ELSE 0 END)\n -- Other Income\n + SUM(CASE WHEN gh.top_category = 'Other Income' THEN t.value_usd ELSE 0 END)\n -- Other Expenses\n - SUM(CASE WHEN gh.top_category = 'Other Expenses' THEN t.value_usd ELSE 0 END)\n ) AS total_net\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000",
387
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n (\n -- Revenue\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END)\n -- Cost of Revenue\n - SUM(CASE WHEN gh.top_category = 'Cost of Revenue' THEN t.value_usd ELSE 0 END)\n -- Expenses\n - SUM(CASE WHEN gh.top_category = 'Expenses' THEN t.value_usd ELSE 0 END)\n -- Other Income\n + SUM(CASE WHEN gh.top_category = 'Other Income' THEN t.value_usd ELSE 0 END)\n -- Other Expenses\n - SUM(CASE WHEN gh.top_category = 'Other Expenses' THEN t.value_usd ELSE 0 END)\n ) AS total_net\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000",
388
388
  "refId": "A",
389
389
  "timeColumns": [
390
390
  "time",
@@ -498,9 +498,9 @@
498
498
  "targets": [
499
499
  {
500
500
  "datasource": "SQLite",
501
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n t.timestamp,\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income') THEN t.value_usd ELSE 0 END) AS \"Total Revenue\",\n SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses') THEN t.value_usd ELSE 0 END) * -1 AS \"Total Expenses\",\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income') THEN t.value_usd ELSE 0 END) - SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses') THEN t.value_usd ELSE 0 END) AS \"Net\"\nFROM treasury_txs AS t\nJOIN group_hierarchy gh\n ON t.txgroup_id = gh.txgroup_id\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\nGROUP BY timestamp\nORDER BY timestamp;",
501
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n t.timestamp,\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income') THEN t.value_usd ELSE 0 END) AS \"Total Revenue\",\n SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses') THEN t.value_usd ELSE 0 END) * -1 AS \"Total Expenses\",\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income') THEN t.value_usd ELSE 0 END) - SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses') THEN t.value_usd ELSE 0 END) AS \"Net\"\nFROM general_ledger AS t\nJOIN group_hierarchy gh\n ON t.txgroup_id = gh.txgroup_id\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\nGROUP BY timestamp\nORDER BY timestamp;",
502
502
  "queryType": "table",
503
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n t.timestamp,\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income') THEN t.value_usd ELSE 0 END) AS \"Total Revenue\",\n SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses') THEN t.value_usd ELSE 0 END) * -1 AS \"Total Expenses\",\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income') THEN t.value_usd ELSE 0 END) - SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses') THEN t.value_usd ELSE 0 END) AS \"Net\"\nFROM treasury_txs AS t\nJOIN group_hierarchy gh\n ON t.txgroup_id = gh.txgroup_id\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\nGROUP BY timestamp\nORDER BY timestamp;",
503
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n t.timestamp,\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income') THEN t.value_usd ELSE 0 END) AS \"Total Revenue\",\n SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses') THEN t.value_usd ELSE 0 END) * -1 AS \"Total Expenses\",\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income') THEN t.value_usd ELSE 0 END) - SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses') THEN t.value_usd ELSE 0 END) AS \"Net\"\nFROM general_ledger AS t\nJOIN group_hierarchy gh\n ON t.txgroup_id = gh.txgroup_id\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\nGROUP BY timestamp\nORDER BY timestamp;",
504
504
  "refId": "A",
505
505
  "timeColumns": [
506
506
  "timestamp"
@@ -643,9 +643,9 @@
643
643
  "targets": [
644
644
  {
645
645
  "datasource": "SQLite",
646
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Sort Me (Inbound)'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
646
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Sort Me (Inbound)'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
647
647
  "queryType": "table",
648
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Sort Me (Inbound)'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
648
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Sort Me (Inbound)'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
649
649
  "refId": "A",
650
650
  "timeColumns": [
651
651
  "time",
@@ -706,9 +706,9 @@
706
706
  "targets": [
707
707
  {
708
708
  "datasource": "SQLite",
709
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Sort Me (Outbound)'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
709
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Sort Me (Outbound)'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
710
710
  "queryType": "table",
711
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Sort Me (Outbound)'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
711
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT txgroup_id, name AS top_category, parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n SUM(t.value_usd) AS total_revenue\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE gh.top_category = 'Sort Me (Outbound)'\n AND t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\n",
712
712
  "refId": "A",
713
713
  "timeColumns": [
714
714
  "time",
@@ -769,9 +769,9 @@
769
769
  "targets": [
770
770
  {
771
771
  "datasource": "SQLite",
772
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n (\n -- Revenue\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END)\n -- Cost of Revenue\n - SUM(CASE WHEN gh.top_category = 'Cost of Revenue' THEN t.value_usd ELSE 0 END)\n -- Expenses\n - SUM(CASE WHEN gh.top_category = 'Expenses' THEN t.value_usd ELSE 0 END)\n -- Other Income\n + SUM(CASE WHEN gh.top_category = 'Other Income' THEN t.value_usd ELSE 0 END)\n -- Other Expenses\n - SUM(CASE WHEN gh.top_category = 'Other Expenses' THEN t.value_usd ELSE 0 END)\n -- Sort Me (Inbound)\n + SUM(CASE WHEN gh.top_category = 'Sort Me (Inbound)' THEN t.value_usd ELSE 0 END)\n -- Sort Me (Outbound)\n - SUM(CASE WHEN gh.top_category = 'Sort Me (Outbound)' THEN t.value_usd ELSE 0 END)\n ) AS total_net\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000",
772
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n (\n -- Revenue\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END)\n -- Cost of Revenue\n - SUM(CASE WHEN gh.top_category = 'Cost of Revenue' THEN t.value_usd ELSE 0 END)\n -- Expenses\n - SUM(CASE WHEN gh.top_category = 'Expenses' THEN t.value_usd ELSE 0 END)\n -- Other Income\n + SUM(CASE WHEN gh.top_category = 'Other Income' THEN t.value_usd ELSE 0 END)\n -- Other Expenses\n - SUM(CASE WHEN gh.top_category = 'Other Expenses' THEN t.value_usd ELSE 0 END)\n -- Sort Me (Inbound)\n + SUM(CASE WHEN gh.top_category = 'Sort Me (Inbound)' THEN t.value_usd ELSE 0 END)\n -- Sort Me (Outbound)\n - SUM(CASE WHEN gh.top_category = 'Sort Me (Outbound)' THEN t.value_usd ELSE 0 END)\n ) AS total_net\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000",
773
773
  "queryType": "table",
774
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n (\n -- Revenue\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END)\n -- Cost of Revenue\n - SUM(CASE WHEN gh.top_category = 'Cost of Revenue' THEN t.value_usd ELSE 0 END)\n -- Expenses\n - SUM(CASE WHEN gh.top_category = 'Expenses' THEN t.value_usd ELSE 0 END)\n -- Other Income\n + SUM(CASE WHEN gh.top_category = 'Other Income' THEN t.value_usd ELSE 0 END)\n -- Other Expenses\n - SUM(CASE WHEN gh.top_category = 'Other Expenses' THEN t.value_usd ELSE 0 END)\n -- Sort Me (Inbound)\n + SUM(CASE WHEN gh.top_category = 'Sort Me (Inbound)' THEN t.value_usd ELSE 0 END)\n -- Sort Me (Outbound)\n - SUM(CASE WHEN gh.top_category = 'Sort Me (Outbound)' THEN t.value_usd ELSE 0 END)\n ) AS total_net\nFROM treasury_txs t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000",
774
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n (\n -- Revenue\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END)\n -- Cost of Revenue\n - SUM(CASE WHEN gh.top_category = 'Cost of Revenue' THEN t.value_usd ELSE 0 END)\n -- Expenses\n - SUM(CASE WHEN gh.top_category = 'Expenses' THEN t.value_usd ELSE 0 END)\n -- Other Income\n + SUM(CASE WHEN gh.top_category = 'Other Income' THEN t.value_usd ELSE 0 END)\n -- Other Expenses\n - SUM(CASE WHEN gh.top_category = 'Other Expenses' THEN t.value_usd ELSE 0 END)\n -- Sort Me (Inbound)\n + SUM(CASE WHEN gh.top_category = 'Sort Me (Inbound)' THEN t.value_usd ELSE 0 END)\n -- Sort Me (Outbound)\n - SUM(CASE WHEN gh.top_category = 'Sort Me (Outbound)' THEN t.value_usd ELSE 0 END)\n ) AS total_net\nFROM general_ledger t\nJOIN group_hierarchy gh USING (txgroup_id)\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000",
775
775
  "refId": "A",
776
776
  "timeColumns": [
777
777
  "time",
@@ -885,9 +885,9 @@
885
885
  "targets": [
886
886
  {
887
887
  "datasource": "SQLite",
888
- "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n t.timestamp,\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income','Sort Me (Inbound)') THEN t.value_usd ELSE 0 END) AS \"Total Revenue (incl. Unsorted)\",\n SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses','Sort Me (Outbound)') THEN t.value_usd ELSE 0 END) * -1 AS \"Total Expenses (incl. Unsorted)\",\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income','Sort Me (Inbound)') THEN t.value_usd ELSE 0 END) - SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses','Sort Me (Outbound)') THEN t.value_usd ELSE 0 END) AS \"Net (incl. Unsorted)\"\nFROM treasury_txs AS t\nJOIN group_hierarchy gh\n ON t.txgroup_id = gh.txgroup_id\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\nGROUP BY timestamp\nORDER BY timestamp;",
888
+ "queryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n t.timestamp,\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income','Sort Me (Inbound)') THEN t.value_usd ELSE 0 END) AS \"Total Revenue (incl. Unsorted)\",\n SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses','Sort Me (Outbound)') THEN t.value_usd ELSE 0 END) * -1 AS \"Total Expenses (incl. Unsorted)\",\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income','Sort Me (Inbound)') THEN t.value_usd ELSE 0 END) - SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses','Sort Me (Outbound)') THEN t.value_usd ELSE 0 END) AS \"Net (incl. Unsorted)\"\nFROM general_ledger AS t\nJOIN group_hierarchy gh\n ON t.txgroup_id = gh.txgroup_id\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\nGROUP BY timestamp\nORDER BY timestamp;",
889
889
  "queryType": "table",
890
- "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n t.timestamp,\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income','Sort Me (Inbound)') THEN t.value_usd ELSE 0 END) AS \"Total Revenue (incl. Unsorted)\",\n SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses','Sort Me (Outbound)') THEN t.value_usd ELSE 0 END) * -1 AS \"Total Expenses (incl. Unsorted)\",\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income','Sort Me (Inbound)') THEN t.value_usd ELSE 0 END) - SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses','Sort Me (Outbound)') THEN t.value_usd ELSE 0 END) AS \"Net (incl. Unsorted)\"\nFROM treasury_txs AS t\nJOIN group_hierarchy gh\n ON t.txgroup_id = gh.txgroup_id\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\nGROUP BY timestamp\nORDER BY timestamp;",
890
+ "rawQueryText": "WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (\n SELECT\n txgroup_id,\n name AS top_category,\n parent_txgroup\n FROM txgroups\n WHERE parent_txgroup IS NULL\n\n UNION ALL\n\n SELECT\n child.txgroup_id,\n parent.top_category,\n child.parent_txgroup\n FROM txgroups AS child\n JOIN group_hierarchy AS parent\n ON child.parent_txgroup = parent.txgroup_id\n)\nSELECT\n t.timestamp,\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income','Sort Me (Inbound)') THEN t.value_usd ELSE 0 END) AS \"Total Revenue (incl. Unsorted)\",\n SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses','Sort Me (Outbound)') THEN t.value_usd ELSE 0 END) * -1 AS \"Total Expenses (incl. Unsorted)\",\n SUM(CASE WHEN gh.top_category in ('Revenue', 'Other Income','Sort Me (Inbound)') THEN t.value_usd ELSE 0 END) - SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses','Other Expenses','Sort Me (Outbound)') THEN t.value_usd ELSE 0 END) AS \"Net (incl. Unsorted)\"\nFROM general_ledger AS t\nJOIN group_hierarchy gh\n ON t.txgroup_id = gh.txgroup_id\nWHERE t.timestamp >= $__from/1000\n AND t.timestamp <= $__to/1000\nGROUP BY timestamp\nORDER BY timestamp;",
891
891
  "refId": "A",
892
892
  "timeColumns": [
893
893
  "timestamp"
Binary file
Binary file
Binary file
Binary file
dao_treasury/db.py CHANGED
@@ -8,6 +8,7 @@ This module defines Pony ORM entities for:
8
8
  - ERC-20 tokens and native coin placeholder (:class:`Token`)
9
9
  - Hierarchical transaction grouping (:class:`TxGroup`)
10
10
  - Treasury transaction records (:class:`TreasuryTx`)
11
+ - Streams and StreamedFunds for streaming payments
11
12
 
12
13
  It also provides helper functions for inserting ledger entries,
13
14
  resolving integrity conflicts, caching transaction receipts,
@@ -21,15 +22,16 @@ from functools import lru_cache
21
22
  from logging import getLogger
22
23
  from os import path
23
24
  from pathlib import Path
24
- from typing import TYPE_CHECKING, Dict, Final, Union, final
25
+ from typing import TYPE_CHECKING, Dict, Final, Tuple, Union, final
26
+ from datetime import date, datetime, time, timezone
25
27
 
26
- from a_sync import AsyncThreadPoolExecutor, a_sync
28
+ from a_sync import AsyncThreadPoolExecutor
27
29
  from brownie import chain
28
30
  from brownie.convert.datatypes import HexString
29
31
  from brownie.exceptions import EventLookupError
30
32
  from brownie.network.event import EventDict, _EventItem
31
33
  from brownie.network.transaction import TransactionReceipt
32
- from eth_typing import ChecksumAddress, HexAddress
34
+ from eth_typing import ChecksumAddress, HexAddress, HexStr
33
35
  from eth_portfolio.structs import (
34
36
  InternalTransfer,
35
37
  LedgerEntry,
@@ -68,6 +70,7 @@ _INSERT_THREAD = AsyncThreadPoolExecutor(1)
68
70
  _SORT_THREAD = AsyncThreadPoolExecutor(1)
69
71
  _SORT_SEMAPHORE = Semaphore(50)
70
72
 
73
+ _UTC = timezone.utc
71
74
 
72
75
  db = Database()
73
76
 
@@ -210,9 +213,10 @@ class Address(DbEntity):
210
213
 
211
214
  treasury_tx_to = Set("TreasuryTx", reverse="to_address")
212
215
  """Inverse relation for transactions sent to this address."""
213
- # streams_from = Set("Stream", reverse="from_address")
214
- # streams_to = Set("Stream", reverse="to_address")
215
- # streams = Set("Stream", reverse="contract")
216
+
217
+ streams_from = Set("Stream", reverse="from_address")
218
+ streams_to = Set("Stream", reverse="to_address")
219
+ streams = Set("Stream", reverse="contract")
216
220
  # vesting_escrows = Set("VestingEscrow", reverse="address")
217
221
  # vests_received = Set("VestingEscrow", reverse="recipient")
218
222
  # vests_funded = Set("VestingEscrow", reverse="funder")
@@ -226,6 +230,10 @@ class Address(DbEntity):
226
230
 
227
231
  __hash__ = DbEntity.__hash__
228
232
 
233
+ @property
234
+ def contract(self) -> Contract:
235
+ return Contract(self.address)
236
+
229
237
  @staticmethod
230
238
  @lru_cache(maxsize=None)
231
239
  def get_dbid(address: HexAddress) -> int:
@@ -380,7 +388,8 @@ class Token(DbEntity):
380
388
 
381
389
  address = Required(Address, column="address_id")
382
390
  """Foreign key to the address record for this token contract."""
383
- # streams = Set('Stream', reverse="token")
391
+
392
+ streams = Set("Stream", reverse="token")
384
393
  # vesting_escrows = Set("VestingEscrow", reverse="token")
385
394
 
386
395
  def __eq__(self, other: Union["Token", Address, ChecksumAddress]) -> bool: # type: ignore [override]
@@ -534,8 +543,10 @@ class TxGroup(DbEntity):
534
543
 
535
544
  child_txgroups = Set("TxGroup", reverse="parent_txgroup")
536
545
  """Set of nested child groups."""
537
- # TODO: implement these
538
- # streams = Set("Stream", reverse="txgroup")
546
+
547
+ streams = Set("Stream", reverse="txgroup")
548
+
549
+ # TODO: implement this
539
550
  # vesting_escrows = Set("VestingEscrow", reverse="txgroup")
540
551
 
541
552
  @property
@@ -896,6 +907,151 @@ class TreasuryTx(DbEntity):
896
907
  TreasuryTx[treasury_tx_dbid].txgroup = txgroup_dbid
897
908
 
898
909
 
910
+ _stream_metadata_cache: Final[Dict[HexStr, Tuple[ChecksumAddress, date]]] = {}
911
+
912
+
913
+ class Stream(DbEntity):
914
+ _table_ = "streams"
915
+ stream_id = PrimaryKey(str)
916
+
917
+ contract = Required("Address", reverse="streams")
918
+ start_block = Required(int)
919
+ end_block = Optional(int)
920
+ token = Required("Token", reverse="streams", index=True)
921
+ from_address = Required("Address", reverse="streams_from")
922
+ to_address = Required("Address", reverse="streams_to")
923
+ reason = Optional(str)
924
+ amount_per_second = Required(Decimal, 38, 1)
925
+ status = Required(str, default="Active")
926
+ txgroup = Optional("TxGroup", reverse="streams")
927
+
928
+ streamed_funds = Set("StreamedFunds")
929
+
930
+ scale = int(1e20)
931
+
932
+ @property
933
+ def is_alive(self) -> bool:
934
+ if self.end_block is None:
935
+ assert self.status in ["Active", "Paused"]
936
+ return self.status == "Active"
937
+ assert self.status == "Stopped"
938
+ return False
939
+
940
+ @property
941
+ def amount_per_minute(self) -> int:
942
+ return self.amount_per_second * 60
943
+
944
+ @property
945
+ def amount_per_hour(self) -> int:
946
+ return self.amount_per_minute * 60
947
+
948
+ @property
949
+ def amount_per_day(self) -> int:
950
+ return self.amount_per_hour * 24
951
+
952
+ @staticmethod
953
+ def check_closed(stream_id: HexStr) -> bool:
954
+ with db_session:
955
+ return any(sf.is_last_day for sf in Stream[stream_id].streamed_funds)
956
+
957
+ @staticmethod
958
+ def _get_start_and_end(stream_dbid: HexStr) -> Tuple[datetime, datetime]:
959
+ with db_session:
960
+ stream = Stream[stream_dbid]
961
+ start_date, end = stream.start_date, datetime.now(_UTC)
962
+ # convert start to datetime
963
+ start = datetime.combine(start_date, time(tzinfo=_UTC), tzinfo=_UTC)
964
+ if stream.end_block:
965
+ end = datetime.fromtimestamp(chain[stream.end_block].timestamp, tz=_UTC)
966
+ return start, end
967
+
968
+ def stop_stream(self, block: int) -> None:
969
+ self.end_block = block
970
+ self.status = "Stopped"
971
+
972
+ def pause(self) -> None:
973
+ self.status = "Paused"
974
+
975
+ @staticmethod
976
+ def _get_token_and_start_date(stream_id: HexStr) -> Tuple[ChecksumAddress, date]:
977
+ try:
978
+ return _stream_metadata_cache[stream_id]
979
+ except KeyError:
980
+ with db_session:
981
+ stream = Stream[stream_id]
982
+ token = stream.token.address.address
983
+ start_date = stream.start_date
984
+ _stream_metadata_cache[stream_id] = token, start_date
985
+ return token, start_date
986
+
987
+ @property
988
+ def stream_contract(self) -> Contract:
989
+ return Contract(self.contract.address)
990
+
991
+ @property
992
+ def start_date(self) -> date:
993
+ return datetime.fromtimestamp(chain[self.start_block].timestamp).date()
994
+
995
+ async def amount_withdrawable(self, block: int) -> int:
996
+ return await self.stream_contract.withdrawable.coroutine(
997
+ self.from_address.address,
998
+ self.to_address.address,
999
+ int(self.amount_per_second),
1000
+ block_identifier=block,
1001
+ )
1002
+
1003
+ def print(self) -> None:
1004
+ symbol = self.token.symbol
1005
+ print(f"{symbol} per second: {self.amount_per_second / self.scale}")
1006
+ print(f"{symbol} per day: {self.amount_per_day / self.scale}")
1007
+
1008
+
1009
+ class StreamedFunds(DbEntity):
1010
+ """Each object represents one calendar day of tokens streamed for a particular stream."""
1011
+
1012
+ _table_ = "streamed_funds"
1013
+
1014
+ date = Required(date)
1015
+ stream = Required(Stream, reverse="streamed_funds")
1016
+ PrimaryKey(stream, date)
1017
+
1018
+ amount = Required(Decimal, 38, 18)
1019
+ price = Required(Decimal, 38, 18)
1020
+ value_usd = Required(Decimal, 38, 18)
1021
+ seconds_active = Required(int)
1022
+ is_last_day = Required(bool)
1023
+
1024
+ @db_session
1025
+ def get_entity(stream_id: str, date: datetime) -> "StreamedFunds":
1026
+ stream = Stream[stream_id]
1027
+ return StreamedFunds.get(date=date, stream=stream)
1028
+
1029
+ @classmethod
1030
+ @db_session
1031
+ def create_entity(
1032
+ cls,
1033
+ stream_id: str,
1034
+ date: datetime,
1035
+ price: Decimal,
1036
+ seconds_active: int,
1037
+ is_last_day: bool,
1038
+ ) -> "StreamedFunds":
1039
+ stream = Stream[stream_id]
1040
+ amount_streamed_today = round(
1041
+ stream.amount_per_second * seconds_active / stream.scale, 18
1042
+ )
1043
+ entity = StreamedFunds(
1044
+ date=date,
1045
+ stream=stream,
1046
+ amount=amount_streamed_today,
1047
+ price=round(price, 18),
1048
+ value_usd=round(amount_streamed_today * price, 18),
1049
+ seconds_active=seconds_active,
1050
+ is_last_day=is_last_day,
1051
+ )
1052
+ return entity
1053
+
1054
+
899
1055
  db.bind(
900
1056
  provider="sqlite", # TODO: let user choose postgres with server connection params
901
1057
  filename=str(SQLITE_DIR / "dao-treasury.sqlite"),
@@ -921,12 +1077,12 @@ def create_stream_ledger_view() -> None:
921
1077
  Examples:
922
1078
  >>> create_stream_ledger_view()
923
1079
  """
1080
+ db.execute("""DROP VIEW IF EXISTS stream_ledger;""")
924
1081
  db.execute(
925
1082
  """
926
- DROP VIEW IF EXISTS stream_ledger;
927
1083
  create view stream_ledger as
928
1084
  SELECT 'Mainnet' as chain_name,
929
- cast(DATE AS timestamp) as timestamp,
1085
+ cast(strftime('%s', date || ' 00:00:00') as INTEGER) as timestamp,
930
1086
  NULL as block,
931
1087
  NULL as hash,
932
1088
  NULL as log_index,
@@ -1007,7 +1163,7 @@ def create_general_ledger_view() -> None:
1007
1163
  create VIEW general_ledger as
1008
1164
  select *
1009
1165
  from (
1010
- SELECT treasury_tx_id, b.chain_name, datetime(a.timestamp, 'unixepoch') AS timestamp, a.block, a.hash, a.log_index, c.symbol AS token, d.address AS "from", d.nickname as from_nickname, e.address AS "to", e.nickname as to_nickname, a.amount, a.price, a.value_usd, f.name AS txgroup, g.name AS parent_txgroup, f.txgroup_id
1166
+ SELECT treasury_tx_id, b.chain_name, a.timestamp, a.block, a.hash, a.log_index, c.symbol AS token, d.address AS "from", d.nickname as from_nickname, e.address AS "to", e.nickname as to_nickname, a.amount, a.price, a.value_usd, f.name AS txgroup, g.name AS parent_txgroup, f.txgroup_id
1011
1167
  FROM treasury_txs a
1012
1168
  LEFT JOIN chains b ON a.chain = b.chain_dbid
1013
1169
  LEFT JOIN tokens c ON a.token_id = c.token_id
@@ -1015,9 +1171,9 @@ def create_general_ledger_view() -> None:
1015
1171
  LEFT JOIN addresses e ON a."to" = e.address_id
1016
1172
  LEFT JOIN txgroups f ON a.txgroup_id = f.txgroup_id
1017
1173
  LEFT JOIN txgroups g ON f.parent_txgroup = g.txgroup_id
1018
- --UNION
1019
- --SELECT -1, chain_name, TIMESTAMP, cast(block AS integer) block, hash, CAST(log_index AS integer) as log_index, token, "from", from_nickname, "to", to_nickname, amount, price, value_usd, txgroup, parent_txgroup, txgroup_id
1020
- --FROM stream_ledger
1174
+ UNION
1175
+ SELECT -1, chain_name, timestamp, block, hash, log_index, token, "from", from_nickname, "to", to_nickname, amount, price, value_usd, txgroup, parent_txgroup, txgroup_id
1176
+ FROM stream_ledger
1021
1177
  --UNION
1022
1178
  --SELECT -1, *
1023
1179
  --FROM vesting_ledger
@@ -1093,7 +1249,7 @@ def create_monthly_pnl_view() -> None:
1093
1249
 
1094
1250
 
1095
1251
  with db_session:
1096
- # create_stream_ledger_view()
1252
+ create_stream_ledger_view()
1097
1253
  # create_vesting_ledger_view()
1098
1254
  create_general_ledger_view()
1099
1255
  create_unsorted_txs_view()
@@ -35,6 +35,7 @@ from dao_treasury.sorting.rule import (
35
35
  OtherIncomeSortRule,
36
36
  RevenueSortRule,
37
37
  )
38
+ from dao_treasury.sorting.rules import *
38
39
  from dao_treasury.types import TxGroupDbid
39
40
 
40
41
 
Binary file
Binary file
@@ -0,0 +1 @@
1
+ from dao_treasury.sorting.rules.ignore import *
@@ -0,0 +1 @@
1
+ from dao_treasury.sorting.rules.ignore.llamapay import *
@@ -0,0 +1,20 @@
1
+ from dao_treasury import TreasuryTx
2
+ from dao_treasury.sorting.factory import ignore
3
+ from dao_treasury.streams import llamapay
4
+
5
+
6
+ @ignore("LlamaPay")
7
+ def is_llamapay_stream_replenishment(tx: TreasuryTx) -> bool:
8
+ if tx.to_address.address in llamapay.factories: # type: ignore [operator]
9
+ # We amortize these streams daily in the `llamapay` module, you'll sort each stream appropriately.
10
+ return True
11
+
12
+ # NOTE: not sure if we want this yet
13
+ # Puling unused funds back from vesting escrow / llamapay
14
+ # elif tx.from_address == "Contract: LlamaPay" and "StreamCancelled" in tx.events:
15
+ # if tx.amount > 0:
16
+ # tx.amount *= -1
17
+ # if tx.value_usd > 0:
18
+ # tx.value_usd *= -1
19
+ # return True
20
+ return False
File without changes
@@ -0,0 +1,376 @@
1
+ import asyncio
2
+ import datetime as dt
3
+ import decimal
4
+ from logging import getLogger
5
+ from typing import (
6
+ Awaitable,
7
+ Callable,
8
+ Dict,
9
+ Final,
10
+ Iterator,
11
+ List,
12
+ Optional,
13
+ Set,
14
+ final,
15
+ )
16
+
17
+ import dank_mids
18
+ import pony.orm
19
+ from a_sync import AsyncThreadPoolExecutor, igather
20
+ from brownie.network.event import _EventItem
21
+ from eth_typing import BlockNumber, ChecksumAddress, HexAddress, HexStr
22
+ from tqdm.asyncio import tqdm_asyncio
23
+
24
+ import y
25
+ from y.time import UnixTimestamp
26
+ from y.utils.events import decode_logs, get_logs_asap
27
+
28
+ from dao_treasury import constants
29
+ from dao_treasury.db import (
30
+ Stream,
31
+ StreamedFunds,
32
+ Address,
33
+ Token,
34
+ must_sort_outbound_txgroup_dbid,
35
+ )
36
+ from dao_treasury._wallet import TreasuryWallet
37
+
38
+
39
+ logger: Final = getLogger(__name__)
40
+
41
+ _UTC: Final = dt.timezone.utc
42
+
43
+ _ONE_DAY: Final = 60 * 60 * 24
44
+
45
+ _STREAMS_THREAD: Final = AsyncThreadPoolExecutor(1)
46
+
47
+ create_task: Final = asyncio.create_task
48
+ sleep: Final = asyncio.sleep
49
+
50
+ datetime: Final = dt.datetime
51
+ timedelta: Final = dt.timedelta
52
+ fromtimestamp: Final = datetime.fromtimestamp
53
+ now: Final = datetime.now
54
+
55
+ Decimal: Final = decimal.Decimal
56
+
57
+ ObjectNotFound: Final = pony.orm.ObjectNotFound
58
+ commit: Final = pony.orm.commit
59
+ db_session: Final = pony.orm.db_session
60
+
61
+ Contract: Final = y.Contract
62
+ Network: Final = y.Network
63
+ get_block_at_timestamp: Final = y.get_block_at_timestamp
64
+ get_price: Final = y.get_price
65
+
66
+
67
+ networks: Final = [Network.Mainnet]
68
+
69
+ factories: List[HexAddress] = []
70
+
71
+ if dai_stream_factory := {
72
+ Network.Mainnet: "0x60c7B0c5B3a4Dc8C690b074727a17fF7aA287Ff2",
73
+ }.get(constants.CHAINID):
74
+ factories.append(dai_stream_factory)
75
+
76
+ if yfi_stream_factory := {
77
+ Network.Mainnet: "0xf3764eC89B1ad20A31ed633b1466363FAc1741c4",
78
+ }.get(constants.CHAINID):
79
+ factories.append(yfi_stream_factory)
80
+
81
+
82
+ def _generate_dates(
83
+ start: dt.datetime, end: dt.datetime, stop_at_today: bool = True
84
+ ) -> Iterator[dt.datetime]:
85
+ current = start
86
+ while current < end:
87
+ yield current
88
+ current += timedelta(days=1)
89
+ if stop_at_today and current.date() > now(_UTC).date():
90
+ break
91
+
92
+
93
+ _StreamToStart = Callable[[HexStr, Optional[BlockNumber]], Awaitable[int]]
94
+
95
+ _streamToStart_cache: Final[Dict[HexStr, _StreamToStart]] = {}
96
+
97
+
98
+ def _get_streamToStart(stream_id: HexStr) -> _StreamToStart:
99
+ if streamToStart := _streamToStart_cache.get(stream_id):
100
+ return streamToStart
101
+ with db_session:
102
+ contract: y.Contract = Stream[stream_id].contract.contract # type: ignore [misc]
103
+ streamToStart = contract.streamToStart.coroutine
104
+ _streamToStart_cache[stream_id] = streamToStart
105
+ return streamToStart
106
+
107
+
108
+ async def _get_start_timestamp(
109
+ stream_id: HexStr, block: Optional[BlockNumber] = None
110
+ ) -> int:
111
+ streamToStart = _streamToStart_cache.get(stream_id)
112
+ if streamToStart is None:
113
+ streamToStart = await _STREAMS_THREAD.run(_get_streamToStart, stream_id)
114
+ # try:
115
+ return int(await streamToStart(f"0x{stream_id}", block_identifier=block)) # type: ignore [call-arg]
116
+ # except Exception:
117
+ # return 0
118
+
119
+
120
+ def _pause_stream(stream_id: HexStr) -> None:
121
+ with db_session:
122
+ Stream[stream_id].pause() # type: ignore [misc]
123
+
124
+
125
+ def _stop_stream(stream_id: str, block: BlockNumber) -> None:
126
+ with db_session:
127
+ Stream[stream_id].stop_stream(block) # type: ignore [misc]
128
+
129
+
130
+ _block_timestamps: Final[Dict[BlockNumber, UnixTimestamp]] = {}
131
+
132
+
133
+ async def _get_block_timestamp(block: BlockNumber) -> UnixTimestamp:
134
+ if timestamp := _block_timestamps.get(block):
135
+ return timestamp
136
+ timestamp = await dank_mids.eth.get_block_timestamp(block)
137
+ _block_timestamps[block] = timestamp
138
+ return timestamp
139
+
140
+
141
+ """
142
+ class _StreamProcessor(ABC):
143
+ @abstractmethod
144
+ async def _load_streams(self) -> None:
145
+ ...
146
+ """
147
+
148
+
149
+ @final
150
+ class LlamaPayProcessor:
151
+ """
152
+ Generalized async processor for DAO stream contracts.
153
+ Args are passed in at construction time.
154
+ Supports time-bounded admin periods for filtering.
155
+ """
156
+
157
+ handled_events: Final = (
158
+ "StreamCreated",
159
+ "StreamCreatedWithReason",
160
+ "StreamModified",
161
+ "StreamPaused",
162
+ "StreamCancelled",
163
+ )
164
+ skipped_events: Final = (
165
+ "PayerDeposit",
166
+ "PayerWithdraw",
167
+ "Withdraw",
168
+ )
169
+
170
+ def __init__(self) -> None:
171
+ self.stream_contracts: Final = {Contract(addr) for addr in factories}
172
+
173
+ async def _get_streams(self) -> None:
174
+ await igather(
175
+ self._load_contract_events(stream_contract)
176
+ for stream_contract in self.stream_contracts
177
+ )
178
+
179
+ async def _load_contract_events(self, stream_contract: y.Contract) -> None:
180
+ events = decode_logs(
181
+ await get_logs_asap(stream_contract.address, None, sync=False)
182
+ )
183
+ keys: Set[str] = set(events.keys())
184
+ for k in keys:
185
+ if k not in self.handled_events and k not in self.skipped_events:
186
+ raise NotImplementedError(f"Need to handle event: {k}")
187
+
188
+ if "StreamCreated" in keys:
189
+ for event in events["StreamCreated"]:
190
+ from_address, *_ = event.values()
191
+ from_address = Address.get_or_insert(from_address).address
192
+ if not TreasuryWallet.check_membership(
193
+ from_address, event.block_number
194
+ ):
195
+ continue
196
+ await _STREAMS_THREAD.run(self._get_stream, event)
197
+
198
+ if "StreamCreatedWithReason" in keys:
199
+ for event in events["StreamCreatedWithReason"]:
200
+ from_address, *_ = event.values()
201
+ from_address = Address.get_or_insert(from_address).address
202
+ if not TreasuryWallet.check_membership(
203
+ from_address, event.block_number
204
+ ):
205
+ continue
206
+ await _STREAMS_THREAD.run(self._get_stream, event)
207
+
208
+ if "StreamModified" in keys:
209
+ for event in events["StreamModified"]:
210
+ from_address, _, _, old_stream_id, *_ = event.values()
211
+ if not TreasuryWallet.check_membership(
212
+ from_address, event.block_number
213
+ ):
214
+ continue
215
+ await _STREAMS_THREAD.run(
216
+ _stop_stream, old_stream_id.hex(), event.block_number
217
+ )
218
+ await _STREAMS_THREAD.run(self._get_stream, event)
219
+
220
+ if "StreamPaused" in keys:
221
+ for event in events["StreamPaused"]:
222
+ from_address, *_, stream_id = event.values()
223
+ if not TreasuryWallet.check_membership(
224
+ from_address, event.block_number
225
+ ):
226
+ continue
227
+ await _STREAMS_THREAD.run(_pause_stream, stream_id.hex())
228
+
229
+ if "StreamCancelled" in keys:
230
+ for event in events["StreamCancelled"]:
231
+ from_address, *_, stream_id = event.values()
232
+ if not TreasuryWallet.check_membership(
233
+ from_address, event.block_number
234
+ ):
235
+ continue
236
+ await _STREAMS_THREAD.run(
237
+ _stop_stream, stream_id.hex(), event.block_number
238
+ )
239
+
240
+ def _get_stream(self, log: _EventItem) -> Stream:
241
+ with db_session:
242
+ if log.name == "StreamCreated":
243
+ from_address, to_address, amount_per_second, stream_id = log.values()
244
+ reason = None
245
+ elif log.name == "StreamCreatedWithReason":
246
+ from_address, to_address, amount_per_second, stream_id, reason = (
247
+ log.values()
248
+ )
249
+ elif log.name == "StreamModified":
250
+ (
251
+ from_address,
252
+ _,
253
+ _,
254
+ old_stream_id,
255
+ to_address,
256
+ amount_per_second,
257
+ stream_id,
258
+ ) = log.values()
259
+ reason = Stream[old_stream_id.hex()].reason # type: ignore [misc]
260
+ else:
261
+ raise NotImplementedError("This is not an appropriate event log.")
262
+
263
+ stream_id_hex = stream_id.hex()
264
+ try:
265
+ return Stream[stream_id_hex] # type: ignore [misc]
266
+ except ObjectNotFound:
267
+ entity = Stream(
268
+ stream_id=stream_id_hex,
269
+ contract=Address.get_dbid(log.address),
270
+ start_block=log.block_number,
271
+ token=Token.get_dbid(Contract(log.address).token()),
272
+ from_address=Address.get_dbid(from_address),
273
+ to_address=Address.get_dbid(to_address),
274
+ amount_per_second=amount_per_second,
275
+ txgroup=must_sort_outbound_txgroup_dbid,
276
+ )
277
+ if reason is not None:
278
+ entity.reason = reason
279
+ commit()
280
+ return entity
281
+
282
+ def streams_for_recipient(
283
+ self, recipient: ChecksumAddress, at_block: Optional[BlockNumber] = None
284
+ ) -> List[Stream]:
285
+ with db_session:
286
+ streams = Stream.select(lambda s: s.to_address.address == recipient)
287
+ if at_block is None:
288
+ return list(streams)
289
+ return [
290
+ s for s in streams if (s.end_block is None or at_block <= s.end_block)
291
+ ]
292
+
293
+ def streams_for_token(
294
+ self, token: ChecksumAddress, include_inactive: bool = False
295
+ ) -> List[Stream]:
296
+ with db_session:
297
+ streams = Stream.select(lambda s: s.token.address.address == token)
298
+ return (
299
+ list(streams)
300
+ if include_inactive
301
+ else [s for s in streams if s.is_alive]
302
+ )
303
+
304
+ async def process_streams(self, run_forever: bool = False) -> None:
305
+ logger.info("Processing stream events and streamed funds...")
306
+ # Always sync events before processing
307
+ await self._get_streams()
308
+ with db_session:
309
+ streams = [s.stream_id for s in Stream.select()]
310
+ await tqdm_asyncio.gather(
311
+ *(
312
+ self.process_stream(stream_id, run_forever=run_forever)
313
+ for stream_id in streams
314
+ ),
315
+ desc="LlamaPay Streams",
316
+ )
317
+
318
+ async def process_stream(
319
+ self, stream_id: HexStr, run_forever: bool = False
320
+ ) -> None:
321
+ start, end = await _STREAMS_THREAD.run(Stream._get_start_and_end, stream_id)
322
+ for date_obj in _generate_dates(start, end, stop_at_today=not run_forever):
323
+ if await self.process_stream_for_date(stream_id, date_obj) is None:
324
+ return
325
+
326
+ async def process_stream_for_date(
327
+ self, stream_id: HexStr, date_obj: dt.datetime
328
+ ) -> Optional[StreamedFunds]:
329
+ entity = await _STREAMS_THREAD.run(
330
+ StreamedFunds.get_entity, stream_id, date_obj
331
+ )
332
+ if entity:
333
+ return entity
334
+
335
+ stream_token, start_date = await _STREAMS_THREAD.run(
336
+ Stream._get_token_and_start_date, stream_id
337
+ )
338
+ check_at = date_obj + timedelta(days=1) - timedelta(seconds=1)
339
+ if check_at > now(tz=_UTC):
340
+ await sleep((check_at - now(tz=_UTC)).total_seconds())
341
+ block = await get_block_at_timestamp(check_at, sync=False)
342
+ price_fut = create_task(get_price(stream_token, block, sync=False))
343
+ start_timestamp = await _get_start_timestamp(stream_id, block)
344
+ if start_timestamp == 0:
345
+ if await _STREAMS_THREAD.run(Stream.check_closed, stream_id):
346
+ price_fut.cancel()
347
+ return None
348
+
349
+ while start_timestamp == 0:
350
+ block -= 1
351
+ start_timestamp = await _get_start_timestamp(stream_id, block)
352
+
353
+ block_datetime = fromtimestamp(await _get_block_timestamp(block), tz=_UTC)
354
+ assert block_datetime.date() == date_obj.date()
355
+ seconds_active = (check_at - block_datetime).seconds
356
+ is_last_day = True
357
+ else:
358
+ seconds_active = int(check_at.timestamp()) - start_timestamp
359
+ is_last_day = False
360
+
361
+ seconds_active_today = min(seconds_active, _ONE_DAY)
362
+ if seconds_active_today < _ONE_DAY and not is_last_day:
363
+ if date_obj.date() != start_date:
364
+ seconds_active_today = _ONE_DAY
365
+
366
+ with db_session:
367
+ price = Decimal(await price_fut)
368
+ entity = await _STREAMS_THREAD.run(
369
+ StreamedFunds.create_entity,
370
+ stream_id,
371
+ date_obj,
372
+ price,
373
+ seconds_active_today,
374
+ is_last_day,
375
+ )
376
+ return entity
dao_treasury/treasury.py CHANGED
@@ -1,4 +1,4 @@
1
- from asyncio import create_task
1
+ from asyncio import create_task, gather
2
2
  from logging import getLogger
3
3
  from pathlib import Path
4
4
  from typing import Final, Iterable, List, Optional, Union
@@ -16,6 +16,7 @@ from dao_treasury._wallet import TreasuryWallet
16
16
  from dao_treasury.constants import CHAINID
17
17
  from dao_treasury.db import TreasuryTx
18
18
  from dao_treasury.sorting._rules import Rules
19
+ from dao_treasury.streams import llamapay
19
20
 
20
21
 
21
22
  Wallet = Union[TreasuryWallet, str]
@@ -108,6 +109,10 @@ class Treasury(a_sync.ASyncGenericBase): # type: ignore [misc]
108
109
  )
109
110
  """An eth_portfolio.Portfolio object used for exporting tx and balance history"""
110
111
 
112
+ self._llamapay: Final = (
113
+ llamapay.LlamaPayProcessor() if CHAINID in llamapay.networks else None
114
+ )
115
+
111
116
  self.asynchronous: Final = asynchronous
112
117
  """A boolean flag indicating whether the API for this `Treasury` object is sync or async by default"""
113
118
 
@@ -120,7 +125,7 @@ class Treasury(a_sync.ASyncGenericBase): # type: ignore [misc]
120
125
  def txs(self) -> a_sync.ASyncIterator[LedgerEntry]:
121
126
  return self.portfolio.ledger.all_entries
122
127
 
123
- async def populate_db(
128
+ async def _insert_txs(
124
129
  self, start_block: BlockNumber, end_block: BlockNumber
125
130
  ) -> None:
126
131
  """Populate the database with treasury transactions in a block range.
@@ -136,7 +141,7 @@ class Treasury(a_sync.ASyncGenericBase): # type: ignore [misc]
136
141
 
137
142
  Examples:
138
143
  >>> # Insert transactions from block 0 to 10000
139
- >>> await treasury.populate_db(0, 10000)
144
+ >>> await treasury._insert_txs(0, 10000)
140
145
  """
141
146
  with db_session:
142
147
  futs = []
@@ -146,9 +151,22 @@ class Treasury(a_sync.ASyncGenericBase): # type: ignore [misc]
146
151
  logger.debug("zero value transfer, skipping %s", entry)
147
152
  continue
148
153
  futs.append(create_task(TreasuryTx.insert(entry)))
149
-
150
154
  if futs:
151
155
  await tqdm_asyncio.gather(*futs, desc="Insert Txs to Postgres")
152
156
  logger.info(f"{len(futs)} transfers exported")
153
157
 
158
+ async def _process_streams(self) -> None:
159
+ if self._llamapay is not None:
160
+ await self._llamapay.process_streams(run_forever=True)
161
+
162
+ async def populate_db(
163
+ self, start_block: BlockNumber, end_block: BlockNumber
164
+ ) -> None:
165
+ """
166
+ Populate the database with treasury transactions and streams in parallel.
167
+ """
168
+ tasks = [self._insert_txs(start_block, end_block)]
169
+ if self._llamapay:
170
+ tasks.append(self._process_streams())
171
+ await gather(*tasks)
154
172
  logger.info("db connection closed")
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dao_treasury
3
- Version: 0.0.30
3
+ Version: 0.0.32
4
4
  Summary: Produce comprehensive financial reports for your on-chain org
5
5
  Classifier: Development Status :: 3 - Alpha
6
6
  Classifier: Intended Audience :: Developers
@@ -14,7 +14,7 @@ Classifier: Operating System :: OS Independent
14
14
  Classifier: Topic :: Software Development :: Libraries
15
15
  Requires-Python: >=3.10,<3.13
16
16
  Description-Content-Type: text/markdown
17
- Requires-Dist: eth-portfolio-temp<0.1,>=0.0.23.dev0
17
+ Requires-Dist: eth-portfolio-temp<0.1,>=0.0.29.dev0
18
18
  Dynamic: classifier
19
19
  Dynamic: description
20
20
  Dynamic: description-content-type
@@ -0,0 +1,49 @@
1
+ bf2b4fe1f86ad2ea158b__mypyc.cp312-win32.pyd,sha256=t574Jt4sYrAKhwJ6lgyZzMjs7nBuZA-9feRJ0lQUfZA,455168
2
+ dao_treasury/ENVIRONMENT_VARIABLES.py,sha256=ci7djcsXc9uRi6_vBQv-avGQrrIacyftXmcwKuitWWU,203
3
+ dao_treasury/__init__.py,sha256=U8BsakN_w15wVE_7MjVbHD9LBal48LfJ6a1Icf5oHdY,1052
4
+ dao_treasury/_docker.cp312-win32.pyd,sha256=OUmqhK5WrJOeq2scAcFxN5clwKiaJNKg7NFSt522HQI,9216
5
+ dao_treasury/_docker.py,sha256=wY26wCrQ8p-L0KfMJftyzI_YAszHjnBWLw94eh0LxxY,5607
6
+ dao_treasury/_nicknames.cp312-win32.pyd,sha256=d-bapuwig4qKreohzWQwy7kQjSMXgAPsGmEDMn1tLXM,9216
7
+ dao_treasury/_nicknames.py,sha256=NpbQ4NtmZF_A_vqTGSal2KzKzkH5t7_wbI8EtMBqEr4,497
8
+ dao_treasury/_wallet.cp312-win32.pyd,sha256=Xh2jb3dCAxkvj84CeJkCIaSz_QXyw0gAGJIwsSgkaGI,9216
9
+ dao_treasury/_wallet.py,sha256=q-H3YrRLWHIjOplVEcY2zqYnv6J--nxXtcx_-a1jcQw,10584
10
+ dao_treasury/constants.cp312-win32.pyd,sha256=G-7yShiKHnVIskFcFNP-HuohVYh3Nu4rheAZlclQFf0,9216
11
+ dao_treasury/constants.py,sha256=VNzlrwC8HB8LdKNmoIfncUACKHfXZxp2GtBBrH_lZKE,522
12
+ dao_treasury/db.py,sha256=naWIASCJCGROMijxdkS-A0g8_HEFrCqCP0FsAjaDRm8,46167
13
+ dao_treasury/docker-compose.yaml,sha256=trksBUUwNGJGcrsgX0k0xVEsl-SjWzYE_4tpO1DjuJg,1421
14
+ dao_treasury/main.py,sha256=yVQGwDgO4XKcxV6tQQPxEcLcZPSEEK1yJS8Djfq3Esc,8294
15
+ dao_treasury/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ dao_treasury/treasury.py,sha256=64_z0lsjOngGFASCVQNUM-QfbC5YqhKMgOdtLh758co,6678
17
+ dao_treasury/types.cp312-win32.pyd,sha256=ymuPAouv42cb-AHRj6gEOQTKJUnz0b9DwLFEDzq1Jcc,9216
18
+ dao_treasury/types.py,sha256=KFz4WKPp4t_RBwIT6YGwOcgbzw8tdHIOcXTFsUA0pJA,3818
19
+ dao_treasury/.grafana/provisioning/dashboards/dashboards.yaml,sha256=DzPkgm6Sz2hB5nNpKyTWTEfRplsYVQ9KUgQZ-yQOu6c,747
20
+ dao_treasury/.grafana/provisioning/dashboards/streams/LlamaPay.json,sha256=zKisR5WewEdpPMMSVLe3w-K8YBg30CYEuzrYjW_LZTQ,3518
21
+ dao_treasury/.grafana/provisioning/dashboards/summary/Monthly.json,sha256=pEHnKgiFgL_oscujk2SVEmkwe-PZiuGjlKf7bcLm2uc,8022
22
+ dao_treasury/.grafana/provisioning/dashboards/transactions/Treasury Transactions.json,sha256=kXaEYWwbwVbkYmj2iWYpHzHVeeBidFpGQoLm5rxUUGU,16361
23
+ dao_treasury/.grafana/provisioning/dashboards/treasury/Cashflow.json,sha256=Q544KS0P30LnBWAjMFr9jHOW83-Eoj76AQEWjNDS93o,43367
24
+ dao_treasury/.grafana/provisioning/dashboards/treasury/Treasury.json,sha256=6y7Fp-2g1iRanRBtWKKN13sXjaKxBvqld7416ZJu4YI,72196
25
+ dao_treasury/.grafana/provisioning/datasources/datasources.yaml,sha256=gLmJsOkEXNzWRDibShfHFySWeuExW-dSB_U0OSfH868,344
26
+ dao_treasury/sorting/__init__.cp312-win32.pyd,sha256=YiRsCPjCk-sK5AlbDBTmRwIddWQXxu2VAUif1-lNw6g,9216
27
+ dao_treasury/sorting/__init__.py,sha256=hHH9LLX11m2YR5NFKiTSVtdLBNGdAyJsvgDNzG3BTBI,5977
28
+ dao_treasury/sorting/_matchers.cp312-win32.pyd,sha256=oghFJ0utsQwzvkXVz-ICR1rsJlYGDIRdEl3dBFQtu-A,9216
29
+ dao_treasury/sorting/_matchers.py,sha256=ACi6aXZCKW5OTiztsID7CXCGJounj5c6ivhOCg2436M,14392
30
+ dao_treasury/sorting/_rules.cp312-win32.pyd,sha256=w3EFJrawtJfg0Fauh0QB-eU6ql4MElKpCq7lIQH_k1Q,9216
31
+ dao_treasury/sorting/_rules.py,sha256=DxhdUgpS0q0LWeLl9W1Bjn5LZz9z4OLA03vQllPMH9k,9229
32
+ dao_treasury/sorting/factory.cp312-win32.pyd,sha256=UtYPiUDnQMK5Er682773zjRqLRiyxLJJxO7rItnlFUs,9216
33
+ dao_treasury/sorting/factory.py,sha256=zlJ18xlMTxv8ACV6_MimCVIDsw3K5AZcyvKaNYY7R14,10484
34
+ dao_treasury/sorting/rule.cp312-win32.pyd,sha256=rQxxFVoMjjx3enIyy3qMLmfyWdhi2UbZ8ZQFkTBYzYw,9216
35
+ dao_treasury/sorting/rule.py,sha256=TsSlaU4UlYr4QWJBdUY7EOAfC_SK6_VA3wEFOFNUUrU,11837
36
+ dao_treasury/sorting/rules/__init__.cp312-win32.pyd,sha256=pyAk9P1cU62sy7QMNDnSqbobAVP7tkvJl4mzt7z1r6s,9216
37
+ dao_treasury/sorting/rules/__init__.py,sha256=hcLfejOEwD8RaM2RE-38Ej6_WkvL9BVGvIIGY848E6E,49
38
+ dao_treasury/sorting/rules/ignore/__init__.cp312-win32.pyd,sha256=6bXC7ydbsHE-cAzb__-6DWTe0JppzdE8VdWkUxJbgtM,9216
39
+ dao_treasury/sorting/rules/ignore/__init__.py,sha256=16THKoGdj6qfkkytuCFVG_R1M6KSErMI4AVE1p0ukS4,58
40
+ dao_treasury/sorting/rules/ignore/llamapay.cp312-win32.pyd,sha256=yKCCiJx0GHvxl5EwwQmo7QYlQqUluJNh0aYAj8MZL6k,9216
41
+ dao_treasury/sorting/rules/ignore/llamapay.py,sha256=aYyAJRlmv419IeaqkcV5o3ffx0UVfteU0lTl80j0BGo,783
42
+ dao_treasury/streams/__init__.cp312-win32.pyd,sha256=ABmRQ7gQdeEL-inkA8yp90T54azAL1tlXIuewpvlOz8,9216
43
+ dao_treasury/streams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
+ dao_treasury/streams/llamapay.cp312-win32.pyd,sha256=z3wWBUrMu07tA7B8V9XsDd6QvV1-ensZ_YcsyARkLjM,9216
45
+ dao_treasury/streams/llamapay.py,sha256=HXG3Qg8R5l1FTVgmSnpOBRoDt2VchjOI-dU9rrC_mjQ,13150
46
+ dao_treasury-0.0.32.dist-info/METADATA,sha256=-MJV9I0Bm8uwE9NjFwVOizFUgmh1GHA4toUB8wNF3Xg,7149
47
+ dao_treasury-0.0.32.dist-info/WHEEL,sha256=LwxTQZ0gyDP_uaeNCLm-ZIktY9hv6x0e22Q-hgFd-po,97
48
+ dao_treasury-0.0.32.dist-info/top_level.txt,sha256=Gw-ri_26lZA_3hwhnOX48mffUbmBGr8NhtoQ0XoMeF8,41
49
+ dao_treasury-0.0.32.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ bf2b4fe1f86ad2ea158b__mypyc
2
+ dao_treasury
Binary file
@@ -1,38 +0,0 @@
1
- 3619d39567c7fe330ece__mypyc.cp312-win32.pyd,sha256=tKHQdhWGJ6LL1tzVXFACbtIFhkJMmZm3Z9uYKMBy2G0,263680
2
- dao_treasury/ENVIRONMENT_VARIABLES.py,sha256=ci7djcsXc9uRi6_vBQv-avGQrrIacyftXmcwKuitWWU,203
3
- dao_treasury/__init__.py,sha256=U8BsakN_w15wVE_7MjVbHD9LBal48LfJ6a1Icf5oHdY,1052
4
- dao_treasury/_docker.cp312-win32.pyd,sha256=21X0gPjErgImTz4Z3CQPplr--kIAkkv86KxBOZclyV4,9216
5
- dao_treasury/_docker.py,sha256=wY26wCrQ8p-L0KfMJftyzI_YAszHjnBWLw94eh0LxxY,5607
6
- dao_treasury/_nicknames.cp312-win32.pyd,sha256=frDnXp7HZvDkP2bZXhIdtwKnGC7iPoXmXXQXYPwvNCI,9216
7
- dao_treasury/_nicknames.py,sha256=NpbQ4NtmZF_A_vqTGSal2KzKzkH5t7_wbI8EtMBqEr4,497
8
- dao_treasury/_wallet.cp312-win32.pyd,sha256=odpyXjRvOgKDH-nqiE69vvj5ZMWq2dkc2hRLCuJjFhg,9216
9
- dao_treasury/_wallet.py,sha256=q-H3YrRLWHIjOplVEcY2zqYnv6J--nxXtcx_-a1jcQw,10584
10
- dao_treasury/constants.cp312-win32.pyd,sha256=6-_HlMg-Ft41SAvWkY6WvMhXjR0ocR-YHDJLGdKxwlk,9216
11
- dao_treasury/constants.py,sha256=VNzlrwC8HB8LdKNmoIfncUACKHfXZxp2GtBBrH_lZKE,522
12
- dao_treasury/db.py,sha256=HMFp3X8rRn3TE0FbqnqgzbMm-WFF6GaGq6UmYYViHgY,41205
13
- dao_treasury/docker-compose.yaml,sha256=trksBUUwNGJGcrsgX0k0xVEsl-SjWzYE_4tpO1DjuJg,1421
14
- dao_treasury/main.py,sha256=yVQGwDgO4XKcxV6tQQPxEcLcZPSEEK1yJS8Djfq3Esc,8294
15
- dao_treasury/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- dao_treasury/treasury.py,sha256=ZkkxaH49CXOgszOayu_IZ5wmqznOp7t1S3lz_M77Ct8,5954
17
- dao_treasury/types.cp312-win32.pyd,sha256=lkeWUubo1wMq8lBMSoaFsQGhRA0sYR_RAmLMMAKcoqk,9216
18
- dao_treasury/types.py,sha256=KFz4WKPp4t_RBwIT6YGwOcgbzw8tdHIOcXTFsUA0pJA,3818
19
- dao_treasury/.grafana/provisioning/dashboards/dashboards.yaml,sha256=43Lof370qTV5TPnVRpWxXIzjRpPX_u9khgee41lAyYQ,570
20
- dao_treasury/.grafana/provisioning/dashboards/summary/Monthly.json,sha256=pEHnKgiFgL_oscujk2SVEmkwe-PZiuGjlKf7bcLm2uc,8022
21
- dao_treasury/.grafana/provisioning/dashboards/transactions/Treasury Transactions.json,sha256=kXaEYWwbwVbkYmj2iWYpHzHVeeBidFpGQoLm5rxUUGU,16361
22
- dao_treasury/.grafana/provisioning/dashboards/treasury/Cashflow.json,sha256=xrUS1csp0hsfHcxhxFekxwzZ3ul-03aDwNw1EurBG9U,43323
23
- dao_treasury/.grafana/provisioning/dashboards/treasury/Treasury.json,sha256=6y7Fp-2g1iRanRBtWKKN13sXjaKxBvqld7416ZJu4YI,72196
24
- dao_treasury/.grafana/provisioning/datasources/datasources.yaml,sha256=gLmJsOkEXNzWRDibShfHFySWeuExW-dSB_U0OSfH868,344
25
- dao_treasury/sorting/__init__.cp312-win32.pyd,sha256=nfvJKGLw26xQeJyQkNUrXTYPr7IoAzFtTaMDuTP70Ng,9216
26
- dao_treasury/sorting/__init__.py,sha256=8scT00tm4LtZrKTnpv6MGdJWqC9L0ksDt_V7lrK7c98,5935
27
- dao_treasury/sorting/_matchers.cp312-win32.pyd,sha256=V3zhA7BVPHNk1L2k4QNgqG1YgrXUE1Zjzm-E8leGTFc,9216
28
- dao_treasury/sorting/_matchers.py,sha256=ACi6aXZCKW5OTiztsID7CXCGJounj5c6ivhOCg2436M,14392
29
- dao_treasury/sorting/_rules.cp312-win32.pyd,sha256=N9mWvQgFuti_M2LKMN-E_l8i_YXk9iDMSJNO2f4HO-4,9216
30
- dao_treasury/sorting/_rules.py,sha256=DxhdUgpS0q0LWeLl9W1Bjn5LZz9z4OLA03vQllPMH9k,9229
31
- dao_treasury/sorting/factory.cp312-win32.pyd,sha256=8bDAj8UvFrIGEMFMhANPu4eFA_NmRh2ULtzFMnSnTpY,9216
32
- dao_treasury/sorting/factory.py,sha256=zlJ18xlMTxv8ACV6_MimCVIDsw3K5AZcyvKaNYY7R14,10484
33
- dao_treasury/sorting/rule.cp312-win32.pyd,sha256=gWnR5zGuv8xWS0j3KiNu6zDd5A4PPEgNG9Di1BQuvWU,9216
34
- dao_treasury/sorting/rule.py,sha256=TsSlaU4UlYr4QWJBdUY7EOAfC_SK6_VA3wEFOFNUUrU,11837
35
- dao_treasury-0.0.30.dist-info/METADATA,sha256=vGTp6PwV3CsZbe3zO5cg0m5UJMEb1ED_hsnUDJ33jGc,7149
36
- dao_treasury-0.0.30.dist-info/WHEEL,sha256=LwxTQZ0gyDP_uaeNCLm-ZIktY9hv6x0e22Q-hgFd-po,97
37
- dao_treasury-0.0.30.dist-info/top_level.txt,sha256=NRjzFf9H2cBekP0cVk8IWoVYf0fTSSKfqvVPvaMhoNs,41
38
- dao_treasury-0.0.30.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- 3619d39567c7fe330ece__mypyc
2
- dao_treasury