mirror of
https://github.com/fluencelabs/cosmos-hackathon-backend
synced 2025-03-14 19:40:51 +00:00
add README & mock validators count
This commit is contained in:
parent
d4d2e0f985
commit
a9c1a5ea53
57
README.md
57
README.md
@ -1 +1,56 @@
|
|||||||
# cosmos-hackathon-backend
|
# Shared Security for Cosmos Zones
|
||||||
|

|
||||||
|
|
||||||
|
- Backend here
|
||||||
|
- Frontend [there](https://github.com/fluencelabs/cosmos-hackathon-frontend)
|
||||||
|
|
||||||
|
## If you want your Zone to be validated by Cosmic Salmon, reach out to @folexeyy on Telegram
|
||||||
|
|
||||||
|
# How to run
|
||||||
|
```bash
|
||||||
|
sbt assembly
|
||||||
|
java -jar ./target/scala-2.12/http-scala-api-assembly-0.1.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
# API
|
||||||
|
### Retreieve running apps
|
||||||
|
```bash
|
||||||
|
curl http://salmon.fluence.one:8080/apps
|
||||||
|
```
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name" : "nameservice",
|
||||||
|
"network" : "namechain",
|
||||||
|
"binaryHash" : "QmQ69JoPDaKFpPSbWvvUGRGG5E83u6nTP2hRegmCoa6aW5",
|
||||||
|
"consensusHeight" : 69386,
|
||||||
|
"validatorsCount" : 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name" : "commercionetwork",
|
||||||
|
"network" : "commercio-testnet1001",
|
||||||
|
"binaryHash" : "QmepV645qHM9XR97KiK7Bvd2jjK3MiKTGbq8cYm7izRyQK",
|
||||||
|
"consensusHeight" : 38783,
|
||||||
|
"validatorsCount" : 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
### Add your app on validation
|
||||||
|
- `nameservice` - any name for your app
|
||||||
|
- `207.154.210.117` - IP address of your validator node
|
||||||
|
- `26657` - RPC port
|
||||||
|
- `QmQ69JoPDaKFpPSbWvvUGRGG5E83u6nTP2hRegmCoa6aW5` - IPFS hash of the Zone app binary (built against glibc)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://salmon.fluence.one:8080/create/nameservice/207.154.210.117/26657/QmQ69JoPDaKFpPSbWvvUGRGG5E83u6nTP2hRegmCoa6aW5"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stream validation results through websocket
|
||||||
|
JavaScript
|
||||||
|
|
||||||
|
```js
|
||||||
|
var ws = new WebSocket("ws://localhost:8080/websocket/commercionetwork")
|
||||||
|
ws.onmessage = console.log
|
||||||
|
```
|
||||||
|
|
||||||
|
For shell, use [websocat](https://github.com/vi/websocat).
|
BIN
img/salmon.png
Normal file
BIN
img/salmon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 159 KiB |
@ -9,6 +9,7 @@ import cats.effect._
|
|||||||
import cats.effect.concurrent.{Deferred, Ref, TryableDeferred}
|
import cats.effect.concurrent.{Deferred, Ref, TryableDeferred}
|
||||||
import cats.instances.list._
|
import cats.instances.list._
|
||||||
import cats.instances.option._
|
import cats.instances.option._
|
||||||
|
import cats.instances.either._
|
||||||
import cats.syntax.applicative._
|
import cats.syntax.applicative._
|
||||||
import cats.syntax.applicativeError._
|
import cats.syntax.applicativeError._
|
||||||
import cats.syntax.either._
|
import cats.syntax.either._
|
||||||
@ -17,7 +18,7 @@ import cats.syntax.functor._
|
|||||||
import cats.syntax.option._
|
import cats.syntax.option._
|
||||||
import cats.{Monad, Traverse}
|
import cats.{Monad, Traverse}
|
||||||
import com.softwaremill.sttp.{SttpBackend, Uri, sttp}
|
import com.softwaremill.sttp.{SttpBackend, Uri, sttp}
|
||||||
import hackhack.ipfs.{IpfsError, IpfsStore}
|
import hackhack.ipfs.{IpfsError, IpfsStore, Multihash}
|
||||||
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
|
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
|
||||||
import io.circe.parser.parse
|
import io.circe.parser.parse
|
||||||
import io.circe.{Decoder, Encoder, Json, ObjectEncoder}
|
import io.circe.{Decoder, Encoder, Json, ObjectEncoder}
|
||||||
@ -54,8 +55,9 @@ object App {
|
|||||||
|
|
||||||
case class AppInfo(name: String,
|
case class AppInfo(name: String,
|
||||||
network: String,
|
network: String,
|
||||||
binaryHash: ByteVector,
|
binaryHash: String,
|
||||||
consensusHeight: Long)
|
consensusHeight: Long,
|
||||||
|
validatorsCount: Int)
|
||||||
|
|
||||||
object AppInfo {
|
object AppInfo {
|
||||||
private implicit val encbc: Encoder[ByteVector] =
|
private implicit val encbc: Encoder[ByteVector] =
|
||||||
@ -180,8 +182,9 @@ class AppRegistry[F[_]: Monad: Concurrent: ContextShift: Timer: LiftIO](
|
|||||||
case (app, status) =>
|
case (app, status) =>
|
||||||
AppInfo(app.name,
|
AppInfo(app.name,
|
||||||
status.node_info.network,
|
status.node_info.network,
|
||||||
app.binaryHash,
|
Multihash.asBase58(app.binaryHash),
|
||||||
status.sync_info.latest_block_height)
|
status.sync_info.latest_block_height,
|
||||||
|
4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,19 +50,21 @@ object ResponseOps {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Multihash {
|
||||||
|
// https://github.com/multiformats/multicodec/blob/master/table.csv
|
||||||
|
val SHA256 = ByteVector(0x12, 32) // 0x12 => SHA256; 32 = 256 bits in bytes
|
||||||
|
def asBase58(hash: ByteVector): String = (SHA256 ++ hash).toBase58
|
||||||
|
}
|
||||||
|
|
||||||
class IpfsClient[F[_]: Monad](ipfsUri: Uri)(
|
class IpfsClient[F[_]: Monad](ipfsUri: Uri)(
|
||||||
implicit sttpBackend: SttpBackend[EitherT[F, Throwable, ?], fs2.Stream[F, ByteBuffer]]
|
implicit sttpBackend: SttpBackend[EitherT[F, Throwable, ?],
|
||||||
|
fs2.Stream[F, ByteBuffer]]
|
||||||
) {
|
) {
|
||||||
|
|
||||||
import IpfsClient._
|
import IpfsClient._
|
||||||
import IpfsLsResponse._
|
import IpfsLsResponse._
|
||||||
import ResponseOps._
|
import ResponseOps._
|
||||||
|
|
||||||
object Multihash {
|
|
||||||
// https://github.com/multiformats/multicodec/blob/master/table.csv
|
|
||||||
val SHA256 = ByteVector(0x12, 32) // 0x12 => SHA256; 32 = 256 bits in bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
// URI for downloading data
|
// URI for downloading data
|
||||||
private val CatUri = ipfsUri.path("/api/v0/cat")
|
private val CatUri = ipfsUri.path("/api/v0/cat")
|
||||||
|
|
||||||
@ -80,12 +82,13 @@ class IpfsClient[F[_]: Monad](ipfsUri: Uri)(
|
|||||||
ByteVector.fromBase58Descriptive(str).map(_.drop(2))
|
ByteVector.fromBase58Descriptive(str).map(_.drop(2))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads data from IPFS.
|
* Downloads data from IPFS.
|
||||||
*
|
*
|
||||||
* @param hash data address in IPFS
|
* @param hash data address in IPFS
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
def download(hash: ByteVector): EitherT[F, Throwable, fs2.Stream[F, ByteBuffer]] = {
|
def download(
|
||||||
|
hash: ByteVector): EitherT[F, Throwable, fs2.Stream[F, ByteBuffer]] = {
|
||||||
// implicit val wtf = sttpBackend
|
// implicit val wtf = sttpBackend
|
||||||
val address = toAddress(hash)
|
val address = toAddress(hash)
|
||||||
val uri = CatUri.param("arg", address)
|
val uri = CatUri.param("arg", address)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user