dao-treasury 0.0.32__cp310-cp310-musllinux_1_2_i686.whl → 0.0.33__cp310-cp310-musllinux_1_2_i686.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.
@@ -0,0 +1,491 @@
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": 1,
21
+ "links": [],
22
+ "liveNow": false,
23
+ "panels": [
24
+ {
25
+ "datasource": "SQLite",
26
+ "fieldConfig": {
27
+ "defaults": {
28
+ "color": {
29
+ "mode": "thresholds"
30
+ },
31
+ "mappings": [],
32
+ "thresholds": {
33
+ "mode": "absolute",
34
+ "steps": [
35
+ {
36
+ "color": "green",
37
+ "value": null
38
+ },
39
+ {
40
+ "color": "red",
41
+ "value": 80
42
+ }
43
+ ]
44
+ }
45
+ },
46
+ "overrides": []
47
+ },
48
+ "gridPos": {
49
+ "h": 4,
50
+ "w": 6,
51
+ "x": 0,
52
+ "y": 0
53
+ },
54
+ "id": 1,
55
+ "options": {
56
+ "colorMode": "value",
57
+ "graphMode": "area",
58
+ "justifyMode": "auto",
59
+ "orientation": "auto",
60
+ "reduceOptions": {
61
+ "calcs": [
62
+ "lastNotNull"
63
+ ],
64
+ "fields": "",
65
+ "values": false
66
+ },
67
+ "textMode": "auto"
68
+ },
69
+ "pluginVersion": "10.2.0",
70
+ "targets": [
71
+ {
72
+ "datasource": "SQLite",
73
+ "queryText": "SELECT SUM(t.value_usd) AS total_revenue FROM general_ledger t JOIN txgroup_hierarchy gh USING (txgroup_id) WHERE gh.top_category = 'Revenue' AND t.timestamp >= $__from/1000 AND t.timestamp <= $__to/1000",
74
+ "queryType": "table",
75
+ "rawQueryText": "SELECT SUM(t.value_usd) AS total_revenue FROM general_ledger t JOIN txgroup_hierarchy gh USING (txgroup_id) WHERE gh.top_category = 'Revenue' AND t.timestamp >= $__from/1000 AND t.timestamp <= $__to/1000",
76
+ "refId": "A",
77
+ "timeColumns": [
78
+ "time",
79
+ "ts"
80
+ ]
81
+ }
82
+ ],
83
+ "title": "Revenue",
84
+ "type": "stat"
85
+ },
86
+ {
87
+ "datasource": "SQLite",
88
+ "fieldConfig": {
89
+ "defaults": {
90
+ "color": {
91
+ "mode": "thresholds"
92
+ },
93
+ "mappings": [],
94
+ "thresholds": {
95
+ "mode": "absolute",
96
+ "steps": [
97
+ {
98
+ "color": "green",
99
+ "value": null
100
+ },
101
+ {
102
+ "color": "red",
103
+ "value": 80
104
+ }
105
+ ]
106
+ }
107
+ },
108
+ "overrides": []
109
+ },
110
+ "gridPos": {
111
+ "h": 4,
112
+ "w": 6,
113
+ "x": 6,
114
+ "y": 0
115
+ },
116
+ "id": 3,
117
+ "options": {
118
+ "colorMode": "value",
119
+ "graphMode": "area",
120
+ "justifyMode": "auto",
121
+ "orientation": "auto",
122
+ "reduceOptions": {
123
+ "calcs": [
124
+ "lastNotNull"
125
+ ],
126
+ "fields": "",
127
+ "values": false
128
+ },
129
+ "textMode": "auto"
130
+ },
131
+ "pluginVersion": "10.2.0",
132
+ "targets": [
133
+ {
134
+ "datasource": "SQLite",
135
+ "queryText": "SELECT SUM(t.value_usd) AS total_revenue FROM general_ledger t JOIN txgroup_hierarchy gh USING (txgroup_id) WHERE gh.top_category = 'Cost of Revenue' AND t.timestamp >= $__from/1000 AND t.timestamp <= $__to/1000",
136
+ "queryType": "table",
137
+ "rawQueryText": "SELECT SUM(t.value_usd) AS total_revenue FROM general_ledger t JOIN txgroup_hierarchy gh USING (txgroup_id) WHERE gh.top_category = 'Cost of Revenue' AND t.timestamp >= $__from/1000 AND t.timestamp <= $__to/1000",
138
+ "refId": "A",
139
+ "timeColumns": [
140
+ "time",
141
+ "ts"
142
+ ]
143
+ }
144
+ ],
145
+ "title": "Cost of Revenue",
146
+ "type": "stat"
147
+ },
148
+ {
149
+ "datasource": "SQLite",
150
+ "fieldConfig": {
151
+ "defaults": {
152
+ "color": {
153
+ "mode": "thresholds"
154
+ },
155
+ "mappings": [],
156
+ "thresholds": {
157
+ "mode": "absolute",
158
+ "steps": [
159
+ {
160
+ "color": "green",
161
+ "value": null
162
+ },
163
+ {
164
+ "color": "red",
165
+ "value": 80
166
+ }
167
+ ]
168
+ }
169
+ },
170
+ "overrides": []
171
+ },
172
+ "gridPos": {
173
+ "h": 4,
174
+ "w": 6,
175
+ "x": 12,
176
+ "y": 0
177
+ },
178
+ "id": 2,
179
+ "options": {
180
+ "colorMode": "value",
181
+ "graphMode": "area",
182
+ "justifyMode": "auto",
183
+ "orientation": "auto",
184
+ "reduceOptions": {
185
+ "calcs": [
186
+ "lastNotNull"
187
+ ],
188
+ "fields": "",
189
+ "values": false
190
+ },
191
+ "textMode": "auto"
192
+ },
193
+ "pluginVersion": "10.2.0",
194
+ "targets": [
195
+ {
196
+ "datasource": "SQLite",
197
+ "queryText": "SELECT SUM(t.value_usd) AS total_revenue FROM general_ledger t JOIN txgroup_hierarchy gh USING (txgroup_id) WHERE gh.top_category = 'Expenses' AND t.timestamp >= $__from/1000 AND t.timestamp <= $__to/1000",
198
+ "queryType": "table",
199
+ "rawQueryText": "SELECT SUM(t.value_usd) AS total_revenue FROM general_ledger t JOIN txgroup_hierarchy gh USING (txgroup_id) WHERE gh.top_category = 'Expenses' AND t.timestamp >= $__from/1000 AND t.timestamp <= $__to/1000",
200
+ "refId": "A",
201
+ "timeColumns": [
202
+ "time",
203
+ "ts"
204
+ ]
205
+ }
206
+ ],
207
+ "title": "Expenses",
208
+ "type": "stat"
209
+ },
210
+ {
211
+ "datasource": "SQLite",
212
+ "description": "",
213
+ "fieldConfig": {
214
+ "defaults": {
215
+ "color": {
216
+ "mode": "thresholds"
217
+ },
218
+ "mappings": [],
219
+ "thresholds": {
220
+ "mode": "absolute",
221
+ "steps": [
222
+ {
223
+ "color": "green",
224
+ "value": null
225
+ },
226
+ {
227
+ "color": "red",
228
+ "value": 80
229
+ }
230
+ ]
231
+ }
232
+ },
233
+ "overrides": []
234
+ },
235
+ "gridPos": {
236
+ "h": 4,
237
+ "w": 6,
238
+ "x": 18,
239
+ "y": 0
240
+ },
241
+ "id": 10,
242
+ "options": {
243
+ "colorMode": "value",
244
+ "graphMode": "area",
245
+ "justifyMode": "auto",
246
+ "orientation": "auto",
247
+ "reduceOptions": {
248
+ "calcs": [
249
+ "lastNotNull"
250
+ ],
251
+ "fields": "",
252
+ "values": false
253
+ },
254
+ "textMode": "auto"
255
+ },
256
+ "pluginVersion": "10.2.0",
257
+ "targets": [
258
+ {
259
+ "datasource": "SQLite",
260
+ "queryText": "SELECT (\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END)\n - SUM(CASE WHEN gh.top_category = 'Cost of Revenue' THEN t.value_usd ELSE 0 END)\n - SUM(CASE WHEN gh.top_category = 'Expenses' THEN t.value_usd ELSE 0 END)\n) AS total_net\nFROM general_ledger t\nJOIN txgroup_hierarchy gh USING (txgroup_id)\nWHERE t.timestamp >= $__from/1000 AND t.timestamp <= $__to/1000",
261
+ "queryType": "table",
262
+ "rawQueryText": "SELECT (\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END)\n - SUM(CASE WHEN gh.top_category = 'Cost of Revenue' THEN t.value_usd ELSE 0 END)\n - SUM(CASE WHEN gh.top_category = 'Expenses' THEN t.value_usd ELSE 0 END)\n) AS total_net\nFROM general_ledger t\nJOIN txgroup_hierarchy gh USING (txgroup_id)\nWHERE t.timestamp >= $__from/1000 AND t.timestamp <= $__to/1000",
263
+ "refId": "A",
264
+ "timeColumns": [
265
+ "time",
266
+ "ts"
267
+ ]
268
+ }
269
+ ],
270
+ "title": "Operating Total",
271
+ "type": "stat"
272
+ },
273
+ {
274
+ "datasource": "SQLite",
275
+ "description": "",
276
+ "fieldConfig": {
277
+ "defaults": {
278
+ "color": {
279
+ "mode": "palette-classic"
280
+ },
281
+ "custom": {
282
+ "axisBorderShow": false,
283
+ "axisCenteredZero": false,
284
+ "axisColorMode": "text",
285
+ "axisLabel": "",
286
+ "axisPlacement": "auto",
287
+ "barAlignment": 0,
288
+ "drawStyle": "bars",
289
+ "fillOpacity": 70,
290
+ "gradientMode": "none",
291
+ "hideFrom": {
292
+ "legend": false,
293
+ "tooltip": false,
294
+ "viz": false
295
+ },
296
+ "insertNulls": false,
297
+ "lineInterpolation": "linear",
298
+ "lineWidth": 1,
299
+ "pointSize": 5,
300
+ "scaleDistribution": {
301
+ "type": "linear"
302
+ },
303
+ "showPoints": "auto",
304
+ "spanNulls": false,
305
+ "stacking": {
306
+ "group": "A",
307
+ "mode": "normal"
308
+ },
309
+ "thresholdsStyle": {
310
+ "mode": "off"
311
+ }
312
+ },
313
+ "mappings": [],
314
+ "thresholds": {
315
+ "mode": "absolute",
316
+ "steps": [
317
+ {
318
+ "color": "green",
319
+ "value": null
320
+ },
321
+ {
322
+ "color": "red",
323
+ "value": 80
324
+ }
325
+ ]
326
+ }
327
+ },
328
+ "overrides": [
329
+ {
330
+ "matcher": {
331
+ "id": "byName",
332
+ "options": "Net (sum)"
333
+ },
334
+ "properties": [
335
+ {
336
+ "id": "custom.drawStyle",
337
+ "value": "line"
338
+ },
339
+ {
340
+ "id": "custom.stacking",
341
+ "value": {
342
+ "group": "A",
343
+ "mode": "none"
344
+ }
345
+ },
346
+ {
347
+ "id": "custom.fillOpacity",
348
+ "value": 19
349
+ }
350
+ ]
351
+ }
352
+ ]
353
+ },
354
+ "gridPos": {
355
+ "h": 12,
356
+ "w": 24,
357
+ "x": 0,
358
+ "y": 4
359
+ },
360
+ "id": 11,
361
+ "options": {
362
+ "legend": {
363
+ "calcs": [],
364
+ "displayMode": "list",
365
+ "placement": "bottom",
366
+ "showLegend": true
367
+ },
368
+ "tooltip": {
369
+ "mode": "single",
370
+ "sort": "none"
371
+ }
372
+ },
373
+ "targets": [
374
+ {
375
+ "datasource": "SQLite",
376
+ "queryText": "SELECT t.timestamp,\r\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END) AS \"Total Revenue\",\r\n SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses') THEN t.value_usd ELSE 0 END) * -1 AS \"Total Expenses\",\r\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END) - SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses') THEN t.value_usd ELSE 0 END) AS \"Net\"\r\nFROM general_ledger AS t\r\nJOIN txgroup_hierarchy gh ON t.txgroup_id = gh.txgroup_id\r\nWHERE t.timestamp >= $__from/1000 AND t.timestamp <= $__to/1000\r\nGROUP BY timestamp\r\nORDER BY timestamp;",
377
+ "queryType": "table",
378
+ "rawQueryText": "SELECT t.timestamp,\r\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END) AS \"Total Revenue\",\r\n SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses') THEN t.value_usd ELSE 0 END) * -1 AS \"Total Expenses\",\r\n SUM(CASE WHEN gh.top_category = 'Revenue' THEN t.value_usd ELSE 0 END) - SUM(CASE WHEN gh.top_category in ('Cost of Revenue','Expenses') THEN t.value_usd ELSE 0 END) AS \"Net\"\r\nFROM general_ledger AS t\r\nJOIN txgroup_hierarchy gh ON t.txgroup_id = gh.txgroup_id\r\nWHERE t.timestamp >= $__from/1000 AND t.timestamp <= $__to/1000\r\nGROUP BY timestamp\r\nORDER BY timestamp;",
379
+ "refId": "A",
380
+ "timeColumns": [
381
+ "timestamp"
382
+ ]
383
+ }
384
+ ],
385
+ "title": "Weekly Cashflow",
386
+ "transformations": [
387
+ {
388
+ "id": "formatTime",
389
+ "options": {
390
+ "outputFormat": "YYYY-WW",
391
+ "timeField": "timestamp",
392
+ "timezone": "browser",
393
+ "useTimezone": true
394
+ }
395
+ },
396
+ {
397
+ "id": "convertFieldType",
398
+ "options": {
399
+ "conversions": [
400
+ {
401
+ "destinationType": "time",
402
+ "targetField": "timestamp"
403
+ }
404
+ ],
405
+ "fields": {}
406
+ }
407
+ },
408
+ {
409
+ "id": "groupBy",
410
+ "options": {
411
+ "fields": {
412
+ "Cost of Revenue": {
413
+ "aggregations": [
414
+ "sum"
415
+ ],
416
+ "operation": "aggregate"
417
+ },
418
+ "Expenses": {
419
+ "aggregations": [
420
+ "sum"
421
+ ],
422
+ "operation": "aggregate"
423
+ },
424
+ "Net": {
425
+ "aggregations": [
426
+ "sum"
427
+ ],
428
+ "operation": "aggregate"
429
+ },
430
+ "Other Expenses": {
431
+ "aggregations": [
432
+ "sum"
433
+ ],
434
+ "operation": "aggregate"
435
+ },
436
+ "Other Income": {
437
+ "aggregations": [
438
+ "sum"
439
+ ],
440
+ "operation": "aggregate"
441
+ },
442
+ "Revenue": {
443
+ "aggregations": [
444
+ "sum"
445
+ ],
446
+ "operation": "aggregate"
447
+ },
448
+ "Timestamp": {
449
+ "aggregations": [],
450
+ "operation": "groupby"
451
+ },
452
+ "Total Expenses": {
453
+ "aggregations": [
454
+ "sum"
455
+ ],
456
+ "operation": "aggregate"
457
+ },
458
+ "Total Revenue": {
459
+ "aggregations": [
460
+ "sum"
461
+ ],
462
+ "operation": "aggregate"
463
+ },
464
+ "timestamp": {
465
+ "aggregations": [],
466
+ "operation": "groupby"
467
+ }
468
+ }
469
+ }
470
+ }
471
+ ],
472
+ "type": "timeseries"
473
+ }
474
+ ],
475
+ "refresh": "",
476
+ "schemaVersion": 38,
477
+ "tags": [],
478
+ "templating": {
479
+ "list": []
480
+ },
481
+ "time": {
482
+ "from": "now-6M",
483
+ "to": "now"
484
+ },
485
+ "timepicker": {},
486
+ "timezone": "",
487
+ "title": "Operating Cashflow Summary",
488
+ "uid": "fdf9969c-357a-4203-ae7b-12816e87bc7e",
489
+ "version": 1,
490
+ "weekStart": ""
491
+ }
dao_treasury/db.py CHANGED
@@ -119,13 +119,13 @@ class Chain(DbEntity):
119
119
  chainid = Required(int, unique=True)
120
120
  """Numeric chain ID matching the connected RPC via :data:`~y.constants.CHAINID`."""
121
121
 
122
- addresses = Set("Address", reverse="chain")
122
+ addresses = Set("Address", reverse="chain", lazy=True)
123
123
  """Relationship to address records on this chain."""
124
124
 
125
- tokens = Set("Token", reverse="chain")
125
+ tokens = Set("Token", reverse="chain", lazy=True)
126
126
  """Relationship to token records on this chain."""
127
127
 
128
- treasury_txs = Set("TreasuryTx")
128
+ treasury_txs = Set("TreasuryTx", lazy=True)
129
129
  """Relationship to treasury transactions on this chain."""
130
130
 
131
131
  @staticmethod
@@ -184,7 +184,7 @@ class Address(DbEntity):
184
184
  address_id = PrimaryKey(int, auto=True)
185
185
  """Auto-incremented primary key for the addresses table."""
186
186
 
187
- chain = Required(Chain, reverse="addresses")
187
+ chain = Required(Chain, reverse="addresses", lazy=True)
188
188
  """Reference to the chain on which this address resides."""
189
189
 
190
190
  address = Required(str, index=True)
@@ -193,7 +193,7 @@ class Address(DbEntity):
193
193
  nickname = Optional(str)
194
194
  """Optional human-readable label (e.g., contract name or token name)."""
195
195
 
196
- is_contract = Required(bool, index=True)
196
+ is_contract = Required(bool, index=True, lazy=True)
197
197
  """Flag indicating whether the address is a smart contract."""
198
198
 
199
199
  composite_key(address, chain)
@@ -204,22 +204,22 @@ class Address(DbEntity):
204
204
  treasury_tx_from: Set["TreasuryTx"]
205
205
  treasury_tx_to: Set["TreasuryTx"]
206
206
 
207
- token = Optional("Token", index=True)
207
+ token = Optional("Token", index=True, lazy=True)
208
208
  """Optional back-reference to a Token if this address is one."""
209
- # partners_tx = Set('PartnerHarvestEvent', reverse='wrapper')
209
+ # partners_tx = Set('PartnerHarvestEvent', reverse='wrapper', lazy=True)
210
210
 
211
- treasury_tx_from = Set("TreasuryTx", reverse="from_address")
211
+ treasury_tx_from = Set("TreasuryTx", reverse="from_address", lazy=True)
212
212
  """Inverse relation for transactions sent from this address."""
213
213
 
214
- treasury_tx_to = Set("TreasuryTx", reverse="to_address")
214
+ treasury_tx_to = Set("TreasuryTx", reverse="to_address", lazy=True)
215
215
  """Inverse relation for transactions sent to this address."""
216
216
 
217
- streams_from = Set("Stream", reverse="from_address")
218
- streams_to = Set("Stream", reverse="to_address")
219
- streams = Set("Stream", reverse="contract")
220
- # vesting_escrows = Set("VestingEscrow", reverse="address")
221
- # vests_received = Set("VestingEscrow", reverse="recipient")
222
- # vests_funded = Set("VestingEscrow", reverse="funder")
217
+ streams_from = Set("Stream", reverse="from_address", lazy=True)
218
+ streams_to = Set("Stream", reverse="to_address", lazy=True)
219
+ streams = Set("Stream", reverse="contract", lazy=True)
220
+ # vesting_escrows = Set("VestingEscrow", reverse="address", lazy=True)
221
+ # vests_received = Set("VestingEscrow", reverse="recipient", lazy=True)
222
+ # vests_funded = Set("VestingEscrow", reverse="funder", lazy=True)
223
223
 
224
224
  def __eq__(self, other: Union["Address", ChecksumAddress, "Token"]) -> bool: # type: ignore [override]
225
225
  if isinstance(other, str):
@@ -367,30 +367,30 @@ class Token(DbEntity):
367
367
  token_id = PrimaryKey(int, auto=True)
368
368
  """Auto-incremented primary key for the tokens table."""
369
369
 
370
- chain = Required(Chain, index=True)
370
+ chain = Required(Chain, index=True, lazy=True)
371
371
  """Foreign key linking to :class:`~dao_treasury.db.Chain`."""
372
372
 
373
- symbol = Required(str, index=True)
373
+ symbol = Required(str, index=True, lazy=True)
374
374
  """Short ticker symbol for the token."""
375
375
 
376
- name = Required(str)
376
+ name = Required(str, lazy=True)
377
377
  """Full human-readable name of the token."""
378
378
 
379
- decimals = Required(int)
379
+ decimals = Required(int, lazy=True)
380
380
  """Number of decimals used for value scaling."""
381
381
 
382
382
  if TYPE_CHECKING:
383
383
  treasury_tx: Set["TreasuryTx"]
384
384
 
385
- treasury_tx = Set("TreasuryTx", reverse="token")
385
+ treasury_tx = Set("TreasuryTx", reverse="token", lazy=True)
386
386
  """Inverse relation for treasury transactions involving this token."""
387
- # partner_harvest_event = Set('PartnerHarvestEvent', reverse="vault")
387
+ # partner_harvest_event = Set('PartnerHarvestEvent', reverse="vault", lazy=True)
388
388
 
389
389
  address = Required(Address, column="address_id")
390
390
  """Foreign key to the address record for this token contract."""
391
391
 
392
- streams = Set("Stream", reverse="token")
393
- # vesting_escrows = Set("VestingEscrow", reverse="token")
392
+ streams = Set("Stream", reverse="token", lazy=True)
393
+ # vesting_escrows = Set("VestingEscrow", reverse="token", lazy=True)
394
394
 
395
395
  def __eq__(self, other: Union["Token", Address, ChecksumAddress]) -> bool: # type: ignore [override]
396
396
  if isinstance(other, str):
@@ -533,7 +533,7 @@ class TxGroup(DbEntity):
533
533
  name = Required(str)
534
534
  """Name of the grouping category, e.g., 'Revenue', 'Expenses'."""
535
535
 
536
- treasury_tx = Set("TreasuryTx", reverse="txgroup")
536
+ treasury_tx = Set("TreasuryTx", reverse="txgroup", lazy=True)
537
537
  """Inverse relation for treasury transactions assigned to this group."""
538
538
 
539
539
  parent_txgroup = Optional("TxGroup", reverse="child_txgroups")
@@ -541,13 +541,13 @@ class TxGroup(DbEntity):
541
541
 
542
542
  composite_key(name, parent_txgroup)
543
543
 
544
- child_txgroups = Set("TxGroup", reverse="parent_txgroup")
544
+ child_txgroups = Set("TxGroup", reverse="parent_txgroup", lazy=True)
545
545
  """Set of nested child groups."""
546
546
 
547
- streams = Set("Stream", reverse="txgroup")
547
+ streams = Set("Stream", reverse="txgroup", lazy=True)
548
548
 
549
549
  # TODO: implement this
550
- # vesting_escrows = Set("VestingEscrow", reverse="txgroup")
550
+ # vesting_escrows = Set("VestingEscrow", reverse="txgroup", lazy=True)
551
551
 
552
552
  @property
553
553
  def fullname(self) -> str:
@@ -623,7 +623,7 @@ class TxGroup(DbEntity):
623
623
  return txgroup # type: ignore [no-any-return]
624
624
 
625
625
 
626
- @lru_cache(100)
626
+ @lru_cache(500)
627
627
  def get_transaction(txhash: str) -> TransactionReceipt:
628
628
  """Fetch and cache a transaction receipt from the connected chain.
629
629
 
@@ -905,6 +905,7 @@ class TreasuryTx(DbEntity):
905
905
  def __set_txgroup(treasury_tx_dbid: int, txgroup_dbid: TxGroupDbid) -> None:
906
906
  with db_session:
907
907
  TreasuryTx[treasury_tx_dbid].txgroup = txgroup_dbid
908
+ commit()
908
909
 
909
910
 
910
911
  _stream_metadata_cache: Final[Dict[HexStr, Tuple[ChecksumAddress, date]]] = {}
@@ -925,9 +926,9 @@ class Stream(DbEntity):
925
926
  status = Required(str, default="Active")
926
927
  txgroup = Optional("TxGroup", reverse="streams")
927
928
 
928
- streamed_funds = Set("StreamedFunds")
929
+ streamed_funds = Set("StreamedFunds", lazy=True)
929
930
 
930
- scale = int(1e20)
931
+ scale = 10**20
931
932
 
932
933
  @property
933
934
  def is_alive(self) -> bool:
@@ -1089,7 +1090,7 @@ def create_stream_ledger_view() -> None:
1089
1090
  symbol as token,
1090
1091
  d.address AS "from",
1091
1092
  d.nickname as from_nickname,
1092
- e.address as "to",
1093
+ e.address AS "to",
1093
1094
  e.nickname as to_nickname,
1094
1095
  amount,
1095
1096
  price,
@@ -1108,6 +1109,31 @@ def create_stream_ledger_view() -> None:
1108
1109
  )
1109
1110
 
1110
1111
 
1112
+ def create_txgroup_hierarchy_view() -> None:
1113
+ """Create or replace the SQL view `txgroup_hierarchy` for recursive txgroup hierarchy.
1114
+
1115
+ This view exposes txgroup_id, top_category, and parent_txgroup for all txgroups,
1116
+ matching the recursive CTE logic used in dashboards.
1117
+ """
1118
+ db.execute("DROP VIEW IF EXISTS txgroup_hierarchy;")
1119
+ db.execute(
1120
+ """
1121
+ CREATE VIEW txgroup_hierarchy AS
1122
+ WITH RECURSIVE group_hierarchy (txgroup_id, top_category, parent_txgroup) AS (
1123
+ SELECT txgroup_id, name AS top_category, parent_txgroup
1124
+ FROM txgroups
1125
+ WHERE parent_txgroup IS NULL
1126
+ UNION ALL
1127
+ SELECT child.txgroup_id, parent.top_category, child.parent_txgroup
1128
+ FROM txgroups AS child
1129
+ JOIN group_hierarchy AS parent
1130
+ ON child.parent_txgroup = parent.txgroup_id
1131
+ )
1132
+ SELECT * FROM group_hierarchy;
1133
+ """
1134
+ )
1135
+
1136
+
1111
1137
  def create_vesting_ledger_view() -> None:
1112
1138
  """Create or replace the SQL view `vesting_ledger` for vesting escrow reporting.
1113
1139
 
@@ -1250,6 +1276,7 @@ def create_monthly_pnl_view() -> None:
1250
1276
 
1251
1277
  with db_session:
1252
1278
  create_stream_ledger_view()
1279
+ create_txgroup_hierarchy_view()
1253
1280
  # create_vesting_ledger_view()
1254
1281
  create_general_ledger_view()
1255
1282
  create_unsorted_txs_view()