Skip to content

Commit

Permalink
Merge branch 'release/4.4.1-1'
Browse files Browse the repository at this point in the history
  • Loading branch information
Evgeniya Bashieva committed Dec 5, 2024
2 parents 7bf8fa6 + b0dee3c commit f8d1c0c
Show file tree
Hide file tree
Showing 105 changed files with 22,810 additions and 382 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/node_modules
/dist
/docs
.idea
.DS_Store
tmp.json
*.tmp
imp
.nx/cache
*.tsbuildinfo
1 change: 0 additions & 1 deletion .nvmrc

This file was deleted.

8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Neon EVM Token transfer SDK Changelog
All notable changes to this project will be documented in this file.

## [4.4.1] (2024-12-05)
### Added
* Refactor: Updated examples and README.md

## [4.4.0] (2024-11-06)
### Added
* Refactor: Updated method signatures to accept parameter objects

## [4.2.0] (2024-08-27)
### Added
* Add: Holder account creation
Expand Down
110 changes: 83 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,6 @@ yarn add @neonevm/token-transfer-core
npm install @neonevm/token-transfer-core
```

For using with `web3.js` we recommend additional using `@neonemv/token-transfer-web3`

```sh
yarn add @neonevm/token-transfer-web3
# or
npm install @neonevm/token-transfer-web3
```

For using with `ethers.js` we recommend additional using `@neonemv/token-transfer-ethers`

```sh
Expand Down Expand Up @@ -57,7 +49,7 @@ const solNeonEvmUrl = `https://devnet.neonevm.org/solana/sol`;
const solanaUrl = `https://api.devnet.solana.com`;
const neonProxyApi = new NeonProxyRpcApi(neonNeonEvmUrl);
const solProxyApi = new NeonProxyRpcApi(solNeonEvmUrl);
// ...
// nativeTokenList returns the native token list for every chain network, first will be NEON, second SOL
const [neonNativeToken, solNativeToken] = await neonProxyApi.nativeTokenList(); // get native tokens for chain networks
const neonProxyStatus = await neonProxyApi.evmParams(); // get evm params config
const solProxyStatus = await solProxyApi.evmParams();
Expand Down Expand Up @@ -98,25 +90,48 @@ const solToken: SPLToken = {
chainId: solChainId
};

// for transfer NEON: Solana -> NeonEvm (NEON)
const transaction = await solanaNEONTransferTransaction(solanaWallet, neonWallet, neonEvmProgram, neonTokenMint, neonToken, amount, neonChainId); // Solana Transaction object
// for transfer NEON: Solana -> NeonEvm (NEON chain)
const transaction = await solanaNEONTransferTransaction({
solanaWallet,
neonWallet,
neonEvmProgram,
neonTokenMint,
token: neonToken,
amount,
chainId: neonChainId
}); // Solana Transaction object
transaction.recentBlockhash = (await connection.getLatestBlockhash('finalized')).blockhash; // Network blockhash
const signature = await connection.sendRawTransaction(transaction.serialize()); // method for sign and send transaction to network

// for transfer SOL: Solana -> NeonEvm (SOL)
const transaction = await solanaSOLTransferTransaction(solanaWallet, neonWallet, solEvmProgram, solTokenMint, neonToken, amount, solChainId); // Solana Transaction object
// for transfer SOL: Solana -> NeonEvm (SOL chain)
const transaction = await solanaSOLTransferTransaction({
connection,
solanaWallet,
neonWallet,
neonEvmProgram: solEvmProgram,
neonTokenMint: solTokenMint,
splToken: solToken,
amount,
chainId: solChainId
}); // Solana Transaction object
transaction.recentBlockhash = (await connection.getLatestBlockhash('finalized')).blockhash; // Network blockhash
const signature = await connection.sendRawTransaction(transaction.serialize()); // method for sign and send transaction to network
```

And for transfer NEON from Neon EVM to Solana, you should known token contract address, you can look it in [this file](https://github.com/neonlabsorg/neon-client-transfer/blob/master/src/data/constants.ts).
And for transfer NEON from Neon EVM to Solana, you should know token contract address, you can look it in [this file](https://github.com/neonlabsorg/neon-client-transfer/blob/master/src/data/constants.ts).

```javascript
const tokenContract = NEON_TRANSFER_CONTRACT_DEVNET; // or SOL_TRANSFER_CONTRACT_DEVNET
const transaction = await neonNeonTransactionWeb3(web3, neonWallet, tokenContract, solanaWallet, amount); // Neon EVM Transaction object
const signedTrx = await web3.eth.accounts.signTransaction(transaction, neonWallet.privateKey);
const transaction = await neonNeonTransactionEthers({
provider,
from: neonWallet.address,
to: tokenContract,
solanaWallet,
amount
}); // Neon EVM Transaction object
const signedTrx = await neonWallet.signTransaction(transaction);
if (signedTrx?.rawTransaction) {
const txResult = web3.eth.sendSignedTransaction(signedTrx.rawTransaction);
const txResult = neonWallet.sendSignedTransaction(signedTrx.rawTransaction);
txResult.on('transactionHash', (hash: string) => console.log(hash));
txResult.on('error', (error: Error) => console.error(error));
}
Expand All @@ -131,10 +146,23 @@ For transfer ERC20 tokens from Solana to Neon EVM, using this patterns:
```javascript
import tokenList from 'token-list/tokenlist.json';

const proxyUrl = `https://devnet.neonevm.org`;
const tokens = tokenList.tokens.filter((token) => token.chainId === CHAIN_ID);
const token = tokens[0];

const transaction = await neonTransferMintTransactionWeb3(connection, web3, proxyApi, proxyStatus, neonEvmProgram/* or solEvmProgram*/, solanaWallet, neonWallet, token, amount, neonChainId /*or solChainId*/);
//The wallet signer from ethers.js, used for signing the transaction.
const walletSigner = new Wallet(keccak256(Buffer.from(`${neonWallet.address.slice(2)}${solanaWallet.publicKey.toBase58()}`, 'utf-8')), new JsonRpcProvider(proxyUrl));

const transaction = await neonTransferMintTransactionEthers({
connection,
proxyApi,
neonEvmProgram/* or solEvmProgram*/,
solanaWallet,
neonWallet: neonWallet.address,
walletSigner,
splToken: token,
amount,
chainId: neonChainId /*or solChainId*/
});
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
const signature = await connection.sendRawTransaction(transaction.serialize());
```
Expand All @@ -147,16 +175,23 @@ import tokenList from 'token-list/tokenlist.json';
const tokens = tokenList.tokens.filter((token) => token.chainId === CHAIN_ID);
const mintPubkey = new PublicKey(token.address_spl);
const associatedToken = getAssociatedTokenAddressSync(mintPubkey, solanaWallet);
const solanaTransaction = createAssociatedTokenAccountTransaction(solanaWallet, mintPubkey, associatedToken, proxyStatus.NEON_HEAP_FRAME);
const solanaTransaction = createAssociatedTokenAccountTransaction({
solanaWallet,
tokenMint: mintPubkey,
associatedToken,
neonHeapFrame: proxyStatus.NEON_HEAP_FRAME
});
solanaTransaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
const neonTransaction = await createMintNeonTransactionWeb3(web3, neonWallet.address, associatedToken, token, amount);
const neonTransaction = await createMintNeonTransactionEthers({
provider,
neonWallet: neonWallet.address,
associatedToken,
splToken: token,
amount
});
const solanaSignature = await connection.sendRawTransaction(transaction.serialize());
const neonSignature = await web3.eth.accounts.signTransaction(transaction, neonWallet.privateKey);
if (signedTrx?.rawTransaction) {
const txResult = web3.eth.sendSignedTransaction(signedTrx.rawTransaction);
txResult.on('transactionHash', (hash: string) => console.log(hash));
txResult.on('error', (error: Error) => console.error(error));
}
const neonSignature = await neonWallet.signTransaction(transaction);
const txResult = neonWallet.sendSignedTransaction(neonSignature.rawTransaction);
```
Within the Neon Transfer codebase, we employ the [web3.js](https://web3js.readthedocs.io/en/v1.10.0/) library to streamline our code. However, if the situation demands, you can opt for alternatives such as [ethers.js](https://docs.ethers.org/v6/) or [WalletConnect](https://walletconnect.com/).
Expand All @@ -176,3 +211,24 @@ yarn test
# or
npm run test
```
### Building Docs
We can run TypeDoc with packages mode to generate a single docs folder in the root of the project.
```sh
# We need to build before building the docs so that `foo` can reference types from `bar`
# TypeDoc can't use TypeScript's build mode to do this for us because build mode may skip
# a project that needs documenting, or include packages that shouldn't be included in the docs
yarn build
# or
npm run build
```
Now you can run docs generation script.
```sh
yarn docs
# or
npm run docs
```
43 changes: 32 additions & 11 deletions __tests__/e2e/erc20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
createAssociatedTokenAccount,
delay,
FaucetDropper,
mintTokenBalanceWeb3,
mintTokenBalanceEthers,
neonSignature,
sendNeonTransaction,
sendNeonTransactionEthers,
Expand All @@ -38,10 +38,31 @@ export async function itSolanaTokenSPL(provider: Web3 | JsonRpcProvider, connect
let transaction: Transaction;
if (provider instanceof JsonRpcProvider) {
const solanaWalletSigner = walletSigner(<JsonRpcProvider>provider, signerPrivateKey(solanaWallet.publicKey, neonWallet.address));
transaction = await neonTransferMintTransactionEthers(connection, neonProxyRpcApi, neonEvmProgram, solanaWallet.publicKey, neonWallet.address, solanaWalletSigner, token, amount, chainId);
transaction = await neonTransferMintTransactionEthers({
connection,
proxyApi: neonProxyRpcApi,
neonEvmProgram,
solanaWallet: solanaWallet.publicKey,
neonWallet: neonWallet.address,
walletSigner: solanaWalletSigner,
splToken: token,
amount,
chainId
});
} else {
const walletSigner = walletSignerWeb3(provider, signerPrivateKey(solanaWallet.publicKey, neonWallet.address));
transaction = await neonTransferMintTransactionWeb3(connection, proxyUrl, neonProxyRpcApi, neonEvmProgram, solanaWallet.publicKey, neonWallet.address, walletSigner, token, amount, chainId);
transaction = await neonTransferMintTransactionWeb3({
connection,
proxyUrl,
proxyApi: neonProxyRpcApi,
neonEvmProgram,
solanaWallet: solanaWallet.publicKey,
neonWallet: neonWallet.address,
walletSigner,
splToken: token,
amount,
chainId
});
}
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
const signer: Signer = toSigner(solanaWallet);
Expand All @@ -51,9 +72,9 @@ export async function itSolanaTokenSPL(provider: Web3 | JsonRpcProvider, connect
await delay(5e3);

const balanceAfter = await splTokenBalance(connection, solanaWallet.publicKey, token);
const balanceMint = await mintTokenBalanceWeb3(proxyUrl, neonWallet.address, token);
const balanceMint = await mintTokenBalanceEthers(neonWallet as Wallet, token);
console.log(`Balance: ${balanceBefore?.uiAmount} > ${balanceAfter?.uiAmount} ${token.symbol} ==> ${balanceMint} ${token.symbol} in Neon`);
expect(balanceAfter.uiAmount).toBeLessThan(balanceBefore.uiAmount!);
expect(balanceAfter?.uiAmount).toBeLessThan(balanceBefore?.uiAmount!);
} catch (e) {
console.log(e);
expect(e instanceof Error ? e.message : '').toBe('');
Expand All @@ -63,10 +84,10 @@ export async function itSolanaTokenSPL(provider: Web3 | JsonRpcProvider, connect
export async function itNeonTokenMint(connection: Connection, provider: Web3 | JsonRpcProvider, proxyUrl: string, faucet: FaucetDropper, token: SPLToken, solanaWallet: Keypair, neonWallet: Web3Account | Wallet) {
const amount = 0.1;
const mintPubkey = new PublicKey(token.address_spl);
let balanceBefore = await mintTokenBalanceWeb3(proxyUrl, neonWallet.address, token);
let balanceBefore = await mintTokenBalanceEthers(neonWallet as Wallet, token);
if (!balanceBefore) {
await faucet.requestERC20(neonWallet.address, token, 1);
balanceBefore = await mintTokenBalanceWeb3(proxyUrl, neonWallet.address, token);
balanceBefore = await mintTokenBalanceEthers(neonWallet as Wallet, token);
await delay(30e6);
}
console.log(`Balance: ${balanceBefore ?? 0} ${token.symbol}`);
Expand All @@ -76,10 +97,10 @@ export async function itNeonTokenMint(connection: Connection, provider: Web3 | J
const associatedToken = getAssociatedTokenAddressSync(mintPubkey, solanaWallet.publicKey);
let neonTransaction: TransactionRequest | TransactionWeb3;
if (provider instanceof JsonRpcProvider) {
neonTransaction = await createMintNeonTransactionEthers(provider, neonWallet.address, associatedToken, token, amount);
neonTransaction = await createMintNeonTransactionEthers({ provider, neonWallet: neonWallet.address, associatedToken, splToken: token, amount });
neonTransaction.nonce = await (neonWallet as Wallet).getNonce();
} else {
neonTransaction = await createMintNeonTransactionWeb3(proxyUrl, neonWallet.address, associatedToken, token, amount);
neonTransaction = await createMintNeonTransactionWeb3({ provider: proxyUrl, neonWallet: neonWallet.address, associatedToken, splToken: token, amount });
}

try {
Expand All @@ -88,8 +109,8 @@ export async function itNeonTokenMint(connection: Connection, provider: Web3 | J
await sendNeonTransaction(provider, <TransactionWeb3>neonTransaction, <Web3Account>neonWallet);
neonSignature(`Neon Signature`, signedNeonTransaction);
expect(signedNeonTransaction.length).toBeGreaterThan(0);
await delay(15e3);
const balanceAfter = await mintTokenBalanceWeb3(proxyUrl, neonWallet.address, token);
await delay(20e3);
const balanceAfter = await mintTokenBalanceEthers(neonWallet as Wallet, token);
const balanceSPL = await splTokenBalance(connection, solanaWallet.publicKey, token);
console.log(`Balance: ${balanceBefore} > ${balanceAfter} ${token.symbol} ==> ${balanceSPL?.uiAmount} ${token.symbol} in Solana`);
expect(balanceAfter).toBeLessThan(balanceBefore);
Expand Down
12 changes: 10 additions & 2 deletions __tests__/e2e/neon-fee.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,15 @@ describe('NEON token transfer tests', () => {
const balanceBefore = await splTokenBalance(connection, solanaWallet.publicKey, neonToken);
console.log(`Balance: ${balanceBefore?.uiAmount ?? 0} ${neonToken.symbol}`);
try {
const transaction = await solanaNEONTransferTransaction(solanaWallet.publicKey, neonWallet.address, neonEvmProgram, neonTokenMint, neonToken, amount, CHAIN_ID);
const transaction = await solanaNEONTransferTransaction({
solanaWallet: solanaWallet.publicKey,
neonWallet: neonWallet.address,
neonEvmProgram,
neonTokenMint,
token: neonToken,
amount,
chainId: CHAIN_ID
});
transaction.recentBlockhash = (await connection.getLatestBlockhash('finalized')).blockhash;
const signature = await sendSolanaTransaction(connection, transaction, [signer], false, { skipPreflight });
expect(signature.length).toBeGreaterThan(0);
Expand All @@ -123,7 +131,7 @@ describe('NEON token transfer tests', () => {
const balanceNeon = await neonBalanceWeb3(NEON_PROXY_URL!
, neonWallet.address);
console.log(`Balance: ${balanceBefore?.uiAmount} > ${balanceAfter?.uiAmount} ${neonToken.symbol} ==> ${balanceNeon} ${neonToken.symbol} in Neon`);
expect(balanceAfter.uiAmount).toBeLessThan(balanceBefore.uiAmount!);
expect(balanceAfter?.uiAmount).toBeLessThan(balanceBefore?.uiAmount!);
} catch (e) {
console.log(e);
expect(e instanceof Error ? e.message : '').toBe('');
Expand Down
Loading

0 comments on commit f8d1c0c

Please sign in to comment.