Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proper many2many/token2box asset persistence #32

Merged
merged 1 commit into from
Aug 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions modules/backend/src/main/resources/h2-schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ create table if not exists ErgoTreeT8 (

create table if not exists Box (
boxId VARCHAR(64) NOT NULL PRIMARY KEY,
blockId VARCHAR(64) NOT NULL REFERENCES Block (blockId) ON DELETE CASCADE,
txId VARCHAR(64) NOT NULL,
ergoTreeHash VARCHAR(64) NOT NULL REFERENCES ErgoTree (hash),
ergoTreeHash VARCHAR(64) NOT NULL REFERENCES ErgoTree (hash) ON DELETE CASCADE,
ergoTreeT8Hash VARCHAR(64) REFERENCES ErgoTreeT8 (hash),
ergValue BIGINT NOT NULL,
r4 VARCHAR,
Expand All @@ -54,16 +53,19 @@ create table if not exists Box (

create table if not exists Asset (
tokenId VARCHAR(64) NOT NULL PRIMARY KEY,
blockId VARCHAR(64) NOT NULL REFERENCES Block (blockId) ON DELETE CASCADE,
boxId VARCHAR(64) NOT NULL REFERENCES Box (boxId),
blockId VARCHAR(64) NOT NULL REFERENCES Block (blockId) ON DELETE CASCADE
);

create table if not exists Asset2Box (
tokenId VARCHAR(64) NOT NULL REFERENCES Asset (tokenId) ON DELETE CASCADE,
boxId VARCHAR(64) NOT NULL REFERENCES Box (boxId) ON DELETE CASCADE,
amount BIGINT NOT NULL
);

create table if not exists Utxo (
boxId VARCHAR(64) NOT NULL PRIMARY KEY REFERENCES Box (boxId),
blockId VARCHAR(64) NOT NULL REFERENCES Block (blockId) ON DELETE CASCADE,
txId VARCHAR(64) NOT NULL,
ergoTreeHash VARCHAR(64) NOT NULL REFERENCES ErgoTree (hash),
ergoTreeHash VARCHAR(64) NOT NULL REFERENCES ErgoTree (hash) ON DELETE CASCADE,
ergoTreeT8Hash VARCHAR(64) REFERENCES ErgoTreeT8 (hash),
ergValue BIGINT NOT NULL,
r4 VARCHAR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ object H2Backend extends Backend {
Server
.serve((BlockRoutes() ++ BoxRoutes()).withDefaultErrorResponse)
.fork
.provideSomeLayer(Server.defaultWithPort(8080))
.provideSomeLayer(Server.defaultWithPort(8088))

override def isEmpty: Task[Boolean] = ???

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package org.ergoplatform.uexplorer.backend

import io.getquill.*
import io.getquill.context.ZioJdbc.DataSourceLayer
import io.getquill.jdbczio.Quill
import org.ergoplatform.uexplorer.*
import org.ergoplatform.uexplorer.backend.Codecs
import org.ergoplatform.uexplorer.backend.blocks.{BlockRepo, PersistentBlockRepo}
import org.ergoplatform.uexplorer.backend.boxes.{BoxRepo, PersistentBoxRepo}
import org.ergoplatform.uexplorer.backend.blocks.BlockRepo
import org.ergoplatform.uexplorer.backend.boxes.*
import org.ergoplatform.uexplorer.db.*
import zio.*

import java.util.UUID
import javax.sql.DataSource

case class PersistentRepo(ds: DataSource, blockRepo: BlockRepo, boxRepo: BoxRepo) extends Repo with Codecs:
Expand Down Expand Up @@ -43,12 +39,18 @@ case class PersistentRepo(ds: DataSource, blockRepo: BlockRepo, boxRepo: BoxRepo
val ergoTrees = outputs.byErgoTree.keys
val ergoTreeT8s = outputs.byErgoTreeT8.keys
val utxos = outputs.byErgoTree.values.flatten
val assetsToBox =
outputs.tokensByUtxo.flatMap { case (box, amountByToken) =>
amountByToken.map { case (token, amount) => Asset2Box(token, box, amount) }
}

val assets = outputs.utxosByTokenId.keySet.map(tokenId => Asset(tokenId, block.blockId))
ctx
.transaction {
for
_ <- preTx
blockId <- blockRepo.insert(block)
_ <- boxRepo.insertUtxos(ergoTrees, ergoTreeT8s, outputs.assets, utxos)
_ <- boxRepo.insertUtxos(ergoTrees, ergoTreeT8s, assetsToBox, assets, utxos)
_ <- boxRepo.deleteUtxos(inputIds)
_ <- postTx
yield blockId
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
package org.ergoplatform.uexplorer.backend.boxes

import org.ergoplatform.uexplorer.db.*
import org.ergoplatform.uexplorer.{BlockId, BoxId, ErgoTreeHash, ErgoTreeT8Hash, TokenId}
import org.ergoplatform.uexplorer.{BoxId, ErgoTreeHash, ErgoTreeT8Hash, TokenId}
import zio.*

trait BoxRepo:

def insertUtxos(
ergoTrees: Iterable[ErgoTree],
ergoTreeT8s: Iterable[ErgoTreeT8],
assets: List[Asset],
utxos: Iterable[Utxo]
ergoTrees: Iterable[ErgoTree],
ergoTreeT8s: Iterable[ErgoTreeT8],
assetsToBox: Iterable[Asset2Box],
assets: Iterable[Asset],
utxos: Iterable[Utxo]
): Task[Iterable[BoxId]]

def deleteUtxo(boxId: BoxId): Task[Long]

def deleteUtxos(boxId: Iterable[BoxId]): Task[Long]

def lookupUnspentAssetsByTokenId(tokenId: TokenId, columns: List[String], filter: Map[String, Any]): Task[Iterable[Asset]]
def lookupUnspentAssetsByTokenId(tokenId: TokenId, columns: List[String], filter: Map[String, Any]): Task[Iterable[Asset2Box]]

def lookupAnyAssetsByTokenId(tokenId: TokenId, columns: List[String], filter: Map[String, Any]): Task[Iterable[Asset]]
def lookupAnyAssetsByTokenId(tokenId: TokenId, columns: List[String], filter: Map[String, Any]): Task[Iterable[Asset2Box]]

def lookupBox(boxId: BoxId): Task[Option[Box]]

Expand Down Expand Up @@ -51,12 +52,13 @@ trait BoxRepo:

object BoxRepo:
def insertUtxos(
ergoTrees: Iterable[ErgoTree],
ergoTreeT8s: Iterable[ErgoTreeT8],
assets: List[Asset],
utxos: Iterable[Utxo]
ergoTrees: Iterable[ErgoTree],
ergoTreeT8s: Iterable[ErgoTreeT8],
assetsToBox: Iterable[Asset2Box],
assets: Iterable[Asset],
utxos: Iterable[Utxo]
): ZIO[BoxRepo, Throwable, Iterable[BoxId]] =
ZIO.serviceWithZIO[BoxRepo](_.insertUtxos(ergoTrees, ergoTreeT8s, assets, utxos))
ZIO.serviceWithZIO[BoxRepo](_.insertUtxos(ergoTrees, ergoTreeT8s, assetsToBox, assets, utxos))

def deleteUtxo(boxId: BoxId): ZIO[BoxRepo, Throwable, Long] =
ZIO.serviceWithZIO[BoxRepo](_.deleteUtxo(boxId))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.ergoplatform.uexplorer.backend.boxes

import org.ergoplatform.uexplorer.db.{Asset, Box, Utxo}
import org.ergoplatform.uexplorer.db.{Asset, Asset2Box, Box, Utxo}
import org.ergoplatform.uexplorer.parser.ErgoTreeParser
import org.ergoplatform.uexplorer.{Address, BoxId, CoreConf, ErgoTreeHash, ErgoTreeHex, ErgoTreeT8Hash, ErgoTreeT8Hex, TokenId}
import zio.http.QueryParams
Expand All @@ -9,22 +9,22 @@ import zio.{Task, ZIO, ZLayer}
case class BoxService(boxRepo: BoxRepo, coreConf: CoreConf) {
import BoxService.allColumns

def getUnspentAssetsByTokenId(tokenId: String, params: QueryParams): Task[Iterable[Asset]] =
def getUnspentAssetsByTokenId(tokenId: String, params: QueryParams): Task[Iterable[Asset2Box]] =
for
tId <- ZIO.attempt(TokenId.fromStringUnsafe(tokenId))
indexFilter = params.map.view.mapValues(_.head).toMap
assets <- boxRepo.lookupUnspentAssetsByTokenId(tId, allColumns, indexFilter)
yield assets

def getSpentAssetsByTokenId(tokenId: String, params: QueryParams): Task[Iterable[Asset]] =
def getSpentAssetsByTokenId(tokenId: String, params: QueryParams): Task[Iterable[Asset2Box]] =
for
tId <- ZIO.attempt(TokenId.fromStringUnsafe(tokenId))
indexFilter = params.map.view.mapValues(_.head).toMap
utxoIds <- boxRepo.lookupUtxoIdsByTokenId(tId)
assets <- boxRepo.lookupAnyAssetsByTokenId(tId, allColumns, indexFilter)
yield assets.filter(a => !utxoIds.contains(a.boxId))

def getAnyAssetsByTokenId(tokenId: String, params: QueryParams): Task[Iterable[Asset]] =
def getAnyAssetsByTokenId(tokenId: String, params: QueryParams): Task[Iterable[Asset2Box]] =
for
tId <- ZIO.attempt(TokenId.fromStringUnsafe(tokenId))
indexFilter = params.map.view.mapValues(_.head).toMap
Expand Down Expand Up @@ -198,13 +198,13 @@ object BoxService {
def layer: ZLayer[BoxRepo with CoreConf, Nothing, BoxService] =
ZLayer.fromFunction(BoxService.apply _)

def getUnspentAssetsByTokenId(tokenId: String, params: QueryParams): ZIO[BoxService, Throwable, Iterable[Asset]] =
def getUnspentAssetsByTokenId(tokenId: String, params: QueryParams): ZIO[BoxService, Throwable, Iterable[Asset2Box]] =
ZIO.serviceWithZIO[BoxService](_.getUnspentAssetsByTokenId(tokenId, params))

def getSpentAssetsByTokenId(tokenId: String, params: QueryParams): ZIO[BoxService, Throwable, Iterable[Asset]] =
def getSpentAssetsByTokenId(tokenId: String, params: QueryParams): ZIO[BoxService, Throwable, Iterable[Asset2Box]] =
ZIO.serviceWithZIO[BoxService](_.getSpentAssetsByTokenId(tokenId, params))

def getAnyAssetsByTokenId(tokenId: String, params: QueryParams): ZIO[BoxService, Throwable, Iterable[Asset]] =
def getAnyAssetsByTokenId(tokenId: String, params: QueryParams): ZIO[BoxService, Throwable, Iterable[Asset2Box]] =
ZIO.serviceWithZIO[BoxService](_.getAnyAssetsByTokenId(tokenId, params))

def getUnspentBoxesByTokenId(tokenId: String, params: QueryParams): ZIO[BoxService, Throwable, Iterable[Utxo]] =
Expand Down
Loading