cyfs_meta_lib/
client.rs

1use crate::MetaMinerTarget;
2use cyfs_base::*;
3use cyfs_base_meta::*;
4
5use http_types::{Method, Request, Url};
6use log::*;
7use primitive_types::H256;
8use serde_json::Value;
9use std::convert::TryFrom;
10use std::time::Duration;
11
12pub struct MetaClient {
13    miner_host: Url,
14    request_timeout: Option<Duration>,
15}
16
17pub const UNION_ACCOUNT_TYPE_CHUNK_PROOF: u8 = 0;
18pub const UNION_ACCOUNT_TYPE_SN_PROOF: u8 = 1;
19pub const UNION_ACCOUNT_TYPE_DNS_PROOF: u8 = 2;
20
21impl MetaClient {
22    pub fn new_target(target: MetaMinerTarget) -> Self {
23        let url = target.miner_url();
24
25        info!(
26            "will select meta service url: target={}, url={}",
27            target.to_string(),
28            &url
29        );
30        Self::new(&url)
31    }
32
33    pub fn new(miner_host: &str) -> Self {
34        let mut host = miner_host.to_owned();
35        if !host.ends_with("/") {
36            host = host + "/";
37        }
38
39        Self {
40            miner_host: Url::parse(&host).unwrap(),
41            request_timeout: None,
42        }
43    }
44
45    pub fn with_timeout(mut self, request_timeout: Duration) -> Self {
46        self.request_timeout = Some(request_timeout);
47        self
48    }
49
50    fn gen_url(&self, path: &str) -> Url {
51        self.miner_host.join(path).unwrap()
52    }
53
54    pub async fn get_balance(
55        &self,
56        account: &ObjectId,
57        coin_id: u8,
58    ) -> BuckyResult<ViewBalanceResult> {
59        let req = self.get_balance_request(account, coin_id);
60        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
61        if let ViewResponse::ViewBalance(br) = resp {
62            Ok(br)
63        } else {
64            Err(BuckyError::new(BuckyErrorCode::Failed, "view failed"))
65        }
66    }
67
68    pub async fn trans(
69        &self,
70        from: &StandardObject,
71        to: &ObjectId,
72        v: i64,
73        coin_id: u8,
74        secret: &PrivateKey,
75    ) -> BuckyResult<TxId> {
76        let req = self.trans_request(from, to, v, coin_id, secret).await?;
77        self.request_miner(req, &mut Vec::new()).await
78    }
79
80    pub async fn trans_ex(
81        &self,
82        from: TxCaller,
83        to: &ObjectId,
84        v: i64,
85        coin_id: u8,
86        secret: &PrivateKey,
87    ) -> BuckyResult<TxId> {
88        let req = self.trans_request_ex(from, to, v, coin_id, secret).await?;
89        self.request_miner(req, &mut Vec::new()).await
90    }
91
92    pub async fn trans_request(
93        &self,
94        from: &StandardObject,
95        to: &ObjectId,
96        v: i64,
97        coin_id: u8,
98        secret: &PrivateKey,
99    ) -> BuckyResult<Request> {
100        self.commit_request(
101            from,
102            secret,
103            MetaTxBody::TransBalance(TransBalanceTx {
104                ctid: CoinTokenId::Coin(coin_id),
105                to: vec![(to.clone(), v)],
106            }),
107            10,
108            10,
109            Vec::new(),
110        )
111        .await
112    }
113
114    pub async fn trans_request_ex(
115        &self,
116        from: TxCaller,
117        to: &ObjectId,
118        v: i64,
119        coin_id: u8,
120        secret: &PrivateKey,
121    ) -> BuckyResult<Request> {
122        self.commit_request_ex(
123            from,
124            secret,
125            MetaTxBody::TransBalance(TransBalanceTx {
126                ctid: CoinTokenId::Coin(coin_id),
127                to: vec![(to.clone(), v)],
128            }),
129            10,
130            10,
131            Vec::new(),
132        )
133        .await
134    }
135
136    async fn create_tx_and_sign(
137        &self,
138        caller: &StandardObject,
139        secret: &PrivateKey,
140        body: MetaTxBody,
141        gas_price: u16,
142        max_fee: u32,
143        tx_data: Vec<u8>,
144    ) -> BuckyResult<MetaTx> {
145        let caller = TxCaller::try_from(caller)?;
146        self.create_tx_and_sign_ex(caller, secret, body, gas_price, max_fee, tx_data)
147            .await
148    }
149
150    async fn create_tx_and_sign_ex(
151        &self,
152        caller: TxCaller,
153        secret: &PrivateKey,
154        body: MetaTxBody,
155        gas_price: u16,
156        max_fee: u32,
157        tx_data: Vec<u8>,
158    ) -> BuckyResult<MetaTx> {
159        let mut nonce = self.get_nonce(&caller.id()?).await?;
160        nonce += 1;
161
162        let mut tx = MetaTx::new(nonce, caller, 0, gas_price, max_fee, None, body, tx_data).build();
163        let signer = RsaCPUObjectSigner::new(secret.public(), secret.clone());
164        sign_and_set_named_object(&signer, &mut tx, &SignatureSource::RefIndex(0)).await?;
165        Ok(tx)
166    }
167
168    pub async fn create_tx_not_sign(
169        &self,
170        caller: TxCaller,
171        body: MetaTxBody,
172        gas_price: u16,
173        max_fee: u32,
174        tx_data: Vec<u8>,
175    ) -> BuckyResult<Tx> {
176        let mut nonce = self.get_nonce(&caller.id()?).await?;
177        nonce += 1;
178        let tx = Tx::new(
179            nonce,
180            caller,
181            0,
182            gas_price,
183            max_fee,
184            None,
185            vec![body].to_vec()?,
186            tx_data,
187        )
188        .build();
189        Ok(tx)
190    }
191
192    pub async fn create_tx_not_sign2(
193        &self,
194        caller: TxCaller,
195        bodys: Vec<MetaTxBody>,
196        gas_price: u16,
197        max_fee: u32,
198        tx_data: Vec<u8>,
199    ) -> BuckyResult<Tx> {
200        let mut nonce = self.get_nonce(&caller.id()?).await?;
201        nonce += 1;
202        let tx = Tx::new(
203            nonce,
204            caller,
205            0,
206            gas_price,
207            max_fee,
208            None,
209            bodys.to_vec()?,
210            tx_data,
211        )
212        .build();
213        Ok(tx)
214    }
215
216    fn commit_signed_tx(&self, tx: MetaTx) -> BuckyResult<Request> {
217        let body = tx.encode_to_vec(true)?;
218        let url = self.gen_url("commit");
219        let mut request = Request::new(Method::Post, url);
220        request.set_body(body);
221        Ok(request)
222    }
223
224    async fn commit_request(
225        &self,
226        caller: &StandardObject,
227        secret: &PrivateKey,
228        body: MetaTxBody,
229        gas_price: u16,
230        max_fee: u32,
231        data: Vec<u8>,
232    ) -> BuckyResult<Request> {
233        let signed_tx = self
234            .create_tx_and_sign(caller, secret, body, gas_price, max_fee, data)
235            .await?;
236        self.commit_signed_tx(signed_tx)
237    }
238
239    async fn commit_request_ex(
240        &self,
241        caller: TxCaller,
242        secret: &PrivateKey,
243        body: MetaTxBody,
244        gas_price: u16,
245        max_fee: u32,
246        tx_data: Vec<u8>,
247    ) -> BuckyResult<Request> {
248        let signed_tx = self
249            .create_tx_and_sign_ex(caller, secret, body, gas_price, max_fee, tx_data)
250            .await?;
251        self.commit_signed_tx(signed_tx)
252    }
253
254    pub fn get_balance_request(&self, account: &ObjectId, coin_id: u8) -> Request {
255        let view = ViewRequest {
256            block: ViewBlockEnum::Tip,
257            method: ViewMethodEnum::ViewBalance(ViewBalanceMethod {
258                account: account.clone(),
259                ctid: vec![CoinTokenId::Coin(coin_id)],
260            }),
261        };
262        self.view_request(view)
263    }
264
265    pub fn view_request(&self, view: ViewRequest) -> Request {
266        let mut req = Request::new(Method::Post, self.gen_url("view"));
267        req.set_body(view.to_hex().unwrap());
268        req
269    }
270
271    pub async fn get_desc(&self, id: &ObjectId) -> BuckyResult<SavedMetaObject> {
272        let req = self.get_desc_request(id);
273        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
274
275        if let ViewResponse::ViewDesc(desc) = resp {
276            Ok(desc)
277        } else {
278            Err(BuckyError::from("get desc failed"))
279        }
280    }
281
282    pub fn get_raw_request(&self, id: &ObjectId) -> Request {
283        let view = ViewRequest {
284            block: ViewBlockEnum::Tip,
285            method: ViewMethodEnum::ViewRaw(ViewRawMethod { id: id.clone() }),
286        };
287        self.view_request(view)
288    }
289
290    pub async fn get_raw_data(&self, id: &ObjectId) -> BuckyResult<Vec<u8>> {
291        let req = self.get_raw_request(id);
292        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
293
294        if let ViewResponse::ViewRaw(desc) = resp {
295            Ok(desc.into())
296        } else {
297            Err(BuckyError::from("get desc failed"))
298        }
299    }
300
301    pub async fn get_chain_status(&self) -> BuckyResult<ChainStatus> {
302        let view = ViewRequest {
303            block: ViewBlockEnum::Tip,
304            method: ViewMethodEnum::ViewStatus,
305        };
306        let request = self.view_request(view);
307        let resp: ViewResponse = self.request_miner(request, &mut Vec::new()).await?;
308        if let ViewResponse::ViewStatus(chain_status) = resp {
309            Ok(chain_status)
310        } else {
311            Err(BuckyError::from("get chain status failed"))
312        }
313    }
314
315    pub async fn get_block(&self, height: i64) -> BuckyResult<Block> {
316        let view = ViewRequest {
317            block: ViewBlockEnum::Number(height),
318            method: ViewMethodEnum::ViewBlock,
319        };
320        let request = self.view_request(view);
321        let resp: ViewResponse = self.request_miner(request, &mut Vec::new()).await?;
322        if let ViewResponse::ViewBlock(block) = resp {
323            Ok(block)
324        } else {
325            Err(BuckyError::from("get block failed"))
326        }
327    }
328
329    pub fn get_desc_request(&self, id: &ObjectId) -> Request {
330        let view = ViewRequest {
331            block: ViewBlockEnum::Tip,
332            method: ViewMethodEnum::ViewDesc(ViewDescMethod { id: id.clone() }),
333        };
334        self.view_request(view)
335    }
336
337    pub async fn create_desc(
338        &self,
339        owner: &StandardObject,
340        desc: &SavedMetaObject,
341        v: i64,
342        price: u32,
343        coin_id: u8,
344        secret: &PrivateKey,
345    ) -> BuckyResult<TxId> {
346        let req = self
347            .create_desc_request(owner, desc, v, coin_id, price, secret)
348            .await?;
349        self.request_miner(req, &mut Vec::new()).await
350    }
351
352    pub async fn create_desc_ex(
353        &self,
354        caller: TxCaller,
355        desc: &SavedMetaObject,
356        v: i64,
357        price: u32,
358        coin_id: u8,
359        secret: &PrivateKey,
360    ) -> BuckyResult<TxId> {
361        let req = self
362            .create_desc_request_ex(caller, desc, v, coin_id, price, secret)
363            .await?;
364        self.request_miner(req, &mut Vec::new()).await
365    }
366
367    pub async fn create_desc_request(
368        &self,
369        owner: &StandardObject,
370        desc: &SavedMetaObject,
371        v: i64,
372        coin_id: u8,
373        price: u32,
374        secret: &PrivateKey,
375    ) -> BuckyResult<Request> {
376        self.commit_request(
377            owner,
378            secret,
379            MetaTxBody::CreateDesc(CreateDescTx {
380                coin_id,
381                from: None,
382                value: v,
383                desc_hash: desc.hash()?,
384                price,
385            }),
386            10,
387            10,
388            desc.to_vec()?,
389        )
390        .await
391    }
392
393    pub async fn create_desc_request_ex(
394        &self,
395        owner: TxCaller,
396        desc: &SavedMetaObject,
397        v: i64,
398        coin_id: u8,
399        price: u32,
400        secret: &PrivateKey,
401    ) -> BuckyResult<Request> {
402        self.commit_request_ex(
403            owner,
404            secret,
405            MetaTxBody::CreateDesc(CreateDescTx {
406                coin_id,
407                from: None,
408                value: v,
409                desc_hash: desc.hash()?,
410                price,
411            }),
412            10,
413            10,
414            desc.to_vec()?,
415        )
416        .await
417    }
418
419    pub async fn update_desc(
420        &self,
421        owner: &StandardObject,
422        desc: &SavedMetaObject,
423        price: Option<u32>,
424        coin_id: Option<u8>,
425        secret: &PrivateKey,
426    ) -> BuckyResult<TxId> {
427        let req = self
428            .update_desc_request(owner, desc, price, coin_id, secret)
429            .await?;
430        self.request_miner(req, &mut Vec::new()).await
431    }
432
433    pub async fn update_desc_ex(
434        &self,
435        owner: TxCaller,
436        desc: &SavedMetaObject,
437        price: Option<u32>,
438        coin_id: Option<u8>,
439        secret: &PrivateKey,
440    ) -> BuckyResult<TxId> {
441        let req = self
442            .update_desc_request_ex(owner, desc, price, coin_id, secret)
443            .await?;
444        self.request_miner(req, &mut Vec::new()).await
445    }
446
447    pub async fn update_desc_request(
448        &self,
449        owner: &StandardObject,
450        desc: &SavedMetaObject,
451        price: Option<u32>,
452        coin_id: Option<u8>,
453        secret: &PrivateKey,
454    ) -> BuckyResult<Request> {
455        self.commit_request(
456            owner,
457            secret,
458            MetaTxBody::UpdateDesc(UpdateDescTx {
459                write_flag: 0,
460                price: price.map(|p| MetaPrice {
461                    coin_id: coin_id.unwrap(),
462                    price: p,
463                }),
464                desc_hash: desc.hash()?,
465            }),
466            10,
467            10,
468            desc.to_vec()?,
469        )
470        .await
471    }
472
473    pub async fn update_desc_request_ex(
474        &self,
475        owner: TxCaller,
476        desc: &SavedMetaObject,
477        price: Option<u32>,
478        coin_id: Option<u8>,
479        secret: &PrivateKey,
480    ) -> BuckyResult<Request> {
481        self.commit_request_ex(
482            owner,
483            secret,
484            MetaTxBody::UpdateDesc(UpdateDescTx {
485                write_flag: 0,
486                price: price.map(|p| MetaPrice {
487                    coin_id: coin_id.unwrap(),
488                    price: p,
489                }),
490                desc_hash: desc.hash()?,
491            }),
492            10,
493            10,
494            desc.to_vec()?,
495        )
496        .await
497    }
498
499    pub async fn bid_name(
500        &self,
501        caller: &StandardObject,
502        owner: Option<ObjectId>,
503        name: &str,
504        price: u64,
505        rent: u32,
506        secret: &PrivateKey,
507    ) -> BuckyResult<TxId> {
508        let req = self
509            .commit_request(
510                caller,
511                secret,
512                MetaTxBody::BidName(BidNameTx {
513                    name: name.to_owned(),
514                    owner: owner.map(|id| id),
515                    name_price: price,
516                    price: rent,
517                }),
518                10,
519                10,
520                Vec::new(),
521            )
522            .await?;
523        self.request_miner(req, &mut Vec::new()).await
524    }
525
526    pub async fn get_name(&self, name: &str) -> BuckyResult<Option<(NameInfo, NameState)>> {
527        let view = ViewRequest {
528            block: ViewBlockEnum::Tip,
529            method: ViewMethodEnum::ViewName(ViewNameMethod {
530                name: name.to_owned(),
531            }),
532        };
533        let _body = view.to_hex()?;
534        let req = self.view_request(view);
535        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
536
537        if let ViewResponse::ViewName(desc) = resp {
538            Ok(desc)
539        } else {
540            Err(BuckyError::from("get name info failed"))
541        }
542    }
543
544    pub async fn update_name(
545        &self,
546        caller: &StandardObject,
547        name: &str,
548        info: NameInfo,
549        write_flag: u8,
550        secret: &PrivateKey,
551    ) -> BuckyResult<TxId> {
552        let req = self
553            .commit_request(
554                caller,
555                secret,
556                MetaTxBody::UpdateName(UpdateNameTx {
557                    name: name.to_owned(),
558                    info,
559                    write_flag,
560                }),
561                10,
562                10,
563                Vec::new(),
564            )
565            .await?;
566        self.request_miner(req, &mut Vec::new()).await
567    }
568
569    pub async fn trans_name(
570        &self,
571        caller: &StandardObject,
572        new_owner: &ObjectId,
573        sub_name: Option<&str>,
574        secret: &PrivateKey,
575    ) -> BuckyResult<TxId> {
576        let req = self
577            .commit_request(
578                caller,
579                secret,
580                MetaTxBody::TransName(TransNameTx {
581                    sub_name: sub_name.map(|str| str.to_owned()),
582                    new_owner: new_owner.clone(),
583                }),
584                10,
585                10,
586                Vec::new(),
587            )
588            .await?;
589        self.request_miner(req, &mut Vec::new()).await
590    }
591    //
592    // pub async fn change_name_state(&self, caller: &Device, name: &str, new_state: NameState, secret: &PrivateKey) -> BuckyResult<TxId> {
593    //     let req = self.commit_request(caller, secret, MetaTxBody::ChangeNameState(ChangeNameStateTx{ name: name.to_owned(), new_state })).await?;
594    //     self.request_miner(req).await
595    // }
596
597    pub async fn get_tx_receipt(&self, tx_hash: &TxId) -> BuckyResult<Option<(Receipt, i64)>> {
598        let req = self.get_receipt_request(tx_hash);
599        self.request_miner(req, &mut Vec::new()).await
600    }
601
602    pub async fn get_tx(&self, tx_hash: &TxId) -> BuckyResult<TxInfo> {
603        let url = self
604            .miner_host
605            .join("tx/")
606            .unwrap()
607            .join(&tx_hash.to_string())
608            .unwrap();
609
610        let req = Request::new(Method::Get, url);
611
612        if let Some(timeout) = &self.request_timeout {
613            match async_std::future::timeout(timeout.to_owned(), self.request_tx(req)).await {
614                Ok(ret) => ret,
615                Err(async_std::future::TimeoutError { .. }) => {
616                    let msg = format!("meta request tx timeout!");
617                    error!("{}", msg);
618
619                    Err(BuckyError::new(BuckyErrorCode::Timeout, msg))
620                }
621            }
622        } else {
623            self.request_tx(req).await
624        }
625    }
626
627    async fn request_tx(&self, req: Request) -> BuckyResult<TxInfo> {
628        debug!("miner request tx url={}", req.url());
629
630        let mut resp = surf::client().send(req).await.map_err(|err| {
631            error!("http connect error! host={}, err={}", self.miner_host, err);
632            err
633        })?;
634        /*
635        let host = self.miner_host.host_str().unwrap();
636        let port = self.miner_host.port().unwrap_or(80);
637        let addr = format!("{}:{}", host, port);
638
639        let stream = TcpStream::connect(addr).await.map_err(|err| {
640            error!(
641                "connect to miner failed! miner={}, err={}",
642                self.miner_host, err
643            );
644            err
645        })?;
646
647        let mut resp = async_h1::connect(stream, req).await.map_err(|err| {
648            error!("http connect error! host={}, err={}", self.miner_host, err);
649            err
650        })?;
651        */
652        let ret: Value = resp.body_json().await?;
653        if 0 == ret.get("err").unwrap().as_u64().unwrap() {
654            Ok(serde_json::from_value(ret.get("result").unwrap().clone())?)
655        } else {
656            Err(BuckyError::new(
657                ret.get("err").unwrap().as_u64().unwrap() as u16,
658                ret.get("msg").unwrap().as_str().unwrap(),
659            ))
660        }
661    }
662
663    async fn get_nonce(&self, account: &ObjectId) -> BuckyResult<i64> {
664        let req = self.get_nonce_request(account);
665        self.request_miner(req, &mut Vec::new()).await
666    }
667
668    pub fn get_nonce_request(&self, account: &ObjectId) -> Request {
669        let mut url = self.gen_url("nonce");
670
671        let query = format!("id={}", &account);
672        url.set_query(Some(&query));
673
674        Request::new(Method::Get, url)
675    }
676
677    pub fn get_receipt_request(&self, tx: &TxId) -> Request {
678        let mut url = self.gen_url("receipt");
679
680        let query = format!("tx={}", tx.as_ref());
681        url.set_query(Some(&query));
682
683        Request::new(Method::Get, url)
684    }
685
686    pub async fn send_to_miner(&self, tx: MetaTx) -> BuckyResult<TxId> {
687        let req = self.commit_signed_tx(tx)?;
688        self.request_miner(req, &mut Vec::new()).await
689    }
690
691    pub async fn request_miner<'de, T: RawDecode<'de>>(
692        &self,
693        req: Request,
694        buf: &'de mut Vec<u8>,
695    ) -> BuckyResult<T> {
696        if let Some(timeout) = &self.request_timeout {
697            match async_std::future::timeout(timeout.to_owned(), self.request_miner_impl(req, buf))
698                .await
699            {
700                Ok(ret) => ret,
701                Err(async_std::future::TimeoutError { .. }) => {
702                    let msg = format!("meta request timeout!");
703                    error!("{}", msg);
704
705                    Err(BuckyError::new(BuckyErrorCode::Timeout, msg))
706                }
707            }
708        } else {
709            self.request_miner_impl(req, buf).await
710        }
711    }
712
713    async fn request_miner_impl<'de, T: RawDecode<'de>>(
714        &self,
715        req: Request,
716        buf: &'de mut Vec<u8>,
717    ) -> BuckyResult<T> {
718        debug!("miner request url={}", req.url());
719
720        let mut resp = surf::client().send(req).await.map_err(|err| {
721            error!("http connect error! host={}, err={}", self.miner_host, err);
722            err
723        })?;
724        /*
725        let host = self.miner_host.host_str().unwrap();
726        let port = self.miner_host.port().unwrap_or(80);
727        let addr = format!("{}:{}", host, port);
728
729        let stream = TcpStream::connect(addr).await.map_err(|err| {
730            error!(
731                "connect to miner failed! miner={}, err={}",
732                self.miner_host, err
733            );
734            err
735        })?;
736
737        let mut resp = async_h1::connect(stream, req).await.map_err(|err| {
738            error!("http connect error! host={}, err={}", self.miner_host, err);
739            err
740        })?;
741        */
742        let ret_hex = resp.body_string().await.map_err(|err| {
743            error!("recv body error! err={}", err);
744            err
745        })?;
746        let ret = Result::<T, u16>::clone_from_hex(ret_hex.as_str(), buf)?;
747
748        match ret {
749            Ok(t) => Ok(t),
750            Err(e) => {
751                if e == ERROR_NOT_FOUND {
752                    Err(BuckyError::new(BuckyErrorCode::NotFound, "NotFound"))
753                } else {
754                    Err(BuckyError::new(BuckyErrorCodeEx::MetaError(e), "meta err"))
755                }
756            }
757        }
758    }
759
760    pub async fn create_union_account(
761        &self,
762        caller: &StandardObject,
763        create_union_tx: CreateUnionTx,
764        secret: &PrivateKey,
765    ) -> BuckyResult<TxId> {
766        let req = self
767            .commit_request(
768                caller,
769                secret,
770                MetaTxBody::CreateUnion(create_union_tx),
771                10,
772                10,
773                vec![],
774            )
775            .await?;
776        self.request_miner(req, &mut Vec::new()).await
777    }
778
779    pub async fn create_deviate_tx(
780        &self,
781        caller: &StandardObject,
782        deviate_tx: DeviateUnionTx,
783        secret: &PrivateKey,
784    ) -> BuckyResult<TxId> {
785        let req = self
786            .commit_request(
787                caller,
788                secret,
789                MetaTxBody::DeviateUnion(deviate_tx),
790                10,
791                10,
792                vec![],
793            )
794            .await?;
795        self.request_miner(req, &mut Vec::new()).await
796    }
797
798    pub async fn withdraw_union(
799        &self,
800        caller: &StandardObject,
801        ctid: CoinTokenId,
802        union_id: &ObjectId,
803        value: i64,
804        secret: &PrivateKey,
805    ) -> BuckyResult<TxId> {
806        let req = self
807            .commit_request(
808                caller,
809                secret,
810                MetaTxBody::WithdrawFromUnion(WithdrawFromUnionTx {
811                    ctid,
812                    union: union_id.clone(),
813                    value,
814                }),
815                10,
816                10,
817                vec![],
818            )
819            .await?;
820        self.request_miner(req, &mut Vec::new()).await
821    }
822
823    pub async fn set_config(
824        &self,
825        caller: &StandardObject,
826        key: &str,
827        value: &str,
828        secret: &PrivateKey,
829    ) -> BuckyResult<TxId> {
830        let req = self
831            .commit_request(
832                caller,
833                secret,
834                MetaTxBody::SetConfig(SetConfigTx {
835                    key: key.to_owned(),
836                    value: value.to_owned(),
837                }),
838                10,
839                10,
840                vec![],
841            )
842            .await?;
843        self.request_miner(req, &mut Vec::new()).await
844    }
845
846    pub async fn auction_name(
847        &self,
848        caller: &StandardObject,
849        name: &str,
850        startting_price: u64,
851        secret: &PrivateKey,
852    ) -> BuckyResult<TxId> {
853        let req = self
854            .commit_request(
855                caller,
856                secret,
857                MetaTxBody::AuctionName(AuctionNameTx {
858                    name: name.to_owned(),
859                    price: startting_price,
860                }),
861                10,
862                10,
863                vec![],
864            )
865            .await?;
866        self.request_miner(req, &mut Vec::new()).await
867    }
868
869    pub async fn cancel_auction_name(
870        &self,
871        caller: &StandardObject,
872        name: &str,
873        secret: &PrivateKey,
874    ) -> BuckyResult<TxId> {
875        let req = self
876            .commit_request(
877                caller,
878                secret,
879                MetaTxBody::CancelAuctionName(CancelAuctionNameTx {
880                    name: name.to_owned(),
881                }),
882                10,
883                10,
884                vec![],
885            )
886            .await?;
887        self.request_miner(req, &mut Vec::new()).await
888    }
889
890    pub async fn buy_back_name(
891        &self,
892        caller: &StandardObject,
893        name: &str,
894        secret: &PrivateKey,
895    ) -> BuckyResult<TxId> {
896        let req = self
897            .commit_request(
898                caller,
899                secret,
900                MetaTxBody::BuyBackName(BuyBackNameTx {
901                    name: name.to_owned(),
902                }),
903                10,
904                10,
905                vec![],
906            )
907            .await?;
908        self.request_miner(req, &mut Vec::new()).await
909    }
910
911    pub async fn remove_desc(
912        &self,
913        caller: &StandardObject,
914        desc_id: &ObjectId,
915        secret: &PrivateKey,
916    ) -> BuckyResult<TxId> {
917        let req = self
918            .commit_request(
919                caller,
920                secret,
921                MetaTxBody::RemoveDesc(RemoveDescTx {
922                    id: desc_id.clone(),
923                }),
924                10,
925                10,
926                Vec::new(),
927            )
928            .await?;
929        self.request_miner(req, &mut Vec::new()).await
930    }
931
932    pub async fn withdraw_from_file(
933        &self,
934        caller: TxCaller,
935        file_id: &ObjectId,
936        v: i64,
937        coin_id: u8,
938        secret: &PrivateKey,
939    ) -> BuckyResult<TxId> {
940        let req = self
941            .commit_request_ex(
942                caller,
943                secret,
944                MetaTxBody::WithdrawToOwner(WithdrawToOwner {
945                    ctid: CoinTokenId::Coin(coin_id),
946                    id: file_id.clone(),
947                    value: v,
948                }),
949                10,
950                10,
951                Vec::new(),
952            )
953            .await?;
954        self.request_miner(req, &mut Vec::new()).await
955    }
956
957    pub async fn create_sub_chain_account(
958        &self,
959        caller: TxCaller,
960        miner_group: MinerGroup,
961        secret: &PrivateKey,
962    ) -> BuckyResult<TxId> {
963        let req = self
964            .commit_request_ex(
965                caller,
966                secret,
967                MetaTxBody::CreateSubChainAccount(miner_group),
968                10,
969                10,
970                Vec::new(),
971            )
972            .await?;
973        self.request_miner(req, &mut Vec::new()).await
974    }
975
976    pub async fn withdraw_from_sub_chain(
977        &self,
978        caller: TxCaller,
979        coin_id: CoinTokenId,
980        value: i64,
981        secret: &PrivateKey,
982    ) -> BuckyResult<TxId> {
983        let req = self
984            .commit_request_ex(
985                caller,
986                secret,
987                MetaTxBody::WithdrawFromSubChain(WithdrawFromSubChainTx { coin_id, value }),
988                10,
989                10,
990                Vec::new(),
991            )
992            .await?;
993        self.request_miner(req, &mut Vec::new()).await
994    }
995
996    pub async fn commit_extension_tx(
997        &self,
998        caller: TxCaller,
999        extension_tx: MetaExtensionTx,
1000        secret: &PrivateKey,
1001        tx_data: Vec<u8>,
1002    ) -> BuckyResult<TxId> {
1003        let req = self
1004            .commit_request_ex(
1005                caller,
1006                secret,
1007                MetaTxBody::Extension(extension_tx),
1008                10,
1009                10,
1010                tx_data,
1011            )
1012            .await?;
1013        self.request_miner(req, &mut Vec::new()).await
1014    }
1015
1016    pub async fn commit_tx(&self, tx: MetaTx) -> BuckyResult<TxId> {
1017        let req = self.commit_signed_tx(tx)?;
1018        self.request_miner(req, &mut Vec::new()).await
1019    }
1020
1021    pub async fn create_contract(
1022        &self,
1023        caller: &StandardObject,
1024        secret: &PrivateKey,
1025        value: u64,
1026        init_data: Vec<u8>,
1027        gas_price: u16,
1028        max_fee: u32,
1029    ) -> BuckyResult<TxId> {
1030        let req = self
1031            .commit_request(
1032                caller,
1033                secret,
1034                MetaTxBody::CreateContract(CreateContractTx { value, init_data }),
1035                gas_price,
1036                max_fee,
1037                Vec::new(),
1038            )
1039            .await?;
1040        info!("create request");
1041        self.request_miner(req, &mut vec![]).await
1042    }
1043
1044    pub async fn create_contract2(
1045        &self,
1046        caller: &StandardObject,
1047        secret: &PrivateKey,
1048        value: u64,
1049        init_data: Vec<u8>,
1050        salt: [u8; 32],
1051        gas_price: u16,
1052        max_fee: u32,
1053    ) -> BuckyResult<TxId> {
1054        let req = self
1055            .commit_request(
1056                caller,
1057                secret,
1058                MetaTxBody::CreateContract2(CreateContract2Tx::new(value, init_data, salt)),
1059                gas_price,
1060                max_fee,
1061                Vec::new(),
1062            )
1063            .await?;
1064        self.request_miner(req, &mut vec![]).await
1065    }
1066
1067    pub async fn call_contract(
1068        &self,
1069        caller: &StandardObject,
1070        secret: &PrivateKey,
1071        address: ObjectId,
1072        value: u64,
1073        data: Vec<u8>,
1074        gas_price: u16,
1075        max_fee: u32,
1076    ) -> BuckyResult<TxId> {
1077        let req = self
1078            .commit_request(
1079                caller,
1080                secret,
1081                MetaTxBody::CallContract(CallContractTx {
1082                    address,
1083                    value,
1084                    data,
1085                }),
1086                gas_price,
1087                max_fee,
1088                Vec::new(),
1089            )
1090            .await?;
1091        self.request_miner(req, &mut vec![]).await
1092    }
1093
1094    pub async fn view_contract(
1095        &self,
1096        address: ObjectId,
1097        data: Vec<u8>,
1098    ) -> BuckyResult<ViewContractResult> {
1099        let view = ViewRequest {
1100            block: ViewBlockEnum::Tip,
1101            method: ViewMethodEnum::ViewContract(ViewContract { address, data }),
1102        };
1103        let req = self.view_request(view);
1104        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
1105        if let ViewResponse::ViewContract(br) = resp {
1106            Ok(br)
1107        } else {
1108            Err(BuckyError::new(
1109                BuckyErrorCode::NotMatch,
1110                "view result type not match",
1111            ))
1112        }
1113    }
1114
1115    pub async fn set_benefi(
1116        &self,
1117        address: &ObjectId,
1118        benefi: &ObjectId,
1119        caller: &StandardObject,
1120        secret: &PrivateKey,
1121    ) -> BuckyResult<TxId> {
1122        let req = self
1123            .commit_request(
1124                caller,
1125                secret,
1126                MetaTxBody::SetBenefi(SetBenefiTx {
1127                    address: address.clone(),
1128                    to: benefi.clone(),
1129                }),
1130                10,
1131                10,
1132                Vec::new(),
1133            )
1134            .await?;
1135        self.request_miner(req, &mut vec![]).await
1136    }
1137
1138    pub async fn get_benefi(&self, address: &ObjectId) -> BuckyResult<ObjectId> {
1139        let view = ViewRequest {
1140            block: ViewBlockEnum::Tip,
1141            method: ViewMethodEnum::ViewBenifi(ViewBenefi {
1142                address: address.clone(),
1143            }),
1144        };
1145        let req = self.view_request(view);
1146        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
1147        if let ViewResponse::ViewBenefi(br) = resp {
1148            Ok(br.address)
1149        } else {
1150            Err(BuckyError::new(
1151                BuckyErrorCode::NotMatch,
1152                "view result type not match",
1153            ))
1154        }
1155    }
1156
1157    pub async fn get_logs(
1158        &self,
1159        address: ObjectId,
1160        topics: Vec<Option<H256>>,
1161        from: i64,
1162        to: i64,
1163    ) -> BuckyResult<Vec<(Vec<H256>, Vec<u8>)>> {
1164        let view = ViewRequest {
1165            block: ViewBlockEnum::Tip,
1166            method: ViewMethodEnum::ViewLog(ViewLog {
1167                address,
1168                topics,
1169                from,
1170                to,
1171            }),
1172        };
1173        let req = self.view_request(view);
1174        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
1175        if let ViewResponse::ViewLog(br) = resp {
1176            Ok(br.logs)
1177        } else {
1178            Err(BuckyError::new(
1179                BuckyErrorCode::NotMatch,
1180                "view result type not match",
1181            ))
1182        }
1183    }
1184
1185    pub async fn nft_create(
1186        &self,
1187        caller: TxCaller,
1188        secret: &PrivateKey,
1189        desc: NFTDesc,
1190        name: String,
1191        state: NFTState,
1192    ) -> BuckyResult<TxId> {
1193        let req = self
1194            .commit_request_ex(
1195                caller,
1196                secret,
1197                MetaTxBody::NFTCreate(NFTCreateTx { desc, name, state }),
1198                10,
1199                10,
1200                Vec::new(),
1201            )
1202            .await?;
1203        self.request_miner(req, &mut Vec::new()).await
1204    }
1205
1206    pub async fn nft_get(
1207        &self,
1208        nft_id: ObjectId,
1209    ) -> BuckyResult<(NFTDesc, String, ObjectId, NFTState)> {
1210        let view = ViewRequest {
1211            block: ViewBlockEnum::Tip,
1212            method: ViewMethodEnum::ViewNFT(nft_id),
1213        };
1214        let req = self.view_request(view);
1215        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
1216        if let ViewResponse::ViewNFT(ret) = resp {
1217            Ok(ret)
1218        } else {
1219            Err(BuckyError::new(
1220                BuckyErrorCode::NotMatch,
1221                "view result type not match",
1222            ))
1223        }
1224    }
1225
1226    pub async fn nft_get_apply_buy_list(
1227        &self,
1228        nft_id: ObjectId,
1229        offset: u32,
1230        length: u8,
1231    ) -> BuckyResult<ViewNFTBuyListResult> {
1232        let view = ViewRequest {
1233            block: ViewBlockEnum::Tip,
1234            method: ViewMethodEnum::ViewNFTApplyBuyList((nft_id, offset, length)),
1235        };
1236        let req = self.view_request(view);
1237        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
1238        if let ViewResponse::ViewNFTApplyBuyList(ret) = resp {
1239            Ok(ret)
1240        } else {
1241            Err(BuckyError::new(
1242                BuckyErrorCode::NotMatch,
1243                "view result type not match",
1244            ))
1245        }
1246    }
1247
1248    pub async fn nft_get_bid_list(
1249        &self,
1250        nft_id: ObjectId,
1251        offset: u32,
1252        length: u8,
1253    ) -> BuckyResult<ViewNFTBuyListResult> {
1254        let view = ViewRequest {
1255            block: ViewBlockEnum::Tip,
1256            method: ViewMethodEnum::ViewNFTBidList((nft_id, offset, length)),
1257        };
1258        let req = self.view_request(view);
1259        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
1260        if let ViewResponse::ViewNFTBidList(ret) = resp {
1261            Ok(ret)
1262        } else {
1263            Err(BuckyError::new(
1264                BuckyErrorCode::NotMatch,
1265                "view result type not match",
1266            ))
1267        }
1268    }
1269
1270    pub async fn nft_get_largest_buy_price(
1271        &self,
1272        nft_id: ObjectId,
1273    ) -> BuckyResult<Option<(ObjectId, CoinTokenId, u64)>> {
1274        let view = ViewRequest {
1275            block: ViewBlockEnum::Tip,
1276            method: ViewMethodEnum::ViewNFTLargestBuyValue(nft_id),
1277        };
1278        let req = self.view_request(view);
1279        let resp: ViewResponse = self.request_miner(req, &mut Vec::new()).await?;
1280        if let ViewResponse::ViewNFTLargestBuyValue(ret) = resp {
1281            Ok(ret)
1282        } else {
1283            Err(BuckyError::new(
1284                BuckyErrorCode::NotMatch,
1285                "view result type not match",
1286            ))
1287        }
1288    }
1289
1290    pub async fn nft_auction(
1291        &self,
1292        caller: TxCaller,
1293        secret: &PrivateKey,
1294        nft_id: ObjectId,
1295        price: u64,
1296        coin_id: CoinTokenId,
1297        duration_block_num: u64,
1298    ) -> BuckyResult<TxId> {
1299        let req = self
1300            .commit_request_ex(
1301                caller,
1302                secret,
1303                MetaTxBody::NFTAuction(NFTAuctionTx {
1304                    nft_id,
1305                    price,
1306                    coin_id,
1307                    duration_block_num,
1308                }),
1309                10,
1310                10,
1311                Vec::new(),
1312            )
1313            .await?;
1314        self.request_miner(req, &mut Vec::new()).await
1315    }
1316
1317    pub async fn nft_bid(
1318        &self,
1319        caller: TxCaller,
1320        secret: &PrivateKey,
1321        nft_id: ObjectId,
1322        price: u64,
1323        coin_id: CoinTokenId,
1324    ) -> BuckyResult<TxId> {
1325        let req = self
1326            .commit_request_ex(
1327                caller,
1328                secret,
1329                MetaTxBody::NFTBid(NFTBidTx {
1330                    nft_id,
1331                    price,
1332                    coin_id,
1333                }),
1334                10,
1335                10,
1336                Vec::new(),
1337            )
1338            .await?;
1339        self.request_miner(req, &mut Vec::new()).await
1340    }
1341
1342    pub async fn nft_buy(
1343        &self,
1344        caller: TxCaller,
1345        secret: &PrivateKey,
1346        nft_id: ObjectId,
1347        price: u64,
1348        coin_id: CoinTokenId,
1349    ) -> BuckyResult<TxId> {
1350        let req = self
1351            .commit_request_ex(
1352                caller,
1353                secret,
1354                MetaTxBody::NFTBuy(NFTBuyTx {
1355                    nft_id,
1356                    price,
1357                    coin_id,
1358                }),
1359                10,
1360                10,
1361                Vec::new(),
1362            )
1363            .await?;
1364        self.request_miner(req, &mut Vec::new()).await
1365    }
1366
1367    pub async fn nft_sell(
1368        &self,
1369        caller: TxCaller,
1370        secret: &PrivateKey,
1371        nft_id: ObjectId,
1372        price: u64,
1373        coin_id: CoinTokenId,
1374        duration_block_num: u64,
1375    ) -> BuckyResult<TxId> {
1376        let req = self
1377            .commit_request_ex(
1378                caller,
1379                secret,
1380                MetaTxBody::NFTSell(NFTSellTx {
1381                    nft_id,
1382                    price,
1383                    coin_id,
1384                    duration_block_num,
1385                }),
1386                10,
1387                10,
1388                Vec::new(),
1389            )
1390            .await?;
1391        self.request_miner(req, &mut Vec::new()).await
1392    }
1393
1394    pub async fn nft_apply_buy(
1395        &self,
1396        caller: TxCaller,
1397        secret: &PrivateKey,
1398        nft_id: ObjectId,
1399        price: u64,
1400        coin_id: CoinTokenId,
1401    ) -> BuckyResult<TxId> {
1402        let req = self
1403            .commit_request_ex(
1404                caller,
1405                secret,
1406                MetaTxBody::NFTApplyBuy(NFTApplyBuyTx {
1407                    nft_id,
1408                    price,
1409                    coin_id,
1410                }),
1411                10,
1412                10,
1413                Vec::new(),
1414            )
1415            .await?;
1416        self.request_miner(req, &mut Vec::new()).await
1417    }
1418
1419    pub async fn nft_cancel_apply_buy(
1420        &self,
1421        caller: TxCaller,
1422        secret: &PrivateKey,
1423        nft_id: ObjectId,
1424    ) -> BuckyResult<TxId> {
1425        let req = self
1426            .commit_request_ex(
1427                caller,
1428                secret,
1429                MetaTxBody::NFTCancelApplyBuyTx(NFTCancelApplyBuyTx { nft_id }),
1430                10,
1431                10,
1432                Vec::new(),
1433            )
1434            .await?;
1435        self.request_miner(req, &mut Vec::new()).await
1436    }
1437
1438    pub async fn nft_agree_apply(
1439        &self,
1440        caller: TxCaller,
1441        secret: &PrivateKey,
1442        nft_id: ObjectId,
1443        user_id: ObjectId,
1444    ) -> BuckyResult<TxId> {
1445        let req = self
1446            .commit_request_ex(
1447                caller,
1448                secret,
1449                MetaTxBody::NFTAgreeApply(NFTAgreeApplyTx { nft_id, user_id }),
1450                10,
1451                10,
1452                Vec::new(),
1453            )
1454            .await?;
1455        self.request_miner(req, &mut Vec::new()).await
1456    }
1457
1458    pub async fn nft_like(
1459        &self,
1460        caller: TxCaller,
1461        secret: &PrivateKey,
1462        nft_id: ObjectId,
1463    ) -> BuckyResult<TxId> {
1464        let req = self
1465            .commit_request_ex(
1466                caller,
1467                secret,
1468                MetaTxBody::NFTLike(NFTLikeTx { nft_id }),
1469                10,
1470                10,
1471                Vec::new(),
1472            )
1473            .await?;
1474        self.request_miner(req, &mut Vec::new()).await
1475    }
1476
1477    // pub async fn public_sn_service(&self, caller: TxCaller, service: SNService, secret: &PrivateKey) -> BuckyResult<TxId> {
1478    //     let req = self.commit_request_ex(caller, secret, MetaTxBody::SNService(SNServiceTx::Publish(service)), Vec::new()).await?;
1479    //     self.request_miner(req, &mut Vec::new()).await
1480    // }
1481    //
1482    // pub async fn purchase_sn_service(&self, caller: TxCaller, contract: Contract, secret: &PrivateKey) -> BuckyResult<TxId> {
1483    //     let req = self.commit_request_ex(caller, secret, MetaTxBody::SNService(SNServiceTx::Purchase(contract)), Vec::new()).await?;
1484    //     self.request_miner(req, &mut Vec::new()).await
1485    // }
1486    //
1487    // pub async fn settle_sn_service(&self, caller: TxCaller, proof: ProofOfService, secret: &PrivateKey) -> BuckyResult<TxId> {
1488    //     let req = self.commit_request_ex(caller, secret, MetaTxBody::SNService(SNServiceTx::Settle(proof)), Vec::new()).await?;
1489    //     self.request_miner(req, &mut Vec::new()).await
1490    // }
1491    //
1492    // pub async fn get_auth_contract(&self, service_id: &ObjectId, user_id: &ObjectId) -> BuckyResult<Contract> {
1493    //     let url = self.gen_url(format!("query_auth_contract/{}/{}", service_id.to_string(), user_id.to_string()).as_str());
1494    //     let req = Request::new(Method::Get, url);
1495    //     self.request_miner(req, &mut Vec::new()).await
1496    // }
1497}