RPC-CORE: getApps(acc: AccountId): undefined:: -32602: Invalid params: 0x prefix is missing. Error: -32602: Invalid params: 0x prefix is missing - substrate

const api = await ApiPromise.create({provider:wsProvider,
rpc:{
cf:{
getApps:{
description:"JUST For Test",
params:[{
name:"acc",
type:"AccountId"
}]
}
}
}});
const alice = keyring.addFromUri('//Alice');
let ker = crypto.encodeDerivedAddress(alice.publicKey,0);
let d = await api.rpc.cf.getApps(ker);
Rust Pallet Code
//function which I am calling
pub fn get_apps(acc:T::AccountId)->Vec<Vec<u8>>{
let data = <AppStore<T>>::get(acc);
data
}
Rust RPC
use jsonrpc_core::{Error as RpcError, ErrorCode, Result};
use jsonrpc_derive::rpc;
use sp_api::ProvideRuntimeApi;
use sp_blockchain::HeaderBackend;
use sp_runtime::{generic::BlockId,traits::Block as BlockT};
use std::sync::Arc;
use cf_runtime::AppApi as AppStorageApi;
#[rpc]
pub trait AppApi<BlockHash,AccountId>{
#[rpc(name="cf_getApps")]
fn get_apps(&self,at:Option<BlockHash>,acc:AccountId)->Result<Vec<Vec<u8>>>;
}
I have tried other prefix like 42 , 5 ,2 but not getting success , I did't understand anything how this error come again and again , and what is the default prefix for substrate node.

Related

Apollo client ignoring argument for GQL REST query

I have a query that is defined like this:
export const getProjectCosts = gql`
query GetProjectCosts($projectId: Int) {
ProjectCostList #rest(type: "ProjectCostList", path: "ProjectCosts/{args.projectId}") {
id
projectId
cost
description
costType
budgetYear
createdByUser
createdDate
}
}
`;
export const useGetProjectCostsListQuery = (baseOptions?: QueryHookOptions<ProjectCostList>) => {
const options = { ...baseOptions };
return useQuery<ProjectCostList>(getProjectCosts, options);
};
I call it like this:
const {
loading: projectCostLoading,
error: projectCostError,
data: projectCostData,
} = useGetProjectCostsListQuery({
variables: {
projectId: args.defaultValues.id,
},
});
I have verified in the debugger that the argument is sent correctly.
However, in the browser I see a warning:
Warning: RestLink caught an error while unpacking ProjectCosts/{args.projectId}|args.projectId This tends to happen if you forgot to pass a parameter needed for creating an #rest(path, or if RestLink was configured to deeply unpack a path parameter that wasn't provided. This message will only log once per detected instance. Trouble-shooting hint: check #rest(path: and the variables provided to this query.
(anonymous) # restLink.ts:567
And a request is sent to api/ProjectCosts/ instead of api/ProjectCosts/1234, which not surprisingly fails with a HTTP 404 error.
Is this a bug or am I doing something wrong?
I found this issue on Github, which looks very similar to what I'm experiencing.
We're using a custom .NET backend.
If it's a bug, is there a workaround?
The problem was that the parameter has to be declared twice.
This is the solution:
export const getProjectCosts = gql`
query GetProjectCosts($projectId: Int!) {
ProjectCostList(projectId: $projectId) #rest(type: "ProjectCostList", path: "ProjectCosts/{args.projectId}") {

How to use zero_copy with anchor in Solana PDAs

I'm building on Solana and need some PDAs to store my program state.
The default with anchor is constantly serialize/deserialize the accounts, even when just passing the address into instructions, which crushes BPM's 4k stack limit REALLY soon for my app.
So I found the zero_copy feature, which is exactly what I need, see https://docs.rs/anchor-lang/latest/anchor_lang/attr.account.html.
The examples shown in the anchor docs, as well as some code samples I found through web search, all refer to wallet-owned accounts, not to PDAs. There is literally NOTHING to find online about zero_copy with PDAs, so I'm wondering if it's possible at all?!
Anyway - I feel I really, really need it, otherwise my PDA accounts will be limited to something around 400 bytes or so.
So I gave it a try:
#[program]
mod myapp {
use super::*;
pub fn create_aff(ctx: Context<CreateAff>, _i: u8) -> Result<()> {
let acc = &mut ctx.accounts.aff_account.load_init()?;
acc.aff_account = ctx.accounts.user.key();
acc.bump = *ctx.bumps.get("aff_account").unwrap();
Ok(())
}
}
#[account(zero_copy)]
pub struct Aff {
aff_account: Pubkey,
bump: u8,
}
#[derive(Accounts)]
#[instruction(i: u8)]
pub struct CreateAff<'info> {
#[account(init, space = 41, payer = user, seeds = [AFFSEED], bump)]
aff_account: AccountInfor<'info, Aff>,
#[account(mut)]
user: Signer<'info>,
/// CHECK: This is not dangerous because we don't read or write from this account
system_program: AccountInfo<'info>,
}
So far, so good. It compiles. Running a simple test:
it("Creates the aff account if doesn't exist", async () => {
const [affPDA, bump] = await PublicKey.findProgramAddress([anchor.utils.bytes.utf8.encode(AFFSEED)],program.programId);
console.log("CreateAff: affPDA is [", affPDA.toString(), "], bump is", bump);
const contents = await program.account.aff.fetchNullable(affPDA);
if (contents == null) {
await program.rpc.createAff({
accounts: {
affAccount: affPDA,
user: usr,
systemProgram: SystemProgram.programId,
},
signers: [],
});
const affe = await program.account.counts.fetch(affPDA);
console.log("affe: ", affe);
assert.ok(true);
} else {
assert.ok(true);
}
});
renders me an error:
Creates the aff account if doesn't exist:
Error: Invalid arguments: affAccount not provided.
at /Users/bb/app/nodestore/node_modules/#project-serum/anchor/dist/cjs/program/common.js:39:23
at Array.forEach (<anonymous>)
at validateAccounts (node_modules/#project-serum/anchor/dist/cjs/program/common.js:33:16)
at ix (node_modules/#project-serum/anchor/dist/cjs/program/namespace/instruction.js:38:46)
at txFn (node_modules/#project-serum/anchor/dist/cjs/program/namespace/transaction.js:16:20)
at Object.rpc [as createAff] (node_modules/#project-serum/anchor/dist/cjs/program/namespace/rpc.js:9:24)
at Context.<anonymous> (tests/nodeshop.js:63:25)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
It's complaining affAccount is not provided, even though I'm clearly passing it in.
So the problem seems to be some part of the runtime cannot handle affAccount being AccountLoader (for zero_copy) rather than the standard AccountInfo.
Any help how I can fix or at least further debug this are highly appreciated.
I got it working. Sometimes it helps just posting a question, it helps thinking things through... ;-)
So great news: zero_copy with PDAs is possible! :-)
Here's what it was:
I originally gave the create_aff function (and the corresponding accounts struct) an i argument, even though I'm not using and additional i in the PDA account seeds. This was just a copy/paste error from a previous PDA I had been working on :-/
Since I was consistent with the i, the compiler didn't complain.
I removed the i parameter from the create_aff's parameter list as well as the #[instruction(i: u8)] from the CreateAff accounts struct declaration and, violĂ , it's working now.
Long live Solana and anchor. Oh, and a recommendation to the builders of anchor: Just make zero_copy the default, and lengthy borsh the exception!

Filter any Event using ethers.js and local node (Ganache-cli)

anyone can help me? I am using ganache-cli with fork bsc mainnet. When I use queryFilter, javascript show me this error: "Number can only safely store up to 53 bits"
In bsc mainnet it works perfectly
How can I solve this?
this is the code :
const {JsonRpcProvider} = require("#ethersproject/providers")
const ethers = require('ethers')
var provider = new ethers.providers.JsonRpcProvider("http://localhost:xxxx")
var abi = [
"event Swap(address indexed sender,uint amount0In,uint amount1In,uint amount0Out,uint amount1Out,address indexed to)"
]
contract = new ethers.Contract("0xd99c7F6C65857AC913a8f880A4cb84032AB2FC5b", abi, provider)
provider.getBlockNumber().then(function(x) {
contract.queryFilter([contract.filters.Swap()], x-48, x).then(function(el) {
console.log(el)
})
})
Guess this workaround should do the trick:
https://github.com/ChainSafe/web3.js/pull/3948#issuecomment-821779691

Cypress - extract URL info

I have this URL :
https://www.acme.com/book/passengers?id=h1c7cafc-5457-4564-af9d-2599c6a37dde&hash=7EPbMqFFQu8T5R3AQr1GCw&gtmsearchtype=City+Break
and want to store these values :
id=h1c7cafc-5457-4564-af9d-2599c6a37dde
hash=7EPbMqFFQu8T5R3AQr1GCw
for use in a later test.
How do I extract these values from the URL? I am using Cypress. Thanks.
Please follow the following steps and that's all there is to it.
You can put this snippet into before() hooks of your spec file and you can access them wherever you want.
cy.location().then(fullUrl => {
let pathName = fullUrl.pathname
let arr = pathName.split('?');
let arrayValues = arr[1].split('&');
cy.log(arrayValues[0]);
cy.log(arrayValues[1]);
cy.log(arrayValues[2]);
})
In case anyone needs the correct answer, use the cy.location('search') to extract the search part of the location data.
Then for convenience, convert it to a javascript object with key/value pairs for each item.
Finally, store it in a Cypress alias to use later in the test.
cy.location('search')
.then(search=> {
const searchValues = search.split('?')[1].split('&')
// yields: [
// id=h1c7cafc-5457-4564-af9d-2599c6a37dde,
// hash=7EPbMqFFQu8T5R3AQr1GCw,
// gtmsearchtype=City+Break
// ]
const searchMap = searchValues.reduce((acc,item) => {
const [key,value] = item.split('=')
acc[key] = value.replace('+', ' ')
return acc
}, {})
// yields: {
// id: "h1c7cafc-5457-4564-af9d-2599c6a37dde",
// hash: "7EPbMqFFQu8T5R3AQr1GCw",
// gtmsearchtype: "City Break"
// }
cy.wrap(searchMap).as('searchMap')
})
Using #Srinu Kodi's answer I got it working changing ...then(fullUrl => ... to
...then((fullUrl) => ...

Rust doesn't accept input from stdin from native messaging - firefox

I am making a native messaging application, with the web API, from firefox. The extension is supposed to call an application that parses stdin and then calls my other rust app, based on some of the data it parsed, but for no apparent reason, the rust app doesn't accept input from firefox (it works when I do it manually).
This is the code of the extension:
/*
On a click on the browser action, send the app a message.
*/
browser.browserAction.onClicked.addListener(() => {
console.log("Sending: ping");
var sending = browser.runtime.sendNativeMessage(
"themefox_manager",
"ping");
sending.then(onResponse, onError);
});
function onResponse(response) {
console.log("Received " + response);
}
function onError(error) {
console.log(`Error: ${error}`);
}
and this the code of the rust app:
use std::fs;
use std::io;
use std::io::prelude::*;
fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let mut file = fs::File::create("/home/user/filename.txt").unwrap();
//
if line.unwrap() == "ping" {
file.write_all(b"TEST").expect("Error");
}
}
}
The weird thing is, that the text file in my home dir first appears, when I close firefox, not when the app gets started. And it also doen't have the text TEST.
Thanks for any help!
Cheers
I managed to make my own solution, taking a bit from this crate.
Quick note: "If you want to skip all of the code and immeditly want to start coding from a template repo, scoll to the bottom of this solution, and you should be able to find more info there."
The code, which reads the input, and then returns it, is the following:
pub fn read_input<R: Read>(mut input: R) -> io::Result<serde_json::Value> {
let length = input.read_u32::<NativeEndian>().unwrap();
let mut buffer = vec![0; length as usize];
input.read_exact(&mut buffer)?;
let json_val: serde_json::Value = serde_json::from_slice(&buffer).unwrap();
Ok(json_val)
}
What the code does, is read the input, which is being passed as a parameter to the function, and then it reads it parses it in a json var and returns the sucess/err value of it.
That code is being used in the main.rs file like this:
let json_val = match lib::read_input(io::stdin()) {
Err(why) => panic!("{}", why.to_string()),
Ok(json_val) => json_val,
};
Here the input is being passed as a parameter to the read_input function.
And to send the code i used the following function:
pub fn write_output<W: Write>(mut output: W, value: &serde_json::Value) -> io::Result<()> {
let msg = serde_json::to_string(value)?;
let len = msg.len();
// Chrome won't accept a message larger than 1MB
if len > 1024 * 1024 {
panic!("Message was too large", length: {}, len)
}
output.write_u32::<NativeEndian>(len as u32)?;
output.write_all(msg.as_bytes())?;
output.flush()?;
Ok(())
}
Which gets the stdout and the message passed as parameters. The function then writes the message to the output (normally stdout, could also be a file for debugging purposes).
The code which calls the function write_output is the following:
let response = serde_json::json!({ "msg": "pong" });
match lib::write_output(io::stdout(), &response) {
Err(why) => panic!("{}", why.to_string()),
Ok(_) => (),
};
The project uses these dependencies, so make sure to add them to Cargo.toml
"byteorder" = "*"
"serde_json" = "*"
The imports for the main.rs file are:
mod lib;
use std::io;
and for the lib.rs file, in which both functions reside:
extern crate serde_json;
use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
use std::error::Error;
use std::fs;
use std::io;
use std::io::{Read, Write};
I also created a git template repo, so that you can start really quick, you can find it here.

Resources