# Smart Contract Call without NEAR Wallet Redirect

Published 2022-06-13

In this article we see how signing transactions work, why you are redirected to the NEAR Wallet when signing a transaction, and what are the applications where this can be used.


# How signing transactions work

When calling a function on a smart contract, a transaction must be signed and submitted to the NEAR blockchain. This is handles by near-api-js when a contract object’s method is called. This then results in the user being redirected to the NEAR Wallet site, where they sign the transaction, and then are redirected to your dApp.

But why is this needed, when the user has already signed in, and created a function access key? And similarly, how is it possible, that the key has to be limited to a specific smart contract, but we can create Contract objects that can interact with any smart contract, not just the one we are authorised for?

What happens behind the scenes, is that near-api-js creates the transaction, but doesn’t sign it itself, instead, it is passed to the Wallet to sign it. We can actually see this, by checking the key that is in the browser’s local storage (Press F12, go to Application, Local Storage) and comparing it to the key used when calling a method that originated from your dApp (this can be seen in the RPC endpoint when checking the Transaction Status). If compared, you can see that it was the user’s key that is in the NEAR Wallet that signed the transaction, not the one that is given to your dApp. The consequence of this, is that normal transactions don’t have the same limitations as FunctionAccess keys.

So in normal use, the user must be redirected to the Wallet page, but there they can interact with any contract you like. But what if you don’t want to have to redirect them?

# Signing a transaction without redirect

If you sign in with a NEAR Wallet, your dApp is given a function access key (more info about how the sign-in workflow works here). You could conceptually use this key to sign the transaction and submit it to the NEAR chain directly.

If your change method doesn't require a full access approval, near-api-js is smart enough to call these without wallet redirect, assuming of course that:

  • No deposit is attached
  • The function for which the key was created is called
  • Only the methods which were specified (if any) are called (if not specified any function is allowed)

However, it is also possible to force the function call, letting it fail if for some reason it cannot be executed with the key. To do this, we need to do a function call independent of the near-api-js wallet connection that handles the redirect. We can do this, by grabbing the near connection and user account id, and creating our own Account object, which then we can use to create the transaction:

const account = new Account(near.connection, wallet.account().accountId);

await account.functionCall({
  contractId: "my-contract.near",
  methodName: "method-to-call",
  args: {},
  gas: "300000000000000",
  attachedDeposit: "0",
});

This assumes that you have already created and configured a near and wallet objects.

const near = await connect(config);
const wallet = new WalletConnection(near, "my-dapp");

Let’s examine what happens here:

First we create an account using the existing connection and the wallet that was used to sign in:

const account = new Account(near.connection, wallet.account().accountId);

Then, we call the smart contract itself, specifying the contract and the method, any arguments, the attached gas and deposit:

await account.functionCall({
  contractId: "my-contract.near",
  methodName: "method-to-call",
  args: {},
  gas: "300000000000000",
  attachedDeposit: "0",
});

It is however important to note, that the contractId must match the one you used for wallet.requestSignIn, and attachedDeposit must be "0". But why?

# Limitations

The function call key the user created when signing in is very limited. It can only be used to call the specific smart contract and it has a limit of 0.25N that they can access, which it cannot transfer or deposit, only use to cover gas fees. If this allowance runs out, a new key must be generated.

This also means, that functions that require any amount of deposit, even if only 1 YoctoNEAR cannot be called with these keys.

It is also important to note that users expect to be redirected when interacting with the chain. And in some cases, this may lead to confusion, where a transaction happens, without the user knowing anything about it.