Skip to content

Muzikanto/react-near

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

react-near

Introduction

Quick implementation of near in your application. Generation of typed smart contract methods. Including ready for use typed methods in popular smart contract Standards.

Navigation

Setup

You'll need to install the package from npm npm i react-near near-api-js.

If you need to generate contract methods npm i -D json-schema-to-typescript fzstd.

Quick Example

// config.ts
const FT_CONTRACT_NAME = 'mfight-ft.testnet';

// app.tsx
function MyApp({ Component, pageProps }: AppProps) {
   return (
      <NearEnvironmentProvider defaultEnvironment={NearEnvironment.TestNet}>
         <NearProvider authContractId='my-contract.testnet'>
            <Component {...pageProps} />
         </NearProvider>
      </NearEnvironmentProvider>
   );
}

// page.tsx
function Page() {
   const nearUser = useNearUser();

   const { data: ftBalance = '0', refetch: refetchFtBalance } = useFtBalanceOf({
      contract: 'mfight-ft.testnet',
      variables: { account_id: nearUser.address as string },
      poolInterval: 1000 * 60 * 5,
      skip: !nearUser.isConnected,
   });
   const [transferCall] = useFtTransferCall({
      contract: 'mfight-ft.testnet',
      gas: GAS_FOR_FT_TRANSFER_CALL,
   });

   const handleTransferCall = () =>
      transferCall(
         { receiver_id: 'example.near', amount: 1000, msg: JSON.stringify({}) },
         parseNearAmount('0.01'),
      );
   const handleSignIn = () => nearUser.connect();

   return (
      <div>
         {nearUser.isConnected && (
            <>
               <span>NEAR balance: {nearUser.balance}</span>
               <span>FT balance: {formatNearAmount(ftBalance, 24)}</span>
               <button onClick={handleTransferCall}>transfer ft</button>
            </>
         )}
         {!nearUser.isConnected && <button onClick={receiver_id}>Connect NEAR</button>}
      </div>
   );
}

Codegen

If you want to generate all the methods of your near contract, you have to:

  • you need to add the abi feature, as in this example abi-example
  • run npm i -D json-schema-to-typescript fzstd
  • add config to your project react-near.json
{
   "dist": "near-api",
   "type": "default", // or "raw", for exclude all hooks
   "contracts": [
      {
         "name": "Nft",
         "abi": "abi/nft.json",
         "mainnet": "mfight-nft.near",
         "testnet": "mfight-nft_v2.testnet"
      },
      {
         "name": "Market",
         "mainnet": "mfight-nft.near",
         "testnet": "mfight-nft_v2.testnet"
      }
   ]
}
  • run script node ./node_modules/react-near/codegen.js

There is also an example: example-app

Api

NearProvider

Create a context of NEAR in the application

// app.tsx
function MyApp({ Component, pageProps }: AppProps) {
   return (
      <NearProvider authContractId='my-contract.testnet'>
         <Component {...pageProps} />
      </NearProvider>
   );
}
function Page() {
   const near = useNear();
   const nearUser = useNearUser();
   const nearAccount = useNearAccount(nearUser.address);

   return (
      <>
         <span>User Address: {account.address}</span>
         <span>Balance: {nearAccount?.balance} NEAR</span>
      </>
   );
}

NearEnvironmentProvider

The state of ENV will be saved in a cookie

// app.tsx
function MyApp({ Component, pageProps }: AppProps) {
   return (
      <NearEnvironmentProvider defaultEnvironment={NearEnvironment.TestNet}>
         <Component {...pageProps} />
      </NearEnvironmentProvider>
   );
}
function Page() {
   const nearEnv = useNearEnv();

   const handleChangeEnv = () => nearEnv.update(NearEnvironment.TestNet);

   return (
      <>
         <span>Current Env: {nearEnv.value}</span>
         <button onClick={handleChangeEnv}>switch to testnet</button>
      </>
   );
}

useNearUser

Everything you need to manage your account

function Page() {
   const nearUser = useNearUser();

   return (
      <>
         <button onClick={() => nearUser.connect()}>Connect wallet</button>
         <button onClick={() => nearUser.disconnect()}>Disconnect wallet</button>

         <span>Is Connected: {nearUser.isConnected}</span>
         <span>Address: {nearUser.address}</span>
      </>
   );
}

Batch transactions

For example, if you need to transfer 2 coins into a liquidity pool in single call

const MT_CONTRACT_ID = 'mt-token.testnet';
const FT_CONTRACT_ID_1 = 'ft-token-one.testnet';
const FT_CONTRACT_ID_2 = 'ft-token-two.testnet';
const POOL_CONTRACT_ID = 'two-tokens-receiver.testnet';

function Page() {
   const nearUser = useNearUser();

   const [ftTransferCall1, ftTransferCallCtx1] = useFtTransferCall({
      contract: 'mfight-ft.testnet',
      gas: GAS_FOR_FT_TRANSFER_CALL,
   });
   const [ftTransferCall2, ftTransferCallCtx2] = useFtTransferCall({
      contract: 'mfight-ft.testnet',
      gas: GAS_FOR_FT_TRANSFER_CALL,
   });
   const [mtBatchTransferCall, mtTransferCallCtx] = useMtBatchTransferCall({
      contract: 'mfight-ft.testnet',
      gas: GAS_FOR_MT_TRANSFER_CALL,
   });

   const handleTransfer = async () => {
      const amount1 = parseNearAmount('1') as string;
      const amount2 = parseNearAmount('1') as string;

      return nearUser.signAndSendTransactions({
         transactions: [
            {
               signerId: nearUser.address as string,
               receiverId: MT_CONTRACT_ID,
               actions: [
                  {
                     type: 'FunctionCall',
                     params: {
                        methodName: 'ft_transfer',
                        args: btoa(JSON.stringify({ receiver_id: 'xx', amount: '1' })),
                        gas: 'xxx',
                        deposit: '1',
                     },
                  },
               ],
            },
         ],
      });
   };

   return (
      <>
         <button onClick={handleTransfer}>Batch Transactions</button>
      </>
   );
}

useNearQuery

Calling the view method from the contract

function Page() {
   const nearUser = useNearUser();

   const {
      data: balance = '0', // method result
      loading, // waiting for result or error
      error, // error, if exists
      refetch, // refresh state
   } = useNearQuery<string, { account_id: string }>('ft_balance_of', {
      contract: 'mfight-ft.testnte', // contract of method
      variables: {
         account_id: 'account.near',
      }, // arguments of method
      poolInterval: 1000 * 60, // refresh state with interval
      skip: !nearUser.isConnected, // method will not be called
      debug: true, // debug method, print info to console
      onError: (err) => console.log(err), // error handler
      onCompleted: (res) => console.log(res), // result handler
   });

   return (
      <>
         <span>Balance: {formatNearAmount(balance)}</span>
         {loading && <span>Loading...</span>}
         {error && <span>Error: {error}</span>}
         <button onClick={() => refetch({}).catch(console.log)}>Force Refresh</button>
      </>
   );
}

useNearMutation

Calling the change method from the contract

function Page() {
   const nearUser = useNearUser();

   const [transfer, { loading, data }] = useNearMutation<
      string,
      { receiver_id: string; amount: string }
   >('ft_transfer', {
      gas: NEAR_GAS, // gas for this method
      contract: 'mfight-ft.testnet',
      debug: true, // debug method, print info to console
      onError: (err) => console.log(err), // error handler
      onCompleted: (res) => console.log(res), // result handler
   });

   return (
      <>
         <span>Result: {data}</span>
         {loading && <span>Loading...</span>}
         <button
            onClick={() =>
               transfer(
                  { amount: parseNearAmount('10'), receiver_id: 'account.near' },
                  parseNearAmount('0.01') as string,
               ).catch(console.log)
            }
         >
            Tranfer
         </button>
      </>
   );
}

useNearStatus

Get result transactions hashes if method is success, or get error if failure

function Page() {
   const { transactionHashes, error } = useNearStatus();

   return (
      <>
         {transactionHashes && <span>Success Tx List: {transactionHashes}</span>}
         {error && <span>{error}</span>}
      </>
   );
}

Contracts

NFT

  • nft_metadata
  • nft_token
  • nft_transfer
  • nft_transfer_call
  • nft_tokens
  • nft_tokens_for_owner
  • nft_total_supply
  • nft_supply_for_owner
  • nft_is_approved
  • nft_approve
  • nft_revoke
  • nft_revoke_all
  • nft_payout
  • nft_transfer_payout

FT

  • ft_metadata
  • ft_transfer
  • ft_transfer_call
  • ft_balance_of
  • ft_total_supply

MT

  • mt_balance_of
  • mt_total_supply
  • mt_batch_transfer
  • mt_batch_transfer_call

Storage

  • storage_balance_of
  • storage_balance_bounds
  • storage_deposit
  • storage_withdraw
  • storage_unregister

Paras

  • nft_approve (useParasNftApprove)
  • get_market_data (useParasMarketData)
  • api collection-stats (useParasCollectionStats)

Ref Finance

  • get_pool (useRefFinancePool)

Utils

  • parseNearAmount with decimals
  • isValidNearAddress
  • parseNearDate
  • formatNearAddress
  • gas and more :)

Authors