Skip to main content

Neon Transfer Client

This page explains how to pass tokens between Solana and Neon EVM programmatically.

TL;DR

Introduction

This page describes how to use the Neon token pass tool: providing the same functionality as the NeonPass UI. The tool is an npm package that supports the transfer of SPL or ERC-20 tokens between Solana and Neon EVM.

Prerequisites

  • You need to integrate Solana-compatible and EVM-compatible wallet providers from supported official libraries such as @solana/web3.js or web3.js, ether.js and WalletConnect.
  • Supported browser plugins (e.g. Phantom or MetaMask wallets).

Step 1: Install and setup

1.1 Install the package

yarn add @neonevm/token-transfer-core
yarn add @neonevm/token-transfer-web3

1.2 Enable access to wallets

Now you need to create a connection to the Solana and NeonEVM devnet, and connect the appropriate wallets to perform transfers between them.

In this example we use web3.js, but you can also use ethers.js as an alternative, by setting @neonevem/token-transfer-ethers instead of @neonevem/token-transfer-web3.

import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import { HttpProvider } from 'web3-providers-http';
import { Web3 } from 'web3';
import { decode } from 'bs58';

const proxyUrl = `https://devnet.neonevm.org`;
const solanaUrl = `https://api.devnet.solana.com`;

const connection = new Connection(solanaUrl, 'confirmed');
const web3 = new Web3(new HttpProvider(proxyUrl));

const neonWallet = web3.eth.accounts.privateKeyToAccount(`<Neon wallet private key>`);
const solanaWallet = Keypair.fromSecretKey(decode(`<Solana wallet private key>`)); // private key in base58 format string

1.3 Configure parameters

We employ the evmParams method from Neon EVM to obtain specific addresses and constants required for seamless operations.

Also the nativeTokenList method contains a list of tokens that are native to Neon EVM and can be used as token gas fee.

import { PublicKey } from '@solana/web3.js';

const neonProxyRpcApi = new NeonProxyRpcApi(proxyUrl);
const evmParams = await neonProxyRpcApi.evmParams();
const nativeTokenList = await neonProxyRpcApi.nativeTokenList();

const id = nativeTokenList.findIndex(i => i.token_name === 'NEON');
const gasToken = nativeTokenList[id];

const neonEvmProgram = new PublicKey(evmParams.NEON_EVM_ID);
const neonTokenMint = new PublicKey(gasToken.token_mint);
const chainId = parseInt(gasToken.token_chain_id, 16);

Step 2: Transfer tokens

2.1 Transfer NEON

This example will generate a transaction to transfer NEON from Solana to Neon EVM.

import {
NEON_TOKEN_MINT_DECIMALS,
solanaNEONTransferTransaction,
SPLToken
} from '@neonevm/token-transfer-core';

const neonToken: SPLToken = {
chainId,
address_spl: '89dre8rZjLNft7HoupGiyxu3MNftR577ZYu8bHe2kK7g',
address: '',
decimals: NEON_TOKEN_MINT_DECIMALS,
name: 'Neon',
symbol: 'NEON',
logoURI: 'https://raw.githubusercontent.com/neonlabsorg/token-list/main/neon_token_md.png'
};

const transaction = await solanaNEONTransferTransaction(solanaWallet.publicKey, neonWallet.address, neonEvmProgram, neonTokenMint, neonToken, amount, chainId);
const signature = await sendSolanaTransaction(connection, transaction, [toSigner(solanaWallet)]);
console.log(signature);

Note: You can find more examples in our repository in the examples folder.

2.2 Transfer ERC-20 tokens

When working with Devnet, Testnet, or Mainnet, different ERC-20 tokens are utilized. We maintain a JSON list of supported tokens. Alternatively, please refer to the token list.

For install token-list to your project, use this pattern:

yarn add token-list@https://github.com/neonlabsorg/token-list.git
# or
npm install token-list@https://github.com/neonlabsorg/token-list.git --save

To transfer ERC-20 tokens from Solana to Neon EVM, use the following patterns:

import { neonTransferMintTransactionWeb3 } from '@neonevm/token-transfer-web3';
import { keccak256 } from 'web3-utils';

const tokenList = require('token-list/tokenlist.json');
const tokens = (tokensData?.tokens as SPLToken[] ?? []).filter(t => t.chainId === chainId);
const token = tokens.find(i => i.symbol === 'USDT');
const amount = '1';

const signer = web3.eth.accounts.privateKeyToAccount(keccak256(solanaWallet.publicKey.toBase58() + neonWallet.address));
const transaction = await neonTransferMintTransactionWeb3(connection, proxyUrl, neonProxyRpcApi, neonEvmProgram, solanaWallet.publicKey, neonWallet.address, signer, token, amount, chainId);
const signature = await sendSolanaTransaction(connection, transaction, [toSigner(solanaWallet)]);
console.log(signature);

2.3 Multi-token gas fee

A new feature that Neon EVM supports is multi-token gas fee. So far this feature is implemented in NeonEVM Devnet, but it is already integrated in Token transfer and is available for testing.

Now gas fee is available for two tokens: NEON and SOL. NEON was described above in this documentation, SOL we will now consider.

For transfer SOL as a native token, it is necessary to change the configuration of Neon EVM.

// Neon EVM Devnet for SOL fee configuration
const proxyUrl = `https://devnet.neonevm.org/solana/sol`;
const solProxyRpcApi = new NeonProxyRpcApi(proxyUrl);
const solProxyStatus = await solProxyRpcApi.evmParams();
const gasTokens = await solProxyRpcApi.nativeTokenList();

const id = gasTokens.findIndex(i => i.token_name === 'SOL');
const gasToken = gasTokens[id];

const neonEvmProgram = new PublicKey(solProxyStatus.NEON_EVM_ID);
const solTokenMint = new PublicKey(gasToken.token_mint);
const chainId = parseInt(gasToken.token_chain_id, 16);
const web3 = new Web3(new HttpProvider(proxyUrl));

To transfer SOL token as native token from Solana to Neon EVM, use the following patterns:

import { solanaSOLTransferTransaction, SPLToken } from '@neonevm/token-transfer-core';

const solToken: SPLToken = {
chainId,
address_spl: 'So11111111111111111111111111111111111111112',
address: '0xc7Fc9b46e479c5Cb42f6C458D1881e55E6B7986c',
decimals: 9,
name: 'SOL',
symbol: 'SOL',
logoURI: 'https://raw.githubusercontent.com/neonlabsorg/token-list/master/assets/solana-wsol-logo.svg'
};
const amount = '1';

const transaction = await solanaSOLTransferTransaction(connection, solanaWallet.publicKey, neonWallet.address, neonEvmProgram, solTokenMint, solToken, amount, chainId);
const signature = await sendSolanaTransaction(connection, transaction, [toSigner(solanaWallet)]);
console.log(signature);

An ERC20 transfer using SOL gas fee is similar to a transfer with NEON gas fee and has been described earlier in this documentation.

Alternative libraries

As mentioned above, the examples in this documentation are presented using the web3.js library, but we have added support for ethers.js as an alternative and put it in a separate package @neonevm/token-transfer-ethers.

yarn add @neonevm/token-transfer-ethers
# or
npm install @neonevm/token-transfer-ethers --save

More examples with using ethers.js can be found in the examples folder of our Github repo.

React Demo App

The following live demo with an open codebase supports the tooling via React App.

Was this page helpful?