@@ -36,112 +36,203 @@ The `contracts` directory, each Rust Wasm library is added. Use the existing di
3636Code 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