fn handle_command(
        &mut self,
        origin: MessageOrigin,
        cmd: Command,
        context: &mut NativeContext,
    ) -> TransactionResult {
        // info!("Command received: {:?}", &cmd);

        let alice = contracts::account_id_from_hex(ALICE)
            .expect("should not failed with valid address; qed.");
        match cmd {
            Command::SetOwner { owner } => {
                if origin.account()? != alice {
                    return Err(TransactionError::BadOrigin);
                }
                self.owner = AccountId::from(*owner.as_fixed_bytes());
                Ok(Default::default())
            }
            Command::SetupBot { token, chat_id } => {
                let sender = origin.account()?;
                if sender != alice && sender != self.owner {
                    return Err(TransactionError::BadOrigin);
                }
                self.bot_token = token;
                self.chat_id = chat_id;
                Ok(Default::default())
            }
            Command::ReportBtcPrice => {
                let sender = origin.account()?;
                if sender != alice && sender != self.owner {
                    return Err(TransactionError::BadOrigin);
                }

                let bot_token = self.bot_token.clone();
                let chat_id = self.chat_id.clone();

                // This Command triggers the use of `AsyncSideTask`, it first send a HTTP request to get the current BTC
                // price from https://min-api.cryptocompare.com/, then sends the price to a Telegram bot through another
                // HTTP request
                //
                // To ensure the state consistency, the time to start the task and the time to upload the HTTP response
                // to chain must be determined. In this case, we start the task in the current `block_number`, and report
                // the result, whether succeeded or failed, to the chain after `duration`
                //
                // Report the result after 2 blocks no matter whether has received the HTTP response
                let block_number = context.block.block_number;
                let duration = 2;

                let mq = context.mq().clone();
                let my_id = context.self_id;

                let default_messages = [mq.prepare_message_to(&(), "^phala/mq/blockhole")];

                context.block.side_task_man.add_async_task(
                    block_number,
                    duration,
                    default_messages,
                    async move {
                        // Do network request in this block and return the result.
                        // Do NOT send mq message in this block.
                        log::info!("Side task starts to get BTC price");
                        let mut resp = match surf::get(
                            "https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD",
                        )
                        .send()
                        .await
                        {
                            Ok(r) => r,
                            Err(_err) => {
                                return Err(Error::NetworkUnavailable.into());
                            }
                        };
                        let result = match resp.body_string().await {
                            Ok(body) => body,
                            Err(err) => {
                                format!("Network error: {:?}", err)
                            }
                        };
                        log::info!("Side task got BTC price: {}", result);

                        let price: BtcPrice =
                            serde_json::from_str(result.as_str()).or(Err(Error::BadBtcPrice))?;
                        let text = format!("BTC price: ${}", price.usd);
                        let uri = format!(
                            "https://api.telegram.org/bot{}/{}",
                            bot_token, "sendMessage"
                        );
                        let data = &TgMessage { chat_id, text };

                        let mut resp = match surf::post(uri)
                            .body_json(data)
                            .map_err(|_| Error::NetworkUnavailable)?
                            .await
                        {
                            Ok(r) => r,
                            Err(_err) => {
                                return Err(Error::NetworkUnavailable.into());
                            }
                        };
                        let result = match resp.body_string().await {
                            Ok(body) => body,
                            Err(err) => {
                                format!("Network error: {:?}", err)
                            }
                        };
                        log::info!("Side task sent BTC price: {}", result);

                        let price = price.usd.to_string();
                        log::info!("Side task reporting price: {:?}", &price);
                        let command = Command::UpdateBtcPrice { price };
                        let message = Payload::Plain(command);

                        Ok([mq.prepare_message_to(&message, command_topic(my_id))])
                    },
                );

                Ok(Default::default())
            }
            // Handle the price updating request from the side-task
            Command::UpdateBtcPrice { price } => {
                log::info!(
                    "UpdateBtcPrice received, origin={}, price={}",
                    origin,
                    price
                );

                if origin != MessageOrigin::Contract(context.self_id) {
                    return Err(TransactionError::BadOrigin);
                }

                self.price = price;
                Ok(Default::default())
            }
        }
    }
/// Handle the Commands from transactions on the blockchain. This method doesn't respond.
Handle the Commands from transactions on the blockchain. This method doesn't respond.
Handle the Commands from transactions on the blockchain . This method doesn ' t respond .
fn handle_command(
        &mut self,
        origin: MessageOrigin,
        cmd: Command,
        context: &mut NativeContext,
    ) -> TransactionResult {
        // info!("Command received: {:?}", &cmd);
        let alice = contracts::account_id_from_hex(ALICE)
            .expect("should not failed with valid address; qed.");
        match cmd {
            Command::SetOwner { owner } => {
                if origin.account()? != alice {
                    return Err(TransactionError::BadOrigin);
                }
                self.owner = AccountId::from(*owner.as_fixed_bytes());
                Ok(Default::default())
            }
            Command::SetupBot { token, chat_id } => {
                let sender = origin.account()?;
                if sender != alice && sender != self.owner {
                    return Err(TransactionError::BadOrigin);
                }
                self.bot_token = token;
                self.chat_id = chat_id;
                Ok(Default::default())
            }
            Command::ReportBtcPrice => {
                let sender = origin.account()?;
                if sender != alice && sender != self.owner {
                    return Err(TransactionError::BadOrigin);
                }
                let bot_token = self.bot_token.clone();
                let chat_id = self.chat_id.clone();
                // This Command triggers the use of `AsyncSideTask`, it first send a HTTP request to get the current BTC
                // price from https://min-api.cryptocompare.com/, then sends the price to a Telegram bot through another
                // HTTP request
                //
                // To ensure the state consistency, the time to start the task and the time to upload the HTTP response
                // to chain must be determined. In this case, we start the task in the current `block_number`, and report
                // the result, whether succeeded or failed, to the chain after `duration`
                //
                // Report the result after 2 blocks no matter whether has received the HTTP response
                let block_number = context.block.block_number;
                let duration = 2;
                let mq = context.mq().clone();
                let my_id = context.self_id;
                let default_messages = [mq.prepare_message_to(&(), "^phala/mq/blockhole")];
                context.block.side_task_man.add_async_task(
                    block_number,
                    duration,
                    default_messages,
                    async move {
                        // Do network request in this block and return the result.
                        // Do NOT send mq message in this block.
                        log::info!("Side task starts to get BTC price");
                        let mut resp = match surf::get(
                            "https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD",
                        )
                        .send()
                        .await
                        {
                            Ok(r) => r,
                            Err(_err) => {
                                return Err(Error::NetworkUnavailable.into());
                            }
                        };
                        let result = match resp.body_string().await {
                            Ok(body) => body,
                            Err(err) => {
                                format!("Network error: {:?}", err)
                            }
                        };
                        log::info!("Side task got BTC price: {}", result);
                        let price: BtcPrice =
                            serde_json::from_str(result.as_str()).or(Err(Error::BadBtcPrice))?;
                        let text = format!("BTC price: ${}", price.usd);
                        let uri = format!(
                            "https://api.telegram.org/bot{}/{}",
                            bot_token, "sendMessage"
                        );
                        let data = &TgMessage { chat_id, text };
                        let mut resp = match surf::post(uri)
                            .body_json(data)
                            .map_err(|_| Error::NetworkUnavailable)?
                            .await
                        {
                            Ok(r) => r,
                            Err(_err) => {
                                return Err(Error::NetworkUnavailable.into());
                            }
                        };
                        let result = match resp.body_string().await {
                            Ok(body) => body,
                            Err(err) => {
                                format!("Network error: {:?}", err)
                            }
                        };
                        log::info!("Side task sent BTC price: {}", result);
                        let price = price.usd.to_string();
                        log::info!("Side task reporting price: {:?}", &price);
                        let command = Command::UpdateBtcPrice { price };
                        let message = Payload::Plain(command);
                        Ok([mq.prepare_message_to(&message, command_topic(my_id))])
                    },
                );
                Ok(Default::default())
            }
            // Handle the price updating request from the side-task
            Command::UpdateBtcPrice { price } => {
                log::info!(
                    "UpdateBtcPrice received, origin={}, price={}",
                    origin,
                    price
                );
                if origin != MessageOrigin::Contract(context.self_id) {
                    return Err(TransactionError::BadOrigin);
                }
                self.price = price;
                Ok(Default::default())
            }
        }
    }
fn handle_command ( & mut self , origin : MessageOrigin , cmd : Command , context : & mut NativeContext , ) -> TransactionResult { // info!("Command received: {:?}", &cmd); let alice = contracts :: account_id_from_hex ( ALICE ) . expect ( " " ) ; match cmd { Command :: SetOwner { owner } => { if origin . account ( ) ? != alice { return Err ( TransactionError :: BadOrigin ) ; } self . owner = AccountId :: from ( * owner . as_fixed_bytes ( ) ) ; Ok ( Default :: default ( ) ) } Command :: SetupBot { token , chat_id } => { let sender = origin . account ( ) ? ; if sender != alice && sender != self . owner { return Err ( TransactionError :: BadOrigin ) ; } self . bot_token = token ; self . chat_id = chat_id ; Ok ( Default :: default ( ) ) } Command :: ReportBtcPrice => { let sender = origin . account ( ) ? ; if sender != alice && sender != self . owner { return Err ( TransactionError :: BadOrigin ) ; } let bot_token = self . bot_token . clone ( ) ; let chat_id = self . chat_id . clone ( ) ; // This Command triggers the use of `AsyncSideTask`, it first send a HTTP request to get the current BTC // price from https://min-api.cryptocompare.com/, then sends the price to a Telegram bot through another // HTTP request // // To ensure the state consistency, the time to start the task and the time to upload the HTTP response // to chain must be determined. In this case, we start the task in the current `block_number`, and report // the result, whether succeeded or failed, to the chain after `duration` // // Report the result after 2 blocks no matter whether has received the HTTP response let block_number = context . block . block_number ; let duration = 2 ; let mq = context . mq ( ) . clone ( ) ; let my_id = context . self_id ; let default_messages = [ mq . prepare_message_to ( & ( ) , " " ) ] ; context . block . side_task_man . add_async_task ( block_number , duration , default_messages , async move { // Do network request in this block and return the result. // Do NOT send mq message in this block. log :: info ! ( " " ) ; let mut resp = match surf :: get ( " " , ) . send ( ) . await { Ok ( r ) => r , Err ( _err ) => { return Err ( Error :: NetworkUnavailable . into ( ) ) ; } } ; let result = match resp . body_string ( ) . await { Ok ( body ) => body , Err ( err ) => { format ! ( " " err ) } } ; log :: info ! ( " " result ) ; let price : BtcPrice = serde_json :: from_str ( result . as_str ( ) ) . or ( Err ( Error :: BadBtcPrice ) ) ? ; let text = format ! ( " " price usd ) ; let uri = format ! ( " " bot_token " " ) ; let data = & TgMessage { chat_id , text } ; let mut resp = match surf :: post ( uri ) . body_json ( data ) . map_err ( | _ | Error :: NetworkUnavailable ) ? . await { Ok ( r ) => r , Err ( _err ) => { return Err ( Error :: NetworkUnavailable . into ( ) ) ; } } ; let result = match resp . body_string ( ) . await { Ok ( body ) => body , Err ( err ) => { format ! ( " " err ) } } ; log :: info ! ( " " result ) ; let price = price . usd . to_string ( ) ; log :: info ! ( " " price ) ; let command = Command :: UpdateBtcPrice { price } ; let message = Payload :: Plain ( command ) ; Ok ( [ mq . prepare_message_to ( & message , command_topic ( my_id ) ) ] ) } , ) ; Ok ( Default :: default ( ) ) } // Handle the price updating request from the side-task Command :: UpdateBtcPrice { price } => { log :: info ! ( " " origin price ) ; if origin != MessageOrigin :: Contract ( context . self_id ) { return Err ( TransactionError :: BadOrigin ) ; } self . price = price ; Ok ( Default :: default ( ) ) } } }
Handle the Commands from transactions on the blockchain.
Handle the Commands from transactions on the blockchain .
&mut self
origin
MessageOrigin
cmd
Command
context
&mut NativeContext
&mut self
origin
MessageOrigin
cmd
Command
context
&mut NativeContext