Skip to content

Commit 6bd4154

Browse files
authored
feat(ensv2): HCA-aware Event.sender + filter + docs (#2014)
1 parent c29b4c5 commit 6bd4154

21 files changed

Lines changed: 244 additions & 95 deletions

File tree

.changeset/hca-aware-events.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"ensapi": minor
3+
---
4+
5+
Adds HCA-aware `Event.sender` to the Omnigraph API alongside the existing `Event.from`. For ENSv2 events that emit an explicit `sender`/`owner`/`account`/ERC1155 `operator` argument, `Event.sender` is set from that argument (the HCA Smart Account address, if used) and falls back to `tx.from` otherwise. Adds a `sender` filter to `EventsWhereInput`. `Account.events` now filters by `sender` (HCA-aware) instead of `tx.from`. Documents HCA-aware semantics on `Domain.owner`, `Registration.registrant`/`unregistrant`, and `*.PermissionsUser.user`.

apps/ensapi/src/lib/resolution/execute-operations.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
type Hex,
77
type Name,
88
type RecordVersion,
9+
toNormalizedAddress,
910
} from "enssdk";
1011
import {
1112
ContractFunctionExecutionError,
@@ -161,6 +162,6 @@ export function interpretOperationWithRawResult(call: Operation, raw: unknown):
161162
return { ...call, result: size(data) === 0 ? null : { contentType, data } };
162163
}
163164
case "interfaceImplementer":
164-
return { ...call, result: interpretAddress(raw as Address) };
165+
return { ...call, result: interpretAddress(toNormalizedAddress(raw as string)) };
165166
}
166167
}

apps/ensapi/src/omnigraph-api/lib/find-events/find-events-resolver.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ interface EventsWhere {
2626
timestamp_gte?: bigint | null;
2727
/** Filter to events at or before this timestamp. */
2828
timestamp_lte?: bigint | null;
29-
/** Filter to events sent by this address. */
29+
/** Filter to events whose `tx.from` matches. Not HCA-aware. */
3030
from?: Address | null;
31+
/** Filter to events whose HCA-aware `sender` matches. */
32+
sender?: Address | null;
3133
}
3234

3335
/**
@@ -49,6 +51,7 @@ function eventsWhereConditions(where?: EventsWhere | null): SQL | undefined {
4951
? lte(ensIndexerSchema.event.timestamp, where.timestamp_lte)
5052
: undefined,
5153
where.from ? eq(ensIndexerSchema.event.from, where.from) : undefined,
54+
where.sender ? eq(ensIndexerSchema.event.sender, where.sender) : undefined,
5255
);
5356
}
5457

apps/ensapi/src/omnigraph-api/schema/account.integration.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ describe("Account.events", () => {
9999
expect(events.length).toBeGreaterThan(0);
100100

101101
for (const event of events) {
102-
expect(event.from).toBe(DEVNET_DEPLOYER);
102+
expect(event.sender).toBe(DEVNET_DEPLOYER);
103103
}
104104
});
105105
});

apps/ensapi/src/omnigraph-api/schema/account.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,14 @@ AccountRef.implement({
9090
// Account.events
9191
//////////////////
9292
events: t.connection({
93-
description: "All Events for which this Account is the sender (i.e. `Transaction.from`).",
93+
description:
94+
"All Events for which this Account is the HCA-aware `sender` (i.e. `Event.sender`).",
9495
type: EventRef,
9596
args: {
9697
where: t.arg({ type: AccountEventsWhereInput }),
9798
},
9899
resolve: (parent, args) =>
99-
resolveFindEvents({ ...args, where: { ...args.where, from: parent.id } }),
100+
resolveFindEvents({ ...args, where: { ...args.where, sender: parent.id } }),
100101
}),
101102

102103
///////////////////////

apps/ensapi/src/omnigraph-api/schema/domain.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ DomainInterfaceRef.implement({
177177
////////////////
178178
owner: t.field({
179179
type: AccountRef,
180-
description: "The owner of this Domain.",
180+
description:
181+
"If this is an ENSv1Domain, this is the effective owner of the Domain. If this is an ENSv2Domain, this is the on-chain owner address (the HCA account address if used).",
181182
nullable: true,
182183
resolve: (parent) => parent.ownerId,
183184
}),

apps/ensapi/src/omnigraph-api/schema/event.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,23 @@ EventRef.implement({
9595
// Event.from
9696
//////////////
9797
from: t.field({
98-
description: "Identifies the sender of the Transaction within which this Event was emitted.",
98+
description:
99+
"Identifies the sender of the Transaction within which this Event was emitted (`tx.from`). Never HCA-aware — always the EOA/relayer that submitted the transaction. Use `Event.sender` for the HCA-aware actor.",
99100
type: "Address",
100101
nullable: false,
101102
resolve: (parent) => parent.from,
102103
}),
103104

105+
////////////////
106+
// Event.sender
107+
////////////////
108+
sender: t.field({
109+
description: "The HCA account address if used, otherwise Transaction.from.",
110+
type: "Address",
111+
nullable: false,
112+
resolve: (parent) => parent.sender,
113+
}),
114+
104115
////////////
105116
// Event.to
106117
////////////
@@ -160,7 +171,7 @@ EventRef.implement({
160171

161172
/**
162173
* Shared filter for events connections. Used by Domain.events, Resolver.events, Permissions.events,
163-
* and Account.events (which excludes `from` since it's implied).
174+
* and Account.events (which excludes `sender` since it's implied).
164175
*/
165176
export const EventsWhereInput = builder.inputType("EventsWhereInput", {
166177
description: "Filter conditions for an events connection.",
@@ -180,16 +191,22 @@ export const EventsWhereInput = builder.inputType("EventsWhereInput", {
180191
}),
181192
from: t.field({
182193
type: "Address",
183-
description: "Filter to events sent by this address.",
194+
description:
195+
"Filter to events whose `tx.from` matches. Not HCA-aware — use `sender` to filter by the HCA account address.",
196+
}),
197+
sender: t.field({
198+
type: "Address",
199+
description:
200+
"Filter to events whose `sender` matches: the HCA account address if used, otherwise Transaction.from.",
184201
}),
185202
}),
186203
});
187204

188205
/**
189-
* Like EventsWhereInput but without `from` (used where `from` is implied, e.g. Account.events).
206+
* Like EventsWhereInput but without `sender` (used where `sender` is implied, e.g. Account.events).
190207
*/
191208
export const AccountEventsWhereInput = builder.inputType("AccountEventsWhereInput", {
192-
description: "Filter conditions for Account.events (where `from` is implied by the Account).",
209+
description: "Filter conditions for Account.events (where `sender` is implied by the Account).",
193210
fields: (t) => ({
194211
selector_in: t.field({
195212
type: ["Hex"],
@@ -204,5 +221,10 @@ export const AccountEventsWhereInput = builder.inputType("AccountEventsWhereInpu
204221
type: "BigInt",
205222
description: "Filter to events at or before this UnixTimestamp.",
206223
}),
224+
from: t.field({
225+
type: "Address",
226+
description:
227+
"Filter to events whose `tx.from` matches. Not HCA-aware — the Account's HCA-aware filter is applied via `sender = Account.id`.",
228+
}),
207229
}),
208230
});

apps/ensapi/src/omnigraph-api/schema/permissions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@ PermissionsUserRef.implement({
260260
// PermissionsUser.user
261261
////////////////////////
262262
user: t.field({
263-
description: "The User for whom these Roles are granted.",
263+
description:
264+
"The user/grantee address this Permission is granted to (the HCA account address if used).",
264265
type: AccountRef,
265266
nullable: false,
266267
resolve: (parent) => parent.user,

apps/ensapi/src/omnigraph-api/schema/registration.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ RegistrationInterfaceRef.implement({
140140
// Registration.registrant
141141
///////////////////////////
142142
registrant: t.field({
143-
description: "The Registrant of a Registration, if exists.",
143+
description:
144+
"The Registrant of a Registration, if exists. For ENSv2 Registrations, the protocol-emitted registrant address (the HCA account address if used).",
144145
type: AccountRef,
145146
nullable: true,
146147
resolve: (parent) => parent.registrantId,
@@ -150,7 +151,8 @@ RegistrationInterfaceRef.implement({
150151
// Registration.unregistrant
151152
/////////////////////////////
152153
unregistrant: t.field({
153-
description: "The Unregistrant of a Registration, if exists.",
154+
description:
155+
"The Unregistrant of a Registration, if exists. For ENSv2 Registrations, the protocol-emitted unregistrant address (the HCA account address if used).",
154156
type: AccountRef,
155157
nullable: true,
156158
resolve: (parent) => parent.unregistrantId,

apps/ensapi/src/omnigraph-api/schema/registry-permissions-user.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ RegistryPermissionsUserRef.implement({
4949
// RegistryPermissionsUser.user
5050
/////////////////////////////////
5151
user: t.field({
52-
description: "The User for whom these Roles are granted.",
52+
description:
53+
"The user/grantee address this Permission is granted to (the HCA account address if used).",
5354
type: AccountRef,
5455
nullable: false,
5556
resolve: (parent) => parent.user,

0 commit comments

Comments
 (0)