0

I have an rpc

#[rpc]
pub trait ShivarthuApi<BlockHash> {
    #[rpc(name = "shivarthu_challengerevidence")]
    fn get_challengers_evidence(
        &self,
        at: Option<BlockHash>,
        profile_citizenid: u128,
        offset: u64,
        limit: u16,
    ) -> Result<Vec<u128>>;
}

With curl when I pass null it gives results

curl http://localhost:9933 -H "Content-Type:application/json;charset=utf-8" -d   '{
     "jsonrpc":"2.0",
      "id":1,
      "method":"shivarthu_challengerevidence",
      "params": [null, 0, 0, 5]
    }'

But without null, it gives error:

{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: invalid type: number, expected a (both 0x-prefixed or not) hex string with length of 64."},"id":1}

But with my front end code using polkadot js it gives error with null or undefined:

 const api2 = await ApiPromise.create({
        provider: wsProvider,
        rpc: {
          shivarthu: {
            challengerevidence: {
              description: 'Challenger Evidence',
              params: [
                {
                  name: 'at',
                  type: 'Hash',
                  isOptional: true,
                },
                {
                  name: 'profile_citizenid',
                  type: 'u128',
                },
                {
                  name: 'offset',
                  type: 'u64',
                },
                {
                  name: 'limit',
                  type: 'u16',
                },
              ],
              type: 'Vec<u128>',
            },
          },
        },
      })
   

      let data = await api2.rpc.shivarthu.challengerevidence(null, 0, 0, 5)
      console.log(data)

Error:

index.js:73 Uncaught (in promise) Error: 9876: Something wrong: Application, UnknownBlock, Header was not found in the database: 0x0000000000000000000000000000000000000000000000000000000000000000

2 Answers 2

4

I believe there is an issue where the JS API only expects the optional at param as the very last one - basically the de-facto standard order of RPC params in Substrate itself.

So basically the form it is used to dealing with and caters for is the following -

#[rpc]
pub trait ShivarthuApi<BlockHash> {
    #[rpc(name = "shivarthu_challengerevidence")]
    fn get_challengers_evidence(
        &self,
        profile_citizenid: u128,
        offset: u64,
        limit: u16,
        at: Option<BlockHash>,
    ) -> Result<Vec<u128>>;
}

An additional tip, for the at params, also add the isHistoric: true (in adition to the existing isOptional) flag to the JS API definition. It indicates to the API that this param may be indicate results from older blocks with different runtime/types.

Once defined for calling, it means it should be completely omitted when not needed -

// no hash, no param
let data = await api2.rpc.shivarthu.challengerevidence(0, 0, 5)

// hash, add param
let data = await api2.rpc.shivarthu.challengerevidence(0, 0, 5, 0x...)
0

Here are changes to be made, moving at to the last:

#[rpc]
pub trait ShivarthuApi<BlockHash> {
    #[rpc(name = "shivarthu_challengerevidence")]
    fn get_challengers_evidence(
        &self,
        profile_citizenid: u128,
        offset: u64,
        limit: u16,
        at: Option<BlockHash>,
    ) -> Result<Vec<u128>>;
}

Similarly, keep at as last argument here in get_challengers_evidence:

impl<C, Block> ShivarthuApi<<Block as BlockT>::Hash> for Shivarthu<C, Block>
where
    Block: BlockT,
    C: Send + Sync + 'static,
    C: ProvideRuntimeApi<Block>,
    C: HeaderBackend<Block>,
    C::Api: ShivarthuRuntimeApi<Block>,
{

    fn get_challengers_evidence(
        &self,      
        profile_citizenid: u128,
        offset: u64,
        limit: u16,
        at: Option<<Block as BlockT>::Hash>,
    ) -> Result<Vec<u128>> {
        let api = self.client.runtime_api();
        let at = BlockId::hash(at.unwrap_or_else(||
            // If the block hash is not supplied assume the best block.
            self.client.info().best_hash));

        let runtime_api_result =
            api.get_challengers_evidence(&at, profile_citizenid, offset, limit);
        runtime_api_result.map_err(|e| RpcError {
            code: ErrorCode::ServerError(9876), // No real reason for this value
            message: "Something wrong".into(),
            data: Some(format!("{:?}", e).into()),
        })
    }
}

But &at should be first argument in let runtime_api_result = api.get_challengers_evidence(&at, profile_citizenid, offset, limit), otherwise it gives compilation error.

And move at to the last in params in polkadotjs, otherwise it gives error,

const api2 = await ApiPromise.create({
        provider: wsProvider,
        rpc: {
          shivarthu: {
            challengerevidence: {
              description: 'Challenger Evidence',
              params: [
                {
                  name: 'profile_citizenid',
                  type: 'u128',
                },
                {
                  name: 'offset',
                  type: 'u64',
                },
                {
                  name: 'limit',
                  type: 'u16',
                },
                {
                  name: 'at',
                  type: 'Hash',
                  isOptional: true,
                  isHistoric: true,
                },
              ],
              type: 'Vec<u128>',
            },
          },
        },
      }) 

Then at becomes optional and gives no error:

 let data = await api2.rpc.shivarthu.challengerevidence(0, 0, 5)
 console.log(data.toString())

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.