Skip to content

Commit

Permalink
feat(io): introduce domain program (#10)
Browse files Browse the repository at this point in the history
* feat(io): intorduce domain program

* feat(domain): introduce package domain

* feat(router): create domain

* feat(program): create domain via router

* feat(router): add labels

* feat(domain): search domains

* feat(domain): create state wasm for domain

* chore(clippy): make clippy happy

* chore(README): update readme
  • Loading branch information
clearloop authored Feb 22, 2024
1 parent 84d6a89 commit b111971
Show file tree
Hide file tree
Showing 14 changed files with 314 additions and 157 deletions.
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ tokio.workspace = true
# It's necessary to include all metawasm crates in the workspace section, otherwise they'll be
# ignored by Cargo and won't be built.
[workspace]
members = ["state", "xtask"]
members = ["state", "xtask", "domain", "domain/state"]

[workspace.dependencies]
gstd = "1.1.1"
Expand Down
54 changes: 14 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,21 @@
[![Open in Gitpod](https://img.shields.io/badge/Open_in-Gitpod-white?logo=gitpod)](https://gitpod.io/#https://github.com/gear-foundation/dapps)
[![CI](https://img.shields.io/github/actions/workflow/status/gear-foundation/dapps/contracts.yml?logo=github&label=CI)](https://github.com/gear-foundation/dapp-template/actions/workflows/ci.yml)
## Deployment

# Gear Template Contract
1. Deploy the code of [program domain](./domain)
2. Deploy the code of [program identity](https://github.com/breathx/demo-identity)
3. Deploy [program router](./)

<!-- Description starts here -->
## Interfaces

A template application. Use this repository as a template when creating a new application repository.
### Write

> https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template
> all write methods are gathered in [program router](./)
<!-- End of the description -->
1. create/update domain
2. add labels for domain
3. create identity
4. update identity

## Initial checklist after creating a new repository
### Read

- [ ] Change the app name in `Cargo.toml`.
- [ ] Fix badges' links in `README.md` (replace `gear-foundation/dapp-template` with `<your_username>/<your_new_app>`).
- [ ] Replace a description in `README.md`.
- [ ] Remove this section.
### 🏗️ Building

```sh
cargo b --workspace
```

### ✅ Testing

Run all tests, except `gclient` ones:
```sh
cargo t --workspace -- --skip gclient
```

Run all tests:
```sh
# Download the node binary.
cargo xtask node
cargo t --workspace
```

### 🚀 Run CI locally (should be done before a commit)
```sh
cargo xtask ci
```

# License

The source code is licensed under the [MIT license](LICENSE).
1. search domains ( [program-router](./state) )
2. read data source of domain ( [program-domain](./domain/state) )
9 changes: 9 additions & 0 deletions domain/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "demo-domain"
version.workspace = true
edition.workspace = true
publish.workspace = true

[dependencies]
gstd.workspace = true
template-io.workspace = true
42 changes: 42 additions & 0 deletions domain/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#![no_std]

use gstd::{msg, prelude::*, ActorId};
use template_io::*;

/// Admin of this domain.
static mut ADMIN: ActorId = ActorId::zero();

/// The resource of the domain.
static mut STATE: Option<Source> = None;

// The `init()` entry point.
#[no_mangle]
extern fn init() {
unsafe { ADMIN = msg::source() }
unsafe { STATE = None }

// TODO:
//
// register domain to the router.
//
// let domain = msg::load::<String>().expect("Invalid payload");
}

// The `handle()` entry point.
#[no_mangle]
extern fn handle() {
let source = msg::load::<Source>().expect("Invalid payload");
let state = unsafe { STATE.as_mut().expect("State isn't initialized") };
*state = source;

// TODO:
//
// register labels to the router
}

// The `state()` entry point.
#[no_mangle]
extern fn state() {
let state = unsafe { STATE.take().expect("State isn't initialized") };
msg::reply(state, 0).expect("Failed to reply from `state()`");
}
13 changes: 13 additions & 0 deletions domain/state/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "demo-domain-state"
version.workspace = true
edition.workspace = true
publish.workspace = true

[dependencies]
gstd.workspace = true
gmeta = { workspace = true, features = ["codegen"] }
template-io.workspace = true

[build-dependencies]
gear-wasm-builder = { workspace = true, features = ["metawasm"] }
3 changes: 3 additions & 0 deletions domain/state/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
gear_wasm_builder::build_metawasm();
}
14 changes: 14 additions & 0 deletions domain/state/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#![no_std]

use gstd::prelude::*;

#[gmeta::metawasm]
pub mod metafns {

pub type State = template_io::Source;

/// Returns all domains (pages) that matches the search input.
pub fn resource(state: State) -> template_io::Source {
state
}
}
11 changes: 0 additions & 11 deletions io/src/handler.rs

This file was deleted.

13 changes: 6 additions & 7 deletions io/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#![no_std]

use gmeta::{In, Metadata, Out};
pub use router::{Command, InitInput, Router};
pub use source::{Footer, Header, Source, State};

mod handler;
mod router;
mod source;

pub use handler::HandleInput;
pub use source::{Content, Footer, Header, Profile, Source, State};

/// The contract metadata. Used by frontend apps & for describing the types of messages that can be
/// sent in contract's entry points. See also [`Metadata`].
pub struct ContractMetadata;
Expand All @@ -16,9 +15,9 @@ pub struct ContractMetadata;
/// doesn't implement it.
impl Metadata for ContractMetadata {
/// I/O types for the `init()` entry point.
type Init = ();
type Init = In<InitInput>;
/// I/O types for the `handle()` entry point.
type Handle = In<HandleInput>;
type Handle = In<Command>;
/// Types for miscellaneous scenarios.
type Others = ();
/// The input type for the `handle_reply()` entry point.
Expand All @@ -29,5 +28,5 @@ impl Metadata for ContractMetadata {
///
/// You can also specify just an output ([`Out`]) or input ([`In`]) type, if both
/// ([`In`]) are expected like here.
type State = Out<State>;
type State = Out<Router>;
}
117 changes: 117 additions & 0 deletions io/src/router.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
//! Types for the router
use crate::Source;
use gstd::{collections::BTreeMap, ActorId, CodeId, Decode, Encode, String, TypeInfo, Vec};

/// The init input for the router program.
#[derive(Encode, Decode, TypeInfo, PartialEq, Eq, Debug, Clone)]
#[codec(crate = gstd::codec)]
#[scale_info(crate = gstd::scale_info)]
pub struct InitInput {
/// The code id of the identity program.
pub identity: CodeId,

/// The code id of the domain program.
pub domain: CodeId,
}

/// Avaiable commands for the router program.
#[derive(Encode, Decode, TypeInfo, PartialEq, Eq, Debug, Clone)]
#[codec(crate = gstd::codec)]
#[scale_info(crate = gstd::scale_info)]
pub enum Command {
CreateDomain(CommandCreateDomain),
AddLabels(CommandAddLabels),
// TODO:
//
// CreateIdentity,
}

/// The command to create a new domain.
#[derive(Encode, Decode, TypeInfo, PartialEq, Eq, Debug, Clone)]
#[codec(crate = gstd::codec)]
#[scale_info(crate = gstd::scale_info)]
pub struct CommandCreateDomain {
/// The domain name.
pub domain: String,
/// The source of the domain.
pub source: Source,
}

/// Add labels for domain
#[derive(Encode, Decode, TypeInfo, PartialEq, Eq, Debug, Clone)]
#[codec(crate = gstd::codec)]
#[scale_info(crate = gstd::scale_info)]
pub struct CommandAddLabels {
/// The domain to add labels.
pub domain: String,
/// labels of the domain.
pub labels: Vec<Label>,
}

// TODO:
//
// /// The command to create a new domain.
// pub struct CommandCreateIdentity {
//
// }

/// Available labels
#[derive(Encode, Decode, TypeInfo, PartialEq, Eq, Debug, Clone)]
#[codec(crate = gstd::codec)]
#[scale_info(crate = gstd::scale_info)]
pub enum Label {
Vara,
Football,
Profile,
}

impl AsRef<str> for Label {
fn as_ref(&self) -> &str {
match self {
Label::Vara => "vara",
Label::Football => "football",
Label::Profile => "profile",
}
}
}

/// Metadata of domain.
#[derive(Encode, Decode, TypeInfo, PartialEq, Eq, Debug, Clone)]
#[codec(crate = gstd::codec)]
#[scale_info(crate = gstd::scale_info)]
pub struct DomainMeta {
pub labels: Vec<Label>,
pub pid: ActorId,
}

impl DomainMeta {
pub fn labels(&self) -> Vec<&str> {
self.labels.iter().map(|l| l.as_ref()).collect()
}
}

/// Router state
#[derive(Encode, Decode, TypeInfo, PartialEq, Eq, Debug, Clone)]
#[codec(crate = gstd::codec)]
#[scale_info(crate = gstd::scale_info)]
pub struct Router(pub BTreeMap<String, DomainMeta>);

impl Router {
/// Create a dummy domain
pub fn create_domain(&mut self, domain: String, pid: ActorId) {
self.0.insert(
domain,
DomainMeta {
pid,
labels: Default::default(),
},
);
}

/// Add labels to a domain.
pub fn add_labels(&mut self, domain: String, labels: Vec<Label>) {
let meta = self.0.get_mut(&domain).expect("Domain not found");
meta.labels.extend(labels);
}
}
Loading

0 comments on commit b111971

Please sign in to comment.