@cryptodevops/n8n-nodes-moralis
Version:
n8n node for Moralis Web3 API
704 lines (703 loc) • 32 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Moralis = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const axios_1 = __importDefault(require("axios"));
class Moralis {
constructor() {
this.description = {
displayName: 'Moralis',
name: 'moralis',
icon: 'file:moralis.svg',
group: ['input'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Interact with Moralis Web3 APIs for blockchain data, NFTs, tokens, and DeFi',
defaults: {
name: 'Moralis',
},
inputs: ['main'],
outputs: ['main'],
usableAsTool: true,
credentials: [
{
name: 'moralisApi',
required: true,
},
],
requestDefaults: {
baseURL: 'https://deep-index.moralis.io/api/v2.2',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Block',
value: 'block',
},
{
name: 'DeFi',
value: 'defi',
},
{
name: 'NFT',
value: 'nft',
},
{
name: 'Token',
value: 'token',
},
{
name: 'Transaction',
value: 'transaction',
},
{
name: 'Wallet',
value: 'wallet',
},
],
default: 'wallet',
},
// Chain selection
{
displayName: 'Chain',
name: 'chain',
type: 'options',
options: [
{
name: 'Arbitrum',
value: 'arbitrum',
},
{
name: 'Avalanche',
value: 'avalanche',
},
{
name: 'Base',
value: 'base',
},
{
name: 'BSC',
value: 'bsc',
},
{
name: 'Ethereum',
value: 'eth',
},
{
name: 'Optimism',
value: 'optimism',
},
{
name: 'Polygon',
value: 'polygon',
},
],
default: 'eth',
description: 'The blockchain to query',
},
// Wallet Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['wallet'],
},
},
options: [
{
name: 'Get Native Balance',
value: 'getNativeBalance',
description: 'Get native token balance of a wallet',
action: 'Get native token balance of a wallet',
},
{
name: 'Get NFTs',
value: 'getWalletNFTs',
description: 'Get NFTs owned by a wallet',
action: 'Get nf ts owned by a wallet',
},
{
name: 'Get Portfolio',
value: 'getWalletPortfolio',
description: 'Get complete wallet portfolio',
action: 'Get complete wallet portfolio',
},
{
name: 'Get Token Balances',
value: 'getTokenBalances',
description: 'Get ERC20 token balances of a wallet',
action: 'Get ERC20 token balances of a wallet',
},
{
name: 'Get Transaction History',
value: 'getWalletTransactions',
description: 'Get transaction history of a wallet',
action: 'Get transaction history of a wallet',
},
],
default: 'getNativeBalance',
},
// Token Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['token'],
},
},
options: [
{
name: 'Get Token Metadata',
value: 'getTokenMetadata',
description: 'Get metadata for a token',
action: 'Get metadata for a token',
},
{
name: 'Get Token Price',
value: 'getTokenPrice',
description: 'Get current price of a token',
action: 'Get current price of a token',
},
{
name: 'Get Token Transfers',
value: 'getTokenTransfers',
description: 'Get transfer history of a token',
action: 'Get transfer history of a token',
},
],
default: 'getTokenMetadata',
},
// NFT Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['nft'],
},
},
options: [
{
name: 'Get NFT Metadata',
value: 'getNFTMetadata',
description: 'Get metadata for an NFT',
action: 'Get metadata for an NFT',
},
{
name: 'Get NFT Owners',
value: 'getNFTOwners',
description: 'Get owners of an NFT collection',
action: 'Get owners of an NFT collection',
},
{
name: 'Get NFT Transfers',
value: 'getNFTTransfers',
description: 'Get transfer history of an NFT',
action: 'Get transfer history of an NFT',
},
{
name: 'Get Collection Stats',
value: 'getCollectionStats',
description: 'Get statistics for an NFT collection',
action: 'Get statistics for an NFT collection',
},
],
default: 'getNFTMetadata',
},
// Transaction Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['transaction'],
},
},
options: [
{
name: 'Get Transaction',
value: 'getTransaction',
description: 'Get details of a transaction',
action: 'Get details of a transaction',
},
{
name: 'Decode Transaction',
value: 'decodeTransaction',
description: 'Decode transaction data',
action: 'Decode transaction data',
},
],
default: 'getTransaction',
},
// Block Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['block'],
},
},
options: [
{
name: 'Get Block',
value: 'getBlock',
description: 'Get block information',
action: 'Get block information',
},
{
name: 'Get Latest Block',
value: 'getLatestBlock',
description: 'Get latest block number',
action: 'Get latest block number',
},
{
name: 'Date to Block',
value: 'dateToBlock',
description: 'Get block number for a specific date',
action: 'Get block number for a specific date',
},
],
default: 'getLatestBlock',
},
// DeFi Operations
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['defi'],
},
},
options: [
{
name: 'Get DeFi Positions',
value: 'getDeFiPositions',
description: 'Get DeFi positions for a wallet',
action: 'Get de fi positions for a wallet',
},
{
name: 'Get Pair Reserves',
value: 'getPairReserves',
description: 'Get liquidity pair reserves',
action: 'Get liquidity pair reserves',
},
],
default: 'getDeFiPositions',
},
// Address parameter
{
displayName: 'Wallet Address',
name: 'address',
type: 'string',
displayOptions: {
show: {
operation: [
'getNativeBalance',
'getTokenBalances',
'getWalletNFTs',
'getWalletTransactions',
'getWalletPortfolio',
'getDeFiPositions',
],
},
},
default: '',
placeholder: '0x...',
description: 'The wallet address to query',
required: true,
},
// Token Address parameter
{
displayName: 'Token Address',
name: 'tokenAddress',
type: 'string',
typeOptions: { password: true },
displayOptions: {
show: {
operation: [
'getTokenMetadata',
'getTokenPrice',
'getTokenTransfers',
],
},
},
default: '',
placeholder: '0x...',
description: 'The token contract address',
required: true,
},
// NFT Address parameter
{
displayName: 'NFT Contract Address',
name: 'nftAddress',
type: 'string',
displayOptions: {
show: {
operation: [
'getNFTMetadata',
'getNFTOwners',
'getNFTTransfers',
'getCollectionStats',
],
},
},
default: '',
placeholder: '0x...',
required: true,
},
// Token ID parameter
{
displayName: 'Token ID',
name: 'tokenId',
type: 'string',
typeOptions: { password: true },
displayOptions: {
show: {
operation: ['getNFTMetadata'],
},
},
default: '',
description: 'The NFT token ID',
required: true,
},
// Transaction Hash parameter
{
displayName: 'Transaction Hash',
name: 'transactionHash',
type: 'string',
displayOptions: {
show: {
operation: ['getTransaction', 'decodeTransaction'],
},
},
default: '',
placeholder: '0x...',
required: true,
},
// Block Number parameter
{
displayName: 'Block Number',
name: 'blockNumber',
type: 'string',
displayOptions: {
show: {
operation: ['getBlock'],
},
},
default: '',
description: 'The block number (or "latest")',
required: true,
},
// Date parameter
{
displayName: 'Date',
name: 'date',
type: 'dateTime',
displayOptions: {
show: {
operation: ['dateToBlock'],
},
},
default: '',
description: 'The date to convert to block number',
required: true,
},
// Additional Fields
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
options: [
{
displayName: 'Limit',
name: 'limit',
type: 'number',
typeOptions: {
minValue: 1,
},
default: 50,
description: 'Max number of results to return',
},
{
displayName: 'Cursor',
name: 'cursor',
type: 'string',
default: '',
description: 'Pagination cursor for next page',
},
{
displayName: 'Include Metadata',
name: 'includeMetadata',
type: 'boolean',
default: true,
description: 'Whether to include metadata in the response',
},
{
displayName: 'Format',
name: 'format',
type: 'options',
options: [
{
name: 'Decimal',
value: 'decimal',
},
{
name: 'Hex',
value: 'hex',
},
],
default: 'decimal',
description: 'Number format for the response',
},
],
},
],
};
}
async execute() {
const items = this.getInputData();
const returnData = [];
for (let i = 0; i < items.length; i++) {
try {
const resource = this.getNodeParameter('resource', i);
const operation = this.getNodeParameter('operation', i);
const chain = this.getNodeParameter('chain', i);
const additionalFields = this.getNodeParameter('additionalFields', i, {});
const credentials = await this.getCredentials('moralisApi');
const apiKey = credentials.apiKey;
const axiosConfig = {
headers: {
'X-API-Key': apiKey,
Accept: 'application/json',
},
};
let endpoint = '';
let responseData;
if (resource === 'wallet') {
const address = this.getNodeParameter('address', i);
if (operation === 'getNativeBalance') {
endpoint = `${address}/balance`;
let queryParams = `chain=${chain}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getTokenBalances') {
endpoint = `${address}/erc20`;
let queryParams = `chain=${chain}`;
if (additionalFields.limit) {
queryParams += `&limit=${additionalFields.limit}`;
}
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getWalletNFTs') {
endpoint = `${address}/nft`;
let queryParams = `chain=${chain}&format=${additionalFields.format || 'decimal'}`;
if (additionalFields.limit) {
queryParams += `&limit=${additionalFields.limit}`;
}
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getWalletTransactions') {
endpoint = `${address}`;
let queryParams = `chain=${chain}`;
if (additionalFields.limit) {
queryParams += `&limit=${additionalFields.limit}`;
}
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getWalletPortfolio') {
endpoint = `wallets/${address}/tokens`;
let queryParams = `chain=${chain}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
}
else if (resource === 'token') {
const tokenAddress = this.getNodeParameter('tokenAddress', i);
if (operation === 'getTokenMetadata') {
endpoint = `erc20/metadata`;
let queryParams = `chain=${chain}&addresses=${tokenAddress}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getTokenPrice') {
endpoint = `erc20/${tokenAddress}/price`;
let queryParams = `chain=${chain}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getTokenTransfers') {
endpoint = `erc20/${tokenAddress}/transfers`;
let queryParams = `chain=${chain}`;
if (additionalFields.limit) {
queryParams += `&limit=${additionalFields.limit}`;
}
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
}
else if (resource === 'nft') {
const nftAddress = this.getNodeParameter('nftAddress', i);
if (operation === 'getNFTMetadata') {
const tokenId = this.getNodeParameter('tokenId', i);
endpoint = `nft/${nftAddress}/${tokenId}`;
let queryParams = `chain=${chain}&format=${additionalFields.format || 'decimal'}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getNFTOwners') {
endpoint = `nft/${nftAddress}/owners`;
let queryParams = `chain=${chain}&format=${additionalFields.format || 'decimal'}`;
if (additionalFields.limit) {
queryParams += `&limit=${additionalFields.limit}`;
}
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getNFTTransfers') {
endpoint = `nft/${nftAddress}/transfers`;
let queryParams = `chain=${chain}&format=${additionalFields.format || 'decimal'}`;
if (additionalFields.limit) {
queryParams += `&limit=${additionalFields.limit}`;
}
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getCollectionStats') {
endpoint = `nft/${nftAddress}/stats`;
let queryParams = `chain=${chain}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
}
else if (resource === 'transaction') {
const transactionHash = this.getNodeParameter('transactionHash', i);
if (operation === 'getTransaction') {
endpoint = `transaction/${transactionHash}`;
let queryParams = `chain=${chain}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'decodeTransaction') {
endpoint = `transaction/${transactionHash}/verbose`;
let queryParams = `chain=${chain}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
}
else if (resource === 'block') {
if (operation === 'getLatestBlock') {
// Get latest block using dateToBlock with current date
endpoint = `dateToBlock`;
let queryParams = `chain=${chain}&date=${new Date().toISOString()}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'dateToBlock') {
const date = this.getNodeParameter('date', i);
endpoint = `dateToBlock`;
let queryParams = `chain=${chain}&date=${new Date(date).toISOString()}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getBlock') {
const blockNumber = this.getNodeParameter('blockNumber', i);
// Use the correct endpoint format for getting block by number
endpoint = `block/${blockNumber}`;
let queryParams = `chain=${chain}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
}
else if (resource === 'defi') {
const address = this.getNodeParameter('address', i);
if (operation === 'getDeFiPositions') {
endpoint = `wallets/${address}/defi/positions`;
let queryParams = `chain=${chain}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
else if (operation === 'getPairReserves') {
const tokenAddress = this.getNodeParameter('tokenAddress', i);
endpoint = `${tokenAddress}/reserves`;
let queryParams = `chain=${chain}`;
const response = await axios_1.default.get(`https://deep-index.moralis.io/api/v2.2/${endpoint}?${queryParams}`, axiosConfig);
responseData = response.data;
}
}
// Process response data
if (responseData) {
returnData.push({
json: {
...responseData,
operation: operation,
resource: resource,
chain: chain,
timestamp: new Date().toISOString(),
},
});
}
else {
returnData.push({
json: {
error: 'No data found',
operation: operation,
resource: resource,
chain: chain,
},
});
}
}
catch (error) {
if (this.continueOnFail()) {
returnData.push({
json: {
error: error.message,
},
pairedItem: {
item: i,
},
});
continue;
}
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, {
itemIndex: i,
});
}
}
return [returnData];
}
}
exports.Moralis = Moralis;