Notus API
Gasless & Transaction Abstraction

Send Your First Transaction

Step-by-step guide to transferring tokens with the Notus API.

Steps

Create a directory

mkdir my-transfer
cd my-transfer
touch index.js

Init project

npm init -y
pnpm init -y
yarn init -y
bun init -y

Install viem

We’ll use viem, a library for blockchain interactions, to simplify our integration. Install it by running:

npm i viem
pnpm add viem
yarn add viem
bun add viem

Initialize Wallet Account

Use your private key to initialize a wallet account. This will allow you to sign messages and interact with the blockchain.

import { privateKeyToAccount } from 'viem/accounts'

const BASE_URL = "https://api.notus.team/api/v1"
const API_KEY = "<api-key>"

const UNI_POLYGON = '0xb33eaad8d922b1083446dc23f610c2567fb5180f'
const USDC_POLYGON = '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359' 

const privateKey = '0x<private-key>'
const account = privateKeyToAccount(privateKey)

Register a Smart Wallet Address

Before initiating a cross-chain swap, register and retrieve the smart wallet address used for Account Abstraction.

async function main() {
  const FACTORY_ADDRESS = "0x0000000000400CdFef5E2714E63d8040b700BC24"
  const externallyOwnedAccount = account.address

  const res = await fetch(`${BASE_URL}/wallets/register`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": API_KEY,
    },
    body: JSON.stringify({
      externallyOwnedAccount: externallyOwnedAccount,
      factory: FACTORY_ADDRESS,
      salt: "0",
    }),
  });

  if (!res?.ok) {
    return
  }

  const response = await res.json();

  const smartWalletAddress = response.wallet.accountAbstraction
}

Note: At this stage, the smart wallet address is not yet deployed onchain. Deployment happens automatically with the user's first onchain transaction (e.g., swap or transfer) via a UserOperation.

Request Transfer

Send the transfer request to the Notus API to get a quote for executing the transfer. Define the parameters for your transfer, specifying the token, amount, sender's address, and recipient's address.


const { data } = await fetch(`${BASE_URL}/crypto/transfer`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': API_KEY,
  },
  body: JSON.stringify(
    {
      payGasFeeToken: USDC_POLYGON, // Token used to pay gas fees
      token: UNI_POLYGON,        // Token to transfer
      amount: '5',               // Amount to transfer
      walletAddress: smartWalletAddress, // Sender's wallet
      signerAddress: externallyOwnedAccount, // Signer's address
      toAddress: '0x<recipient-address>', // Replace <recipient-address> with the recipient's wallet
      chainId: 137,          // Blockchain network
      gasFeePaymentMethod: 'DEDUCT_FROM_AMOUNT', // Fee payment method
    }
  ),
}).then((res) => res.json());

Note: The payGasFeeToken field should contain the address of an ERC-20 token held in the smart wallet. This token will be used to pay both the partner’s transactionFeePercent and the gas fees for the UserOperation. In most cases, payGasFeeToken is the same as token, typically the token the user already holds in their wallet.

Execute Transfer

Sign the transfer quote and execute the transfer using the Notus API.

  const signature = await account.signMessage({
    message: {
      raw: data.quoteId, // Quote ID from the transfer quote
    },
  })

  const { userOpHash } = await fetch(`${BASE_URL}/crypto/execute-user-op`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': API_KEY,
    },
    body: JSON.stringify({ signature, quoteId: data.quoteId }),
  }).then((res) => res.json())

  console.log(userOpHash)