Skip to content

Commit

Permalink
Merge pull request #550 from alephium/add-missing-data
Browse files Browse the repository at this point in the history
Add missing data
  • Loading branch information
tdroxler authored Jun 17, 2024
2 parents 9ca73d9 + 32535b1 commit 33a8ff7
Show file tree
Hide file tree
Showing 69 changed files with 1,581 additions and 692 deletions.
416 changes: 377 additions & 39 deletions app/src/main/resources/explorer-backend-openapi.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ trait BlockEndpoints extends BaseEndpoint with QueryParams {
.tag("Blocks")
.in("blocks")

val getBlockByHash: BaseEndpoint[BlockHash, BlockEntryLite] =
val getBlockByHash: BaseEndpoint[BlockHash, BlockEntry] =
blocksEndpoint.get
.in(path[BlockHash]("block_hash"))
.out(jsonBody[BlockEntryLite])
.out(jsonBody[BlockEntry])
.description("Get a block with hash")

val getBlockTransactions: BaseEndpoint[(BlockHash, Pagination), ArraySeq[Transaction]] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ object EndpointExamples extends EndpointsExamples {
.from(Hex.unsafe("bdaf9dc514ce7d34b6474b8ca10a3dfb93ba997cb9d5ff1ea724ebe2af48abe5"))
.get

val version: Byte = 1
val networkId: Byte = 0

private val outputRef: OutputRef =
OutputRef(hint = 23412, key = hash)

Expand All @@ -66,6 +69,8 @@ object EndpointExamples extends EndpointsExamples {
contract
)

private val addressAsset: Address.Asset = Address.asset(address1.toBase58).get

private val groupIndex1: GroupIndex = new GroupIndex(1)
private val groupIndex2: GroupIndex = new GroupIndex(2)

Expand All @@ -84,7 +89,8 @@ object EndpointExamples extends EndpointsExamples {
txHashRef = Some(txId),
address = Some(address1),
attoAlphAmount = Some(U256.Two),
tokens = Some(tokens)
tokens = Some(tokens),
contractInput = false
)

private val outputAsset: AssetOutput =
Expand All @@ -95,7 +101,8 @@ object EndpointExamples extends EndpointsExamples {
address = address1,
tokens = Some(tokens),
lockTime = Some(ts),
message = Some(hash.bytes)
message = Some(hash.bytes),
fixedOutput = true
)

private val outputContract: Output =
Expand All @@ -104,7 +111,8 @@ object EndpointExamples extends EndpointsExamples {
key = hash,
attoAlphAmount = U256.Two,
address = address1,
tokens = Some(tokens)
tokens = Some(tokens),
fixedOutput = false
)

/** Main API objects
Expand All @@ -121,16 +129,41 @@ object EndpointExamples extends EndpointsExamples {
hashRate = HashRate.a128EhPerSecond.value
)

private val blockEntry: BlockEntry =
BlockEntry(
hash = blockHash,
timestamp = ts,
chainFrom = groupIndex1,
chainTo = groupIndex2,
height = Height.unsafe(42),
deps = ArraySeq(blockHash),
nonce = hash.bytes,
version = 1,
depStateHash = hash,
txsHash = hash,
txNumber = 1,
target = hash.bytes,
hashRate = HashRate.a128EhPerSecond.value,
parent = Some(blockHash),
mainChain = true,
ghostUncles = ArraySeq(GhostUncle(blockHash, addressAsset))
)

private val transaction: Transaction =
Transaction(
hash = txId,
blockHash = blockHash,
timestamp = ts,
inputs = ArraySeq(input),
outputs = ArraySeq(outputAsset, outputContract),
version = version,
networkId = networkId,
scriptOpt = None,
gasAmount = org.alephium.protocol.model.minimalGas.value,
gasPrice = org.alephium.protocol.model.nonCoinbaseMinGasPrice.value,
scriptExecutionOk = true,
inputSignatures = ArraySeq(hash.bytes),
scriptSignatures = ArraySeq(hash.bytes),
coinbase = false
)

Expand All @@ -141,9 +174,14 @@ object EndpointExamples extends EndpointsExamples {
timestamp = ts,
inputs = ArraySeq(input),
outputs = ArraySeq(outputAsset, outputContract),
version = version,
networkId = networkId,
scriptOpt = None,
gasAmount = org.alephium.protocol.model.minimalGas.value,
gasPrice = org.alephium.protocol.model.nonCoinbaseMinGasPrice.value,
scriptExecutionOk = true,
inputSignatures = ArraySeq(hash.bytes),
scriptSignatures = ArraySeq(hash.bytes),
coinbase = false
)

Expand Down Expand Up @@ -313,6 +351,9 @@ object EndpointExamples extends EndpointsExamples {
implicit val blockEntryLiteExample: List[Example[BlockEntryLite]] =
simpleExample(blockEntryLite)

implicit val blockEntryExample: List[Example[BlockEntry]] =
simpleExample(blockEntry)

implicit val transactionsExample: List[Example[ArraySeq[Transaction]]] =
simpleExample(ArraySeq(transaction, transaction))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ import java.math.BigInteger

import scala.collection.immutable.ArraySeq

import akka.util.ByteString

import org.alephium.api.UtilJson._
import org.alephium.explorer.api.Codecs._
import org.alephium.explorer.api.Json.groupIndexReadWriter
import org.alephium.explorer.service.FlowEntity
import org.alephium.json.Json._
import org.alephium.protocol.Hash
import org.alephium.protocol.model.{BlockHash, GroupIndex}
import org.alephium.util.TimeStamp
import org.alephium.util.{AVector, TimeStamp}

final case class BlockEntry(
hash: BlockHash,
Expand All @@ -35,10 +38,39 @@ final case class BlockEntry(
chainTo: GroupIndex,
height: Height,
deps: ArraySeq[BlockHash],
transactions: ArraySeq[Transaction],
nonce: ByteString,
version: Byte,
depStateHash: Hash,
txsHash: Hash,
txNumber: Int,
target: ByteString,
hashRate: BigInteger,
parent: Option[BlockHash],
mainChain: Boolean,
hashRate: BigInteger
) extends FlowEntity
ghostUncles: ArraySeq[GhostUncle]
) extends FlowEntity {

def toProtocol(
transactions: ArraySeq[Transaction]
): org.alephium.api.model.BlockEntry = {
org.alephium.api.model.BlockEntry(
hash,
timestamp,
chainFrom.value,
chainTo.value,
height.value,
AVector.from(deps),
AVector.from(transactions.map(_.toProtocol())),
nonce,
version,
depStateHash,
txsHash,
target,
AVector.from(ghostUncles.map(_.toProtocol()))
)
}

}

object BlockEntry {
implicit val codec: ReadWriter[BlockEntry] = macroRW
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,17 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the library. If not, see <http://www.gnu.org/licenses/>.

package org.alephium.explorer.persistence.model
package org.alephium.explorer.api.model

import org.alephium.protocol.model.BlockHash
import org.alephium.api.model.GhostUncleBlockEntry
import org.alephium.explorer.api.Codecs._
import org.alephium.json.Json._
import org.alephium.protocol.model.{Address, BlockHash}

/** Class for defining rows in table [[org.alephium.explorer.persistence.schema.BlockDepsSchema]]
*/
final case class BlockDepEntity(hash: BlockHash, dep: BlockHash, order: Int)
final case class GhostUncle(blockHash: BlockHash, miner: Address.Asset) {
def toProtocol(): GhostUncleBlockEntry = GhostUncleBlockEntry(blockHash, miner)
}

object GhostUncle {
implicit val codec: ReadWriter[GhostUncle] = macroRW
}
12 changes: 10 additions & 2 deletions app/src/main/scala/org/alephium/explorer/api/model/Input.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import scala.collection.immutable.ArraySeq
import akka.util.ByteString
import sttp.tapir.Schema

import org.alephium.api.{model => protocol}
import org.alephium.api.TapirSchemas._
import org.alephium.api.UtilJson._
import org.alephium.explorer.api.Json._
Expand All @@ -35,8 +36,15 @@ final case class Input(
txHashRef: Option[TransactionId] = None,
address: Option[Address] = None,
attoAlphAmount: Option[U256] = None,
tokens: Option[ArraySeq[Token]] = None
)
tokens: Option[ArraySeq[Token]] = None,
contractInput: Boolean
) {
def toProtocol(): protocol.AssetInput =
protocol.AssetInput(
outputRef = outputRef.toProtocol(),
unlockScript = unlockScript.getOrElse(ByteString.empty)
)
}

object Input {
implicit val readWriter: ReadWriter[Input] = macroRW
Expand Down
67 changes: 64 additions & 3 deletions app/src/main/scala/org/alephium/explorer/api/model/Output.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import org.alephium.json.Json._
import org.alephium.protocol.Hash
import org.alephium.protocol.model.{Address, TransactionId}
import org.alephium.util.{TimeStamp, U256}
import org.alephium.util.AVector

sealed trait Output {
def hint: Int
Expand All @@ -37,6 +38,7 @@ sealed trait Output {
def address: Address
def tokens: Option[ArraySeq[Token]]
def spent: Option[TransactionId]
def fixedOutput: Boolean
}

@SuppressWarnings(Array("org.wartremover.warts.DefaultArguments"))
Expand All @@ -49,8 +51,9 @@ final case class AssetOutput(
tokens: Option[ArraySeq[Token]] = None,
lockTime: Option[TimeStamp] = None,
message: Option[ByteString] = None,
spent: Option[TransactionId] = None
) extends Output
spent: Option[TransactionId] = None,
fixedOutput: Boolean
) extends Output {}

@SuppressWarnings(Array("org.wartremover.warts.DefaultArguments"))
@upickle.implicits.key("ContractOutput")
Expand All @@ -60,11 +63,69 @@ final case class ContractOutput(
attoAlphAmount: U256,
address: Address,
tokens: Option[ArraySeq[Token]] = None,
spent: Option[TransactionId] = None
spent: Option[TransactionId] = None,
fixedOutput: Boolean
) extends Output

object Output {

def toFixedAssetOutput(
output: Output
): Option[org.alephium.api.model.FixedAssetOutput] = {
output match {
case asset: AssetOutput if asset.fixedOutput =>
asset.address match {
case assetAddress: Address.Asset =>
val amount = org.alephium.api.model.Amount(asset.attoAlphAmount)
Some(
org.alephium.api.model.FixedAssetOutput(
asset.hint,
asset.key,
amount,
assetAddress,
tokens = asset.tokens
.map(tokens => AVector.from(tokens.map(_.toProtocol())))
.getOrElse(AVector.empty),
lockTime = asset.lockTime.getOrElse(TimeStamp.zero),
asset.message.getOrElse(ByteString.empty)
)
)
case _ => None
}
case _ => None
}
}

def toProtocol(output: Output): Option[org.alephium.api.model.Output] =
(output, output.address) match {
case (asset: AssetOutput, assetAddress: Address.Asset) =>
Some(
org.alephium.api.model.AssetOutput(
output.hint,
output.key,
org.alephium.api.model.Amount(output.attoAlphAmount),
assetAddress,
tokens =
output.tokens.map(t => AVector.from(t.map(_.toProtocol()))).getOrElse(AVector.empty),
lockTime = asset.lockTime.getOrElse(TimeStamp.zero),
message = asset.message.getOrElse(ByteString.empty)
)
)
case (_: ContractOutput, contractAddress: Address.Contract) =>
Some(
org.alephium.api.model.ContractOutput(
output.hint,
output.key,
org.alephium.api.model.Amount(output.attoAlphAmount),
contractAddress,
tokens = output.tokens
.map(tokens => AVector.from(tokens.map(_.toProtocol())))
.getOrElse(AVector.empty)
)
)
case _ => None
}

implicit val assetReadWriter: ReadWriter[AssetOutput] = macroRW
implicit val contractReadWriter: ReadWriter[ContractOutput] = macroRW

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ import org.alephium.explorer.api.Json._
import org.alephium.json.Json._
import org.alephium.protocol.Hash

final case class OutputRef(hint: Int, key: Hash)
final case class OutputRef(hint: Int, key: Hash) {

def toProtocol(): org.alephium.api.model.OutputRef =
org.alephium.api.model.OutputRef(hint, key)
}

object OutputRef {
implicit val readWriter: ReadWriter[OutputRef] = macroRW
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ import org.alephium.protocol.model.TokenId
import org.alephium.serde._
import org.alephium.util.U256

final case class Token(id: TokenId, amount: U256)
final case class Token(id: TokenId, amount: U256) {
def toProtocol(): org.alephium.api.model.Token = org.alephium.api.model.Token(id, amount)
}

object Token {
implicit val readWriter: ReadWriter[Token] = macroRW
Expand Down
Loading

0 comments on commit 33a8ff7

Please sign in to comment.