Awesome
<div align="center"> <p align="center"> <img src="./docs/head.png" alt="React Hook Form Logo - React hook custom hook for form validation" /> </p> </div> <div align="center"></div>
react-moralis
React components and hooks for your Moralis project
This project is a thin React wrapper around Moralis, to easily call functionalities and display data.
Please check the official documentation of Moralis for all the functionalities of Moralis.
⚙️ Quick start
Make sure to have react
, react-dom
and moralis-v1
installed as dependencies, then install react-moralis
In short:
npm install react react-dom moralis-v1 react-moralis
or
yarn add react react-dom moralis-v1 react-moralis
Make sure to also
moralis-v1
to the latest version, when you updatereact-moralis
.
Then wrap your app in a <MoralisProvider>
, and provide your appId and serverUrl:
import React from "react";
import ReactDOM from "react-dom";
import { MoralisProvider } from "react-moralis";
ReactDOM.render(
<MoralisProvider appId="xxxxxxxx" serverUrl="xxxxxxxx">
<App />
</MoralisProvider>,
document.getElementById("root"),
);
And call the hooks inside your app:
import React from "react";
import { useMoralis } from "react-moralis";
function App() {
const { authenticate, isAuthenticated, user } = useMoralis();
if (!isAuthenticated) {
return (
<div>
<button onClick={() => authenticate()}>Authenticate</button>
</div>
);
}
return (
<div>
<h1>Welcome {user.get("username")}</h1>
</div>
);
}
🧭 Table of contents
react-moralis
- ⚙️ Quick start
- 🧭 Table of contents
- 🚀 Usage
- Wrap your app in a
MoralisProvider
useMoralis()
useMoralisQuery()
useMoralisSubscription()
useMoralisFile()
useMoralisCloudFunction()
useMoralisWeb3Api()
useMoralisSolanaApi()
useNewMoralisObject()
useWeb3ExecuteFunction()
useWeb3Transfer()
useChain()
- Web3-api wrappers
- Dex Plugin Hooks
Web3
- Utils
- Components
- Wrap your app in a
- Handling responses
- Webpack v5 support
- 😖 Error handling
- ⌨️ Typescript
- ⚛️ React native
- 🧑💻 Development
🚀 Usage
Wrap your app in a MoralisProvider
In order to let your components have access to Moralis functions, wrap your app in a <MoralisProvider />
component. This will handle the whole initialization for you.
You need to provide the appId
and serverUrl
, which can be obtained from your dashboard.
<MoralisProvider appId="xxxxxxxx" serverUrl="xxxxxxxx">
<App />
</MoralisProvider>
This component will automatically initialize Moralis with the provided key and appId.
It will also keep the authentication of the user automatically in sync and easy accessible (see useMoralis
), and give access to all the other hooks.
Now you can use the hooks below in all App.tsx and all of its children:
useMoralis
for authentication and user datauseMoralisQuery
for easy queryuseMoralisCloudFunction
for easy cloud functionsuseMoralisSubscription
for easy subscriptionuseMoralisFile
for easy file uploads
useMoralis()
Initialize
By wrapping your app in a <MoralisProvider>
, it will automatically initialize with your provided appId and serverUrl:
<MoralisProvider
appId="xxxxxxxx"
serverUrl="xxxxxxxx"
>
<App />
</MoralisProvider>
If you want do not want to initialize automatically, but rather do it manually, you can provide the initializeOnMount=false
prop:
<MoralisProvider
initializeOnMount={false}
>
<App />
</MoralisProvider>
and then when you're ready to initialize, call initialize
:
const { initialize, isInitialized } = useMoralis()
<Button
disabled={isInitialized}
onClick={()=>{
initialize({
appId: 'xxx',
serverUrl: 'xxx'
})
}}
>
Initialize
</Button>
Or alternatively, you can set the appId
and serverUrl
on the MoralisProvider
and call initialize
without any params:
<MoralisProvider
initializeOnMount={false}
appId="xxx"
serverUrl="xxx"
>
<App />
</MoralisProvider>
const { initialize, isInitialized } = useMoralis()
<Button
disabled={isInitialized}
onClick={()=>{initialize()}}
>
Initialize
</Button>
and then when you're ready to initialize, call initialize
:
const { initialize, isInitialized } = useMoralis()
<Button onClick={()=>{
initialize({
appId: 'xxx',
serverUrl: 'xxx'
})
}}>
Initialize
</Button>
If you do not specify initializeOnMount={false}
, or set initializeOnMount={true}
, then you must specify the appId and serverUrl directly on <MoralisProvider>
when the app renders.
Authenticate
The useMoralis
hook provides all the basics functionalities that you need for authentication and user data.
You can use it inside a component and have access to various data and functions:
const { Moralis, isInitialized, ...rest } = useMoralis();
You will have access to the following values by using this hook:
Option | Description |
---|---|
Moralis | The global Moralis instance (same as the global Moralis object) |
isInitialized | A boolean, indicating if Moralis has been initialized |
isInitializing | A boolean, indicating if Moralis is currently initializing |
Option | Description |
---|---|
authenticate() | The authentication function, to authenticate via web3 |
logout() | The logout function that will end the users session |
signup() | The signup function that will signup a new user with an username and password |
signin() | The signin function that will sign in a user with a username and password |
auth | Auth state object (see below) |
authError | Error object when authentication failed (auth.state will be "error"); |
isAuthenticated | A boolean, indication if authenticated |
isUnauthenticated | A boolean, indication if user is authenticated |
isAuthenticating | A boolean, indication if user is authenticating (started but not finished) |
hasAuthError | A boolean, indication if authentication has an error |
isLoggingOut | A boolean, indication if the user is logging out (started but not finished) |
isAuthUndefined | A boolean, indication if the authentication is unknown, this is the initial state, before checking if the user is already logged in. It will resolve withing a few ms into isAuthenticated or isUnauthenticated |
Option | Description |
---|---|
setUserData() | function to set userData and directly sync it in the app AND Moralis (see below) |
user | user object from Moralis.User.current , containing the state of the logged in user. It automatically will be (un)set automatically when logging in and out, or setting user data |
enableWeb3 | function to enable web3 |
web3 | The web3 instance of Moralis.Web3 ; |
isWeb3Enabled | Boolean to indicate if web3 has been enabled via the enableWeb3 function |
account | address of the connected web3 wallet |
chainId | chain id of the blockchain that the web3 wallet is connected to |
Authentication state
The authentication state, and the user object will be updated, when the user authenticates or logs out.
The auth object has the following format:
{
state: "unauthenticated",
error: null,
}
where state can be one of the following enums
enum AuthenticationState {
UNDEFINED = "undefined",
UNAUTHENTICATED = "unauthenticated",
AUTHENTICATED = "authenticated",
AUTHENTICATING = "authenticating",
LOGGING_OUT = "logging_out",
ERROR = "error",
}
authenticate()
(web3)
You can call the authenticate()
function to authenticate the user via web3, as long as a user has an active web3Provider (such as MetaMask).
This function calls the MoralisWeb3.authenticate()
internally and will update the auth
state and user
state of your app automatically.
Example:
const User = () => {
const { authenticate, isAuthenticated, user } = useMoralis();
if (!isAuthenticated) {
return (
<div>
<button onClick={() => authenticate()}>Authenticate</button>
</div>
);
}
return (
<div>
<h1>Hi {user.get("username")}</h1>
</div>
);
};
If you need direct feedback after authentication, you can provide an option
object as argument to the authenticate
call with onComplete
, onError
and/or onSuccess
:
Example:
authenticate({ onComplete: () => alert("🎉") })
Elrond
If you want to authenticate via Elrond, you can provide the "erd"
authentication type in the options type:
authenticate({ type: "erd" })
Walletconnect
If you want to use walletconnect, instead of metamask, you can add the provider
option:
authenticate({ provider: "walletconnect" })
For some wallets you might want to specify the default chainId, to do so you can provide a chainId
option:
authenticate({ provider: "walletconnect", chainId: 56 })
Custom signing message
To adjust the signing message, you can provide signingMessage
as an option:
authenticate({ signingMessage: "Moralis Authentication" })
signup()
(non-crypto)
To signup users without web3, and use a password/username, you can use the signup function.
Example:
const Signup = () => {
const { signup, isAuthenticated, user } = useMoralis();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [email, setEmail] = useState("");
return (
<div>
// [Your form and inputs somewhere here... ]
<button onClick={() => signup(username, password, email)}>Sign up</button>
</div>
);
};
If you need to provide more data, than just the username, password and email, then you can provide an extra argument with an object, containing the data:
Example:
signup(username, password, email, { phone: "01234567" });
After calling this function the auth
and user
will automatically be updated to reflect the new state.
login()
(non-crypto)
Similar to signup, you can also login via a hook function:
Example:
const Login = () => {
const { login } = useMoralis();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
]
return (
<div>
// [Your form and inputs somewhere here... ]
<button onClick={() => login(username, password)}>Login</button>
</div>
);
};
After calling this function the auth
and user
will automatically be updated to reflect the new state.
logout()
Following the same principle as authentication/login, you can call logout
and let the MoralisProvider handle the internal authentication state.
Example:
const LogoutButton = () => {
const { logout, isAuthenticating } = useMoralis();
return (
<button onClick={() => logout()} disabled={isAuthenticating}>
Authenticate
</button>
)
};
After calling this function the auth
and user
will automatically be updated to reflect the new state.
Update the user with setUserData()
When you want to set userData, you can use the setUserData()
function from useMoralis
.
This accepts an object with key-value pairs of data that you want to set.
Upon calling this function:
- The user is updated on Moralis
- The user is updated in the React app
So this means that at the places where you use const {user} = useMoralis()
, the user data will automatically be updated.
Example:
const { setUserData, userError, isUserUpdating, user } = useMoralis();
return (
<div>
{userError && <p>{userError.message}</p>}
<pre>
{JSON.stringify(user)}
</pre>
<button
onClick={() => setUserData({
username: "Batman",
email: "batman@marvel.com",
numberOfCats: 12,
})}
disabled={isUserUpdating}
>
Set user data
</button>
</div>
)
Refetch user data refetchUserData()
When your user data gets updated outside the app (via cloudfunctions or in another session for example), you might want to force a refetch of the user data. You can use refetchUserData
for this.
Example:
const { refetchUserData, isUserUpdating, userError, user } = useMoralis();
return (
<div>
{userError && <p>{userError.message}</p>}
<pre>
{JSON.stringify(user)}
</pre>
<button onClick={() => refetchUserData()} disabled={isUserUpdating}>
Refetch user data
</button>
</div>
)
useMoralisQuery()
Fetch Queries
The useMoralisQuery
is heavily inspired by react-query. It handles all the async logic and manages the loading/error/data state internally and will automatically execute the query upon mounting in your component.
Example:
const { data, error, isLoading } = useMoralisQuery("GameScore");
This query will fetch "GameScore" for you when the component mounts.
The hook will return data
, error
and isLoading
, which you can use to render the component.
Example:
const { data, error, isLoading } = useMoralisQuery("GameScore");
if (error) {
return <span>🤯</span>;
}
if (isLoading) {
return <span>🙄</span>;
}
return <pre>{JSON.stringify(data, null, 2)}</pre>;
Filter queries
You can filer the query via a second argument. You can mutate the query in any way that Moralis.Query can.
Example:
const { data, error, isLoading } = useMoralisQuery("GameScore", query =>
query
.greaterThanOrEqualTo("score", 100)
.descending("score")
.limit(limit),
);
This example will fetch the top 3 scores that are at least 100, in descending order.
You can also filter dynamically, but you need to provide a dependency array as third argument (similar to other hooks), to specify when this hook needs to update.
Example:
const [limit, setLimit] = useState(3);
const { data, error, isLoading } = useMoralisQuery(
"GameScore",
query =>
query
.greaterThanOrEqualTo("score", 100)
.descending("score")
.limit(limit),
[limit],
);
Automatic updates with dependencies
This query will automatically refetch when the limit is changed.
If you want to disable the automatic fetching, you can also manually fetch. You need to provide autoFetch: false
as option in the 4th argument. In that case it will ignore the dependencies and will only fetch if you manually call fetch()
Example:
const { fetch, data, error, isLoading } = useMoralisQuery(
"GameScore",
query =>
query
.greaterThanOrEqualTo("score", 100)
.descending("score")
.limit(limit),
[],
{ autoFetch: false },
);
return <button onClick={() => fetch}>Fetch manually</button>;
Realtime / live queries
The useMoralisQuery
hook can also be used to update upon realtime events. All you need to do is provide live: true
. If any events update the query, then the data
is automatically updated.
Example:
const [limit, setLimit] = useState(3);
const { data, error, isLoading } = useMoralisQuery(
"GameScore",
query =>
query
.greaterThanOrEqualTo("score", 100)
.descending("score")
.limit(limit),
[limit],
{
live: true,
},
);
By default we use these rules
Eventname | Action |
---|---|
"create" | Add to the data |
"update" | Update if object is already in data |
"enter" | Add to the data |
"leave" | Remove to the data |
"delete" | Remove to the data |
You can override these rules with your own functions.
const [limit, setLimit] = useState(3);
const { data, error, isLoading } = useMoralisQuery(
"GameScore",
query =>
query
.greaterThanOrEqualTo("score", 100)
.descending("score")
.limit(limit),
[limit],
{
live: true,
onLiveEnter: (entity, all) => [...all, entity],
onLiveCreate: (entity, all) => [...all, entity],
onLiveDelete: (entity, all) => all.filter(e => e.id !== entity.id),
onLiveLeave: (entity, all) => all.filter(e => e.id !== entity.id),
onLiveUpdate: (entity, all) =>
all.map(e => (e.id === entity.id ? entity : e)),
},
);
useMoralisSubscription()
Listen for query events
This hook is used when you use useMoralisQuery
with live: true
. But if you want fine-grained control over subscriptions, and want to do actions upon the events, then you can use this hook.
It's as simple as calling this hook with the callbacks that you want. The first 3 arguments are the same as useMoralisQuery
(queryName, filter, dependencies). In the last argument, you can specify the callbacks:
Eventname | callback |
---|---|
"create" | onCreate |
"update" | onUpdate |
"enter" | onEnter |
"leave" | onLeave |
"delete" | onDelete |
They will all return the object as data.
For example if you want to notify when a new player was added:
Example:
useMoralisSubscription("GameScore", q => q, [], {
onCreate: data => alert(`${data.attributes.playerName} was just created`),
});
This hook will handle the subscribing and unsubscribing automatically. It will automatically subscribe/unsubscribe when the component mounts/unmounts. All you have to do is use this hook.
You can disable the subscription by providing: enabled: false
Example:
useMoralisSubscription("GameScore", q => q, [], {
onCreate: data => alert(`${data.attributes.playerName} was just created`),
enabled: false,
});
useMoralisFile()
Get the data, and saveFunction with the useMoralisFile
hook
const {
error,
isUploading,
moralisFile,
saveFile,
} = useMoralisFile();
Save to Moralis
All you need to do is call the save function with a valid file:
saveFile("batman.jpeg", file);
Then you can read the state from the provided variables error
,
isUploading
and
moralisFile
,
Save to IPFS
saveFile("batman.jpeg", file, { saveIPFS: true });
Then you can get the ipfs data via moralisFile._ipfs
and moralisFile._hash
or moralisFile.ipfs()
and moralisFile.hash()
Other options
Additionally you can also provide metadata, tags or specify the fileType in the options like:
Example:
const metadata = { createdById: "some-user-id" };
const tags = { groupId: "some-group-id" };
saveFile("batman.jpeg", file, {
type: "image/jpeg",
metadata,
tags,
saveIPFS: true,
});
useMoralisCloudFunction()
You can use the useMoralisCloudFunction
hook to run cloud functions easily. All you need to do is provide a name for the function, and it will automatically fetch the data for you.
Example:
const { data, error, isLoading } = useMoralisCloudFunction("topScores");
If you have a function that requires parameters, then you can provide it as second argument:
Example:
const { data, error, isLoading } = useMoralisCloudFunction("topScores", {
limit,
});
Trigger manually
If you rather want to trigger the fetching manually, you can provide autoFetch: false
as option. And call the fetch
function manually.
Example:
const { fetch, data, error, isLoading } = useMoralisCloudFunction(
"topScores",
{
limit
},
{ autoFetch: false }
);
<button onClick={() => fetch()}>Fetch manually<button>
useMoralisWeb3Api()
This hook will expose all the convenience functions of the Moralis.Web3API
in the sdk (ex. Web3Api.native.getBlock
or Web3Api.account.getNativeBalance
). You can use this function in any way you want, for example:
const Web3Api = useMoralisWeb3Api()
const fetchBlock = async() => {
const result = await Web3Api.native.getBlock({
block_number_or_hash: '100000'
})
console.log(result)
}
Resolve data with useMoralisWeb3ApiCall()
You can also use a resolver, to resolve the asynchronous function. This works similar to useMoralisQuery or useMoralisCloudFunction. It will resolve the data/error for you and will re-trigger if dependencies change.
For this you can use useMoralisWeb3ApiCall()
:
const [block, setBlock] = useState('100000');
const Web3Api = useMoralisWeb3Api()
const { fetch, data, error, isLoading } = useMoralisWeb3ApiCall(Web3Api.native.getBlock, {
block_number_or_hash: block,
});
return (
<div>
<button onClick={() => fetch()}>Refetch</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
)
useMoralisSolanaApi()
This hook will expose all the convenience functions of the Moralis.SolanaAPI
in the sdk (ex. SolanaApi.account.balance
). You can use this function in any way you want, for example:
const SolanaApi = useMoralisSolanaApi()
const fetchBalance = async() => {
const result = await SolanaApi.account.balance({
network: "mainnet",
address: "3yFwqXBfZY4jBVUafQ1YEXw189y2dN3V5KQq9uzBDy1E",
})
console.log(result)
}
Resolve data with useMoralisSolanaApiCall()
You can also use a resolver, to resolve the asynchronous function. This works similar to useMoralisQuery or useMoralisCloudFunction. It will resolve the data/error for you and will re-trigger if dependencies change.
For this you can use useMoralisSolanaApiCall()
:
const SolanaApi = useMoralisSolanaApi()
const { fetch, data, error, isLoading } = useMoralisSolanaApiCall(SolanaApi.account.balance, {
network: "mainnet",
address: "3yFwqXBfZY4jBVUafQ1YEXw189y2dN3V5KQq9uzBDy1E",
});
return (
<div>
<button onClick={() => fetch()}>Refetch</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
)
useNewMoralisObject()
This is a wrapper around the save method for a Moralis.Object
. It creates a new object, and resolves the data, error and loading state, similar to the other hooks.
Example:
const AddScoreButton = ({user, score}) => {
const { isSaving, error, save } = useNewMoralisObject('GameScore');
return (<div>
{error && <ErrorMessage error={error} />}
<button onClick={() => save({score, user})} disabled={isSaving}>Save score</button>
</div>)
}
useWeb3ExecuteFunction()
You can use the useWeb3ExecuteFunction
hook to execute on-chain functions. You need to provide the correct abi
of the contract, the corresponding contractAddress
, the functionName
that you would like to execute, and any parameters (params
) thet you need to send with the function.
Example:
const ShowUniswapObserveValues = () => {
const { data, error, fetch, isFetching, isLoading } = useWeb3ExecuteFunction({
abi: usdcEthPoolAbi,
contractAddress: usdcEthPoolAddress,
functionName: "observe",
params: {
secondsAgos: [0, 10],
},
});
return (<div>
{error && <ErrorMessage error={error} />}
<button onClick={() => fetch()} disabled={isFetching}>Fetch data</button>
{data && <pre>
{JSON.stringify(data),
null,
2,
)}
</pre>}
</div>)
}
Example with executing by fetch:
const ShowUniswapObserveValues = () => {
const { data, error, fetch, isFetching, isLoading } = useWeb3ExecuteFunction();
const options = {
abi: usdcEthPoolAbi,
contractAddress: usdcEthPoolAddress,
functionName: "observe",
params: {
secondsAgos: [0, 10],
},
}
return (<div>
{error && <ErrorMessage error={error} />}
<button onClick={() => fetch({ params: options })} disabled={isFetching}>Fetch data</button>
{data && <pre>
{JSON.stringify(data)}
</pre>}
</div>)
}
useWeb3Transfer()
You can use the useWeb3Transfer
hook to transfer any native coins (ETH, BNB etc.), or any ERC20, ERC721 or ERC1155 tokens.
Example:
const TransferEth = () => {
const {fetch, error, isFetching} = useWeb3Transfer({
amount: Moralis.Units.ETH(0.5),
receiver: "0x0000000000000000000000000000000000000000",
type: "native",
});
return (<div>
{error && <ErrorMessage error={error} />}
<button onClick={() => fetch()} disabled={isFetching}>Transfer</button>
</div>)
}
Example:
const TransferWeth = () => {
const {fetch, error, isFetching} = useWeb3Transfer({
amount: Moralis.Units.Token(20, 18),
receiver: "0x0000000000000000000000000000000000000000",
type: "erc20",
contractAddress: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
});
return (<div>
{error && <ErrorMessage error={error} />}
<button onClick={() => fetch()} disabled={isFetching}>Transfer</button>
</div>)
}
useChain()
Hook for fast network switching or getting info about current network. To change the current network, set the target chainId to switchNetwork
function. If the user does not have the target network in the wallet, it will automatically ask permission to add it to the wallet.
Example:
import { useChain } from "react-moralis";
function Chains() {
const { switchNetwork, chainId, chain, account } = useChain();
return (
<>
<button onClick={() => switchNetwork("0x1")}>Switch to Ethereum</button>
<p>Current chainId: {chainId}</p>
</>
);
}
Web3-api wrappers
useApiContract()
Execute a on-chain contract's function. It calls Moralis API and doesn't require web3 to be enabled.
Options
address
: The contract address (i.e. 0x1a2b3x...).functionName
: The name of the contract's function that you want to call.abi
: The contract's abi.chain
(optional): The blockchain to get data from. Valid values are listed on the intro page in the Transactions and Balances section. Default value: 'eth'.params
(optional): Any parameter you want to send with the function.
Example
import { useApiContract } from "react-moralis";
const {
runContractFunction,
data,
error,
isLoading,
isFetching,
} = useApiContract({
address: ensRegistryAddress,
functionName: "resolver",
abi: ensRegistryAbi,
params: { node: hashedDomain },
});
return (<div>
{error && <ErrorMessage error={error} />}
<button onClick={() => runContractFunction()} disabled={isFetching}>Run contract function</button>
{data && <pre>
{JSON.stringify(data),
null,
2,
)}
</pre>}
</div>)
Example return (Object)
{
"result": "0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41"
}
useERC20Balances()
Gets all token balances of a current user or specified address.
Options:
chain
(optional): The blockchain to get data from. Valid values are listed on the intro page in the Transactions and Balances section. Default value: current chain.address
(optional): A user address (i.e. 0x1a2b3x...). If specified, the user attached to the query is ignored and the address will be used instead.to_block
(optional): The block number on which the balances should be checked
Example
import { useERC20Balances } from "react-moralis";
const { fetchERC20Balances, data, isLoading, isFetching, error } = useERC20Balances();
const ERC20Balances = () => {
return (
<div>
{error && <>{JSON.stringify(error)}</>}
<button onClick={() => fetchERC20Balances({ params: { chain: "0x1" } })}>Refetch</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
Example return (Object)
{
"total": 1,
"page": 0,
"page_size": 500,
"result": [
{
"token_address": "0x2d30ca6f024dbc1307ac8a1a44ca27de6f797ec22ef20627a1307243b0ab7d09",
"name": "Kylin Network",
"symbol": "KYL",
"logo": "https://cdn.moralis.io/eth/0x67b6d479c7bb412c54e03dca8e1bc6740ce6b99c.png",
"thumbnail": "https://cdn.moralis.io/eth/0x67b6d479c7bb412c54e03dca8e1bc6740ce6b99c_thumb.png",
"decimals": "18",
"balance": "123456789"
}
]
}
useERC20Transfers()
Gets ERC20 token transfers of a current user or specified address.
Options:
chain
(optional): The blockchain to get data from. Valid values are listed on the intro page in the Transactions and Balances section. Default value: current chain.address
(optional): A user address (i.e. 0x1a2b3x...). If specified, the user attached to the query is ignored and the address will be used instead.from_date
(optional): The date from where to get the transactions (any format that is accepted by momentjs). Provide the param 'from_block' or 'from_date' If 'from_date' and 'from_block' are provided, 'from_block' will be used.to_date
(optional): Get the transactions to this date (any format that is accepted by momentjs). Provide the param 'to_block' or 'to_date' If 'to_date' and 'to_block' are provided, 'to_block' will be used.from_block
(optional): The minimum block number from where to get the transactions Provide the param 'from_block' or 'from_date' If 'from_date' and 'from_block' are provided, 'from_block' will be used.to_block
(optional): The maximum block number from where to get the transactions. Provide the param 'to_block' or 'to_date' If 'to_date' and 'to_block' are provided, 'to_block' will be used.offset
(optional): Offset.limit
(optional): Limit.
Example
import { useERC20Transfers } from "react-moralis";
const { fetchERC20Transfers, data, error, isLoading, isFetching, } = useERC20Transfers();
const ERC20Transfers = () => {
return (
<div>
{error && <>{JSON.stringify(error)}</>}
<button onClick={() => fetchERC20Transfers({ params: { chain: "0x1" } })}>Refetch</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
Example return (Object)
{
"total": 1,
"page": 0,
"page_size": 500,
"result": [
{
"transaction_hash": "0x2d30ca6f024dbc1307ac8a1a44ca27de6f797ec22ef20627a1307243b0ab7d09",
"address": "0x057Ec652A4F150f7FF94f089A38008f49a0DF88e",
"block_timestamp": "2021-04-02T10:07:54.000Z",
"block_number": "12526958",
"block_hash": "0x0372c302e3c52e8f2e15d155e2c545e6d802e479236564af052759253b20fd86",
"to_address": "0x62AED87d21Ad0F3cdE4D147Fdcc9245401Af0044",
"from_address": "0xd4a3BebD824189481FC45363602b83C9c7e9cbDf",
"value": "650000000000000000"
}
]
}
useNativeBalance()
Gets native balance for a current user or specified address.
Options:
chain
(optional): The blockchain to get data from. Valid values are listed on the intro page in the Transactions and Balances section. Default value: current chain.address
(optional): A user address (i.e. 0x1a2b3x...). If specified, the user attached to the query is ignored and the address will be used instead.to_block
(optional): The block number on which the balances should be checked
Example:
import { useNativeBalance } from "react-moralis";
function NativeBalance() {
const { getBalances, data: balance, nativeToken, error, isLoading } = useNativeBalance({ chain : "ropsten" });
return <div>{balance.formatted}</div>;
}
Example return of balance (Object)
{
balance: '996869309795359886',
formatted: '0.9969 ROP'
}
Example return of nativeToken (Object)
{
name: 'Ropsten Ether',
symbol: 'ROP',
decimals: 18
}
useNativeTransactions()
Gets the transactions from the current user or specified address. Returns an object with the number of transactions and the array of native transactions
Options:
chain
(optional): The blockchain to get data from. Valid values are listed on the intro page in the Transactions and Balances section. Default value: current chain.address
(optional): A user address (i.e. 0x1a2b3x...). If specified, the user attached to the query is ignored and the address will be used instead.from_date
(optional): The date from where to get the transactions (any format that is accepted by momentjs). Provide the param 'from_block' or 'from_date' If 'from_date' and 'from_block' are provided, 'from_block' will be used.to_date
(optional): Get the transactions to this date (any format that is accepted by momentjs). Provide the param 'to_block' or 'to_date' If 'to_date' and 'to_block' are provided, 'to_block' will be used.from_block
(optional): The minimum block number from where to get the transactions Provide the param 'from_block' or 'from_date' If 'from_date' and 'from_block' are provided, 'from_block' will be used.to_block
(optional): The maximum block number from where to get the transactions. Provide the param 'to_block' or 'to_date' If 'to_date' and 'to_block' are provided, 'to_block' will be used.offset
(optional): Offset.limit
(optional): Limit.
Example
import { useNativeTransactions } from "react-moralis";
const { getNativeTransations, data, chainId, error, isLoading, isFetching } = useNativeTransactions();
const NativeTransactions = () => {
return (
<div>
{error && <>{JSON.stringify(error)}</>}
<button onClick={() => getNativeTransations({ params: { chain: "0x1" } })}>Refetch</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
Example return (Object)
{
"total": 1,
"page": 0,
"page_size": 500,
"result": [
{
"hash": "0x057Ec652A4F150f7FF94f089A38008f49a0DF88e",
"nonce": "326595425",
"transaction_index": "25",
"from_address": "0xd4a3BebD824189481FC45363602b83C9c7e9cbDf",
"to_address": "0xa71db868318f0a0bae9411347cd4a6fa23d8d4ef",
"value": "650000000000000000",
"gas": "6721975",
"gas_price": "20000000000",
"input": "string",
"receipt_cumulative_gas_used": "1340925",
"receipt_gas_used": "1340925",
"receipt_contract_address": "0x1d6a4cf64b52f6c73f201839aded7379ce58059c",
"receipt_root": "string",
"receipt_status": "1",
"block_timestamp": "2021-04-02T10:07:54.000Z",
"block_number": "12526958",
"block_hash": "0x0372c302e3c52e8f2e15d155e2c545e6d802e479236564af052759253b20fd86"
}
]
}
useNFTBalances()
Gets all NFTs from the current user or address. Supports both ERC721 and ERC1155. Returns an object with the number of NFT objects and the array of NFT objects.
Options:
chain
(optional): The blockchain to get data from. Valid values are listed on the intro page in the Transactions and Balances section. Default value: current chain (if the chain is not supported it will use the Eth chain).address
(optional): A user address (i.e. 0x1a2b3x...). If specified, the user attached to the query is ignored and the address will be used instead.
Example
import { useNFTBalances } from "react-moralis";
const { getNFTBalances, data, error, isLoading, isFetching } = useNFTBalances();
const NFTBalances = () => {
return (
<div>
{error && <>{JSON.stringify(error)}</>}
<button onClick={() => getNFTBalances({ params: { chain: "0x1" } })}>Refetch NFTBalances</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
Example return (Object)
{
"total": 1,
"page": 0,
"page_size": 500,
"result": [
{
"token_address": "0x057Ec652A4F150f7FF94f089A38008f49a0DF88e",
"token_id": "15",
"contract_type": "ERC721",
"owner_of": "0x057Ec652A4F150f7FF94f089A38008f49a0DF88e",
"block_number": "88256",
"block_number_minted": "88256",
"token_uri": "string",
"metadata": "string",
"synced_at": "string",
"amount": "1",
"name": "CryptoKitties",
"symbol": "RARI"
}
]
}
useNFTTransfers()
Gets the NFT transfers. Returns an object with the number of NFT transfers and the array of NFT transfers.
Options:
chain
(optional): The blockchain to get data from. Valid values are listed on the intro page in the Transactions and Balances section. Default value: current chain (if the chain is not supported it will use the Eth chain).address
(optional): A user address (i.e. 0x1a2b3x...). If specified, the user attached to the query is ignored and the address will be used instead.offset
(optional): Offset.direction
(optional): The transfer direction. Available values : both, to, from . Default value : both.format
(optional): he format of the token id. Available values : decimal, hex. Default value : decimal.limit
(optional): Limit.
Example
import { useNFTTransfers } from "react-moralis";
const { fetch, data, error, isLoading, isFetching } = useNFTTransfers();
const NFTTransfers = () => {
return (
<div>
{error && <>{JSON.stringify(error)}</>}
<button onClick={() => fetch({ params: { chain: "0x1" } })}>Refetch</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
};
Example return (Object)
{
"total": 1,
"page": 0,
"page_size": 500,
"result": [
{
"token_address": "0x057Ec652A4F150f7FF94f089A38008f49a0DF88e",
"token_id": "15",
"from_address": "0x057Ec652A4F150f7FF94f089A38008f49a0DF88e",
"to_address": "0x057Ec652A4F150f7FF94f089A38008f49a0DF88e",
"amount": "1",
"contract_type": "ERC721",
"block_number": "88256",
"block_timestamp": "2021-06-04T16:00:15",
"block_hash": "string",
"transaction_hash": "0x057Ec652A4F150f7FF94f089A38008f49a0DF88e",
"transaction_type": "string",
"transaction_index": "string",
"log_index": 0
}
]
}
useTokenPrice()
Gets the price nominated in the native token and usd for a given token contract address
Options:
chain
(optional): The blockchain to get data from. Valid values are listed on the intro page in the Transactions and Balances section. Default value: current chain (if the chain is not supported it will use the Eth chain).address
(optional): A user address (i.e. 0x1a2b3x...). If specified, the user attached to the query is ignored and the address will be used instead.exchange
(optional): The factory name or address of the token exchange. Possible exchanges, for different chains are: ETH mainnet:uniswap-v3
,sushiswap
,uniswap-v2
, BSC mainnet:pancakeswap-v2
,pancakeswap-v1
. Polygon mainnet:quickswap
. If no exchange is specified, all exchanges are checked (in the order as listed above) until a valid pool has been found. Note that this request can take more time. So specifying the exchange will result in faster responses most of the time.to_block
(optional): Returns the price for a given blocknumber (historical price-data).
Example
import { useTokenPrice } from "react-moralis";
const TokenPrice = () => {
const { fetchTokenPrice, data: formattedData, error, isLoading, isFetching } = useTokenPrice({ address: "0x1f9840...1f984", chain: "eth" });
return (
<div>
{error && <>{JSON.stringify(error)}</>}
<button onClick={() => fetchTokenPrice({ params: { address: "0x6...361", chain: "bsc" } })}>Refetch</button>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
Example return (Object)
{
"exchangeAddress": "0x1f98431c8ad98523631ae4a59f267346ea31f984",
"exchangeName": "Uniswap v3",
"formattedNative": "0.004695 ETH",
"formattedUsd": "$20.38",
"nativePrice": {
"decimals": 18,
"name": "Ether",
"symbol": "ETH",
"value": "4695118425598734"
},
"usdPrice": 20.37791922835578
}
useWeb3Contract()
You can use the useWeb3Contract
hook to execute on-chain functions. You need to provide the correct abi
of the contract, the corresponding contractAddress
, the functionName
that you would like to execute, and any parameters (params
) thet you need to send with the function.
Options:
address
: The contract address (i.e. 0x1a2b3x...).functionName
: The name of the contract's function that you want to call.abi
: The contract's abi.params
(optional): Any parameter you want to send with the function.
Example:
const ShowUniswapObserveValues = () => {
const { data, error, runContractFunction, isFetching, isLoading } =
useWeb3Contract({
abi: usdcEthPoolAbi,
contractAddress: usdcEthPoolAddress,
functionName: "observe",
params: {
secondsAgos: [0, 10],
},
});
return (
<div>
{error && <ErrorMessage error={error} />}
<button onClick={() => runContractFunction()} disabled={isFetching}>
Fetch data
</button>
{data && <pre>{JSON.stringify(data)}</pre>}
</div>
);
};
Example with executing by fetch:
const ShowUniswapObserveValues = () => {
const { data, error, runContractFunction, isFetching, isLoading } =
useWeb3Contract();
const options = {
abi: usdcEthPoolAbi,
contractAddress: usdcEthPoolAddress,
functionName: "observe",
params: {
secondsAgos: [0, 10],
},
};
return (
<div>
{error && <ErrorMessage error={error} />}
<button
onClick={() => runContractFunction({ params: options })}
disabled={isFetching}
>
Fetch data
</button>
{data && <pre>{JSON.stringify(data)}</pre>}
</div>
);
};
Dex Plugin Hooks
useOneInchQuote()
Hook for getting swap quote info.
Example:
import { useOneInchQuote } from "react-moralis";
function Quote() {
const { getQuote, data, isFetching, isLoading, error } = useOneInchQuote({
chain: 'bsc', // The blockchain you want to use (eth/bsc/polygon)
fromTokenAddress: '0x0da6ed8b13214ff28e9ca979dd37439e8a88f6c4', // The token you want to swap
toTokenAddress: '0x6fd7c98458a943f469e1cf4ea85b173f5cd342f4', // The token you want to receive
amount: 1000,
});
return (
<div>
{error && <>{JSON.stringify(error)}</>}
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
useOneInchSwap()
Hook for swap.
Example:
import { useOneInchQuote } from "react-moralis";
function Swap() {
const { swap, data, isFetching, isLoading, error } = useOneInchSwap();
const options = {
chain: 'bsc', // The blockchain you want to use (eth/bsc/polygon)
fromTokenAddress: '0x0da6ed8b13214ff28e9ca979dd37439e8a88f6c4', // The token you want to swap
toTokenAddress: '0x6fd7c98458a943f469e1cf4ea85b173f5cd342f4', // The token you want to receive
amount: 1000,
fromAddress: '0x6217e65d864d77DEcbFF0CFeFA13A93f7C1dD064', // Your wallet address
slippage: 1,
}
return (
<div>
{error && <>{JSON.stringify(error)}</>}
<button onClick={()=> swap(options)}>Swap</button>
</div>
);
}
useOneInchTokens()
Hook for get supported token list.
Example:
import { useOneInchQuote } from "react-moralis";
const SupportedTokens = () => {
const { getSupportedTokens, data, isFetching, isLoading, error } = useOneInchTokens({ chain: 'bsc' });
return (
<div>
{error && <>{JSON.stringify(error)}</>}
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}
Web3
In order to use (non enabled) web3 functionalities, you can just use:
const { web3 } = useMoralis()
Enable web3 via metamask
If you need features from an enabled web3 instance, then you need to enable web3 first. By default, metamask will be used to get a provider:
Example:
const EnableWeb3 = ({user, score}) => {
const { web3, enableWeb3, isWeb3Enabled, isWeb3EnableLoading, web3EnableError } = useMoralis()
if(isWeb3Enabled){
return null
}
return <div>
{web3EnableError && <ErrorMessage error={web3EnableError} />}
<button onClick={() => enableWeb3()} disabled={isWeb3EnableLoading}>Enable web3</button>
</div>
}
Enable web3 via Walletconnect
Optionally, you can specify to use walletconnect as a provider, to enable web3 via walletconnect:
Example:
const EnableWeb3 = ({user, score}) => {
const { web3, enableWeb3, isWeb3Enabled, isWeb3EnableLoading, web3EnableError } = useMoralis()
if(isWeb3Enabled){
return null
}
return <div>
{web3EnableError && <ErrorMessage error={web3EnableError} />}
<button onClick={() => enableWeb3({provider: 'walletconnect'})} disabled={isWeb3EnableLoading}>Enable web3</button>
</div>
}
Utils
Resolve/Lookup ens names
If you want to resolve/lookup ENS names, then you can use useEnsName
or useEnsAddress
.
useEnsName
Resolve the ENS name and lookup the address, avatar, email and url details (if they are set)
example:
const {
address,
avatar,
email,
url,
isLoading,
error
} = useEnsName("ricmoo.eth");
useEnsAddress
Lookup if an ENS name is registered for the address example:
const { name, isLoading, error } = useEnsAddress("0x5555763613a12D8F3e73be831DFf8598089d3dCa");
Components
If you want to support Moralis, you can use the ByMoralis
component, to render our logo 🙏:
Example:
const App = () => {
import { ByMoralis } from "react-moralis";
return (
<div>
<ByMoralis width={300} />
<ByMoralis width={300} variant="dark" />
<ByMoralis width={300} variant="light" />
</div>
)
}
You can specify the color scheme; dark
, light
or colour
(default), the width (defaults to 250px) and a custom styling via the style
prop.
Handling responses
The easiest way to handle the responses of the different async methods (fetch, save etc.), is to read the data directly from the hook. The data will return error
, data
and isLoading
/isFetching
. These values can easily be used to (conditionally) render different parts of your app.
For other logic, you might want to listen directly for success/error responses. This is facilitated by passing one or more callback (onComplete
, onError
and/or onSuccess
) to the fetch/save etc. functions:
Callback | Description |
---|---|
onSuccess | Fires when the request resolves successfully. If possible it is returned with the resolved data. |
onError | Fires when the request returns an error. It will return the corresponding error. |
onComplete | Fires when a request finishes (regardless of a success/error response) |
Example:
const { fetch } = useMoralisQuery("GameScore");
const fetchAndNotify = () => {
fetch({
onSuccess: () => notifyUser(user.get("objectId")),
onError: (error) => showErrorToast(error)
});
};
Webpack v5 support
You may see the following error in your project:
ERROR in ../../node_modules/dotenv/lib/main.js 26:13-28
Module not found: Error: Can't resolve 'path' in '../node_modules/dotenv/lib'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
There are a lot of breaking changes in Webpack v5. Set up your project to work with moralis
and react-moralis
:
configuring Webpack v5
We highly recommend you to use the stable 4.0.3
version of Webpack. If you want to use Moralis on your project with Webpack v5 you need to add the fallback to your webpack.config.js
file:
module.exports = {
resolve: {
fallback: {
assert: require.resolve('assert'),
crypto: require.resolve('crypto-browserify'),
http: require.resolve('stream-http'),
https: require.resolve('https-browserify'),
os: require.resolve('os-browserify/browser'),
stream: require.resolve('stream-browserify'),
},
},
};
create-react-app
To be able to work with moralis
and react-moralis
on the create-react-app project you need to use the < 5
version of react-scripts
:
npx create-react-app --scripts-version 4.0.3
😖 Error handling
For most hooks, we will resolve the error for you in an error variable. For example, the following function will not throw an error (initially or when you call fetch
manually).
If you have a useCase where you do want to respond to an error directly you can provide throwOnError
as an options parameter. For example:
const { data, error, isLoading, fetch } = useMoralisQuery("GameScore");
const fetchAndUseError = async () => {
try {
await fetch({ throwOnError: true });
} catch (error) {
alert("You got an error");
}
};
⌨️ Typescript
This library offers first-class Typescript support.
⚛️ React native
In order to use this library with react-native, you need to provide the environment="native"
property to the MoralisProvider
. Also you need to provide the Moralis library from moralis/react-native.js
like:
import Moralis from "moralis-v1/react-native.js"
const getMoralis = () => Moralis
<MoralisProvider
appId={appId}
serverUrl={serverUrl}
environment="native"
getMoralis={getMoralis}
>
<App/>
</MoralisProvider>
🧑💻 Development
Make sure to have node
and yarn
installed.
- Clone this repo
-
cd react-moralis yarn install
Please follow the code guidelines before submitting a PR.
- Make sure the code is clear and readable
- Adhere to the style rules of Eslint, Prettier and Conventional Commit
Examples
React Boilerplate https://github.com/ethereum-boilerplate/ethereum-boilerplate
React Native Boilerplate https://github.com/ethereum-boilerplate/ethereum-react-native-boilerplate