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 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 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 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 }