blockchain-api
Version:
API utilities for interacting with the Exatechl2 blockchain
348 lines (345 loc) • 12.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TOKEN_RELATED_EVENTS = exports.EVENT_SIGNATURES = void 0;
exports.parseAddressFromTopic = parseAddressFromTopic;
exports.getEventType = getEventType;
exports.enhanceEvent = enhanceEvent;
exports.enhanceEvents = enhanceEvents;
exports.enhanceEventResponse = enhanceEventResponse;
exports.getAddressEvents = getAddressEvents;
exports.getTransactionEvents = getTransactionEvents;
exports.getAllEvents = getAllEvents;
exports.getTokenTransfers = getTokenTransfers;
exports.getTokenTransfersByToken = getTokenTransfersByToken;
exports.getTokenTransfersByAddress = getTokenTransfersByAddress;
const explorerApi_1 = require("../../core/explorerApi");
const formatters_1 = require("../../utils/formatters");
const tokens_1 = require("../tokens/tokens");
exports.EVENT_SIGNATURES = {
Transfer: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
Approval: '0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925',
Mint: '0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885',
Burn: '0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5',
Pause: '0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258',
Unpause: '0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa',
OwnershipTransferred: '0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0',
RoleGranted: '0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d',
RoleRevoked: '0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b',
};
exports.TOKEN_RELATED_EVENTS = [
exports.EVENT_SIGNATURES.Transfer,
exports.EVENT_SIGNATURES.Mint,
exports.EVENT_SIGNATURES.Burn
];
/**
*
* @param topic
* @returns
*/
function parseAddressFromTopic(topic) {
if (!topic || typeof topic !== 'string') {
return '';
}
if (topic.length >= 42) {
return '0x' + topic.substring(topic.length - 40).toLowerCase();
}
return topic.toLowerCase();
}
/**
*
* @param signature
* @returns
*/
function getEventType(signature) {
for (const [name, sig] of Object.entries(exports.EVENT_SIGNATURES)) {
if (sig.toLowerCase() === signature.toLowerCase()) {
return name;
}
}
return 'Unknown';
}
/**
*
*
* @param event
* @returns
*/
async function enhanceEvent(event) {
if (!event)
return null;
const enhancedEvent = { ...event };
if (event.from_address || event.to_address || event.tx_hash) {
enhancedEvent.transaction = {
from: event.from_address,
to: event.to_address,
hash: event.tx_hash
};
if (event.method_signature || event.method_name) {
enhancedEvent.transaction.method = {
signature: event.method_signature || null,
name: event.method_name || 'unknown'
};
}
}
enhancedEvent.technical = {
signature: event.topics && event.topics[0] ? event.topics[0] : null,
topics: event.topics || [],
data: event.data || '0x',
address: event.address || null,
blockNumber: event.block_number,
logIndex: event.log_index,
method: event.method_signature ? {
signature: event.method_signature,
name: event.method_name || 'unknown'
} : null
};
if (event.topics && event.topics[0]) {
const signature = event.topics[0];
const eventType = getEventType(signature);
enhancedEvent.event_type = eventType;
if (eventType === 'Transfer') {
let from = '';
if (event.raw_from) {
from = parseAddressFromTopic(event.raw_from);
}
else if (event.from_address) {
from = event.from_address.toLowerCase();
}
else if (event.topics && event.topics.length > 1) {
from = parseAddressFromTopic(event.topics[1]);
}
let to = '';
if (event.raw_to) {
to = parseAddressFromTopic(event.raw_to);
}
else if (event.to_address && event.address && event.to_address.toLowerCase() !== event.address.toLowerCase()) {
to = event.to_address.toLowerCase();
}
else if (event.topics && event.topics.length > 2) {
to = parseAddressFromTopic(event.topics[2]);
}
const isTaxTransfer = from && to && from.toLowerCase() === to.toLowerCase();
let tokenSymbol = event.token_symbol || 'TOKEN';
let decimals = event.decimals || 18;
if ((!event.token_symbol || event.token_symbol === 'TOKEN' || event.token_symbol === 'UNKNOWN') && event.address) {
try {
const tokenInfo = await (0, tokens_1.getTokenInfo)(event.address);
if (tokenInfo) {
tokenSymbol = tokenInfo.symbol || 'TOKEN';
decimals = tokenInfo.decimals || 18;
}
}
catch (error) {
console.warn(`Failed to get token info for ${event.address}: ${error.message}`);
}
}
const value = (0, formatters_1.formatTokenAmount)(event.data, decimals);
enhancedEvent.token_transfer = {
from,
to,
value,
token_address: event.address || event.token_address,
token_symbol: tokenSymbol,
is_tax: isTaxTransfer
};
const shortFrom = (0, formatters_1.truncateString)(from);
const shortTo = (0, formatters_1.truncateString)(to);
if (isTaxTransfer) {
enhancedEvent.display_type = 'Self-Transfer';
enhancedEvent.description = `Token Fee: ${value} ${tokenSymbol} retained as transaction fee`;
enhancedEvent.transfer_type = 'fee';
}
else {
enhancedEvent.display_type = 'Transfer';
enhancedEvent.description = `Transfer ${value} ${tokenSymbol} from ${shortFrom} to ${shortTo}`;
enhancedEvent.transfer_type = 'transfer';
}
enhancedEvent.parameters = [
{ name: 'signature', value: signature },
{ name: 'topic1', value: event.topics[1] },
{ name: 'topic2', value: event.topics[2] },
{ name: 'data', value: event.data }
];
}
else if (eventType === 'Approval') {
const owner = event.topics && event.topics.length > 1 ? parseAddressFromTopic(event.topics[1]) : '';
const spender = event.topics && event.topics.length > 2 ? parseAddressFromTopic(event.topics[2]) : '';
let tokenSymbol = event.token_symbol || 'TOKEN';
let decimals = event.decimals || 18;
if ((!event.token_symbol || event.token_symbol === 'TOKEN' || event.token_symbol === 'UNKNOWN') && event.address) {
try {
const tokenInfo = await (0, tokens_1.getTokenInfo)(event.address);
if (tokenInfo) {
tokenSymbol = tokenInfo.symbol || 'TOKEN';
decimals = tokenInfo.decimals || 18;
}
}
catch (error) {
console.warn(`Failed to get token info for ${event.address}: ${error.message}`);
}
}
const value = (0, formatters_1.formatTokenAmount)(event.data, decimals);
enhancedEvent.token_approval = {
owner,
spender,
value,
token_address: event.address,
token_symbol: tokenSymbol
};
const shortOwner = (0, formatters_1.truncateString)(owner);
const shortSpender = (0, formatters_1.truncateString)(spender);
enhancedEvent.description = `Approval: ${shortOwner} approved ${shortSpender} to spend ${value} ${tokenSymbol}`;
enhancedEvent.display_type = 'Approval';
enhancedEvent.parameters = [
{ name: 'signature', value: signature },
{ name: 'topic1', value: event.topics[1] },
{ name: 'topic2', value: event.topics[2] },
{ name: 'data', value: event.data }
];
}
else {
enhancedEvent.display_type = eventType;
}
}
return enhancedEvent;
}
/**
*
* @param events
* @returns
*/
async function enhanceEvents(events) {
if (!events || !Array.isArray(events)) {
return [];
}
const enhancedEvents = [];
for (const event of events) {
const enhanced = await enhanceEvent(event);
enhancedEvents.push(enhanced);
}
return enhancedEvents;
}
/**
*
* @param response
* @returns
*/
async function enhanceEventResponse(response) {
if (!response)
return response;
if (response.events) {
const enhancedEvents = await enhanceEvents(response.events);
return {
...response,
events: enhancedEvents
};
}
else if (response.transfers) {
const enhancedTransfers = await enhanceEvents(response.transfers);
return {
...response,
transfers: enhancedTransfers
};
}
else if (response.token_events) {
const enhancedEvents = await enhanceEvents(response.token_events);
return {
...response,
token_events: enhancedEvents
};
}
else if (response.data && Array.isArray(response.data)) {
const enhancedData = await enhanceEvents(response.data);
return {
...response,
data: enhancedData
};
}
return response;
}
/**
* @param address
* @param params
* @returns
*/
async function getAddressEvents(address, params = {}) {
const queryParams = {
page: params.page || 1,
limit: params.limit || 10
};
if (params.eventType) {
queryParams.eventType = params.eventType;
}
const response = await (0, explorerApi_1.callExplorerApi)(`events/address/${address}`, queryParams);
return await enhanceEventResponse(response);
}
/**
* @param txHash
* @param params
* @returns
*/
async function getTransactionEvents(txHash, params = {}) {
const queryParams = {};
if (params.eventType) {
queryParams.eventType = params.eventType;
}
const response = await (0, explorerApi_1.callExplorerApi)(`events/tx/${txHash}`, queryParams);
return await enhanceEventResponse(response);
}
/**
*
* @param params
* @returns
*/
async function getAllEvents(params = {}) {
const queryParams = {
page: params.page || 1,
limit: params.limit || 10
};
if (params.eventType) {
queryParams.eventType = params.eventType;
}
const response = await (0, explorerApi_1.callExplorerApi)('events', queryParams);
return await enhanceEventResponse(response);
}
/**
*
* @param params
* @returns
*/
async function getTokenTransfers(params = {}) {
const queryParams = {
page: params.page || 1,
limit: params.limit || 10
};
const response = await (0, explorerApi_1.callExplorerApi)('events/token-transfers', queryParams);
return await enhanceEventResponse(response);
}
/**
*
* @param tokenAddress
* @param params
* @returns
*/
async function getTokenTransfersByToken(tokenAddress, params = {}) {
const queryParams = {
page: params.page || 1,
limit: params.limit || 10
};
const response = await (0, explorerApi_1.callExplorerApi)(`events/token-transfers/token/${tokenAddress}`, queryParams);
return await enhanceEventResponse(response);
}
/**
*
* @param address
* @param params
* @returns
*/
async function getTokenTransfersByAddress(address, params = {}) {
const queryParams = {
page: params.page || 1,
limit: params.limit || 10
};
const response = await (0, explorerApi_1.callExplorerApi)(`events/token-transfers/address/${address}`, queryParams);
return await enhanceEventResponse(response);
}