charli3_dendrite 1.0.0.dev1__tar.gz → 1.1.0.dev0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/PKG-INFO +1 -1
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/pyproject.toml +1 -1
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/backend/dbsync/__init__.py +80 -65
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/backend/dbsync/models.py +28 -10
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/LICENSE +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/README.md +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/__init__.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/backend/__init__.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/backend/backend_base.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/backend/blockfrost.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/backend/utils.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dataclasses/__init__.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dataclasses/datums.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dataclasses/models.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/__init__.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/__init__.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/amm_base.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/amm_types.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/minswap.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/muesli.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/spectrum.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/sundae.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/vyfi.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/wingriders.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/core/__init__.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/core/base.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/core/errors.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/ob/__init__.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/ob/axo.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/ob/geniusyield.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/ob/ob_base.py +0 -0
- {charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/utility.py +0 -0
|
@@ -3,14 +3,12 @@ import logging
|
|
|
3
3
|
import os
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from threading import Lock
|
|
6
|
-
from typing import List
|
|
7
|
-
from typing import Optional
|
|
8
6
|
|
|
9
|
-
import psycopg_pool
|
|
10
|
-
from dotenv import load_dotenv
|
|
11
|
-
from psycopg.rows import dict_row
|
|
7
|
+
import psycopg_pool # type: ignore
|
|
8
|
+
from dotenv import load_dotenv # type: ignore
|
|
9
|
+
from psycopg.rows import dict_row # type: ignore
|
|
12
10
|
from psycopg_pool import PoolTimeout
|
|
13
|
-
from pycardano import Address
|
|
11
|
+
from pycardano import Address # type: ignore
|
|
14
12
|
|
|
15
13
|
from charli3_dendrite.backend.backend_base import AbstractBackend
|
|
16
14
|
from charli3_dendrite.backend.dbsync.models import OrderSelector
|
|
@@ -32,7 +30,7 @@ class DbsyncBackend(AbstractBackend):
|
|
|
32
30
|
for retrieving blockchain data.
|
|
33
31
|
"""
|
|
34
32
|
|
|
35
|
-
def __init__(self):
|
|
33
|
+
def __init__(self) -> None:
|
|
36
34
|
"""Initialize the DbsyncBackend with database connection details."""
|
|
37
35
|
self.lock = Lock()
|
|
38
36
|
self.POOL = None
|
|
@@ -51,8 +49,11 @@ class DbsyncBackend(AbstractBackend):
|
|
|
51
49
|
with self.lock:
|
|
52
50
|
if self.POOL is None:
|
|
53
51
|
conninfo = (
|
|
54
|
-
f"host={self.DBSYNC_HOST}
|
|
55
|
-
f"
|
|
52
|
+
f"host={self.DBSYNC_HOST} "
|
|
53
|
+
+ f"port={self.DBSYNC_PORT} "
|
|
54
|
+
+ f"dbname={self.DBSYNC_DB_NAME} "
|
|
55
|
+
+ f"user={self.DBSYNC_USER} "
|
|
56
|
+
+ f"password={self.DBSYNC_PASS}"
|
|
56
57
|
)
|
|
57
58
|
self.POOL = psycopg_pool.ConnectionPool(
|
|
58
59
|
conninfo=conninfo,
|
|
@@ -65,6 +66,9 @@ class DbsyncBackend(AbstractBackend):
|
|
|
65
66
|
check=psycopg_pool.ConnectionPool.check_connection,
|
|
66
67
|
)
|
|
67
68
|
try:
|
|
69
|
+
if self.POOL is None:
|
|
70
|
+
raise ValueError("Connection pool has not been initialized.")
|
|
71
|
+
|
|
68
72
|
self.POOL.open()
|
|
69
73
|
self.POOL.wait(timeout=60.0) # Increased from 30 to 60 seconds
|
|
70
74
|
except PoolTimeout as e:
|
|
@@ -72,7 +76,9 @@ class DbsyncBackend(AbstractBackend):
|
|
|
72
76
|
f"Database connection pool initialization timed out: {e}",
|
|
73
77
|
)
|
|
74
78
|
logging.error(
|
|
75
|
-
f"Connection info: host={self.DBSYNC_HOST},
|
|
79
|
+
f"Connection info: host={self.DBSYNC_HOST}, "
|
|
80
|
+
+ f"port={self.DBSYNC_PORT}, "
|
|
81
|
+
+ f"user={self.DBSYNC_USER}",
|
|
76
82
|
)
|
|
77
83
|
raise
|
|
78
84
|
except Exception as e:
|
|
@@ -80,7 +86,7 @@ class DbsyncBackend(AbstractBackend):
|
|
|
80
86
|
raise
|
|
81
87
|
return self.POOL
|
|
82
88
|
|
|
83
|
-
def db_query(self, query: str, args:
|
|
89
|
+
def db_query(self, query: str, args: dict | None = None) -> list[dict]:
|
|
84
90
|
"""Execute a database query using the connection pool.
|
|
85
91
|
|
|
86
92
|
Args:
|
|
@@ -90,15 +96,16 @@ class DbsyncBackend(AbstractBackend):
|
|
|
90
96
|
Returns:
|
|
91
97
|
List[tuple]: The query results.
|
|
92
98
|
"""
|
|
93
|
-
with self.get_dbsync_pool().connection() as conn
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
with self.get_dbsync_pool().connection() as conn, conn.cursor(
|
|
100
|
+
row_factory=dict_row,
|
|
101
|
+
) as cursor:
|
|
102
|
+
cursor.execute(query, args)
|
|
103
|
+
return cursor.fetchall()
|
|
97
104
|
|
|
98
105
|
def get_pool_utxos(
|
|
99
106
|
self,
|
|
107
|
+
addresses: list[str],
|
|
100
108
|
assets: list[str] | None = None,
|
|
101
|
-
addresses: list[str] | None = None,
|
|
102
109
|
limit: int = 1000,
|
|
103
110
|
page: int = 0,
|
|
104
111
|
historical: bool = True,
|
|
@@ -135,12 +142,11 @@ LEFT JOIN multi_asset ma ON ma.id = mtxo.ident"""
|
|
|
135
142
|
LEFT JOIN tx ON txo.tx_id = tx.id
|
|
136
143
|
LEFT JOIN datum ON txo.data_hash = datum.hash
|
|
137
144
|
LEFT JOIN block ON tx.block_id = block.id
|
|
138
|
-
LEFT JOIN tx_in ON tx_in.tx_out_id = txo.tx_id AND tx_in.tx_out_index = txo.index
|
|
139
145
|
WHERE datum.hash IS NOT NULL"""
|
|
140
146
|
|
|
141
147
|
if not historical:
|
|
142
148
|
datum_selector += """
|
|
143
|
-
AND
|
|
149
|
+
AND txo.consumed_by_tx_id IS NULL"""
|
|
144
150
|
|
|
145
151
|
if assets is not None:
|
|
146
152
|
datum_selector += """
|
|
@@ -166,8 +172,8 @@ OFFSET %(offset)s"""
|
|
|
166
172
|
def get_pool_in_tx(
|
|
167
173
|
self,
|
|
168
174
|
tx_hash: str,
|
|
175
|
+
addresses: list[str],
|
|
169
176
|
assets: list[str] | None = None,
|
|
170
|
-
addresses: list[str] | None = None,
|
|
171
177
|
) -> PoolStateList:
|
|
172
178
|
"""Get transactions by policy or address."""
|
|
173
179
|
# Use the pool selector to format the output
|
|
@@ -244,20 +250,20 @@ AND ma.policy = ANY(%(policies)b) AND ma.name = ANY(%(names)b)"""
|
|
|
244
250
|
return PoolSelector.parse(r)
|
|
245
251
|
|
|
246
252
|
def get_script_from_address(self, address: Address) -> ScriptReference:
|
|
247
|
-
|
|
253
|
+
"""Get a reference script from an address."""
|
|
254
|
+
query = UTxOSelector.select()
|
|
248
255
|
|
|
249
|
-
|
|
256
|
+
query += """
|
|
250
257
|
FROM script s
|
|
251
258
|
LEFT JOIN tx_out ON s.id = tx_out.reference_script_id
|
|
252
259
|
LEFT JOIN tx ON tx.id = tx_out.tx_id
|
|
253
260
|
LEFT JOIN datum ON tx_out.inline_datum_id = datum.id
|
|
254
261
|
LEFT JOIN block on block.id = tx.block_id
|
|
255
|
-
|
|
256
|
-
WHERE s.hash = %(address)b AND tx_in.tx_in_id IS NULL
|
|
262
|
+
WHERE s.hash = %(address)b AND tx_out.consumed_by_tx_id IS NULL
|
|
257
263
|
ORDER BY block.time DESC
|
|
258
264
|
LIMIT 1
|
|
259
265
|
"""
|
|
260
|
-
r = self.db_query(
|
|
266
|
+
r = self.db_query(query, {"address": address.payment_part.payload})
|
|
261
267
|
|
|
262
268
|
if r[0]["assets"] is not None and r[0]["assets"][0]["lovelace"] is None:
|
|
263
269
|
r[0]["assets"] = None
|
|
@@ -269,6 +275,7 @@ LIMIT 1
|
|
|
269
275
|
address: Address,
|
|
270
276
|
asset: str | None = None,
|
|
271
277
|
) -> ScriptReference | None:
|
|
278
|
+
"""Get a reference datum from an address."""
|
|
272
279
|
kwargs = {"address": address.payment_part.payload}
|
|
273
280
|
|
|
274
281
|
if asset is not None:
|
|
@@ -279,9 +286,9 @@ LIMIT 1
|
|
|
279
286
|
},
|
|
280
287
|
)
|
|
281
288
|
|
|
282
|
-
|
|
289
|
+
query = UTxOSelector.select()
|
|
283
290
|
|
|
284
|
-
|
|
291
|
+
query += """
|
|
285
292
|
FROM tx_out
|
|
286
293
|
LEFT JOIN ma_tx_out mtxo ON mtxo.tx_out_id = tx_out.id
|
|
287
294
|
LEFT JOIN multi_asset ma ON ma.id = mtxo.ident
|
|
@@ -289,20 +296,19 @@ LEFT JOIN tx ON tx.id = tx_out.tx_id
|
|
|
289
296
|
LEFT JOIN datum ON tx_out.inline_datum_id = datum.id
|
|
290
297
|
LEFT JOIN block on block.id = tx.block_id
|
|
291
298
|
LEFT JOIN script s ON s.id = tx_out.reference_script_id
|
|
292
|
-
|
|
293
|
-
WHERE tx_out.payment_cred = %(address)b AND txi.tx_in_id IS NULL"""
|
|
299
|
+
WHERE tx_out.payment_cred = %(address)b AND tx_out.consumed_by_tx_id IS NULL"""
|
|
294
300
|
|
|
295
301
|
if asset is not None:
|
|
296
|
-
|
|
302
|
+
query += """
|
|
297
303
|
AND policy = %(policy)b AND name = %(name)b
|
|
298
304
|
"""
|
|
299
305
|
|
|
300
|
-
|
|
306
|
+
query += """
|
|
301
307
|
AND tx_out.inline_datum_id IS NOT NULL
|
|
302
308
|
ORDER BY block.time DESC
|
|
303
309
|
LIMIT 1
|
|
304
310
|
"""
|
|
305
|
-
r = self.db_query(
|
|
311
|
+
r = self.db_query(query, kwargs)
|
|
306
312
|
|
|
307
313
|
if r[0]["assets"] is not None and r[0]["assets"][0]["lovelace"] is None:
|
|
308
314
|
r[0]["assets"] = None
|
|
@@ -315,7 +321,8 @@ LIMIT 1
|
|
|
315
321
|
after_time: datetime | int | None = None,
|
|
316
322
|
limit: int = 1000,
|
|
317
323
|
page: int = 0,
|
|
318
|
-
):
|
|
324
|
+
) -> SwapTransactionList:
|
|
325
|
+
"""Get historical orders at an order submission address."""
|
|
319
326
|
if isinstance(after_time, int):
|
|
320
327
|
after_time = datetime.fromtimestamp(after_time)
|
|
321
328
|
|
|
@@ -338,19 +345,20 @@ LEFT JOIN (
|
|
|
338
345
|
block.time AS "block_time",
|
|
339
346
|
block.block_no,
|
|
340
347
|
tx.block_index AS "block_index",
|
|
341
|
-
tx_in.tx_out_id,
|
|
342
|
-
tx_in.tx_out_index,
|
|
348
|
+
tx_in.tx_id as "tx_out_id",
|
|
349
|
+
tx_in.index as "tx_out_index",
|
|
343
350
|
txo.inline_datum_id,
|
|
344
351
|
txo.reference_script_id,
|
|
345
352
|
txo.address,
|
|
346
353
|
datum.hash as "datum_hash",
|
|
347
354
|
datum.bytes as "datum_bytes"
|
|
348
|
-
FROM tx_in
|
|
349
|
-
LEFT JOIN tx ON tx.id = tx_in.
|
|
355
|
+
FROM tx_out tx_in
|
|
356
|
+
LEFT JOIN tx ON tx.id = tx_in.consumed_by_tx_id
|
|
350
357
|
LEFT JOIN tx_out txo ON tx.id = txo.tx_id
|
|
351
358
|
LEFT JOIN block ON tx.block_id = block.id
|
|
352
359
|
LEFT JOIN datum ON txo.data_hash = datum.hash
|
|
353
|
-
) txo_output ON txo_output.tx_out_id = txo_stake.tx_id
|
|
360
|
+
) txo_output ON txo_output.tx_out_id = txo_stake.tx_id
|
|
361
|
+
AND txo_output.tx_out_index = txo_stake.index
|
|
354
362
|
WHERE datum.hash IS NOT NULL"""
|
|
355
363
|
|
|
356
364
|
if after_time is not None:
|
|
@@ -390,12 +398,12 @@ OFFSET %(offset)s"""
|
|
|
390
398
|
limit: int = 1000,
|
|
391
399
|
page: int = 0,
|
|
392
400
|
) -> SwapTransactionList:
|
|
401
|
+
"""Get order UTxOs by either block number or tx hash."""
|
|
393
402
|
utxo_selector = """
|
|
394
403
|
SELECT (
|
|
395
404
|
SELECT array_agg(DISTINCT txo.address)
|
|
396
405
|
FROM tx_out txo
|
|
397
|
-
|
|
398
|
-
WHERE txi.tx_in_id = txo_stake.tx_id
|
|
406
|
+
WHERE txo.consumed_by_tx_id = txo_stake.tx_id
|
|
399
407
|
) AS "submit_address_inputs",
|
|
400
408
|
txo_stake.address as "submit_address_stake",
|
|
401
409
|
ENCODE(txo_stake.tx_hash, 'hex') as "submit_tx_hash",
|
|
@@ -452,7 +460,10 @@ OFFSET %(offset)s"""
|
|
|
452
460
|
)::jsonb,
|
|
453
461
|
jsonb_build_array(json_build_object('lovelace',txo_output.value::TEXT)::jsonb)
|
|
454
462
|
) AS "assets",
|
|
455
|
-
(
|
|
463
|
+
(
|
|
464
|
+
txo_output.inline_datum_id IS NOT NULL OR
|
|
465
|
+
txo_output.reference_script_id IS NOT NULL
|
|
466
|
+
) as "plutus_v2"
|
|
456
467
|
"""
|
|
457
468
|
|
|
458
469
|
utxo_selector += """FROM (
|
|
@@ -472,8 +483,7 @@ OFFSET %(offset)s"""
|
|
|
472
483
|
LEFT JOIN tx ON tx.id = txo.tx_id
|
|
473
484
|
LEFT JOIN block ON tx.block_id = block.id
|
|
474
485
|
LEFT JOIN datum ON txo.data_hash = datum.hash
|
|
475
|
-
LEFT JOIN
|
|
476
|
-
LEFT JOIN tx tx_in_ref ON tx_in.tx_in_id = tx_in_ref.id
|
|
486
|
+
LEFT JOIN tx tx_in_ref ON txo.consumed_by_tx_id = tx_in_ref.id
|
|
477
487
|
WHERE txo.payment_cred = ANY(%(addresses)b) AND txo.data_hash IS NOT NULL"""
|
|
478
488
|
|
|
479
489
|
if out_tx_hash is not None:
|
|
@@ -501,19 +511,20 @@ OFFSET %(offset)s"""
|
|
|
501
511
|
block.time AS "block_time",
|
|
502
512
|
block.block_no,
|
|
503
513
|
tx.block_index AS "block_index",
|
|
504
|
-
tx_in.tx_out_id,
|
|
505
|
-
tx_in.tx_out_index,
|
|
514
|
+
tx_in.tx_id as "tx_out_id",
|
|
515
|
+
tx_in.index as "tx_out_index",
|
|
506
516
|
txo.inline_datum_id,
|
|
507
517
|
txo.reference_script_id,
|
|
508
518
|
txo.address,
|
|
509
519
|
datum.hash as "datum_hash",
|
|
510
520
|
datum.bytes as "datum_bytes"
|
|
511
|
-
FROM tx_in
|
|
512
|
-
LEFT JOIN tx ON tx.id = tx_in.
|
|
521
|
+
FROM tx_out tx_in
|
|
522
|
+
LEFT JOIN tx ON tx.id = tx_in.consumed_by_tx_id
|
|
513
523
|
LEFT JOIN tx_out txo ON tx.id = txo.tx_id
|
|
514
524
|
LEFT JOIN block ON tx.block_id = block.id
|
|
515
525
|
LEFT JOIN datum ON txo.data_hash = datum.hash
|
|
516
|
-
) txo_output ON txo_output.tx_out_id = txo_stake.tx_id
|
|
526
|
+
) txo_output ON txo_output.tx_out_id = txo_stake.tx_id
|
|
527
|
+
AND txo_output.tx_out_index = txo_stake.index
|
|
517
528
|
WHERE txo_stake.datum_hash IS NOT NULL
|
|
518
529
|
ORDER BY txo_stake.tx_id ASC
|
|
519
530
|
LIMIT %(limit)s
|
|
@@ -551,7 +562,8 @@ OFFSET %(offset)s"""
|
|
|
551
562
|
after_time: datetime | int | None = None,
|
|
552
563
|
limit: int = 1000,
|
|
553
564
|
page: int = 0,
|
|
554
|
-
):
|
|
565
|
+
) -> SwapTransactionList:
|
|
566
|
+
"""Get order cancel UTxOs."""
|
|
555
567
|
if isinstance(after_time, int):
|
|
556
568
|
after_time = datetime.fromtimestamp(after_time)
|
|
557
569
|
|
|
@@ -559,8 +571,7 @@ OFFSET %(offset)s"""
|
|
|
559
571
|
SELECT (
|
|
560
572
|
SELECT array_agg(DISTINCT tx_out.address)
|
|
561
573
|
FROM tx_out
|
|
562
|
-
|
|
563
|
-
WHERE txi.tx_in_id = txo.tx_id
|
|
574
|
+
WHERE tx_out.consumed_by_tx_id = txo.tx_id
|
|
564
575
|
) AS "submit_address_inputs",
|
|
565
576
|
txo.address as "submit_address_stake",
|
|
566
577
|
ENCODE(tx.hash, 'hex') as "submit_tx_hash",
|
|
@@ -617,7 +628,8 @@ COALESCE(
|
|
|
617
628
|
)::jsonb,
|
|
618
629
|
jsonb_build_array(json_build_object('lovelace',txo_output.value::TEXT)::jsonb)
|
|
619
630
|
) AS "assets",
|
|
620
|
-
(txo_output.inline_datum_id IS NOT NULL OR txo_output.reference_script_id IS NOT NULL)
|
|
631
|
+
(txo_output.inline_datum_id IS NOT NULL OR txo_output.reference_script_id IS NOT NULL)
|
|
632
|
+
AS "plutus_v2"
|
|
621
633
|
"""
|
|
622
634
|
|
|
623
635
|
utxo_selector += """FROM (
|
|
@@ -629,15 +641,15 @@ COALESCE(
|
|
|
629
641
|
block.time AS "block_time",
|
|
630
642
|
block.block_no,
|
|
631
643
|
tx.block_index AS "block_index",
|
|
632
|
-
tx_in.tx_out_id,
|
|
633
|
-
tx_in.
|
|
644
|
+
tx_in.tx_id as "tx_out_id",
|
|
645
|
+
tx_in.index as "tx_index",
|
|
634
646
|
txo.inline_datum_id,
|
|
635
647
|
txo.reference_script_id,
|
|
636
648
|
txo.address,
|
|
637
649
|
datum.hash as "datum_hash",
|
|
638
650
|
datum.bytes as "datum_bytes"
|
|
639
|
-
FROM tx_in
|
|
640
|
-
LEFT JOIN tx ON tx.id = tx_in.
|
|
651
|
+
FROM tx_out tx_in
|
|
652
|
+
LEFT JOIN tx ON tx.id = tx_in.tx_id
|
|
641
653
|
LEFT JOIN tx_out txo ON tx.id = txo.tx_id
|
|
642
654
|
LEFT JOIN block ON tx.block_id = block.id
|
|
643
655
|
LEFT JOIN datum ON txo.data_hash = datum.hash"""
|
|
@@ -653,8 +665,8 @@ COALESCE(
|
|
|
653
665
|
|
|
654
666
|
utxo_selector += """
|
|
655
667
|
GROUP BY tx.hash, txo.value, txo.id, block.hash, block.time, block.block_no,
|
|
656
|
-
tx.block_index, tx_in.
|
|
657
|
-
txo.address, datum.hash, datum.bytes
|
|
668
|
+
tx.block_index, tx_in.tx_id, tx_in.index, txo.inline_datum_id,
|
|
669
|
+
txo.reference_script_id, txo.address, datum.hash, datum.bytes
|
|
658
670
|
HAVING COUNT(DISTINCT txo.address) = 1
|
|
659
671
|
) txo_output
|
|
660
672
|
LEFT JOIN tx_out txo ON txo.tx_id = txo_output.tx_out_id
|
|
@@ -664,8 +676,7 @@ LEFT JOIN tx_out txo ON txo.tx_id = txo_output.tx_out_id
|
|
|
664
676
|
LEFT JOIN tx ON tx.id = txo.tx_id
|
|
665
677
|
LEFT JOIN block ON tx.block_id = block.id
|
|
666
678
|
LEFT JOIN datum ON txo.data_hash = datum.hash
|
|
667
|
-
LEFT JOIN
|
|
668
|
-
LEFT JOIN tx tx_in_ref ON tx_in.tx_in_id = tx_in_ref.id
|
|
679
|
+
LEFT JOIN tx tx_in_ref ON txo.tx_id = tx_in_ref.id
|
|
669
680
|
WHERE txo.id IS NOT NULL
|
|
670
681
|
ORDER BY txo.tx_id ASC
|
|
671
682
|
LIMIT %(limit)s
|
|
@@ -696,32 +707,36 @@ OFFSET %(offset)s"""
|
|
|
696
707
|
block_time: datetime | None = None,
|
|
697
708
|
) -> str | None:
|
|
698
709
|
"""Get the target address for the given asset."""
|
|
699
|
-
|
|
710
|
+
query = """
|
|
700
711
|
SELECT DISTINCT txo.address, block.time
|
|
701
712
|
FROM (
|
|
702
713
|
SELECT tx.id, tx.block_id
|
|
703
714
|
FROM tx_out txo
|
|
704
715
|
LEFT JOIN tx ON tx.id = txo.tx_id
|
|
705
|
-
WHERE txo.payment_cred = DECODE(
|
|
716
|
+
WHERE txo.payment_cred = DECODE(
|
|
717
|
+
'55ff0e63efa0694e8065122c552e80c7b51768b7f20917af25752a7c', 'hex'
|
|
718
|
+
)
|
|
706
719
|
) as tx
|
|
707
720
|
LEFT JOIN block ON block.id = tx.block_id
|
|
708
721
|
LEFT JOIN tx_out txo ON tx.id = txo.tx_id
|
|
709
722
|
LEFT JOIN ma_tx_out mtxo on txo.id = mtxo.tx_out_id
|
|
710
723
|
LEFT JOIN multi_asset ma ON ma.id = mtxo.ident
|
|
711
724
|
WHERE ma.policy = %(policy)b AND ma.name = %(name)b
|
|
712
|
-
AND txo.payment_cred != DECODE(
|
|
725
|
+
AND txo.payment_cred != DECODE(
|
|
726
|
+
'55ff0e63efa0694e8065122c552e80c7b51768b7f20917af25752a7c', 'hex'
|
|
727
|
+
)"""
|
|
713
728
|
|
|
714
729
|
if block_time is not None:
|
|
715
|
-
|
|
730
|
+
query += """
|
|
716
731
|
AND block.time <= %(block_time)s"""
|
|
717
732
|
|
|
718
|
-
|
|
733
|
+
query += """
|
|
719
734
|
ORDER BY block.time DESC"""
|
|
720
735
|
|
|
721
736
|
policy = bytes.fromhex(assets.unit()[:56])
|
|
722
737
|
name = bytes.fromhex(assets.unit()[56:])
|
|
723
738
|
r = self.db_query(
|
|
724
|
-
|
|
739
|
+
query,
|
|
725
740
|
{
|
|
726
741
|
"policy": policy,
|
|
727
742
|
"name": name,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
"""Methods for abstracting SQL selections and parsing results."""
|
|
1
2
|
from abc import ABC
|
|
2
|
-
from abc import
|
|
3
|
+
from abc import abstractmethod
|
|
3
4
|
|
|
4
5
|
from charli3_dendrite.dataclasses.models import DendriteBaseModel
|
|
5
6
|
from charli3_dendrite.dataclasses.models import PoolStateList
|
|
@@ -8,20 +9,27 @@ from charli3_dendrite.dataclasses.models import SwapTransactionList
|
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class AbstractDBSyncStructure(ABC):
|
|
11
|
-
|
|
12
|
+
"""Abstract class with required methods for SQL queries."""
|
|
13
|
+
|
|
14
|
+
@classmethod
|
|
15
|
+
@abstractmethod
|
|
12
16
|
def select(cls) -> str:
|
|
13
17
|
"""The selectin part of a DBSync query."""
|
|
14
18
|
raise NotImplementedError
|
|
15
19
|
|
|
16
|
-
@
|
|
17
|
-
|
|
20
|
+
@classmethod
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def parse(cls, data: dict | list[dict]) -> DendriteBaseModel:
|
|
18
23
|
"""Parse data returned from a dbsync query."""
|
|
19
24
|
raise NotImplementedError
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
class PoolSelector(AbstractDBSyncStructure):
|
|
28
|
+
"""Query selections and parsing classes for AMM pools."""
|
|
29
|
+
|
|
23
30
|
@classmethod
|
|
24
31
|
def select(cls) -> str:
|
|
32
|
+
"""Select SQL query for swap pools."""
|
|
25
33
|
return """
|
|
26
34
|
SELECT txo.address,
|
|
27
35
|
ENCODE(tx.hash, 'hex') as "tx_hash",
|
|
@@ -52,13 +60,17 @@ COALESCE (
|
|
|
52
60
|
"""
|
|
53
61
|
|
|
54
62
|
@classmethod
|
|
55
|
-
def parse(cls, data: dict) -> PoolStateList:
|
|
63
|
+
def parse(cls, data: dict | list[dict]) -> PoolStateList:
|
|
64
|
+
"""Parse pools from a query."""
|
|
56
65
|
return PoolStateList.model_validate(data)
|
|
57
66
|
|
|
58
67
|
|
|
59
68
|
class UTxOSelector(AbstractDBSyncStructure):
|
|
69
|
+
"""Selection queries and parsing classes for reference scripts and datums."""
|
|
70
|
+
|
|
60
71
|
@classmethod
|
|
61
72
|
def select(cls) -> str:
|
|
73
|
+
"""Selection SQL query for reference scripts and datums."""
|
|
62
74
|
return """
|
|
63
75
|
SELECT ENCODE(tx.hash, 'hex') as "tx_hash",
|
|
64
76
|
tx_out.index as "tx_index",
|
|
@@ -82,19 +94,22 @@ COALESCE (
|
|
|
82
94
|
ENCODE(s.bytes, 'hex') as "script" """
|
|
83
95
|
|
|
84
96
|
@classmethod
|
|
85
|
-
def parse(cls, data: dict) -> ScriptReference:
|
|
97
|
+
def parse(cls, data: dict | list[dict]) -> ScriptReference:
|
|
98
|
+
"""Parsing class for UTxOs containing a reference script or datum."""
|
|
86
99
|
return ScriptReference.model_validate(data)
|
|
87
100
|
|
|
88
101
|
|
|
89
102
|
class OrderSelector(AbstractDBSyncStructure):
|
|
103
|
+
"""SQL query for orders and the associated pydantic parsing class."""
|
|
104
|
+
|
|
90
105
|
@classmethod
|
|
91
106
|
def select(cls) -> str:
|
|
107
|
+
"""The SQL select statement for orders."""
|
|
92
108
|
return """
|
|
93
109
|
SELECT (
|
|
94
110
|
SELECT array_agg(DISTINCT txo.address)
|
|
95
111
|
FROM tx_out txo
|
|
96
|
-
|
|
97
|
-
WHERE txi.tx_in_id = txo_stake.tx_id
|
|
112
|
+
WHERE txo.consumed_by_tx_id = txo_stake.tx_id
|
|
98
113
|
) AS "submit_address_inputs",
|
|
99
114
|
txo_stake.address as "submit_address_stake",
|
|
100
115
|
ENCODE(tx.hash, 'hex') as "submit_tx_hash",
|
|
@@ -151,9 +166,12 @@ COALESCE(
|
|
|
151
166
|
)::jsonb,
|
|
152
167
|
jsonb_build_array(json_build_object('lovelace',txo_output.value::TEXT)::jsonb)
|
|
153
168
|
) AS "assets",
|
|
154
|
-
(
|
|
169
|
+
(
|
|
170
|
+
txo_output.inline_datum_id IS NOT NULL OR txo_output.reference_script_id IS NOT NULL
|
|
171
|
+
) as "plutus_v2"
|
|
155
172
|
"""
|
|
156
173
|
|
|
157
174
|
@classmethod
|
|
158
|
-
def parse(cls, data: dict) -> SwapTransactionList:
|
|
175
|
+
def parse(cls, data: dict | list[dict]) -> SwapTransactionList:
|
|
176
|
+
"""Parse and validate orders."""
|
|
159
177
|
return SwapTransactionList.model_validate(data)
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/__init__.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/backend/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/backend/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/minswap.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/muesli.py
RENAMED
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/sundae.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/amm/vyfi.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/core/base.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/core/errors.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/ob/__init__.py
RENAMED
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/ob/axo.py
RENAMED
|
File without changes
|
|
File without changes
|
{charli3_dendrite-1.0.0.dev1 → charli3_dendrite-1.1.0.dev0}/src/charli3_dendrite/dexs/ob/ob_base.py
RENAMED
|
File without changes
|
|
File without changes
|