Skip to content

Commit e105bba

Browse files
authored
Update README.md
1 parent 03f16d9 commit e105bba

File tree

1 file changed

+196
-105
lines changed

1 file changed

+196
-105
lines changed

README.md

Lines changed: 196 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -36,112 +36,203 @@ The `contracts` directory, each Rust Wasm library is added. Use the existing di
3636
Code example
3737

3838
```rust
39+
use crate::sdk::focused_transform_patch_str;
40+
use crate::sdk::read_dag;
41+
use crate::sdk::submit_proof;
42+
use crate::sdk::{generate_proof, get_proof, read_dag_block, write_dag_block};
43+
use juniper::FieldResult;
3944

40-
// Enclosed with allow(unused) to enable WasmEdge and wasm_bindgen bindings
41-
#![allow(unused)]
42-
fn main() {
43-
use base64::*;
44-
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
45-
use hex::{FromHex, ToHex};
46-
47-
// We are using Juniper as Graphql API
48-
use juniper::{
49-
graphql_object, EmptyMutation, EmptySubscription, FieldError, GraphQLEnum, RootNode,
50-
Variables,
51-
};
52-
use serde_hex::utils::fromhex;
53-
use std::convert::TryInto;
54-
use std::fmt::Display;
55-
use std::io::Cursor;
56-
use std::str;
57-
use wasm_bindgen::prelude::*;
58-
59-
#[derive(Clone, Copy, Debug)]
60-
struct Context;
61-
impl juniper::Context for Context {}
62-
63-
#[derive(Clone, Copy, Debug, GraphQLEnum)]
64-
enum UserKind {
65-
Admin,
66-
User,
67-
Guest,
68-
}
69-
70-
#[derive(Clone, Debug)]
71-
struct User {
72-
id: i32,
73-
kind: UserKind,
74-
name: String,
75-
}
76-
77-
#[graphql_object(context = Context)]
78-
impl User {
79-
fn id(&self) -> i32 {
80-
self.id
81-
}
82-
83-
fn kind(&self) -> UserKind {
84-
self.kind
85-
}
86-
87-
fn name(&self) -> &str {
88-
&self.name
89-
}
90-
91-
async fn friends(&self) -> Vec<User> {
92-
vec![]
93-
}
94-
}
95-
96-
#[derive(Clone, Copy, Debug)]
97-
struct Query;
98-
99-
#[graphql_object(context = Context)]
100-
impl Query {
101-
async fn users() -> Vec<User> {
102-
vec![User {
103-
id: 1,
104-
kind: UserKind::Admin,
105-
name: "user1".into(),
106-
}]
107-
}
108-
109-
// WIP: Fetch from host function or instance
110-
async fn request(cid: String) -> Result<String, FieldError> {
111-
Ok(ancon::dag::get(&cid).await?.text().await?)
112-
}
113-
}
114-
115-
type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;
116-
117-
fn schema() -> Schema {
118-
Schema::new(
119-
Query,
120-
EmptyMutation::<Context>::new(),
121-
EmptySubscription::<Context>::new(),
122-
)
123-
}
124-
125-
126-
#[wasm_bindgen]
127-
pub fn execute(query: &str) -> JsFuture<Vec<String>> {
128-
// Create a context object.
129-
let ctx = Context;
130-
131-
let m = EmptyMutation::new();
132-
let s = EmptySubscription::new();
133-
134-
let v = Variables::new();
135-
136-
let sch = Schema::new(Query, m, s);
137-
// Run the executor.
138-
let res = juniper::execute(
139-
query, // "query { favoriteEpisode }",
140-
None, &sch, &v, &ctx,
141-
);
142-
res
143-
// Ensure the value matches.
45+
extern crate juniper;
46+
47+
use juniper::{
48+
graphql_object, EmptyMutation, EmptySubscription, FieldError, GraphQLEnum, GraphQLValue,
49+
RootNode, Variables,
50+
};
51+
use serde::{Deserialize, Serialize};
52+
use serde_json::json;
53+
54+
use std::collections::HashMap;
55+
56+
use std::str;
57+
use std::vec::*;
58+
59+
pub struct Context {
60+
pub metadata: HashMap<String, Ancon721Metadata>,
61+
pub transfer: HashMap<String, MetadataPacket>,
62+
}
63+
64+
impl juniper::Context for Context {}
65+
66+
#[derive(Clone, Debug, Serialize, Deserialize)]
67+
pub struct MetadataPacket {
68+
pub cid: String,
69+
pub from_owner: String,
70+
pub result_cid: String,
71+
pub to_owner: String,
72+
pub to_address: String,
73+
pub token_id: String,
74+
pub proof: String,
75+
}
76+
77+
#[graphql_object(context = Context)]
78+
impl MetadataPacket {
79+
fn cid(&self) -> &str {
80+
&self.cid
81+
}
82+
83+
fn from_owner(&self) -> &str {
84+
&self.from_owner
85+
}
86+
87+
fn result_cid(&self) -> &str {
88+
&self.result_cid
89+
}
90+
fn to_owner(&self) -> &str {
91+
&self.to_owner
14492
}
93+
94+
fn to_address(&self) -> &str {
95+
&self.to_address
96+
}
97+
98+
fn token_id(&self) -> &str {
99+
&self.token_id
100+
}
101+
fn proof(&self) -> &str {
102+
&self.proof
103+
}
104+
}
105+
106+
#[derive(Clone, Debug, Serialize, Deserialize)]
107+
pub struct Ancon721Metadata {
108+
pub name: String,
109+
pub description: String,
110+
pub image: String,
111+
pub parent: String,
112+
pub owner: String,
113+
pub sources: Vec<String>,
145114
}
146115

147-
```
116+
#[graphql_object(context = Context)]
117+
impl Ancon721Metadata {
118+
fn name(&self) -> &str {
119+
&self.name
120+
}
121+
122+
fn description(&self) -> &str {
123+
&self.description
124+
}
125+
126+
fn image(&self) -> &str {
127+
&self.image
128+
}
129+
fn parent(&self) -> &str {
130+
&self.parent
131+
}
132+
133+
fn owner(&self) -> &str {
134+
&self.owner
135+
}
136+
137+
async fn sources(&self) -> &Vec<String> {
138+
&self.sources
139+
}
140+
}
141+
142+
// pub struct Subscription;
143+
144+
// type StringStream = Pin<Box<dyn Stream<Item = Result<String, FieldError>> + Send>>;
145+
146+
// #[graphql_subscription(context = Database)]
147+
// impl Subscription {
148+
// async fn hello_world() -> StringStream {
149+
// let stream =
150+
// futures::stream::iter(vec![Ok(String::from("Hello")), Ok(String::from("World!"))]);
151+
// Box::pin(stream)
152+
// }
153+
// }
154+
#[derive(Clone, Copy, Debug)]
155+
pub struct Query;
156+
157+
#[graphql_object(context = Context)]
158+
impl Query {
159+
fn api_version() -> &'static str {
160+
"0.1"
161+
}
162+
163+
pub fn metadata(context: &Context, cid: String, path: String) -> Ancon721Metadata {
164+
let v = read_dag(&cid);
165+
let res = serde_json::from_slice(&v);
166+
res.unwrap()
167+
}
168+
}
169+
170+
#[derive(Clone, Copy, Debug)]
171+
pub struct Mutation;
172+
173+
#[graphql_object(context = Context)]
174+
impl Mutation {
175+
//Dagblock mutation
176+
fn transfer(context: &Context, input: MetadataTransactionInput) -> Vec<MetadataPacket> {
177+
let v = read_dag(&input.cid);
178+
let res = serde_json::from_slice(&v);
179+
let metadata: Ancon721Metadata = res.unwrap();
180+
181+
//generate current metadata proof packet
182+
let proof = generate_proof(&input.cid);
183+
184+
let updated_cid =
185+
focused_transform_patch_str(&input.cid, "owner", &metadata.owner, &input.new_owner);
186+
let updated =
187+
focused_transform_patch_str(&updated_cid, "parent", &metadata.parent, &input.cid);
188+
189+
//generate updated metadata proof packet
190+
let proof_cid = apply_request_with_proof(input.clone(), &proof, &updated);
191+
let v = read_dag(&proof_cid);
192+
let res = serde_json::from_slice(&v);
193+
let packet: MetadataPacket = res.unwrap();
194+
let current_packet = MetadataPacket {
195+
cid: input.cid,
196+
from_owner: input.owner,
197+
result_cid: updated,
198+
to_address: "".to_string(),
199+
to_owner: input.new_owner,
200+
token_id: "".to_string(),
201+
proof: proof,
202+
};
203+
let result = vec![current_packet, packet];
204+
result
205+
}
206+
}
207+
208+
#[derive(Clone, Debug, GraphQLInputObject, Serialize, Deserialize)]
209+
struct MetadataTransactionInput {
210+
path: String,
211+
cid: String,
212+
owner: String,
213+
new_owner: String,
214+
}
215+
216+
type Schema = RootNode<'static, Query, Mutation, EmptySubscription<Context>>;
217+
218+
pub fn schema() -> Schema {
219+
Schema::new(Query, Mutation, EmptySubscription::<Context>::new())
220+
}
221+
222+
fn apply_request_with_proof(
223+
input: MetadataTransactionInput,
224+
prev_proof: &str,
225+
new_cid: &str,
226+
) -> String {
227+
// Must combined proofs (prev and new) in host function
228+
// then send to chain and return result
229+
let js = json!({
230+
"previous": prev_proof,
231+
"next_cid": new_cid,
232+
"input": input
233+
});
234+
submit_proof(&js.to_string())
235+
}
236+
237+
238+
```

0 commit comments

Comments
 (0)