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

feat(io): introduce domain program #10

Merged
merged 9 commits into from
Feb 22, 2024
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
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
Loading