FAQ for NEAR JavaScript API
A collection of Frequently Asked Questions by the community.
General
Can I use near-api-js
on a static html page?
You can load the script from a CDN.
<script src="https://cdn.jsdelivr.net/npm/near-api-js@0.45.1/dist/near-api-js.min.js"></script>
Make sure you load the latest version.
Versions list is on npmjs.com
Example Implementation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<ul id="messages"></ul>
<textarea id="text" placeholder="Add Message"></textarea>
<button id="add-text">Add Text</button>
<script src="https://cdn.jsdelivr.net/npm/near-api-js@0.45.1/dist/near-api-js.min.js"></script>
<script>
// connect to NEAR
const near = new nearApi.Near({
keyStore: new nearApi.keyStores.BrowserLocalStorageKeyStore(),
networkId: 'testnet',
nodeUrl: 'https://rpc.testnet.near.org',
walletUrl: 'https://testnet.mynearwallet.com/'
});
// connect to the NEAR Wallet
const wallet = new nearApi.WalletConnection(near, 'my-app');
// connect to a NEAR smart contract
const contract = new nearApi.Contract(wallet.account(), 'guest-book.testnet', {
viewMethods: ['getMessages'],
changeMethods: ['addMessage']
});
const button = document.getElementById('add-text');
if (!wallet.isSignedIn()) {
button.textContent = 'SignIn with NEAR'
}
// call the getMessages view method
contract.getMessages()
.then(messages => {
const ul = document.getElementById('messages');
messages.forEach(message => {
const li = document.createElement('li');
li.textContent = `${message.sender} - ${message.text}`;
ul.appendChild(li);
})
});
// Either sign in or call the addMessage change method on button click
document.getElementById('add-text').addEventListener('click', () => {
if (wallet.isSignedIn()) {
contract.addMessage({
args: { text: document.getElementById('text').value },
amount: nearApi.utils.format.parseNearAmount('1')
})
} else {
wallet.requestSignIn({
contractId: 'guest-book.testnet',
methodNames: ['getMessages', 'addMessage']
});
}
});
</script>
</body>
</html>
What front-end frameworks can I use the JavaScript API with?
The JavaScript API is framework-agnostic. You can include it in any front-end framework, such as React, Vue, Angular, and others.
You can use create-near-app
to quickly bootstrap projects with different templates:
npx create-near-app
Can I use the JavaScript API with mobile JavaScript frameworks such as React Native?
The JavaScript API can be used in most JavaScript runtimes, and under the hood, it’s an abstraction over NEAR’s RPC API. However, notice that the Wallet can’t be used everywhere. For example, in React Native apps you’ll be able to use the Wallet in web versions of the apps, but it won’t work in the native app deployments.
You can use the Wallet in WebView
components in iOS or Android, however be aware that it uses LocalStorage
for KeyStore
, and it’s your responsibility to persist the storage when you manage loading of WebView
components.
Transactions
How to check the status of transaction
Please refer to examples about transactions in the Cookbook.
How transactions are signed and sent by near-api-js
There are a few steps involved before transaction data is communicated to the network and eventually included in a block. The following steps are taken when creating, signing and ultimately a transaction from a user's account:
- The user creates a transaction object using the
account.signAndSendTransaction
method. This method accepts an array of actions and returns an object for the outcome of the transaction. - The transaction is signed using the
account.signTransaction
method. This method accepts an array of actions and returns a signed transaction object. - The signed transaction object is sent to the network using the
account.connection.provider.sendTransaction
method. This method accepts a signed transaction object and returns a transaction hash. This step performs the borsh serialization of the transaction object and calls thebroadcast_tx_commit
JSON RPC method with the serialized transaction object encoded in base64.
How to send batch transactions
You may batch send transactions by using the signAndSendTransaction({})
method from account
. This method takes an array of transaction actions, and if one fails, the entire operation will fail. Here's a simple example:
const { connect, transactions, keyStores } = require("near-api-js");
const fs = require("fs");
const path = require("path");
const homedir = require("os").homedir();
const CREDENTIALS_DIR = ".near-credentials";
const CONTRACT_NAME = "spf.idea404.testnet";
const WASM_PATH = path.join(__dirname, "../build/uninitialized_nft.wasm");
const credentialsPath = path.join(homedir, CREDENTIALS_DIR);
const keyStore = new keyStores.UnencryptedFileSystemKeyStore(credentialsPath);
const config = {
keyStore,
networkId: "testnet",
nodeUrl: "https://rpc.testnet.near.org",
};
sendTransactions();
async function sendTransactions() {
const near = await connect({ ...config, keyStore });
const account = await near.account(CONTRACT_NAME);
const args = { some_field: 1, another_field: "hello" };
const balanceBefore = await account.getAccountBalance();
console.log("Balance before:", balanceBefore);
try {
const result = await account.signAndSendTransaction({
receiverId: CONTRACT_NAME,
actions: [
transactions.deployContract(fs.readFileSync(WASM_PATH)), // Contract does not get deployed
transactions.functionCall("new", Buffer.from(JSON.stringify(args)), 10000000000000, "0"), // this call fails
transactions.transfer("1" + "0".repeat(24)), // 1 NEAR is not transferred either
],
});
console.log(result);
} catch (e) {
console.log("Error:", e);
}
const balanceAfter = await account.getAccountBalance();
console.log("Balance after:", balanceAfter);
}
Balance before: {
total: '49987878054959838200000000',
stateStaked: '4555390000000000000000000',
staked: '0',
available: '45432488054959838200000000'
}
Receipts: 2PPueY6gnA4YmmQUzc8DytNBp4PUpgTDhmEjRSHHVHBd, 3isLCW9SBH1MrPjeEPAmG9saHLj9Z2g7HxzfBdHmaSaG
Failure [spf.idea404.testnet]: Error: {"index":1,"kind":{"ExecutionError":"Smart contract panicked: panicked at 'Failed to deserialize input from JSON.: Error(\"missing field `owner_id`\", line: 1, column: 40)', nft/src/lib.rs:47:1"}}
Error: ServerTransactionError: {"index":1,"kind":{"ExecutionError":"Smart contract panicked: panicked at 'Failed to deserialize input from JSON.: Error(\"missing field `owner_id`\", line: 1, column: 40)', nft/src/lib.rs:47:1"}}
at parseResultError (/Users/dennis/Code/naj-test/node_modules/near-api-js/lib/utils/rpc_errors.js:31:29)
at Account.<anonymous> (/Users/dennis/Code/naj-test/node_modules/near-api-js/lib/account.js:156:61)
at Generator.next (<anonymous>)
at fulfilled (/Users/dennis/Code/naj-test/node_modules/near-api-js/lib/account.js:5:58)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
type: 'FunctionCallError',
context: undefined,
index: 1,
kind: {
ExecutionError: 'Smart contract panicked: panicked at \'Failed to deserialize input from JSON.: Error("missing field `owner_id`", line: 1, column: 40)\', nft/src/lib.rs:47:1'
},
transaction_outcome: {
block_hash: '5SUhYcXjXR1svCxL5BhCuw88XNdEjKXqWgA9X4XZW1dW',
id: 'SKQqAgnSN27fyHpncaX3fCUxWknBrMtxxytWLRDQfT3',
outcome: {
executor_id: 'spf.idea404.testnet',
gas_burnt: 4839199843770,
logs: [],
metadata: [Object],
receipt_ids: [Array],
status: [Object],
tokens_burnt: '483919984377000000000'
},
proof: [ [Object], [Object], [Object], [Object], [Object] ]
}
}
Balance after: {
total: '49985119959346682700000000',
stateStaked: '4555390000000000000000000',
staked: '0',
available: '45429729959346682700000000'
}
You may also find an example of batch transactions in the Cookbook.
Accounts
What’s the difference between Account
and ConnectedWalletAccount
?
Interaction with the wallet is only possible in a web-browser environment because NEAR’s Wallet is web-based.
The difference between Account
and ConnectedWalletAccount
is mostly about the way it signs transactions. The ConnectedWalletAccount
uses the wallet to approve transactions.
Under the hood the ConnectedWalletAccount
inherits and overrides some methods of Account
.
How to create implicit accounts?
You can read about it in the article about Implicit Accounts.
Contracts
How do I attach gas / a deposit?
After contract is instantiated you can then call the contract and specify the amount of attached gas.
await contract.method_name(
{
arg_name: "value", // argument name and value - pass empty object if no args required
},
"300000000000000", // attached GAS (optional)
"1000000000000000000000000" // attached deposit in yoctoNEAR (optional)
);