Build
Skip to content

Using your Embedded Wallet

Once the user has been authenticated, you can now utilize common web3 functions to interact with the blockchain - completely seamlessly.

  • Get Wallet Address: Access the wallet linked to the user's authenticated account. This wallet serves as the gateway to all account functions.
  • Sign Messages: Signing a message using the embedded wallet.
  • Send Transactions: After a user has been authenticated, use the WaaS SDK to send transactions using crafted EVM calldata.

Install SDK

If you have not already done so, make sure the Embedded Wallet SDK is installed in your project:

pnpm
pnpm install @0xsequence/waas

Get Wallet Address

Each user's wallet address is unique, cannot be changed, and is 42 characters long, starting with 0x:

import { SequenceWaaS } from "@0xsequence/waas";
 
const sequence = new SequenceWaaS(
  {
    projectAccessKey: `${process.env.VITE_PROJECT_ACCESS_KEY}`,
    waasConfigKey: `${process.env.VITE_WAAS_CONFIG_KEY}`,
    network: "arbitrum-nova",
  }
);
 
const { wallet } = await sequence.signIn({ idToken }, "Session name")
const address = await sequence.getAddress();
 
console.log(address == wallet) // true
 
console.log(address)
0xE4b10c53aa75E19E088cfDD0cff7D46a0E4206F0

Sign Messages

Wallets can sign messages, which can be validated both onchain and offchain:

import { SequenceWaaS } from "@0xsequence/waas";
 
const sequence = new SequenceWaaS(
  {
    projectAccessKey: `${process.env.PROJECT_ACCESS_KEY}`,
    waasConfigKey: `${process.env.WAAS_CONFIG_KEY}`,
    network: "arbitrum-nova",
  }
);
 
await sequence.signIn({ idToken }, "Session name");
 
const signature = await sequence.signMessage({
  chainId: 42170,
  message: "Hello world",
});
 
console.log(signature);
{
  "code": "signedMessage",
  "data": {
    "message": "0x48656c6c6f20776f726c64",
    "signature": "0x0100010000000002012128ff2dd168dc250dc3da93db3131f737e6961a0000fe0100030000000006010001000074000197013331090a763fc7ef2216502cfbff5d855530f977a0ee6db3615722ed9bad498781d8ed72d52b5c9717708ac757f7789c9567e5468566179bd03f72d1fc7b1c010400002c01011111b16c6268897233eddea98a041b326b0faef2010122229ce37ccfee1cbab2b743b22c314b5667cf1a06020001000074000100deb9091f5beb1ebd8d91a1b81e562a70cdb3a1cdafc5e61087b18d1c221c570754ecbe056bdef5f82c388a9bf53f074521aeaf5afdeed3a2ba70adb89362631b010400002c0101444444444444444444444444444444444444444401015555555555555555555555555555555555555555030100a5a91b133336e5ef1c7e23c13974535018fab1c0"
  }
}

Send Transactions

All wallets can send transactions right after creation. No extra steps are required to create the wallet, as all users have a wallet by default.

Raw transaction

  • Immediate Transactions: Wallets are ready to send transactions immediately upon creation.
  • Raw Transactions: Specify transaction parameters such as recipient, value, and data. Gas limits and nonce are managed automatically.
  • Network Requirements: Transactions require specifying a chainId for the intended network., for example 1 for Ethereum mainnet, 42161 for Arbitrum, etc.
import { Sequence, isSentTransactionResponse } from "@0xsequence/waas";
 
const sequence = new SequenceWaaS(
  {
    projectAccessKey: `${process.env.PROJECT_ACCESS_KEY}`,
    waasConfigKey: `${process.env.WAAS_CONFIG_KEY}`,
    network: "arbitrum-nova",
  }
);
 
await sequence.signIn({ idToken }, "Session name");
 
const tx = await sequence.sendTransaction({
  chainId: 42161,
  transactions: [
    {
      to: "0x27CabC9700EE6Db2797b6AC1e1eCe81C72A2cD8D",
      value: "200000000000000000000", // 200 ETH
      data: "0x9fa2b3c4",
    },
  ],
});
 
if (isSentTransactionResponse(tx)) {
  console.log(tx);
}
{
  "code": "transactionReceipt",
  "data": {
    "txHash": "0xf2e9f728abd65089f25efda5852e605ced377f4e2c89dbf143b124623ed09b2c",
    "metaTxHash": "acc36ed4ef40db74137266e48d863083a5c7e85e2735d69adafcb5b362b6cfc0",
    "nativeReceipt": { ... },
    "receipt": { ... },
    "request": { ... },
    "simulations": [ ... ],
  }
}

Send ERC20 Tokens

Helper methods are available for common operations, such as sending ERC20 tokens. This automatically handles the data field of the transaction:

import { Sequence, isSentTransactionResponse } from "@0xsequence/waas";
 
const sequence = new SequenceWaaS(
  {
    projectAccessKey: `${process.env.PROJECT_ACCESS_KEY}`,
    waasConfigKey: `${process.env.WAAS_CONFIG_KEY}`,
    network: "mumbai",
  },
  defaults.TEST
);
 
await sequence.signIn({ idToken }, "Session name");
 
const tx = await sequence.sendERC20({
  chainId: 42161,
  token: "0x6b175474e89094c44da98b954eedeac495271d0f", // DAI
  to: "0x27CabC9700EE6Db2797b6AC1e1eCe81C72A2cD8D", // Recipient
  value: "200000000000000000000", // 200 DAI
});
 
if (isSentTransactionResponse(tx)) {
  console.log(tx);
}
{
  "code": "transactionReceipt",
  "data": {
    "txHash": "0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3",
    "metaTxHash": "01a087979dccbbc49a45b72d987e5651d65bd97349ccbfdd601b0b7beee9ddc4",
    "nativeReceipt": { ... },
    "receipt": { ... },
    "request": { ... },
    "simulations": [ ... ],
  }
}

Send ERC721 Tokens

Sending ERC721 tokens has a helper method. This automatically handles the data field of the transaction:

import { Sequence, isSentTransactionResponse } from "@0xsequence/waas";
 
const sequence = new SequenceWaaS(
  {
    projectAccessKey: `${process.env.PROJECT_ACCESS_KEY}`,
    waasConfigKey: `${process.env.WAAS_CONFIG_KEY}`,
    network: "arbitrum-nova",
  }
);
 
await sequence.signIn({ idToken });
 
const tx = await sequence.sendERC721({
  chainId: 42161,
  token: "0xF87E31492Faf9A91B02Ee0dEAAd50d51d56D5d4d", // Decentraland LAND
  to: "0x27CabC9700EE6Db2797b6AC1e1eCe81C72A2cD8D", // Recipient
  id: "33347671958251969419410711528313284722562", // Asset ID
});
 
if (isSentTransactionResponse(tx)) {
  console.log(tx);
}
{
  "code": "transactionReceipt",
  "data": {
    "txHash": "0x4936962d9972a70bffc27f376f55d9c60c12e762819fa6384fdb466664122b6e",
    "metaTxHash": "e6513a60b63359a365f0d3f05744d89823278ec829fc5cb4d275bb815d0f5887",
    "nativeReceipt": { ... },
    "receipt": { ... },
    "request": { ... },
    "simulations": [ ... ],
  }
}

Send ERC1155 Tokens

Sending ERC1155 tokens is also supported:

import { Sequence, isSentTransactionResponse } from "@0xsequence/waas";
 
const sequence = new SequenceWaaS(
  {
    projectAccessKey: `${process.env.PROJECT_ACCESS_KEY}`,
    waasConfigKey: `${process.env.WAAS_CONFIG_KEY}`,
    network: "arbitrum-nova",
  }
);
 
await sequence.signIn({ idToken });
 
const tx = await sequence.sendERC1155({
  chainId: 137,
  token: "0x631998e91476da5b870d741192fc5cbc55f5a52e", // Skyweaver assets
  values: [
    {
      id: "66547", // Asset ID
      value: "200", // Amount for this asset
    },
    {
      id: "68572",
      value: "1000",
    },
  ],
});

Call any Contract

Use callContract to interact with any contract method, either through a function signature or ABI, supporting both named and positional arguments.

Function Signature

Providing a function signature is the easiest way to call a contract method, as it doesn't require an ABI. The function signature can be provided with named parameters or positional parameters.

Named Arguments
const tx = await sequence.callContract({
  to: "0x503388C73Ca663eA34e103c11C9F47C9433af471", // Contract address
  abi: "mint(address to, uint256 tokenId)", // Function signature
  func: "mint", // Function name
  args: {
    to: "0xf439e432d54c2Bf5518A1901D3791070d4192986",
    tokenId: "1",
  },
  value: 0, // Value to send
});
Positional Arguments

Notice that passing a named function signature with positional arguments is allowed.

const tx = await sequence.callContract({
  to: "0x503388C73Ca663eA34e103c11C9F47C9433af471", // Contract address
  abi: "mint(address,uint256)", // Function signature
  func: "mint", // Function name
  args: ["0xf439e432d54c2Bf5518A1901D3791070d4192986", "1"],
  value: 0, // Value to send
});

ABI

Providing an ABI is more verbose, but allows for more flexibility, as a single ABI can be used to call multiple methods. ABIs support named arguments and positional arguments.

const abi = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]`;
 
const tx = await sequence.callContract({
  to: "0x6b175474e89094c44da98b954eedeac495271d0f", // Contract address
  abi: abi, // ABI
  func: "transfer", // Function name
  args: {
    _to: "0xf439e432d54c2Bf5518A1901D3791070d4192986",
    _value: "1",
  },
  value: 0, // Value to send
});