diff --git a/src/api/aptos.ts b/src/api/aptos.ts index fa2368292..f3a83b3c3 100644 --- a/src/api/aptos.ts +++ b/src/api/aptos.ts @@ -5,6 +5,7 @@ import { Account } from "./account"; import { AptosConfig } from "./aptos_config"; import { Coin } from "./coin"; import { Collection } from "./collection"; +import { Event } from "./event"; import { Faucet } from "./faucet"; import { General } from "./general"; import { Staking } from "./staking"; @@ -20,6 +21,8 @@ export class Aptos { readonly collection: Collection; + readonly event: Event; + readonly faucet: Faucet; readonly general: General; @@ -52,6 +55,7 @@ export class Aptos { this.account = new Account(this.config); this.coin = new Coin(this.config); this.collection = new Collection(this.config); + this.event = new Event(this.config); this.faucet = new Faucet(this.config); this.general = new General(this.config); this.staking = new Staking(this.config); @@ -64,6 +68,7 @@ export interface Aptos extends Account, Coin, Collection, + Event, Faucet, General, Staking, @@ -94,6 +99,7 @@ function applyMixin(targetClass: any, baseClass: any, baseClassProp: string) { applyMixin(Aptos, Account, "account"); applyMixin(Aptos, Coin, "coin"); applyMixin(Aptos, Collection, "collection"); +applyMixin(Aptos, Event, "event"); applyMixin(Aptos, Faucet, "faucet"); applyMixin(Aptos, General, "general"); applyMixin(Aptos, Staking, "staking"); diff --git a/src/api/event.ts b/src/api/event.ts new file mode 100644 index 000000000..507a06c3f --- /dev/null +++ b/src/api/event.ts @@ -0,0 +1,29 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +import { getEventsByCreationNumber } from "../internal/event"; +import { AnyNumber, GetEventsResponse } from "../types"; +import { AptosConfig } from "./aptos_config"; + +/** + * A class to query all `Event` Aptos related queries + */ +export class Event { + readonly config: AptosConfig; + + constructor(config: AptosConfig) { + this.config = config; + } + + /** + * Get events by creation number and the address + * + * @param args.address - The account address + * @param args.creationNumber - The event creation number + * @returns Promise + */ + async getEventsByCreationNumber(args: { address: string; creationNumber: AnyNumber }): Promise { + const data = await getEventsByCreationNumber({ aptosConfig: this.config, ...args }); + return data; + } +} diff --git a/src/internal/event.ts b/src/internal/event.ts new file mode 100644 index 000000000..eae882ce1 --- /dev/null +++ b/src/internal/event.ts @@ -0,0 +1,51 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +/** + * This file contains the underlying implementations for exposed API surface in + * the {@link api/event}. By moving the methods out into a separate file, + * other namespaces and processes can access these methods without depending on the entire + * event namespace and without having a dependency cycle error. + */ + +import { AptosConfig } from "../api/aptos_config"; +import { AccountAddress } from "../core"; +import { AnyNumber, GetEventsResponse, HexInput } from "../types"; +import { GetEventsQuery } from "../types/generated/operations"; +import { GetEvents } from "../types/generated/queries"; +import { queryIndexer } from "./general"; + +/** + * Get events by creation number and the address + * + * @param args.aptosConfig - The aptos config + * @param args.address - The account address + * @param args.creationNumber - The event creation number + * @returns Promise + */ +export async function getEventsByCreationNumber(args: { + aptosConfig: AptosConfig; + address: HexInput; + creationNumber: AnyNumber; +}): Promise { + const { aptosConfig, creationNumber } = args; + const address = AccountAddress.fromHexInput({ input: args.address }).toString(); + + const whereCondition: any = { + account_address: { _eq: address }, + creation_number: { _eq: creationNumber }, + }; + + const graphqlQuery = { + query: GetEvents, + variables: { where_condition: whereCondition }, + }; + + const data = await queryIndexer({ + aptosConfig, + query: graphqlQuery, + originMethod: "getEventsByCreationNumber", + }); + + return data.events; +} diff --git a/src/internal/queries/getEventsByCreationNumber.graphql b/src/internal/queries/getEventsByCreationNumber.graphql new file mode 100644 index 000000000..e01fe2bb8 --- /dev/null +++ b/src/internal/queries/getEventsByCreationNumber.graphql @@ -0,0 +1,12 @@ +query getEvents($where_condition: events_bool_exp, $offset: Int, $limit: Int) { + events(where: $where_condition, offset: $offset, limit: $limit) { + sequence_number + type + transaction_version + transaction_block_height + event_index + data + creation_number + account_address + } +} diff --git a/src/types/generated/operations.ts b/src/types/generated/operations.ts index d4e3bf01c..c04d0e245 100644 --- a/src/types/generated/operations.ts +++ b/src/types/generated/operations.ts @@ -376,6 +376,25 @@ export type GetDelegatedStakingActivitiesQuery = { }>; }; +export type GetEventsQueryVariables = Types.Exact<{ + where_condition?: Types.InputMaybe; + offset?: Types.InputMaybe; + limit?: Types.InputMaybe; +}>; + +export type GetEventsQuery = { + events: Array<{ + sequence_number: any; + type: string; + transaction_version: any; + transaction_block_height: any; + event_index: any; + data: any; + creation_number: any; + account_address: string; + }>; +}; + export type GetNumberOfDelegatorsQueryVariables = Types.Exact<{ where_condition: Types.NumActiveDelegatorPerPoolBoolExp; order_by?: Types.InputMaybe | Types.NumActiveDelegatorPerPoolOrderBy>; diff --git a/src/types/generated/queries.ts b/src/types/generated/queries.ts index e2ce85f0b..f7e74bf4f 100644 --- a/src/types/generated/queries.ts +++ b/src/types/generated/queries.ts @@ -246,6 +246,20 @@ export const GetDelegatedStakingActivities = ` } } `; +export const GetEvents = ` + query getEvents($where_condition: events_bool_exp, $offset: Int, $limit: Int) { + events(where: $where_condition, offset: $offset, limit: $limit) { + sequence_number + type + transaction_version + transaction_block_height + event_index + data + creation_number + account_address + } +} + `; export const GetNumberOfDelegators = ` query getNumberOfDelegators($where_condition: num_active_delegator_per_pool_bool_exp!, $order_by: [num_active_delegator_per_pool_order_by!]) { num_active_delegator_per_pool(where: $where_condition, order_by: $order_by) { @@ -435,6 +449,17 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = "query", ); }, + getEvents( + variables?: Types.GetEventsQueryVariables, + requestHeaders?: Dom.RequestInit["headers"], + ): Promise { + return withWrapper( + (wrappedRequestHeaders) => + client.request(GetEvents, variables, { ...requestHeaders, ...wrappedRequestHeaders }), + "getEvents", + "query", + ); + }, getNumberOfDelegators( variables: Types.GetNumberOfDelegatorsQueryVariables, requestHeaders?: Dom.RequestInit["headers"], diff --git a/src/types/indexer.ts b/src/types/indexer.ts index 4baea044d..50c29d0ab 100644 --- a/src/types/indexer.ts +++ b/src/types/indexer.ts @@ -21,6 +21,7 @@ import { GetNumberOfDelegatorsQuery, GetCollectionDataQuery, GetChainTopUserTransactionsQuery, + GetEventsQuery, } from "./generated/operations"; /** @@ -43,6 +44,7 @@ export type GetAccountCollectionsWithOwnedTokenResponse = GetAccountCollectionsWithOwnedTokensQuery["current_collection_ownership_v2_view"]; export type GetAccountCoinsDataResponse = GetAccountCoinsDataQuery["current_fungible_asset_balances"]; export type GetChainTopUserTransactionsResponse = GetChainTopUserTransactionsQuery["user_transactions"]; +export type GetEventsResponse = GetEventsQuery["events"]; export type GetNumberOfDelegatorsResponse = GetNumberOfDelegatorsQuery["num_active_delegator_per_pool"]; export type GetDelegatedStakingActivitiesResponse = GetDelegatedStakingActivitiesQuery["delegated_staking_activities"]; diff --git a/tests/e2e/api/event.test.ts b/tests/e2e/api/event.test.ts new file mode 100644 index 000000000..6a1f05c4b --- /dev/null +++ b/tests/e2e/api/event.test.ts @@ -0,0 +1,27 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +import { Account, Aptos, AptosConfig, Network } from "../../../src"; +import { FUND_AMOUNT, INDEXER_WAIT_TIME } from "../../unit/helper"; +import { sleep } from "../../../src/utils/helpers"; + +describe("Event", () => { + test("it should get fund events by creation number and address", async () => { + const config = new AptosConfig({ network: Network.LOCAL }); + const aptos = new Aptos(config); + + // Fund the account + const testAccount = Account.generate(); + await aptos.fundAccount({ accountAddress: testAccount.accountAddress.toString(), amount: FUND_AMOUNT }); + + await sleep(INDEXER_WAIT_TIME); + const events = await aptos.getEventsByCreationNumber({ + address: testAccount.accountAddress.toString(), + creationNumber: 0, + }); + + // Ensure events are returned and that the event type is CoinRegisterEvent + expect(events.length).toBeGreaterThan(0); + expect(events[0].type).toEqual("0x1::account::CoinRegisterEvent"); + }); +});