UNPKG

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
"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