Promise based NEAR Contract, NEAR Wallet, and NEAR RPC Client for browser. This was designed to facilitate the React integration with NEAR Blockchain and avoid the huge boilerplate of setting up a wallet and contract.
Documentation
Table of Contents
Features
- Simplified Wallet and Contract integration
- Supports the Promise API
- Easy to create a Contract Interface
- Wallet connection modal to be easily used
- Automatic transforms for JSON data
- Client side events to tell when the api is ready
- Helpful react hooks
- Cache System for contract
view
Installing
Using npm:
npm install @wpdas/naxios @near-wallet-selector/modal-ui@9.0.3
Using yarn:
yarn add @wpdas/naxios @near-wallet-selector/modal-ui@9.0.3
How to Use
Preparing it
Import the NEAR Wallet Selector styles. The app needs it to render the Wallet Selector correctly.
import '@near-wallet-selector/modal-ui/styles.css'
Using It
It's super easy to get a Wallet and/or Contract API in place all at once. Take a look:
import naxios from '@wpdas/naxios'
const naxiosInstance = new naxios({
rpcNodeUrl: 'https://free.rpc.fastnear.com',
fallbackRpcNodesUrls: ['https://free.rpc.fastnear.com', 'https://near.lava.build:443'],
contractId: CONTRACT_ID,
network: 'testnet',
})
export const walletApi = naxiosInstance.walletApi()
export const contractApi = naxiosInstance.contractApi()
export const socialDBcontractApi = naxiosInstance.contractApi({ contractId: 'v1.social08.testnet' })
export const greetingContractApi = naxiosInstance.contractApi({
contractId: 'dev-1692221685438-15421910364142',
})
export const rpcApi = naxiosInstance.rpcApi()
Opening the Sign-in Wallet Selector Modal
You can open up the NEAR Wallet Selector modal by calling signInModal():
import { walletApi } from './web3Api'
walletApi.signInModal()
Customizing the Wallets Options for NEAR Wallet Selector
By default, naxios only uses @near-wallet-selector/my-near-wallet as a means of connecting the wallet. However, you can add other wallet selectors as follows:
npm install @near-wallet-selector/ledger @near-wallet-selector/my-near-wallet
Then, you can start naxius as follows:
import naxios from '@wpdas/naxios'
import { setupMyNearWallet } from '@near-wallet-selector/my-near-wallet'
import { setupLedger } from '@near-wallet-selector/ledger'
const naxiosInstance = new naxios({
contractId: CONTRACT_ID,
network: 'testnet',
walletSelectorModules: [setupMyNearWallet(), setupLedger()],
})
export const walletApi = naxiosInstance.walletApi()
Find out all the NEAR wallet selectors here: NEAR Wallet Selector
Contract API Reference
view: Make a read-only call to retrieve information from the network. It has the following parameters:
method: Contract's method name.
props?: an optional parameter with args for the contract's method.
config?: currently, this has the useCache and expirationTime prop. When useCache is true, this is going to use non-expired cached data instead of calling the contract's method. expirationTime prop can be used to overwrite the default expiration time set while calling contractApi method.
call: Call a method that changes the contract's state. This is payable. It has the following parameters:
method: Contract's method name
props?: an optional parameter with args for the contract's method, gas, deposit to be attached and callbackUrl if you want to take the user to a specific page after a transaction succeeds.
callMultiple: Call multiple methods that change the contract's state. This is payable and has the following parameters:
transactionsList: A list of Transaction props. You can use buildTransaction(...) to help you out
callbackUrl?: A page to take the user to after all the transactions succeed.
Wallet API Reference
accounts: Signed-in Accounts.
accountId: Main/first signed-in account ID in the accounts list.
contractId: Contract ID.
initNear: Initializes a connection to the NEAR blockchain. This is called automatically when there's any contract interaction.
network: Current network (testnet, mainnet or localnet).
recentlySignedInWallets: Returns ID-s of 5 recently signed in wallets.
selectedWalletId: Selected Wallet Id
signInModal: Open up the Signin Wallet Modal.
wallet: Wallet instance.
walletSelector: WalletSelector instance.
Contract View
Using a view method is free.
import { greetingContractApi } from './web3Api'
greetingContractApi.view<string>('get_greeting').then((response) => console.log(response))
Contract Call
You need to pay for every request you make for a call method. This is going to change data and store it within the blockchain.
import { greetingContractApi } from './web3Api'
const args: { message: 'Hi there!!!' }
greetingContractApi.call<string | undefined>('set_greeting', args).then((response) => console.log(response || 'done!'))
Contract Multiple Calls at Once
As well as the call, you will need to pay for every request you make. This is going to change data and store it within the blockchain.
import { buildTransaction } from '@wpdas/naxios'
import { contractApi } from './web3Api'
const transactionA = buildTransaction('set_greeting', { args: { greeting: 'Hello my dear!' } })
const transactionB = buildTransaction('set_age', { args: { age: 22 } })
const transactionC = buildTransaction('update_state', {
receiverId: 'my-state-contract.testnet',
args: { allowed: true },
})
const callbackUrl = 'https://my-page.com/callback-success'
contractApi.callMultiple([transactionA, transactionB, transactionC], callbackUrl).then(() => console.log('Done!'))
Cache System
There are two kinds of cache systems to be used. They are Memory Cache and Storage Cache.
Memory Cache: will be cleared when the app refreshes, as its data lives in memory only.
Storage Cache: The data will remain even when the browser tab is refreshed. Data is persisted using Local Storage.
When instantiating a cache, you need to provide the expirationTime (in seconds). This is used as the default value of expirantion and to know when the cache should be returned instead of making a real contract call. When the cache expires, a real call to the contract is made. Each contract's method has its own time of expiration.
import naxios, { StorageCache } from '@wpdas/naxios'
export const cachedGreetingContractApi = naxiosInstance.contractApi({
contractId: 'dev-1692221685438-15421910364142',
cache: new StorageCache({ expirationTime: 5 * 60 }),
})
Then, to use cached view, you can just pass the configuration object saying you want to use cached data.
import { cachedGreetingContractApi } from './web3Api'
const args: {}
const config: { useCache: true }
cachedGreetingContractApi.view<string>('get_greeting', args, config).then((response) => console.log(response))
NEAR RPC API
Naxios also provides access to the NEAR RPC API, so that you can query any data you want. Visit NEAR RPC API Docs to learn how to use it.
import { rpcApi } from './web3Api'
rpcApi
.query({
request_type: 'view_account',
finality: 'final',
account_id: 'wendersonpires.near',
})
.then((data) => console.log('Account Data:', data))
Utils
queueCalls
queueCalls can be used to queue promise function calls so that they are executed linearly one after another.
import { queueCalls } from '@wpdas/naxios'
const promise1 = queueCalls.queue(() => promiseMethod1())
const promise2 = queueCalls.queue(() => promiseMethod2())
buildTransaction
The buildTransaction method is useful when you need to build a contract's Transaction body, mainly when you want to make multiple contract calls.
See reference here.
validateNearAddress
This is used to check if an address is a valid NEAR address.
import { validateNearAddress } from '@wpdas/naxios'
console.log(validateNearAddress('fake.near'))
console.log(validateNearAddress('fake.nears'))
console.log(validateNearAddress('fake.testnet'))
console.log(validateNearAddress('fake'))
calculateDepositByDataSize
Calculate required deposit for data being stored. (~0.00001N per byte) with a bit extra for buffer
import { calculateDepositByDataSize } from '@wpdas/naxios'
const myData = { age: 22, name: 'user name' }
console.log(calculateDepositByDataSize(myData))
isClient
Simple checker to say if this is running on server or client.
import { isClient } from '@wpdas/naxios'
if (isClient()) {
console.log('Hi from client')
} else {
console.log('Hi from server')
}
Contributing
Feel free to open issues or pull requests. For major changes, please open an issue first to discuss what you would like to change.