UNPKG

@cryptodevops/n8n-nodes-bitquery-api

Version:

Nœud n8n pour les APIs Raydium et PumpFun - Accès aux données des pools et tokens Solana sur les DEX Raydium et PumpFun

561 lines (560 loc) 19.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BitqueryApi = void 0; const n8n_workflow_1 = require("n8n-workflow"); const axios_1 = __importDefault(require("axios")); class BitqueryApi { constructor() { this.description = { displayName: 'Bitquery API', name: 'bitqueryApi', icon: 'file:bitquery.svg', group: ['transform'], version: 1, subtitle: '={{$parameter["queryType"]}}', description: 'Accède aux données blockchain multi-chaînes via l\'API Bitquery - Transactions, UTXO, statistiques réseau', defaults: { name: 'Bitquery API', }, // eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node inputs: ["main" /* NodeConnectionType.Main */], // eslint-disable-next-line n8n-nodes-base/node-class-description-outputs-wrong outputs: ["main" /* NodeConnectionType.Main */], credentials: [ { name: 'bitqueryApi', required: true, }, ], properties: [ { displayName: 'Type De Requête', name: 'queryType', type: 'options', noDataExpression: true, default: 'raydium_latest_pools', options: [ { name: 'PumpFun API - Top 10 Tokens By Marketcap Change In Last 5 Mins', value: 'pumpfun_marketcap_change', description: 'Récupère le top 10 des tokens Pump Fun par changement de marketcap dans les 5 dernières minutes', }, { name: 'PumpFun API - Top 100 About To Graduate Pump Fun Tokens', value: 'pumpfun_graduating_tokens', description: 'Récupère le top 100 des tokens sur le point de graduer de Pump Fun', }, { name: 'Raydium API - Latest Pools Created On Launchpad', value: 'raydium_launchpad_pools', description: 'Récupère les derniers pools créés sur le launchpad Raydium', }, { name: 'Raydium API - Latest Pools Created On Raydium', value: 'raydium_latest_pools', description: 'Récupère les derniers pools créés sur Raydium', }, { name: 'Raydium API - Latest Trades For A Specific Currency', value: 'raydium_latest_trades', description: 'Récupère les derniers trades pour une devise spécifique sur Raydium', }, { name: 'Raydium API - Top 100 About To Graduate Launchpad Tokens', value: 'raydium_graduating_tokens', description: 'Récupère le top 100 des tokens sur le point de graduer du launchpad Raydium', }, ], }, { displayName: 'Program Method', name: 'programMethod', type: 'string', default: 'initializeUserWithNonce', description: 'The program method to filter by', displayOptions: { show: { queryType: ['raydium_latest_pools'], }, }, }, { displayName: 'Program Address', name: 'programAddress', type: 'string', default: '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8', description: 'The program address to filter by', displayOptions: { show: { queryType: ['raydium_latest_pools'], }, }, }, { displayName: 'Currency Mint Address', name: 'currencyMintAddress', type: 'string', default: '4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R', description: 'The mint address of the currency to filter trades', displayOptions: { show: { queryType: ['raydium_latest_trades'], }, }, }, { displayName: 'Trade Limit', name: 'tradeLimit', type: 'number', default: 10, description: 'Number of trades to retrieve', displayOptions: { show: { queryType: ['raydium_latest_trades'], }, }, }, { displayName: 'Tokens Limit', name: 'tokensLimit', type: 'number', default: 100, description: 'Number of tokens to retrieve', displayOptions: { show: { queryType: ['raydium_graduating_tokens', 'pumpfun_graduating_tokens'], }, }, }, { displayName: 'Top Tokens Limit', name: 'topTokensLimit', type: 'number', default: 10, description: 'Number of top tokens to retrieve by marketcap change', displayOptions: { show: { queryType: ['pumpfun_marketcap_change'], }, }, } ], }; } async execute() { const items = this.getInputData(); const returnData = []; for (let i = 0; i < items.length; i++) { try { const queryType = this.getNodeParameter('queryType', i); const credentials = await this.getCredentials('bitqueryApi'); const baseUrl = 'https://streaming.bitquery.io'; const headers = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${credentials.apiKey}`, }; let query = ''; let variables = {}; switch (queryType) { case 'raydium_latest_pools': const programMethod = this.getNodeParameter('programMethod', i); const programAddress = this.getNodeParameter('programAddress', i); query = ` subscription { Solana { Instructions( where: { Transaction: {Result: {Success: true}} Instruction: { Program: { Method: {is: "${programMethod}"} Address: {is: "${programAddress}"} } } } ) { Block { Time Date } Transaction { Signature } Instruction { AncestorIndexes CallerIndex Depth Data ExternalSeqNumber InternalSeqNumber Index Accounts { Address IsWritable Token { Mint Owner ProgramId } } CallPath Logs Program { AccountNames Method Json Name Arguments { Type Name Value { __typename ... on Solana_ABI_Integer_Value_Arg { integer } ... on Solana_ABI_String_Value_Arg { string } ... on Solana_ABI_Address_Value_Arg { address } ... on Solana_ABI_BigInt_Value_Arg { bigInteger } ... on Solana_ABI_Bytes_Value_Arg { hex } ... on Solana_ABI_Boolean_Value_Arg { bool } ... on Solana_ABI_Float_Value_Arg { float } ... on Solana_ABI_Json_Value_Arg { json } } } } } } } } `; break; case 'raydium_latest_trades': const currencyMintAddress = this.getNodeParameter('currencyMintAddress', i); const tradeLimit = this.getNodeParameter('tradeLimit', i); query = ` query { Solana { Buyside: DEXTrades( limit:{count:${tradeLimit}} orderBy:{descending:Block_Time} where: {Trade: {Buy: {Currency: {MintAddress: {is: "${currencyMintAddress}"}}}, Dex: {ProgramAddress: {is: "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"}}}} ) { Trade { Dex { ProgramAddress ProtocolFamily ProtocolName } Buy { Account { Address } Amount Currency { Decimals Symbol MintAddress Name } PriceAgaistSellCurrency: Price } Sell { Account { Address } Amount Currency { Decimals Symbol MintAddress Name } PriceAgaistBuyCurrency: Price } } Block { Time Height } Transaction { Signature FeePayer Signer } } Sellside: DEXTrades( limit:{count:${tradeLimit}} orderBy:{descending:Block_Time} where: {Trade: {Sell: {Currency: {MintAddress: {is: "${currencyMintAddress}"}}}, Dex: {ProgramAddress: {is: "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"}}}} ) { Trade { Dex { ProgramAddress ProtocolFamily ProtocolName } Buy { Account { Address } Amount Currency { Decimals Symbol MintAddress Name } PriceAgaistSellCurrency: Price } Sell { Account { Address } Amount Currency { Decimals Symbol MintAddress Name } PriceAgaistBuyCurrency: Price } } Block { Time Height } Transaction { Signature FeePayer Signer } } } } `; break; case 'raydium_launchpad_pools': query = ` { Solana(network: solana, dataset: realtime) { Instructions( where: {Instruction: {Program: {Address: {is: "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj"}, Method: {is: "PoolCreateEvent"}}}} orderBy: {descending: Block_Time} ) { Instruction { Accounts { Address } Program { Name Method AccountNames Arguments { Name Type Value { ... on Solana_ABI_Integer_Value_Arg { integer } ... on Solana_ABI_String_Value_Arg { string } ... on Solana_ABI_Address_Value_Arg { address } ... on Solana_ABI_BigInt_Value_Arg { bigInteger } ... on Solana_ABI_Bytes_Value_Arg { hex } ... on Solana_ABI_Boolean_Value_Arg { bool } ... on Solana_ABI_Float_Value_Arg { float } ... on Solana_ABI_Json_Value_Arg { json } } } } } } } } `; break; case 'raydium_graduating_tokens': const tokensLimit = this.getNodeParameter('tokensLimit', i); query = ` { Solana { DEXPools( limitBy: {by: Pool_Market_BaseCurrency_MintAddress, count: 1} limit: {count: ${tokensLimit}} orderBy: {ascending: Pool_Base_PostAmount} where: {Pool: {Base: {PostAmount: {gt: "206900000"}}, Dex: {ProgramAddress: {is: "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj"}}, Market: {QuoteCurrency: {MintAddress: {in: ["11111111111111111111111111111111", "So11111111111111111111111111111111111111112"]}}}}, Transaction: {Result: {Success: true}}, Block: {Time: {since_relative:{minutes_ago:5}}}} ) { Bonding_Curve_Progress_precentage: calculate(expression:"100 - ((($Pool_Base_Balance - 206900000) * 100) / 793100000)") Pool { Market { BaseCurrency { MintAddress Name Symbol } MarketAddress QuoteCurrency { MintAddress Name Symbol } } Dex { ProtocolName ProtocolFamily } Base { Balance: PostAmount(maximum: Block_Time) } Quote { PostAmount PriceInUSD PostAmountInUSD } } } } } `; break; case 'pumpfun_graduating_tokens': const pumpfunTokensLimit = this.getNodeParameter('tokensLimit', i); query = ` { Solana { DEXPools( limitBy: {by: Pool_Market_BaseCurrency_MintAddress, count: 1} limit: {count: ${pumpfunTokensLimit}} orderBy: {ascending: Pool_Base_PostAmount} where: {Pool: {Base: {PostAmount: {gt: "206900000"}}, Dex: {ProgramAddress: {is: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"}}, Market: {QuoteCurrency: {MintAddress: {in: ["11111111111111111111111111111111", "So11111111111111111111111111111111111111112"]}}}}, Transaction: {Result: {Success: true}}, Block: {Time: {since_relative:{minutes_ago:5}}}} ) { Bonding_Curve_Progress_precentage: calculate(expression:"100 - ((($Pool_Base_Balance - 206900000) * 100) / 793100000)") Pool { Market { BaseCurrency { MintAddress Name Symbol } MarketAddress QuoteCurrency { MintAddress Name Symbol } } Dex { ProtocolName ProtocolFamily } Base { Balance: PostAmount(maximum: Block_Time) } Quote { PostAmount PriceInUSD PostAmountInUSD } } } } } `; break; case 'pumpfun_marketcap_change': const topTokensLimit = this.getNodeParameter('topTokensLimit', i); query = ` query MyQuery { Solana { DEXTradeByTokens( limit: {count: ${topTokensLimit}} orderBy:{descendingByField:"Marketcap_Change_5min"} where: {Trade: {Dex: {ProgramAddress: {is: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"}}}, Transaction: {Result: {Success: true}}, Block: {Time: {since_relative: {hours_ago: 6}}}} ) { Trade { Currency { Name Symbol MintAddress } Price_5min_ago: PriceInUSD(minimum:Block_Time if:{Block:{Time:{since_relative:{minutes_ago:5}}}}) Price_1h_ago: PriceInUSD(minimum:Block_Time if:{Block:{Time:{since_relative:{hours_ago:1}}}}) Price_6h_ago: PriceInUSD(minimum: Block_Time) CurrentPrice: PriceInUSD(maximum: Block_Time) Side { Currency { Name Symbol MintAddress } } } Marketcap_Change_5min: calculate(expression: "(($Trade_CurrentPrice - $Trade_Price_5min_ago) / $Trade_Price_5min_ago) * 100") Marketcap_Change_1h: calculate(expression: "(($Trade_CurrentPrice - $Trade_Price_1h_ago) / $Trade_Price_1h_ago) * 100") Marketcap_Change_6h: calculate(expression: "(($Trade_CurrentPrice - $Trade_Price_6h_ago) / $Trade_Price_6h_ago) * 100") } } } `; break; default: throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Type de requête non supporté: ${queryType}`, { itemIndex: i }); } const response = await axios_1.default.post(`${baseUrl}/eap`, { query: query, variables: variables, }, { headers }); if (response.data.errors) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Erreur API Bitquery: ${JSON.stringify(response.data.errors)}`, { itemIndex: i }); } returnData.push({ json: response.data.data, pairedItem: { item: i }, }); } 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.BitqueryApi = BitqueryApi;