@cryptodevops/n8n-nodes-blockchain-explorer
Version:
n8n node for accessing multiple blockchain networks (Ethereum, BSC, Polygon, Fantom, Avalanche, Arbitrum, Optimism, etc.) with comprehensive analytics and data retrieval capabilities
737 lines (736 loc) • 30.1 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlockchainExplorer = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const axios_1 = __importDefault(require("axios"));
const BlockchainExplorerApi_credentials_1 = require("../../credentials/BlockchainExplorerApi.credentials");
class BlockchainExplorer {
constructor() {
this.description = {
displayName: 'Blockchain Explorer',
name: 'blockchainExplorer',
icon: 'file:blockchain-explorer.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["network"] + " - " + $parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Interact with multiple blockchain networks via their explorer APIs (Etherscan-compatible)',
defaults: {
name: 'Blockchain Explorer',
},
inputs: ["main" /* NodeConnectionType.Main */],
outputs: ["main" /* NodeConnectionType.Main */],
credentials: [
{
name: 'blockchainExplorerApi',
required: true,
},
],
properties: [
{
displayName: 'Network',
name: 'network',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Arbitrum',
value: 'arbitrum',
},
{
name: 'Avalanche',
value: 'avalanche',
},
{
name: 'Binance Smart Chain',
value: 'bsc',
},
{
name: 'Celo',
value: 'celo',
},
{
name: 'Cronos',
value: 'cronos',
},
{
name: 'Ethereum',
value: 'ethereum',
},
{
name: 'Fantom',
value: 'fantom',
},
{
name: 'Moonbeam',
value: 'moonbeam',
},
{
name: 'Optimism',
value: 'optimism',
},
{
name: 'Polygon',
value: 'polygon',
},
],
default: 'ethereum',
description: 'The blockchain network to query',
},
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Account',
value: 'account',
},
{
name: 'Block',
value: 'block',
},
{
name: 'Contract',
value: 'contract',
},
{
name: 'Gas',
value: 'gas',
},
{
name: 'Stat',
value: 'stats',
},
{
name: 'Token',
value: 'token',
},
{
name: 'Transaction',
value: 'transaction',
},
],
default: 'account',
},
// Account Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['account'],
},
},
options: [
{
name: 'Get Balance',
value: 'getBalance',
description: 'Get native token balance for a single address',
action: 'Get native token balance',
},
{
name: 'Get Balance Multi',
value: 'getBalanceMulti',
description: 'Get native token balance for multiple addresses',
action: 'Get native token balance for multiple addresses',
},
{
name: 'Get Internal Transactions',
value: 'getInternalTxs',
description: 'Get list of internal transactions by address',
action: 'Get internal transactions',
},
{
name: 'Get NFT Transfers',
value: 'getTokenNftTx',
description: 'Get list of NFT token transfer events by address',
action: 'Get NFT transfers',
},
{
name: 'Get Normal Transactions',
value: 'getNormalTxs',
description: 'Get list of normal transactions by address',
action: 'Get normal transactions',
},
{
name: 'Get Token Transfers',
value: 'getTokenTx',
description: 'Get list of token transfer events by address',
action: 'Get token transfers',
},
],
default: 'getBalance',
},
// Block Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['block'],
},
},
options: [
{
name: 'Get Block Reward',
value: 'getBlockReward',
description: 'Get block and uncle rewards by block number',
action: 'Get block reward',
},
{
name: 'Get Block Number by Timestamp',
value: 'getBlockNumberByTime',
description: 'Get estimated block number by Unix timestamp',
action: 'Get block number by timestamp',
},
{
name: 'Get Block by Number',
value: 'getBlockByNumber',
description: 'Get block details by block number',
action: 'Get block by number',
},
],
default: 'getBlockReward',
},
// Contract Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['contract'],
},
},
options: [
{
name: 'Get ABI',
value: 'getAbi',
description: 'Get contract ABI for verified contract source codes',
action: 'Get contract ABI',
},
{
name: 'Get Source Code',
value: 'getSourceCode',
description: 'Get contract source code for verified contracts',
action: 'Get contract source code',
},
{
name: 'Verify Contract',
value: 'verifyContract',
description: 'Verify and publish contract source code',
action: 'Verify contract',
},
],
default: 'getAbi',
},
// Gas Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['gas'],
},
},
options: [
{
name: 'Get Gas Oracle',
value: 'getGasOracle',
description: 'Get gas oracle data',
action: 'Get gas oracle',
},
{
name: 'Get Gas Price',
value: 'getGasPrice',
description: 'Get current gas price',
action: 'Get gas price',
},
],
default: 'getGasOracle',
},
// Stats Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['stats'],
},
},
options: [
{
name: 'Get Token Supply',
value: 'getTokenSupply',
description: 'Get total supply of native token',
action: 'Get token supply',
},
{
name: 'Get Token Price',
value: 'getTokenPrice',
description: 'Get latest native token price',
action: 'Get token price',
},
{
name: 'Get Chain Stats',
value: 'getChainStats',
description: 'Get blockchain statistics',
action: 'Get chain stats',
},
],
default: 'getTokenSupply',
},
// Token Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['token'],
},
},
options: [
{
name: 'Get Token Supply',
value: 'getTokenSupply',
description: 'Get token total supply by contract address',
action: 'Get token supply',
},
{
name: 'Get Token Balance',
value: 'getTokenBalance',
description: 'Get token account balance by contract address',
action: 'Get token balance',
},
{
name: 'Get Token Info',
value: 'getTokenInfo',
description: 'Get token information by contract address',
action: 'Get token info',
},
],
default: 'getTokenSupply',
},
// Transaction Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['transaction'],
},
},
options: [
{
name: 'Get Transaction Status',
value: 'getTxReceiptStatus',
description: 'Get transaction execution status',
action: 'Get transaction status',
},
{
name: 'Get Transaction Receipt',
value: 'getTxReceipt',
action: 'Get transaction receipt',
},
],
default: 'getTxReceiptStatus',
},
// Common Parameters
{
displayName: 'Address',
name: 'address',
type: 'string',
required: true,
displayOptions: {
show: {
operation: [
'getBalance',
'getNormalTxs',
'getInternalTxs',
'getTokenTx',
'getTokenNftTx',
'getTokenBalance',
],
},
},
default: '',
placeholder: '0x...',
description: 'The blockchain address to query',
},
{
displayName: 'Addresses',
name: 'addresses',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['getBalanceMulti'],
},
},
default: '',
placeholder: '0x...,0x...',
description: 'Comma-separated list of addresses (max 20)',
},
{
displayName: 'Contract Address',
name: 'contractAddress',
type: 'string',
required: true,
displayOptions: {
show: {
operation: [
'getAbi',
'getSourceCode',
'verifyContract',
'getTokenSupply',
'getTokenBalance',
'getTokenInfo',
],
},
},
default: '',
placeholder: '0x...',
description: 'The contract address to query',
},
{
displayName: 'Transaction Hash',
name: 'txHash',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['getTxReceiptStatus', 'getTxReceipt'],
},
},
default: '',
placeholder: '0x...',
description: 'The transaction hash to query',
},
{
displayName: 'Block Number',
name: 'blockNumber',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['getBlockReward', 'getBlockByNumber'],
},
},
default: '',
placeholder: '12345678',
description: 'The block number to query',
},
{
displayName: 'Timestamp',
name: 'timestamp',
type: 'string',
required: true,
displayOptions: {
show: {
operation: ['getBlockNumberByTime'],
},
},
default: '',
placeholder: '1578638524',
description: 'Unix timestamp',
},
{
displayName: 'Start Block',
name: 'startBlock',
type: 'string',
displayOptions: {
show: {
operation: ['getNormalTxs', 'getInternalTxs', 'getTokenTx', 'getTokenNftTx'],
},
},
default: '0',
description: 'Starting block number (0 for earliest)',
},
{
displayName: 'End Block',
name: 'endBlock',
type: 'string',
displayOptions: {
show: {
operation: ['getNormalTxs', 'getInternalTxs', 'getTokenTx', 'getTokenNftTx'],
},
},
default: '99999999',
description: 'Ending block number (99999999 for latest)',
},
{
displayName: 'Page',
name: 'page',
type: 'number',
displayOptions: {
show: {
operation: ['getNormalTxs', 'getInternalTxs', 'getTokenTx', 'getTokenNftTx'],
},
},
default: 1,
description: 'Page number for pagination',
},
{
displayName: 'Offset',
name: 'offset',
type: 'number',
displayOptions: {
show: {
operation: ['getNormalTxs', 'getInternalTxs', 'getTokenTx', 'getTokenNftTx'],
},
},
default: 10,
description: 'Number of transactions to return (max 10000)',
},
{
displayName: 'Sort',
name: 'sort',
type: 'options',
displayOptions: {
show: {
operation: ['getNormalTxs', 'getInternalTxs', 'getTokenTx', 'getTokenNftTx'],
},
},
options: [
{
name: 'Ascending',
value: 'asc',
},
{
name: 'Descending',
value: 'desc',
},
],
default: 'asc',
description: 'Sort order',
},
],
};
}
async execute() {
const items = this.getInputData();
const returnData = [];
const nodeInstance = this.getNode();
for (let i = 0; i < items.length; i++) {
try {
const credentials = await this.getCredentials('blockchainExplorerApi');
const network = this.getNodeParameter('network', i);
const resource = this.getNodeParameter('resource', i);
const operation = this.getNodeParameter('operation', i);
// Get base URL
let baseUrl = credentials.customBaseUrl;
if (!baseUrl) {
baseUrl = BlockchainExplorerApi_credentials_1.BlockchainExplorerApi.getBaseUrl(credentials.network, credentials.environment);
}
// Build API parameters
const params = {
apikey: credentials.apiKey,
};
// Set module and action based on resource and operation
BlockchainExplorer.setModuleAndAction(params, resource, operation);
// Add operation-specific parameters
BlockchainExplorer.addOperationParameters(this, params, operation, i);
// Make API request
const response = await axios_1.default.get(baseUrl, { params });
if (response.data.status === '0' && response.data.message !== 'OK') {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `API Error: ${response.data.result || response.data.message}`, { itemIndex: i });
}
returnData.push({
json: {
network,
resource,
operation,
...response.data,
},
pairedItem: { item: i },
});
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: { error: error.message },
pairedItem: { item: i },
});
continue;
}
throw error;
}
}
return [returnData];
}
static setModuleAndAction(params, resource, operation) {
switch (resource) {
case 'account':
params.module = 'account';
switch (operation) {
case 'getBalance':
params.action = 'balance';
break;
case 'getBalanceMulti':
params.action = 'balancemulti';
break;
case 'getNormalTxs':
params.action = 'txlist';
break;
case 'getInternalTxs':
params.action = 'txlistinternal';
break;
case 'getTokenTx':
params.action = 'tokentx';
break;
case 'getTokenNftTx':
params.action = 'tokennfttx';
break;
}
break;
case 'block':
params.module = 'block';
switch (operation) {
case 'getBlockReward':
params.action = 'getblockreward';
break;
case 'getBlockNumberByTime':
params.action = 'getblocknobytime';
break;
case 'getBlockByNumber':
params.action = 'getblockbynumber';
break;
}
break;
case 'contract':
params.module = 'contract';
switch (operation) {
case 'getAbi':
params.action = 'getabi';
break;
case 'getSourceCode':
params.action = 'getsourcecode';
break;
case 'verifyContract':
params.action = 'verifysourcecode';
break;
}
break;
case 'gas':
params.module = 'gastracker';
switch (operation) {
case 'getGasOracle':
params.action = 'gasoracle';
break;
case 'getGasPrice':
params.action = 'gasprice';
break;
}
break;
case 'stats':
params.module = 'stats';
switch (operation) {
case 'getTokenSupply':
params.action = 'ethsupply';
break;
case 'getTokenPrice':
params.action = 'ethprice';
break;
case 'getChainStats':
params.action = 'chainsize';
break;
}
break;
case 'token':
params.module = 'stats';
switch (operation) {
case 'getTokenSupply':
params.action = 'tokensupply';
break;
case 'getTokenBalance':
params.module = 'account';
params.action = 'tokenbalance';
break;
case 'getTokenInfo':
params.action = 'tokeninfo';
break;
}
break;
case 'transaction':
params.module = 'transaction';
switch (operation) {
case 'getTxReceiptStatus':
params.action = 'gettxreceiptstatus';
break;
case 'getTxReceipt':
params.action = 'gettxreceipt';
break;
}
break;
}
}
static addOperationParameters(executeFunctions, params, operation, itemIndex) {
switch (operation) {
case 'getBalance':
case 'getNormalTxs':
case 'getInternalTxs':
case 'getTokenTx':
case 'getTokenNftTx':
params.address = executeFunctions.getNodeParameter('address', itemIndex);
break;
case 'getBalanceMulti':
params.address = executeFunctions.getNodeParameter('addresses', itemIndex);
params.tag = 'latest';
break;
case 'getTokenBalance':
params.address = executeFunctions.getNodeParameter('address', itemIndex);
params.contractaddress = executeFunctions.getNodeParameter('contractAddress', itemIndex);
params.tag = 'latest';
break;
case 'getAbi':
case 'getSourceCode':
case 'verifyContract':
case 'getTokenSupply':
case 'getTokenInfo':
params.address = executeFunctions.getNodeParameter('contractAddress', itemIndex);
break;
case 'getTxReceiptStatus':
case 'getTxReceipt':
params.txhash = executeFunctions.getNodeParameter('txHash', itemIndex);
break;
case 'getBlockReward':
case 'getBlockByNumber':
params.blockno = executeFunctions.getNodeParameter('blockNumber', itemIndex);
break;
case 'getBlockNumberByTime':
params.timestamp = executeFunctions.getNodeParameter('timestamp', itemIndex);
params.closest = 'before';
break;
}
// Add pagination parameters for transaction lists
if (['getNormalTxs', 'getInternalTxs', 'getTokenTx', 'getTokenNftTx'].includes(operation)) {
params.startblock = executeFunctions.getNodeParameter('startBlock', itemIndex, '0');
params.endblock = executeFunctions.getNodeParameter('endBlock', itemIndex, '99999999');
params.page = executeFunctions.getNodeParameter('page', itemIndex, 1);
params.offset = executeFunctions.getNodeParameter('offset', itemIndex, 10);
params.sort = executeFunctions.getNodeParameter('sort', itemIndex, 'asc');
}
// Add tag parameter for balance operations
if (['getBalance'].includes(operation)) {
params.tag = 'latest';
}
}
}
exports.BlockchainExplorer = BlockchainExplorer;