n8n-nodes-ethereum-automation
Version:
n8n node for Ethereum operations including wallet creation, sending ETH/ERC20 tokens, and transaction monitoring
492 lines • 21.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Ethereum = void 0;
const ethers_1 = require("ethers");
class Ethereum {
constructor() {
this.description = {
displayName: 'Ethereum',
name: 'ethereum',
icon: 'file:ethereum.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Interact with Ethereum blockchain',
defaults: {
name: 'Ethereum',
},
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'ethereumWallet',
required: true,
displayOptions: {
show: {
resource: [
'transaction',
'token'
],
operation: [
'sendEth',
'sendToken',
],
}
}
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Wallet',
value: 'wallet',
},
{
name: 'Transaction',
value: 'transaction',
},
{
name: 'Token',
value: 'token',
},
],
default: 'wallet',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['wallet'],
},
},
options: [
{
name: 'Create Wallet',
value: 'create',
description: 'Create a new Ethereum wallet',
action: 'Create a new wallet',
},
{
name: 'Get ETH Balance',
value: 'getBalance',
description: 'Get ETH balance of any wallet address',
action: 'Get the balance of any wallet address',
},
],
default: 'create',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['transaction'],
},
},
options: [
{
name: 'Send ETH',
value: 'sendEth',
description: 'Send ETH to another address',
action: 'Send ETH to another address',
},
{
name: 'Get Transaction',
value: 'getTransaction',
description: 'Get transaction details by hash',
action: 'Get transaction details',
},
],
default: 'sendEth',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['token'],
},
},
options: [
{
name: 'Send Token',
value: 'sendToken',
description: 'Send ERC20 tokens to another address',
action: 'Send ERC20 tokens to another address',
},
{
name: 'Get Token Balance',
value: 'getTokenBalance',
description: 'Get ERC20 token balance of an address',
action: 'Get token balance of an address',
},
],
default: 'sendToken',
},
{
displayName: 'RPC URL',
name: 'walletRpcUrl',
type: 'string',
displayOptions: {
show: {
resource: ['wallet']
},
},
default: 'https://ethereum-rpc.publicnode.com',
description: 'Ethereum RPC endpoint URL (optional)',
required: false,
},
{
displayName: 'Number of Wallets',
name: 'numberOfWallets',
type: 'number',
displayOptions: {
show: {
resource: ['wallet'],
operation: ['create'],
},
},
default: 1,
description: 'Number of wallets to create',
required: true,
},
{
displayName: 'Wallet Address',
name: 'walletAddress',
type: 'string',
displayOptions: {
show: {
resource: ['wallet'],
operation: ['getBalance'],
},
},
default: '',
description: 'Wallet address to check balance for (leave empty to use credential wallet)',
},
{
displayName: 'RPC URL',
name: 'rpcUrl',
type: 'string',
displayOptions: {
show: {
resource: ['transaction'],
},
},
default: 'https://ethereum-rpc.publicnode.com',
description: 'Ethereum RPC endpoint URL (optional)',
required: false,
},
{
displayName: 'To Address',
name: 'toAddress',
type: 'string',
displayOptions: {
show: {
resource: ['transaction'],
operation: ['sendEth'],
},
},
default: '',
description: 'Recipient address',
},
{
displayName: 'Amount (ETH)',
name: 'amount',
type: 'number',
displayOptions: {
show: {
resource: ['transaction'],
operation: ['sendEth'],
},
},
default: 0,
description: 'Amount of ETH to send',
},
{
displayName: 'Transaction Hash',
name: 'transactionHash',
type: 'string',
displayOptions: {
show: {
resource: ['transaction'],
operation: ['getTransaction'],
},
},
default: '',
description: 'Transaction hash to retrieve',
},
{
displayName: 'RPC URL',
name: 'tokenRpcUrl',
type: 'string',
displayOptions: {
show: {
resource: ['token'],
},
},
default: 'https://ethereum-rpc.publicnode.com',
description: 'Ethereum RPC endpoint URL (optional)',
required: false,
},
{
displayName: 'Token Contract Address',
name: 'tokenContractAddress',
type: 'string',
displayOptions: {
show: {
resource: ['token'],
},
},
default: '',
description: 'ERC20 token contract address',
},
{
displayName: 'To Address',
name: 'tokenToAddress',
type: 'string',
displayOptions: {
show: {
resource: ['token'],
operation: ['sendToken'],
},
},
default: '',
description: 'Recipient address',
},
{
displayName: 'Token Amount',
name: 'tokenAmount',
type: 'string',
displayOptions: {
show: {
resource: ['token'],
operation: ['sendToken'],
},
},
default: '',
description: 'Amount of tokens to send (in decimal format, e.g., 100.5)',
},
{
displayName: 'Token Decimals',
name: 'tokenDecimals',
type: 'number',
displayOptions: {
show: {
resource: ['token'],
operation: ['sendToken'],
},
},
default: 18,
description: 'Number of decimals for the token (6 for USDC, 18 for most tokens)',
required: true,
},
{
displayName: 'Address',
name: 'tokenBalanceAddress',
type: 'string',
displayOptions: {
show: {
resource: ['token'],
operation: ['getTokenBalance'],
},
},
default: '',
description: 'Address to check token balance for (leave empty to use credential wallet)',
},
],
};
}
async execute() {
var _a, _b, _c;
const returnData = [];
const items = this.getInputData();
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
let credentials;
const operationsNeedingCredentials = ['sendEth', 'sendToken'];
if (operationsNeedingCredentials.includes(operation)) {
credentials = await this.getCredentials('ethereumWallet');
if (!credentials) {
throw new Error('EthereumWallet credential is required for this operation');
}
}
for (let i = 0; i < items.length; i++) {
try {
if (resource === 'wallet') {
const rpcUrl = this.getNodeParameter('walletRpcUrl', i) || 'https://ethereum-rpc.publicnode.com';
const provider = new ethers_1.ethers.JsonRpcProvider(rpcUrl, 1);
if (operation === 'create') {
const numberOfWallets = this.getNodeParameter('numberOfWallets', i);
const wallets = [];
for (let j = 0; j < numberOfWallets; j++) {
const wallet = ethers_1.ethers.Wallet.createRandom();
const mnemonic = (_a = wallet.mnemonic) === null || _a === void 0 ? void 0 : _a.phrase;
wallets.push({
address: wallet.address,
privateKey: wallet.privateKey,
mnemonic: mnemonic,
});
}
if (numberOfWallets === 1) {
returnData.push({
json: wallets[0],
});
}
else {
returnData.push({
json: {
wallets: wallets,
count: numberOfWallets,
},
});
}
}
else if (operation === 'getBalance') {
let walletAddress = this.getNodeParameter('walletAddress', i);
const balance = await provider.getBalance(walletAddress);
const balanceInEth = ethers_1.ethers.formatEther(balance);
returnData.push({
json: {
address: walletAddress,
balance: balanceInEth,
balanceWei: balance.toString()
},
});
}
}
else if (resource === 'transaction') {
const rpcUrl = this.getNodeParameter('rpcUrl', i) || 'https://ethereum-rpc.publicnode.com';
const provider = new ethers_1.ethers.JsonRpcProvider(rpcUrl, 1);
if (operation === 'sendEth') {
const toAddress = this.getNodeParameter('toAddress', i);
const amount = this.getNodeParameter('amount', i);
if (!credentials) {
throw new Error('No credentials returned for transaction operations.');
}
const wallet = new ethers_1.ethers.Wallet(credentials.privateKey, provider);
const amountWei = ethers_1.ethers.parseEther(amount.toString());
const tx = await wallet.sendTransaction({
to: toAddress,
value: amountWei,
});
returnData.push({
json: {
transactionHash: tx.hash,
from: tx.from,
to: tx.to,
value: amount
},
});
}
else if (operation === 'getTransaction') {
const transactionHash = this.getNodeParameter('transactionHash', i);
const tx = await provider.getTransaction(transactionHash);
if (tx) {
returnData.push({
json: {
hash: tx.hash,
from: tx.from,
to: tx.to,
value: ethers_1.ethers.formatEther(tx.value),
gasPrice: (_b = tx.gasPrice) === null || _b === void 0 ? void 0 : _b.toString(),
gasLimit: (_c = tx.gasLimit) === null || _c === void 0 ? void 0 : _c.toString(),
nonce: tx.nonce,
data: tx.data,
},
});
}
else {
throw new Error('Transaction not found');
}
}
}
else if (resource === 'token') {
const rpcUrl = this.getNodeParameter('tokenRpcUrl', i) || 'https://ethereum-rpc.publicnode.com';
const provider = new ethers_1.ethers.JsonRpcProvider(rpcUrl, 1);
if (operation === 'sendToken') {
const tokenContractAddress = this.getNodeParameter('tokenContractAddress', i);
const toAddress = this.getNodeParameter('tokenToAddress', i);
const tokenAmount = this.getNodeParameter('tokenAmount', i);
const tokenDecimals = this.getNodeParameter('tokenDecimals', i);
if (!credentials) {
throw new Error('No credentials returned for token operations.');
}
const wallet = new ethers_1.ethers.Wallet(credentials.privateKey, provider);
const amountWei = ethers_1.ethers.parseUnits(tokenAmount, tokenDecimals);
const contract = new ethers_1.ethers.Contract(tokenContractAddress, [
'function transfer(address to, uint256 amount) returns (bool)',
'function decimals() view returns (uint8)',
'function symbol() view returns (string)',
], wallet);
const tx = await contract.transfer(toAddress, amountWei);
returnData.push({
json: {
transactionHash: tx.hash,
from: wallet.address,
to: toAddress,
tokenContract: tokenContractAddress,
amount: tokenAmount
},
});
}
else if (operation === 'getTokenBalance') {
const tokenContractAddress = this.getNodeParameter('tokenContractAddress', i);
let address = this.getNodeParameter('tokenBalanceAddress', i);
if (!address) {
if (!credentials) {
throw new Error('No credentials returned for token operations.');
}
const wallet = new ethers_1.ethers.Wallet(credentials.privateKey);
address = wallet.address;
}
const contract = new ethers_1.ethers.Contract(tokenContractAddress, [
'function balanceOf(address owner) view returns (uint256)',
'function decimals() view returns (uint8)',
'function symbol() view returns (string)',
], provider);
const balance = await contract.balanceOf(address);
const decimals = await contract.decimals();
const symbol = await contract.symbol();
const formattedBalance = ethers_1.ethers.formatUnits(balance, decimals);
returnData.push({
json: {
address: address,
tokenContract: tokenContractAddress,
balance: formattedBalance,
balanceRaw: balance.toString(),
symbol: symbol,
decimals: decimals
},
});
}
}
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
error: error instanceof Error ? error.message : String(error),
},
});
continue;
}
throw error;
}
}
return [returnData];
}
}
exports.Ethereum = Ethereum;
//# sourceMappingURL=Ethereum.node.js.map