How to setup cycle payed in agent-rs update call?

canister has a concat_update which need caller pay the cycles.

How can I attached the cycles using agent-rs?

You cannot attach cycles from outside the Internet Computer. You’d have to proxy the calls through a canister.

1 Like

Then, any example to demo a proxy call through wallet canister? I try to find one, but not found yet

The best I have handy is this: sdk/src/dfx/src/commands/wallet/mod.rs at master · dfinity/sdk · GitHub

The ic-utils/WalletCanister can be used to pay cycles.
In the following testcase

  1. from_pem_wo_parameter is defined to handle .pem without parameter
  2. candid::Encode!() is used to format the parameters to bytes
  3. wallet.call is used as agent
    #[tokio::test]
    async fn test_call_concate_update(){
        let identity = Secp256k1Identity::from_pem_wo_parameter(IDENTITY_FILE_WITHOUT_PARAMS.as_bytes()).unwrap();
        let a: Agent =  Agent::builder().with_url("http://127.0.0.1:4943").with_identity(identity).build().unwrap();
        a.fetch_root_key().await.unwrap();
        let wallet_canister_id = Principal::from_text("bnz7o-iuaaa-aaaaa-qaaaa-cai").unwrap();
        let wallet = WalletCanister::create( &a, wallet_canister_id).await.unwrap();

        let canister_id = Principal::from_text("bkyz2-fmaaa-aaaaa-qaaaq-cai").unwrap();
        let s1 = "hello";
        let s2 = "world";  
        let args = candid::Encode!(&s1, &s2).unwrap();
        println!("args: {:?}", hex::encode(args.clone()));
        let decoded_args: (String, String) = candid::Decode!(&args, String, String).unwrap();
        println!("Decoded arguments: {:?}", decoded_args);

        let mut arg =Argument::new();
        arg.set_raw_arg(args);

        let response = wallet.call::<(String,), &str>(canister_id, "concat_update", arg, 200_000_000).call_and_wait().await;
        println!("Response: {:?}", response.unwrap().0);
    }

    #[cfg(feature = "pem")]
    pub fn from_pem_wo_parameter<R: io::Read>(pem_reader: R) -> Result<Self, PemError> {
        use sec1::{pem::PemLabel, EcPrivateKey};

        // const EC_PARAMETERS: &str = "EC PARAMETERS";
        // const SECP256K1: &[u8] = b"\x06\x05\x2b\x81\x04\x00\x0a";

        let contents = pem_reader.bytes().collect::<Result<Vec<u8>, io::Error>>()?;

        for pem in pem::parse_many(contents)? {
            // if pem.tag() == EC_PARAMETERS && pem.contents() != SECP256K1 {
            //     return Err(PemError::UnsupportedKeyCurve(
            //         "secp256k1".to_string(),
            //         pem.contents().to_vec(),
            //     ));
            // }

            if pem.tag() != EcPrivateKey::PEM_LABEL {
                continue;
            }
            let private_key =
                SecretKey::from_sec1_der(pem.contents()).map_err(|_| pkcs8::Error::KeyMalformed)?;
            return Ok(Self::from_private_key(private_key));
        }
        Err(pem::PemError::MissingData.into())
    }
1 Like