dao-treasury 0.0.30__cp310-cp310-win_amd64.whl → 0.0.32__cp310-cp310-win_amd64.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.
- bf2b4fe1f86ad2ea158b__mypyc.cp310-win_amd64.pyd +0 -0
- dao_treasury/.grafana/provisioning/dashboards/dashboards.yaml +8 -0
- dao_treasury/.grafana/provisioning/dashboards/streams/LlamaPay.json +116 -0
- dao_treasury/.grafana/provisioning/dashboards/treasury/Cashflow.json +22 -22
- dao_treasury/_docker.cp310-win_amd64.pyd +0 -0
- dao_treasury/_nicknames.cp310-win_amd64.pyd +0 -0
- dao_treasury/_wallet.cp310-win_amd64.pyd +0 -0
- dao_treasury/constants.cp310-win_amd64.pyd +0 -0
- dao_treasury/db.py +172 -16
- dao_treasury/sorting/__init__.cp310-win_amd64.pyd +0 -0
- dao_treasury/sorting/__init__.py +1 -0
- dao_treasury/sorting/_matchers.cp310-win_amd64.pyd +0 -0
- dao_treasury/sorting/_rules.cp310-win_amd64.pyd +0 -0
- dao_treasury/sorting/factory.cp310-win_amd64.pyd +0 -0
- dao_treasury/sorting/rule.cp310-win_amd64.pyd +0 -0
- dao_treasury/sorting/rules/__init__.cp310-win_amd64.pyd +0 -0
- dao_treasury/sorting/rules/__init__.py +1 -0
- dao_treasury/sorting/rules/ignore/__init__.cp310-win_amd64.pyd +0 -0
- dao_treasury/sorting/rules/ignore/__init__.py +1 -0
- dao_treasury/sorting/rules/ignore/llamapay.cp310-win_amd64.pyd +0 -0
- dao_treasury/sorting/rules/ignore/llamapay.py +20 -0
- dao_treasury/streams/__init__.cp310-win_amd64.pyd +0 -0
- dao_treasury/streams/__init__.py +0 -0
- dao_treasury/streams/llamapay.cp310-win_amd64.pyd +0 -0
- dao_treasury/streams/llamapay.py +376 -0
- dao_treasury/treasury.py +22 -4
- dao_treasury/types.cp310-win_amd64.pyd +0 -0
- {dao_treasury-0.0.30.dist-info → dao_treasury-0.0.32.dist-info}/METADATA +2 -2
- dao_treasury-0.0.32.dist-info/RECORD +49 -0
- dao_treasury-0.0.32.dist-info/top_level.txt +2 -0
- 3619d39567c7fe330ece__mypyc.cp310-win_amd64.pyd +0 -0
- dao_treasury-0.0.30.dist-info/RECORD +0 -38
- dao_treasury-0.0.30.dist-info/top_level.txt +0 -2
- {dao_treasury-0.0.30.dist-info → dao_treasury-0.0.32.dist-info}/WHEEL +0 -0
Binary file
|
@@ -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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
214
|
-
|
215
|
-
|
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
|
-
|
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
|
-
|
538
|
-
|
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(
|
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,
|
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
|
-
|
1019
|
-
|
1020
|
-
|
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
|
-
|
1252
|
+
create_stream_ledger_view()
|
1097
1253
|
# create_vesting_ledger_view()
|
1098
1254
|
create_general_ledger_view()
|
1099
1255
|
create_unsorted_txs_view()
|
Binary file
|
dao_treasury/sorting/__init__.py
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
from dao_treasury.sorting.rules.ignore import *
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
from dao_treasury.sorting.rules.ignore.llamapay import *
|
Binary file
|
@@ -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
|
Binary file
|
File without changes
|
Binary file
|
@@ -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
|
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.
|
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.
|
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.
|
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.cp310-win_amd64.pyd,sha256=oVJdu_qDxisnpC6bhgb1uDzg4paUuJh62nSepbZQJUA,477696
|
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.cp310-win_amd64.pyd,sha256=rBbVvUi80qKXM5RR7IdbQqbZ03zOS6G_YcxStiBmDaA,10752
|
5
|
+
dao_treasury/_docker.py,sha256=wY26wCrQ8p-L0KfMJftyzI_YAszHjnBWLw94eh0LxxY,5607
|
6
|
+
dao_treasury/_nicknames.cp310-win_amd64.pyd,sha256=_mzIXVtLoeueXlM4qCNuZFRfEnwsL7Vu_bW_-XG_BcM,10752
|
7
|
+
dao_treasury/_nicknames.py,sha256=NpbQ4NtmZF_A_vqTGSal2KzKzkH5t7_wbI8EtMBqEr4,497
|
8
|
+
dao_treasury/_wallet.cp310-win_amd64.pyd,sha256=-frqml_JT45wc8axlTwURKKNq1d3TC45ibnReHDw-uE,10752
|
9
|
+
dao_treasury/_wallet.py,sha256=q-H3YrRLWHIjOplVEcY2zqYnv6J--nxXtcx_-a1jcQw,10584
|
10
|
+
dao_treasury/constants.cp310-win_amd64.pyd,sha256=jVwq6bffqdMCet_liVovc-uVvs-90yzGnf8bYRRvPM0,10752
|
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.cp310-win_amd64.pyd,sha256=Y02XlXDTGhom3Pks8Mk161zxQ05Uq75GeWq6w1uSK90,10752
|
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__.cp310-win_amd64.pyd,sha256=ciLpWGbrJVabuRXmnlGyLMR39ux6ZZU67ztDaFCR1xw,10752
|
27
|
+
dao_treasury/sorting/__init__.py,sha256=hHH9LLX11m2YR5NFKiTSVtdLBNGdAyJsvgDNzG3BTBI,5977
|
28
|
+
dao_treasury/sorting/_matchers.cp310-win_amd64.pyd,sha256=cawD9MBPVQ_vLj9018L0eH_lYIOcoH4eoU23_BMF5DU,10752
|
29
|
+
dao_treasury/sorting/_matchers.py,sha256=ACi6aXZCKW5OTiztsID7CXCGJounj5c6ivhOCg2436M,14392
|
30
|
+
dao_treasury/sorting/_rules.cp310-win_amd64.pyd,sha256=RjxDAf6_oa5pDXRwjhI9-3iJhLu3P7p_4XQH1v9Xstc,10752
|
31
|
+
dao_treasury/sorting/_rules.py,sha256=DxhdUgpS0q0LWeLl9W1Bjn5LZz9z4OLA03vQllPMH9k,9229
|
32
|
+
dao_treasury/sorting/factory.cp310-win_amd64.pyd,sha256=hcwROGUzYVXZ4T367ee3LyJdpr_FEkh8JCflKA51ejQ,10752
|
33
|
+
dao_treasury/sorting/factory.py,sha256=zlJ18xlMTxv8ACV6_MimCVIDsw3K5AZcyvKaNYY7R14,10484
|
34
|
+
dao_treasury/sorting/rule.cp310-win_amd64.pyd,sha256=rByJC-S3N2palBkuus8aIr1zsck5qyumRspRzhdNUSA,10752
|
35
|
+
dao_treasury/sorting/rule.py,sha256=TsSlaU4UlYr4QWJBdUY7EOAfC_SK6_VA3wEFOFNUUrU,11837
|
36
|
+
dao_treasury/sorting/rules/__init__.cp310-win_amd64.pyd,sha256=VeY2pAX5D2TkN3tJlkF0gpYfD7TWJMNC1VL-O7RFYmE,10752
|
37
|
+
dao_treasury/sorting/rules/__init__.py,sha256=hcLfejOEwD8RaM2RE-38Ej6_WkvL9BVGvIIGY848E6E,49
|
38
|
+
dao_treasury/sorting/rules/ignore/__init__.cp310-win_amd64.pyd,sha256=D38AqjDQcj6nBE-b4WFqYSt6ds2-8Kqg53PxTy5r6f0,10752
|
39
|
+
dao_treasury/sorting/rules/ignore/__init__.py,sha256=16THKoGdj6qfkkytuCFVG_R1M6KSErMI4AVE1p0ukS4,58
|
40
|
+
dao_treasury/sorting/rules/ignore/llamapay.cp310-win_amd64.pyd,sha256=1TJhBiW4T0juEGvgfyPjtADX_zJ9eFmC_R2-2xNxChI,10752
|
41
|
+
dao_treasury/sorting/rules/ignore/llamapay.py,sha256=aYyAJRlmv419IeaqkcV5o3ffx0UVfteU0lTl80j0BGo,783
|
42
|
+
dao_treasury/streams/__init__.cp310-win_amd64.pyd,sha256=Z4ja9IqgASVW2aUuJBLnvCRbfXVWBztHr6z-r9U8GiQ,10752
|
43
|
+
dao_treasury/streams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
|
+
dao_treasury/streams/llamapay.cp310-win_amd64.pyd,sha256=h9LJpJ9Wh5JIn1VVX-rDtV6ToFcKxqnBMVjwxfXtdX0,10752
|
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=KUuBC6lxAbHCKilKua8R9W_TM71_-9Sg5uEP3uDWcoU,101
|
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,,
|
Binary file
|
@@ -1,38 +0,0 @@
|
|
1
|
-
3619d39567c7fe330ece__mypyc.cp310-win_amd64.pyd,sha256=4aBtRIHh3rO6jm7191NOtxqVWsyaWy4LaVmP7gqaTcU,276480
|
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.cp310-win_amd64.pyd,sha256=j3kJ1fcmUEn6YpmYOCyFknZiQkNR_HvK_-AzhMA9Mbc,10752
|
5
|
-
dao_treasury/_docker.py,sha256=wY26wCrQ8p-L0KfMJftyzI_YAszHjnBWLw94eh0LxxY,5607
|
6
|
-
dao_treasury/_nicknames.cp310-win_amd64.pyd,sha256=SwJp73M0yI-FpBp3Q4tDBSLuwGA0D_et8FBsqKfiiP8,10752
|
7
|
-
dao_treasury/_nicknames.py,sha256=NpbQ4NtmZF_A_vqTGSal2KzKzkH5t7_wbI8EtMBqEr4,497
|
8
|
-
dao_treasury/_wallet.cp310-win_amd64.pyd,sha256=0LAAsVYSfy-2EgvR3v_8Gc4L76s1vvUHOHQ7Wctq8Uw,10752
|
9
|
-
dao_treasury/_wallet.py,sha256=q-H3YrRLWHIjOplVEcY2zqYnv6J--nxXtcx_-a1jcQw,10584
|
10
|
-
dao_treasury/constants.cp310-win_amd64.pyd,sha256=IpDGwcIgr84ffa1cV-A6wBOeLVFhfrtv_q6pi5fsBfE,10752
|
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.cp310-win_amd64.pyd,sha256=XIsZEBtxVCLs2aDAtMmlEagz439IzBa8BKfLLxxjsdE,10752
|
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__.cp310-win_amd64.pyd,sha256=JqZOxj2DFO0LlT-u2rzXnwiRhpGp_YTchKmI0ofqdJw,10752
|
26
|
-
dao_treasury/sorting/__init__.py,sha256=8scT00tm4LtZrKTnpv6MGdJWqC9L0ksDt_V7lrK7c98,5935
|
27
|
-
dao_treasury/sorting/_matchers.cp310-win_amd64.pyd,sha256=Fg5_q3Tw0wb_UGi0LRzBAuaSnHOYuWZcEO3glMzlQh0,10752
|
28
|
-
dao_treasury/sorting/_matchers.py,sha256=ACi6aXZCKW5OTiztsID7CXCGJounj5c6ivhOCg2436M,14392
|
29
|
-
dao_treasury/sorting/_rules.cp310-win_amd64.pyd,sha256=E1cyE5OR2yFuM_KATiXEeWHopjQyrAyhwZq4LHPqVNo,10752
|
30
|
-
dao_treasury/sorting/_rules.py,sha256=DxhdUgpS0q0LWeLl9W1Bjn5LZz9z4OLA03vQllPMH9k,9229
|
31
|
-
dao_treasury/sorting/factory.cp310-win_amd64.pyd,sha256=e5RcJXTzqowVRHCw1_GDpUQfsDIDeGrPre3DBnsfg3A,10752
|
32
|
-
dao_treasury/sorting/factory.py,sha256=zlJ18xlMTxv8ACV6_MimCVIDsw3K5AZcyvKaNYY7R14,10484
|
33
|
-
dao_treasury/sorting/rule.cp310-win_amd64.pyd,sha256=I5X7GPV9c605s7gZ4eCsd0SCz_nevzZs4hVMbrAAme4,10752
|
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=KUuBC6lxAbHCKilKua8R9W_TM71_-9Sg5uEP3uDWcoU,101
|
37
|
-
dao_treasury-0.0.30.dist-info/top_level.txt,sha256=NRjzFf9H2cBekP0cVk8IWoVYf0fTSSKfqvVPvaMhoNs,41
|
38
|
-
dao_treasury-0.0.30.dist-info/RECORD,,
|
File without changes
|