@ethersproject/abstract-provider#Log TypeScript Examples
The following examples show how to use
@ethersproject/abstract-provider#Log.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: base-provider.ts From bodhi.js with Apache License 2.0 | 6 votes |
getTXReceiptByHash = async (txHash: string): Promise<TXReceipt | null> => {
const tx = await this._getMinedTXReceipt(txHash);
if (!tx) return null;
return this.formatter.receipt({
to: tx.to || null,
from: tx.from,
contractAddress: tx.contractAddress || null,
transactionIndex: tx.transactionIndex,
gasUsed: tx.gasUsed,
logsBloom: tx.logsBloom,
blockHash: tx.blockHash,
transactionHash: tx.transactionHash,
logs: Array.isArray(tx.logs) ? tx.logs : (tx.logs.nodes as Log[]),
blockNumber: tx.blockNumber,
cumulativeGasUsed: tx.cumulativeGasUsed,
type: tx.type,
status: tx.status,
effectiveGasPrice: EFFECTIVE_GAS_PRICE,
confirmations: (await this._getBlockHeader('latest')).number.toNumber() - tx.blockNumber
});
};
Example #2
Source File: Provider.ts From evm-provider.js with Apache License 2.0 | 6 votes |
/**
* Get an array of filtered logs from the chain's head.
* @param filter The filter to apply to the logs
* @returns A promise that resolves to an array of filtered logs
*/
async getLogs(filter: Filter): Promise<Array<Log>> {
if (!this.dataProvider) return this._fail('getLogs');
return this.dataProvider.getLogs(filter, this._resolveBlockNumber);
}
Example #3
Source File: DataProvider.ts From evm-provider.js with Apache License 2.0 | 6 votes |
/**
*
* @param filter The filter to apply to the logs
* @param resolveBlockNumber The block to retrieve the logs from, defaults
* to the head
* @returns A promise that resolves to an array of filtered logs
*/
abstract getLogs(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
filter: any,
resolveBlockNumber: (
blockTag?: BlockTag | Promise<BlockTag>
) => Promise<number | undefined>
): Promise<Array<Log>>;
Example #4
Source File: transaction.ts From tx2uml with MIT License | 6 votes |
static parseTransactionLogs(logs: Array<Log>, contracts: Contracts) {
// for each tx log
for (const log of logs) {
// see if we have the contract source for the log
const contract = contracts[log.address.toLowerCase()]
if (contract?.ethersContract) {
// try and parse the log topic
try {
const event =
contract.ethersContract.interface.parseLog(log)
contract.events.push(parseEvent(contract, event))
} catch (err) {
debug(
`Failed to parse log with topic ${log?.topics[0]} on contract ${log.address}`
)
}
}
// also parse the events on any contracts that are delegated to
contract?.delegatedToContracts?.forEach(delegatedToContract => {
// try and parse the log topic
try {
const event =
delegatedToContract.ethersContract.interface.parseLog(
log
)
contract.events.push(parseEvent(contract, event))
} catch (err) {
debug(
`Failed to parse log with topic ${log?.topics[0]} on contract ${log.address}`
)
}
})
}
}
Example #5
Source File: EthereumNodeClient.ts From tx2uml with MIT License | 6 votes |
// Parse Transfer events from a transaction receipt
static parseTransferEvents(logs: Array<Log>): Transfer[] {
const transferEvents: Transfer[] = []
// parse eve
const tokenEventInterface = new ethers.utils.Interface(
TransferEventsABI
)
logs.forEach(log => {
try {
const event = tokenEventInterface.parseLog(log)
if (event.name === "Transfer") {
transferEvents.push({
to: event.args.to,
from: event.args.from,
value: event.args.value,
tokenAddress: log.address,
ether: false,
})
}
} catch (err) {
if (err.reason !== "no matching event")
throw new VError(err, "Failed to parse event log")
}
})
return transferEvents
}
Example #6
Source File: useRawLogs.ts From useDApp with MIT License | 6 votes |
/**
* @public
*/
export function useRawLogs(
filter: Filter | FilterByBlockHash | Promise<Filter | FilterByBlockHash> | Falsy,
queryParams: QueryParams = {}
): Log[] | undefined {
const { library } = useEthers()
const providers = useReadonlyNetworks()
const _blockNumber = useBlockNumber()
const blockNumbers = useBlockNumbers()
const [logs, setLogs] = useState<Log[] | undefined>()
const { chainId } = queryParams
const [provider, blockNumber] = useMemo(
() => (chainId ? [providers[chainId], blockNumbers[chainId]] : [library, _blockNumber]),
[providers, library, blockNumbers, _blockNumber, chainId]
)
async function updateLogs() {
setLogs(!filter ? undefined : await provider?.getLogs(filter))
}
useEffect(() => {
void updateLogs()
}, [provider, blockNumber])
return logs
}
Example #7
Source File: eip1193-bridge.ts From bodhi.js with Apache License 2.0 | 6 votes |
// async eth_newFilter(params: any[]): Promise<any> {
// }
// async eth_newBlockFilter(params: any[]): Promise<any> {
// }
// async eth_newPendingTransactionFilter(params: any[]): Promise<any> {
// }
// async eth_uninstallFilter(params: any[]): Promise<any> {
// }
// async eth_getFilterChanges(params: any[]): Promise<any> {
// }
// async eth_getFilterLogs(params: any[]): Promise<any> {
// }
async eth_getLogs(params: any[]): Promise<Log[]> {
validate([{ type: 'object' }], params);
const result = await this.#provider.getLogs(params[0]);
return hexlifyRpcResult(result);
}
Example #8
Source File: endpoint.test.ts From bodhi.js with Apache License 2.0 | 6 votes |
expectLogsEqual = (a: Log[], b: Log[]): boolean => {
expect(a.length).to.greaterThan(0);
expect(a.length).to.equal(b.length);
expect(
a.every(({ transactionHash: t0, logIndex: l0 }) =>
b.find(({ transactionHash: t1, logIndex: l1 }) => t0 === t1 && parseInt(l0) === parseInt(l1))
)
);
}
Example #9
Source File: subqlProvider.ts From bodhi.js with Apache License 2.0 | 6 votes |
getFilteredLogs = async (filter: Filter & FilterByBlockHash): Promise<Log[]> => {
const queryFilter = getLogsQueryFilter(filter);
const res = await this.queryGraphql(`
query {
logs${queryFilter} {
${LOGS_NODES}
}
}
`);
return adaptLogs(res.logs!.nodes as LogGQL[]);
};
Example #10
Source File: subqlProvider.ts From bodhi.js with Apache License 2.0 | 6 votes |
getAllLogs = async (): Promise<Log[]> => {
const res = await this.queryGraphql(`
query {
logs {
${LOGS_NODES}
}
}
`);
return adaptLogs(res.logs!.nodes as LogGQL[]);
};
Example #11
Source File: logs.ts From bodhi.js with Apache License 2.0 | 6 votes |
filterLog = (log: Log, filter: any): boolean => {
const { address: targetAddr, topics: targetTopics } = filter;
if (targetAddr) {
if (typeof targetAddr === 'string') {
if (log.address.toLowerCase() !== targetAddr.toLowerCase()) return false;
} else if (Array.isArray(targetAddr)) {
if (!targetAddr.map((x: string) => x.toLowerCase()).includes(log.address.toLowerCase())) return false;
}
}
if (targetTopics?.length > 0) {
if (!log.topics?.length) return false;
const _targetTopics = targetTopics
.flat()
.filter((x: any) => x)
.map((x: string) => x.toLowerCase());
for (const t of log.topics) {
if (_targetTopics.includes(t.toLowerCase())) return true;
}
return false;
}
return true;
}
Example #12
Source File: DataProvider.ts From bodhi.js with Apache License 2.0 | 6 votes |
/**
*
* @param filter The filter to apply to the logs
* @param resolveBlockNumber The block to retrieve the logs from, defaults
* to the head
* @returns A promise that resolves to an array of filtered logs
*/
abstract getLogs(
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
filter: any,
resolveBlockNumber: (blockTag?: BlockTag | Promise<BlockTag>) => Promise<number | undefined>
): Promise<Array<Log>>;
Example #13
Source File: endpoint.test.ts From bodhi.js with Apache License 2.0 | 5 votes |
logsEq = (a: Log[], b: Log[]): boolean =>
a.length === b.length &&
a.every(({ transactionHash: t0, logIndex: l0 }) =>
b.find(({ transactionHash: t1, logIndex: l1 }) => t0 === t1 && parseInt(l0) === parseInt(l1))
)
Example #14
Source File: index.ts From defillama-sdk with GNU Affero General Public License v3.0 | 5 votes |
// SMALL INCOMPATIBILITY: On the old API we don't return ids but we should
export async function getLogs(params: {
target: Address;
topic: string;
keys: string[]; // This is just used to select only part of the logs
fromBlock: number;
toBlock: number; // DefiPulse's implementation is buggy and doesn't take this into account
topics?: string[]; // This is an outdated part of DefiPulse's API which is still used in some old adapters
chain?: Chain;
}) {
if(params.toBlock === undefined || params.fromBlock === undefined){
throw new Error("toBlock and fromBlock need to be defined in all calls to getLogs")
}
const filter = {
address: params.target,
topics: params.topics ?? [utils.id(params.topic)],
fromBlock: params.fromBlock,
toBlock: params.toBlock, // We don't replicate Defipulse's bug because the results end up being the same anyway and hopefully they'll eventually fix it
};
let logs: Log[] = [];
let blockSpread = params.toBlock - params.fromBlock;
let currentBlock = params.fromBlock;
while (currentBlock < params.toBlock) {
const nextBlock = Math.min(params.toBlock, currentBlock + blockSpread);
try {
const partLogs = await getProvider(params.chain).getLogs({
...filter,
fromBlock: currentBlock,
toBlock: nextBlock,
});
logs = logs.concat(partLogs);
currentBlock = nextBlock;
} catch (e) {
if (blockSpread >= 2e3) {
// We got too many results
// We could chop it up into 2K block spreads as that is guaranteed to always return but then we'll have to make a lot of queries (easily >1000), so instead we'll keep dividing the block spread by two until we make it
blockSpread = Math.floor(blockSpread / 2);
} else {
throw e;
}
}
}
if (params.keys.length > 0) {
if (params.keys[0] !== "topics") {
throw new Error("Unsupported");
}
return {
output: logs.map((log) => log.topics),
};
}
return {
output: logs,
};
}
Example #15
Source File: logs.ts From useDApp with MIT License | 5 votes |
/**
* @internal Intended for internal use - use it on your own risk
*/
export function decodeLogs<T extends TypedContract, EN extends ContractEventNames<T>>(
filter: TypedFilter | Falsy,
result: Log[] | Falsy | Error
): LogsResult<T, EN> {
if (!result || !filter) {
return undefined
}
try {
if (result instanceof Error) {
return {
value: undefined,
error: result,
}
}
const decodedLogs: Awaited<DetailedEventRecord<T, EN>>[] = []
for (const log of result) {
const data = filter.contract.interface.decodeEventLog(filter.event, log.data, log.topics) as EventRecord<T, EN>
decodedLogs.push({
data,
blockNumber: log.blockNumber,
blockHash: log.blockHash,
transactionIndex: log.transactionIndex,
transactionHash: log.transactionHash,
removed: log.removed,
})
}
return {
value: decodedLogs,
error: undefined,
}
} catch (error) {
return {
value: undefined,
error: error as Error,
}
}
}
Example #16
Source File: EthereumNodeClient.d.ts From tx2uml with MIT License | 5 votes |
static parseTransferEvents(logs: Array<Log>): Transfer[];
Example #17
Source File: transaction.d.ts From tx2uml with MIT License | 5 votes |
static parseTransactionLogs(logs: Array<Log>, contracts: Contracts): void;
Example #18
Source File: logs.ts From bodhi.js with Apache License 2.0 | 5 votes |
adaptLogs = (logs: LogGQL[]): Log[] =>
logs.map((log) => ({
...log,
data: log.data || ''
}))
Example #19
Source File: base-provider.ts From bodhi.js with Apache License 2.0 | 5 votes |
// Bloom-filter Queries
getLogs = async (rawFilter: Filter & FilterByBlockHash): Promise<Log[]> => {
if (!this.subql) {
return logger.throwError(
'missing subql url to fetch logs, to initialize base provider with subql, please provide a subqlUrl param.'
);
}
const { fromBlock, toBlock, blockHash } = rawFilter;
const filter = { ...rawFilter };
if (blockHash && (fromBlock || toBlock)) {
return logger.throwError(
'`fromBlock` and `toBlock` is not allowed in params when `blockHash` is present',
Logger.errors.INVALID_ARGUMENT,
{
blockHash,
fromBlock,
toBlock
}
);
}
if (blockHash) {
const blockNumber = (await this._getBlockHeader(blockHash)).number.toNumber();
filter.fromBlock = blockNumber;
filter.toBlock = blockNumber;
} else {
const fromBlockNumber = await this._getBlockNumberFromTag(fromBlock ?? 'latest');
const toBlockNumber = await this._getBlockNumberFromTag(toBlock ?? 'latest');
filter.fromBlock = fromBlockNumber;
filter.toBlock = toBlockNumber;
}
const filteredLogs = await this.subql.getFilteredLogs(filter);
return filteredLogs.map((log) => this.formatter.filterLog(log));
};
Example #20
Source File: logs.test.ts From useDApp with MIT License | 4 votes |
describe('decodeLogs', () => {
const mockProvider = new MockProvider()
const [deployer] = mockProvider.getWallets()
let token: Contract
beforeEach(async () => {
token = await deployMockToken(deployer)
})
it('Returns undefined if the filter and result are undefined', () => {
expect(decodeLogs(undefined, undefined)).to.be.undefined
})
it('Returns undefined if the result is undefined', () => {
const filter: TypedFilter = {
contract: token,
event: 'Transfer',
args: [],
}
expect(decodeLogs(filter, undefined)).to.be.undefined
})
it('Returns undefined if the filter is undefined', () => {
expect(decodeLogs(undefined, [])).to.be.undefined
})
it('Returns an error if passed an error as the result', () => {
const filter: TypedFilter = {
contract: token,
event: 'Transfer',
args: [],
}
const error = Error('')
const decodedLogs = decodeLogs(filter, error)
expect(decodedLogs?.error).to.equal(error)
expect(decodedLogs?.value).to.be.undefined
})
it('Returns an empty array when passed an empty array of logs', () => {
const filter: TypedFilter = {
contract: token,
event: 'Transfer',
args: [],
}
const logs: Log[] = []
const decodedLogs = decodeLogs(filter, logs)
expect(decodedLogs?.error).to.be.undefined
expect(decodedLogs?.value).to.be.empty
})
it('Returns an error when the event topic is a mismatch', () => {
const filter: TypedFilter = {
contract: token,
event: 'Transfer',
args: [],
}
const logs: Log[] = [
{
address: token.address,
topics: [
ethers.utils.id('Transfer2(address,address,uint256)'),
ethers.utils.hexZeroPad(AddressZero, 32),
ethers.utils.hexZeroPad(AddressZero, 32),
],
data: ethers.utils.hexZeroPad(AddressZero, 32),
blockHash: '0x0',
blockNumber: 0,
logIndex: 0,
transactionIndex: 0,
transactionHash: '0x0',
removed: false,
},
]
const decodedLogs = decodeLogs(filter, logs)
expect(decodedLogs?.value).to.be.undefined
expect(decodedLogs?.error).to.be.a('Error')
})
it('Works when passed valid logs', () => {
const filter: TypedFilter = {
contract: token,
event: 'Transfer',
args: [],
}
const from = AddressZero
const to = deployer.address
const value = BigNumber.from(1)
const blockHash = '0x0'
const blockNumber = 1
const logIndex = 2
const transactionIndex = 3
const removed = true
const transactionHash = '0x11'
const logs: Log[] = [
{
address: token.address,
topics: [
ethers.utils.id('Transfer(address,address,uint256)'),
ethers.utils.hexZeroPad(from, 32),
ethers.utils.hexZeroPad(to, 32),
],
data: ethers.utils.hexZeroPad(ethers.utils.hexlify(value), 32),
blockHash,
blockNumber,
logIndex,
transactionIndex,
transactionHash,
removed,
},
{
address: token.address,
topics: [
ethers.utils.id('Transfer(address,address,uint256)'),
ethers.utils.hexZeroPad(from, 32),
ethers.utils.hexZeroPad(to, 32),
],
data: ethers.utils.hexZeroPad(ethers.utils.hexlify(value), 32),
blockHash,
blockNumber,
logIndex,
transactionIndex,
transactionHash,
removed,
},
]
const decodedLogs = decodeLogs(filter, logs)
expect(decodedLogs?.error).to.be.undefined
const theLogs = decodedLogs as LogsResult<typeof token, 'Transfer'>
expect(theLogs?.value).to.have.length(2)
expect(theLogs?.value![0].blockHash).to.equal(blockHash)
expect(theLogs?.value![0].blockNumber).to.equal(blockNumber)
expect(theLogs?.value![0].removed).to.equal(removed)
expect(theLogs?.value![0].transactionIndex).to.equal(transactionIndex)
expect(theLogs?.value![0].transactionHash).to.equal(transactionHash)
expect(theLogs?.value![0].data.from).to.equal(from)
expect(theLogs?.value![0].data.to).to.equal(to)
expect(theLogs?.value![0].data.value).to.equal(value)
})
})