NEAR FunctionCallError(HostError(GuestPanic { panic_msg: "panicked at 'Failed to deserialize input from JSON.: Error(\"the account ID is invalid\", - nearprotocol

Via CLI, this works: NEAR_ENV=testnet near view dev-1643292007908-55838431863482 nft_tokens_for_owner '{"account_id": "hatchet.testnet"}' and produces the expected result.
I'm now trying to do the same thing via near-api-js but am getting:
Unhandled Runtime Error
Error: Querying [object Object] failed: wasm execution failed with error: FunctionCallError(HostError(GuestPanic { panic_msg: "panicked at 'Failed to deserialize input from JSON.: Error(\"the account ID is invalid\", line: 1, column: 17)', src/contract/nft.rs:65:1" })).
{
"error": "wasm execution failed with error: FunctionCallError(HostError(GuestPanic { panic_msg: \"panicked at 'Failed to deserialize input from JSON.: Error(\\\"the account ID is invalid\\\", line: 1, column: 17)', src/contract/nft.rs:65:1\" }))",
"logs": [],
"block_height": 81208522,
"block_hash": "5vWcrkVjshewYgLZTTHTZgLN7SF3qpYPovnPUUM1ucBt"
}
Call Stack
JsonRpcProvider.query
node_modules/near-api-js/lib/providers/json-rpc-provider.js (123:0)
async Account.viewFunction
node_modules/near-api-js/lib/account.js (366:0)
I've tried multiple totally separate approaches using near-api-js, and they both result in this error.
My current approach is:
export type NFT = Contract & {
nft_mint: (args: any, gas: any, depositAmount: any) => Promise<any>; // TODO Add types
nft_token: (args: any) => Promise<any>;
nft_tokens_for_owner: (args: any) => Promise<any>;
};
export function getNftContract(account: Account) {
const contract = new Contract(
account, // the account object that is connecting
certificateContractName,
{
viewMethods: ['nft_token', 'nft_tokens_for_owner'], // view methods do not change state but usually return a value
changeMethods: ['nft_mint'], // change methods modify state
},
);
return contract;
}
async function getCertificates(accountId: string): Promise<string[]> {
const keyStore = new BrowserLocalStorageKeyStore();
const near = await getNearConnection(keyStore);
const account = new Account(near.connection, ''); // account_id not required for 'view' call
const contract = getNftContract(account);
const response = await (contract as NFT).nft_tokens_for_owner({ account_id: accountId });
console.log({ account, accountId, response });
return []; // TODO
}
I'm using testnet, and the accountId I'm passing is hatchet.testnet.

This was a good lesson for me.
I started looking at the source code of https://docs.rs/near-sdk/3.1.0/src/near_sdk/json_types/account.rs.html#63 and https://docs.rs/near-sdk/3.1.0/src/near_sdk/environment/env.rs.html#816-843
I homed in on that "The account ID is invalid" error message.
But I knew I was passing a valid account ID.
It turns out the problem had nothing to do with NEAR. It was a Next.js / React problem:
My component's account_id was temporarily empty and trying to call nft_tokens_for_owner too soon (i.e. before account_id had been populated with a value).

Related

Terminate a graphql request from Apollo Link

I have an ApolloLink setup for the AWSAppSyncClient in my React project to check if the user is authorized to make the graphql request. If the user is not authorized then, link should not invoke the forward method rather just return an Error for unauthorized access (making it a terminating link).
I tried returning the plain Error response (also tried it with Observable.of), but the request doesn't resolves but keeps on to retry the request on an endless loop.
Need a better solution to implement it.
const authLink = new ApolloLink((operation, forward) => {
const { operationName } = operation;
if (checkIfNotAuthorized(operationName)) {
const error = new Error('Access denied');
return { errors: [error], data: null };
}
return forward(operation);
});

ThrottlerGuard not working on Websocket in Nestjs

I'm creating an application that is using Nestjs with websockets, but now I need to add rate limit on the sockets, but analyzing the documentation documentation link and implementing what it says in it, when I use #UseGuards(MyGuard) an error occurs in the application.
My Guard:
#Injectable()
export class NewThrottlerGuard extends ThrottlerGuard {
protected async handleRequest(
context: ExecutionContext,
limit: number,
ttl: number,
): Promise<boolean> {
console.log('Request');
const client = context.switchToWs().getClient();
const ip = client.conn.remoteAddress;
const key = this.generateKey(context, ip);
const ttls = await this.storageService.getRecord(key);
if (ttls.length >= limit) {
throw new ThrottlerException();
}
await this.storageService.addRecord(key, ttl);
return true;
}
}
Websocket:
#UseGuards(NewThrottlerGuard)
#SubscribeMessage('sendMessage')
sendMessage(
#ConnectedSocket() client: Socket,
#MessageBody() message: string,
) {
client.rooms.forEach((room) => {
if (room !== client.id) {
client.broadcast.to(room).emit('message', message);
}
});
}
Error in console:
/node_modules/#nestjs/common/utils/validate-each.util.js:22
throw new InvalidDecoratorItemException(decorator, item, context.name);
^
Error: Invalid guard passed to #UseGuards() decorator (ChatGateway).
at validateEach
The file in: #nestjs/common/utils/validate-each.util.js:22
function validateEach(context, arr, predicate, decorator, item) {
if (!context || !context.name) {
return true;
}
console.log(context, arr)
const errors = arr.some(str => !predicate(str));
if (errors) {
throw new InvalidDecoratorItemException(decorator, item, context.name);
}
return true;
}
i put some console.log then in the terminal it show:
[Function: ChatGateway] [ undefined ]
In Github Throttler documentation they say: You cannot bind the guard with APP_GUARD or app.useGlobalGuards() due to how Nest binds global guards.
So, im using #UseGuards()
The guard itself was written correctly, but it was put in a location that importing it made a circular reference between files, so when #UseGuards() was used it became #UseGuards(undefined) which caused the cryptic error message. Moving the guard to a dedicated file will fix the error
I follow your github reference settings and it doesn't work,The following is my code, where is my setting wrong, and the request to ws is not intercepted(In the handleRequest method)

How to use TeamsFx useGraph hook to get meeting infos

I would like to use TeamsFx React package to call MS Graph Api.
I tried to do separated component
import { useContext } from "react";
import { useGraph } from "#microsoft/teamsfx-react";
import { TeamsFxContext } from "../Context";
import { TeamsFxProvider } from "#microsoft/mgt-teamsfx-provider";
import { Providers, ProviderState } from "#microsoft/mgt-element";
import * as microsoftTeams from "#microsoft/teams-js";
export function MeetingContext(props: { showFunction?: boolean; environment?: string }) {
const { teamsfx } = useContext(TeamsFxContext);
const { loading, error, data, reload } = useGraph(
async (graph, teamsfx, scope) => {
// Call graph api directly to get user profile information
let profile;
try {
profile = await graph.api("/me").get();
} catch (error) {
console.log(error);
}
// Initialize Graph Toolkit TeamsFx provider
const provider = new TeamsFxProvider(teamsfx, scope);
Providers.globalProvider = provider;
Providers.globalProvider.setState(ProviderState.SignedIn);
let photoUrl = "";
let meeting =null;
try {
const photo = await graph.api("/me/photo/$value").get();
photoUrl = URL.createObjectURL(photo);
microsoftTeams.getContext(async (context)=>{
console.log(context);
try {
meeting = await graph.api(`/me/onlineMeetings/${context.meetingId}`).get();
} catch (error) {
console.error(error);
}
})
} catch {
// Could not fetch photo from user's profile, return empty string as placeholder.
}
console.log(meeting);
return { meeting };
},
{ scope: ["User.Read","User.Read","OnlineMeetingArtifact.Read.All"," OnlineMeetings.Read"], teamsfx: teamsfx }
);
return (
<>
</>
)
}
When I debug my interpreter stops on
profile = await graph.api("/me").get();
Then it does not pass after.
I would like also to know what should I put in scope field ?
Should I put the authorisations listed here ?
Should I also Add them in registered app in Azure Portal ?
Update:
I'm getting response from
Failed to get access token cache silently, please login first: you need login first before get access token.
I'm using the teams toolkit and I'm already logged in . I don't know what Should I do to be considered as logged in ?
Update :
I have updated my app api authorisations in azure portal now I'm not getting anymore this error.
But I'm getting a new error :
meeting = await graph.api(`/me/onlineMeetings/${context.chatId}`).get();
"Invalid meeting id
19:meeting_MzU0MzFhYTQtNjlmOS00NGI4LTg1MTYtMGI3ZTkwOWYwMzk4#thread.v2."
I'll post a new question about this as it not the original problem
You can get the details of an online meeting using videoTeleconferenceId, meeting ID, or joinWebURL.
Instead of ChatID you have to use meeting ID or you have to use filter with videoTeleconferenceId or joinWebURL.
The invalid meeting ID error get because
chatID is not the correct parameter for this graph API.
You can refer below API for getting meeting information.
To get an onlineMeeting using meeting ID with delegated (/me) and app (/users/{userId}) permission:
GET /me/onlineMeetings/{meetingId}
GET /users/{userId}/onlineMeetings/{meetingId}
To get an onlineMeeting using videoTeleconferenceId with app permission*:
GET /communications/onlineMeetings/?$filter=VideoTeleconferenceId%20eq%20'{videoTeleconferenceId}'
To get an onlineMeeting using joinWebUrl with delegated and app permission:
GET /me/onlineMeetings?$filter=JoinWebUrl%20eq%20'{joinWebUrl}'
GET /users/{userId}/onlineMeetings?$filter=JoinWebUrl%20eq%20'{joinWebUrl}'
Ref Doc: https://learn.microsoft.com/en-us/graph/api/onlinemeeting-get?view=graph-rest-1.0&tabs=http

ExecutionError: Exceeded the prepaid gas -- when called from front end

The transfer() function works perfectly fine when testing and through the CLI. However, when I try to call it from the front end, it returns
Uncaught (in promise) Error: {"index":0,"kind":{"ExecutionError":"Exceeded the prepaid gas."}}
It is not a complex call and only involves just 1. transferring tokens 2. updating a value in storage. Can anyone give me pointers as to why this might be happening?
document.querySelector('#transfer-to-owner').onclick = () => {
console.log("Transfer about to begin")
try {
window.contract.transfer({})
} catch (e) {
'Something went wrong! ' +
'Check your browser console for more info.'
}
}
contract from this repo
const XCC_GAS: Gas = 20_000_000_000_000;
transfer(): void {
this.assert_owner()
assert(this.contributions.received > u128.Zero, "No received (pending) funds to be transferred")
const to_self = Context.contractName
const to_owner = ContractPromiseBatch.create(this.owner)
// transfer earnings to owner then confirm transfer complete
const promise = to_owner.transfer(this.contributions.received)
promise.then(to_self).function_call("on_transfer_complete", '{}', u128.Zero, XCC_GAS)
}
#mutateState()
on_transfer_complete(): void {
assert_self()
assert_single_promise_success()
logging.log("transfer complete")
// reset contribution tracker
this.contributions.record_transfer()
}
near-api-js and near-shell use a different default value for gas.
near-api-js:
const DEFAULT_FUNC_CALL_GAS = new BN('30_000_000_000_000');
near-shell:
.option('gas', {
desc: 'Max amount of gas this call can use (in gas units)',
type: 'string',
default: '100_000_000_000_000'
})
I added _s to make it clearer that near-shell uses more than 3 times the amount of gas by default.

Apollo Client on React - How to retrieve the error message fomated?

I can't find info about it in anywhere...
Consider this very simple scenario...
<Mutation mutation={LOGIN_MUTATION}>
{(login, { data, loading, error }) => {
if (error) {
console.log(error)
}
I am receiving a string error message like...
Error: GraphQL error: ERROR_INVALID_LOGIN_PROVIDER
at new ApolloError (bundle.umd.js:92)
at MutationData.onMutationCompleted (react-hooks.cjs.js:636)
at react-hooks.cjs.js:559
at tryCallOne (core.js:37)
at core.js:123
at JSTimers.js:289
at _callTimer (JSTimers.js:146)
at _callImmediatesPass (JSTimers.js:194)
at Object.callImmediates (JSTimers.js:458)
at MessageQueue.__callImmediates (MessageQueue.js:366)
I can't take actions based on the error message formated in this way. ERROR_INVALID_LOGIN_PROVIDER could be ERROR_INVALID_PASSWORD, for example...
I need to take decisions based on the error messages. but I just receive a string containing the graphql error, the modules inside the js and a lot of information that's not important. Is there any way to receive the error message formatted imn a way that I can extract only the server error ?
This should be possible
error in your example should be an ApolloError with the possible GraphQLErrors or a NetworkError
(login, { data, loading, error }) => {
if (error) {
if (error.graphQlErrors && error.graphQLErrors.length > 0) {
// There are graphQL errors and there may be multiple but its always an array.
// You should handle it properly
const { message } = error.graphQLErrors[0]
console.log(message) // e.g. ERROR_INVALID_LOGIN_PROVIDER
} else if (error.networkError) {
// There may be a network error
const { message } = error.networkError
console.log(message) // e.g. NetworkError when attempting to fetch resource.
}
}

Resources