Ensure you have a .env
file or other definition with your chosen relayer endpoint. We have provided a sample one here.
RELAYER_API_URL=https://relayerapi.emailwallet.org
When you want more flexibility, you can deploy your own relayer via the Relayer Infrastructure.
These endpoints concern basic universal features like sending ERC20s and ERC721s. You can see how to hit this or staging APIs for account recovery or oauth login in those specific docs. For safe signers, simply adding an email wallet address to a Safe Wallet on Base Sepolia will automatically trigger the email-based signer flow -- to make that multichain, please reach out to the team.
Endpoint:
POST /api/createAccount
Request Body:
{
"email_addr": "[email protected]"
}
Example:
const createAccount = async (email) => {
const response = await fetch(`${RELAYER_API_URL}/api/createAccount`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email_addr: email }),
});
const textResponse = await response.text();
console.log("Parsed response:", textResponse);
return textResponse != "0x" ? textResponse : "";
};
createAccount('[email protected]')
.then(address => console.log('Account Address:', address))
.catch(error => console.error('Error:', error));
Endpoint:
POST /api/isAccountCreated
Request Body:
{
"email_addr": "[email protected]"
}
Example:
const isAccountCreated = async (email) => {
const response = await fetch(`${RELAYER_API_URL}/api/isAccountCreated`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email_addr: email }),
});
const text = await response.text();
return text == "true" ? "Account exists" : "Account does not exist";
};
isAccountCreated('[email protected]')
.then(status => console.log('Account Status:', status))
.catch(error => console.error('Error:', error));
Endpoint:
POST /api/send
Request Body:
{
"email_addr": "[email protected]",
"amount": 100,
"token_id": "token123",
"recipient_addr": "[email protected]",
"is_recipient_email": true
}
Example:
const sendAsset = async (amountString, tokenId, recipientAddr) => {
const email = localStorage.getItem("loggedInUser") || "";
const isRecipientEmail = recipientAddr.includes("@");
const amount = parseFloat(amountString);
const response = await fetch(`${RELAYER_API_URL}/api/send`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email_addr: email,
amount,
token_id: tokenId,
recipient_addr: recipientAddr,
is_recipient_email: isRecipientEmail,
}),
});
const data = await response.text();
return data ? "Asset sent successfully" : "Failed to send asset";
};
sendAsset('100', 'token123', '[email protected]')
.then(status => console.log('Send Status:', status))
.catch(error => console.error('Error:', error));
Endpoint:
POST /api/recoverAccountCode
Request Body:
{
"email_addr": "[email protected]"
}
Example:
const recoverAccountCode = async (email) => {
const response = await fetch(`${RELAYER_API_URL}/api/recoverAccountCode`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email_addr: email }),
});
const data = await response.text();
return data
? "Account key recovery email sent"
: "Failed to send account key recovery email";
};
recoverAccountCode('[email protected]')
.then(status => console.log('Recovery Status:', status))
.catch(error => console.error('Error:', error));
Endpoint:
POST /api/getWalletAddress
Request Body:
{
"email_addr": "[email protected]",
"account_code": "<characters with 256 bits of entropy>"
}
Example:
const getWalletAddress = async (email, accountKey) => {
let code = accountKey.startsWith("0x") ? accountKey : `0x${accountKey}`;
const response = await fetch(`${RELAYER_API_URL}/api/getWalletAddress`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email_addr: email, account_code: code }),
});
const data = await response.text();
return data || "Failed to fetch address, no address found";
};
getWalletAddress('[email protected]', 'accountKey123')
.then(address => console.log('Wallet Address:', address))
.catch(error => console.error('Error:', error));
Endpoint:
POST /api/nftTransfer
Request Body:
{
"email_addr": "[email protected]",
"nft_id": 123,
"nft_addr": "0xNFTContractAddress",
"recipient_addr": "[email protected]",
"is_recipient_email": true
}
Example:
const transferNFT = async (nftId, nftAddr, recipientAddr) => {
const email = localStorage.getItem("loggedInUser") || "";
const isRecipientEmail = recipientAddr.includes("@");
const response = await fetch(`${RELAYER_API_URL}/api/nftTransfer`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email_addr: email,
nft_id: Number(nftId),
nft_addr: nftAddr,
recipient_addr: recipientAddr,
is_recipient_email: isRecipientEmail,
}),
});
const data = await response.text();
return data ? "NFT transferred successfully" : "Failed to transfer NFT";
};
transferNFT('nft123', '0xNFTContractAddress', '[email protected]')
.then(status => console.log('Transfer Status:', status))
.catch(error => console.error('Error:', error));