-
Notifications
You must be signed in to change notification settings - Fork 16
resolution api: support contenthash, pubkey, abi, interfaces, dnszonehash, version #1967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
b0d4b95
checkpoint: next i need to edit the spec
shrugs d977b06
Merge branch 'main' into feat/extend-protocol-resolution
shrugs e05ec90
spec: linear operation passes, abi bitmask, enssdk semantic types
shrugs e6c4fef
checkpoint: refactor forward-resolution into a linear sequence of ope…
shrugs 825d8ad
DRY up handlers with ensureResolverAndRecords
shrugs 59db517
fix: update changeset
shrugs f859e39
fix: update changeset
shrugs c68236f
feat: wire new selection fields through api surface
shrugs a50d37b
fix: address bot review feedback
shrugs a552d3d
refactor: inline VersionChanged handler body
shrugs 2fcbc1d
extract isInterfaceId to enssdk; inline bigint revival in client
shrugs 29b3137
cleaning up
shrugs 8e9ae23
fix: remove unnecessary executeOperationsWithUniversalResolver helper
shrugs 514e173
version: distinguish unsupported/unseen from explicit 0n
shrugs 5dfc020
regenerate openapi spec
shrugs 5cd5444
accelerate-ensip19: no-op on non-name selection, don't 500
shrugs 3fa7b15
Merge branch 'main' into feat/extend-protocol-resolution
shrugs 1cb6b47
enskit: fix intermittent TS2742 on OmnigraphProvider
shrugs 9c76ac5
ResolverRecordsResponse: accept readonly tuple selections
shrugs 466fef9
fix: add back integration test for universal resolver encoded labelha…
shrugs 6dd481d
Merge remote-tracking branch 'origin/main' into feat/extend-protocol-…
shrugs File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| --- | ||
| "@ensnode/ensdb-sdk": minor | ||
| "@ensnode/ensnode-sdk": minor | ||
| "ensindexer": minor | ||
| "ensapi": minor | ||
| "enssdk": minor | ||
| --- | ||
|
|
||
| Resolution API: support `contenthash`, `pubkey`, `abi`, `interfaces`, `dnszonehash`, and `version` selection. Protocol acceleration indexes `contenthash`, `pubkey`, `dnszonehash`, and handles `VersionChanged` (clears records for the node, bumps version). `ABI` (bitmask query, contract-equivalent) and `interface` records are selectable but always resolved via RPC. Adds `ContentType` / `InterfaceId` / `RecordVersion` semantic types to `enssdk`. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
apps/ensapi/src/lib/resolution/accelerate-ensip19-reverse-resolver.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import type { InterpretedName } from "enssdk"; | ||
| import { parseReverseName } from "enssdk"; | ||
|
|
||
| import type { ResolverRecordsSelection } from "@ensnode/ensnode-sdk"; | ||
|
|
||
| import { getENSIP19ReverseNameRecordFromIndex } from "@/lib/protocol-acceleration/get-primary-name-from-index"; | ||
| import { isOperationResolved, type Operation } from "@/lib/resolution/operations"; | ||
|
|
||
| /** | ||
| * Acceleration pass for a Known ENSIP-19 Reverse Resolver, retrieving the Primary Name from | ||
| * the index if possible. | ||
| * | ||
| * If the caller didn't select `name`, this is a no-op — any other selected operations flow | ||
| * through to the RPC tail unchanged. A reverse resolver won't meaningfully answer them either | ||
| * way; letting the rpc return its natural null-per-record response preserves parity with the | ||
| * unaccelerated path. | ||
| */ | ||
| export async function accelerateENSIP19ReverseResolver({ | ||
| operations, | ||
| name, | ||
| selection, | ||
| }: { | ||
| operations: Operation[]; | ||
| name: InterpretedName; | ||
| selection: ResolverRecordsSelection; | ||
| }): Promise<Operation[]> { | ||
| if (selection.name !== true) return operations; | ||
|
|
||
| // parse the Reverse Name into { address, coinType } | ||
| const parsed = parseReverseName(name); | ||
| if (!parsed) { | ||
| throw new Error( | ||
| `Invariant(ENSIP-19 Reverse Resolver): expected a valid reverse name, got '${name}'.`, | ||
| ); | ||
| } | ||
|
shrugs marked this conversation as resolved.
|
||
|
|
||
| const result = await getENSIP19ReverseNameRecordFromIndex(parsed.address, parsed.coinType); | ||
|
|
||
| // resolve the 'name' operation with the indexed result, passing others along as-is | ||
| return operations.map((op) => { | ||
| if (isOperationResolved(op)) return op; | ||
| if (op.functionName === "name") return { ...op, result }; | ||
| return op; | ||
| }); | ||
| } | ||
80 changes: 80 additions & 0 deletions
80
apps/ensapi/src/lib/resolution/accelerate-known-onchain-static-resolver.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| import type { AccountId, Node } from "enssdk"; | ||
|
|
||
| import type { ResolverRecordsSelection } from "@ensnode/ensnode-sdk"; | ||
|
|
||
| import { getRecordsFromIndex } from "@/lib/protocol-acceleration/get-records-from-index"; | ||
| import { isOperationResolved, type Operation } from "@/lib/resolution/operations"; | ||
|
|
||
| type IndexedRecords = Awaited<ReturnType<typeof getRecordsFromIndex>>; | ||
|
|
||
| /** | ||
| * Acceleration pass for a Known On-Chain Static Resolver whose records are fully indexed. | ||
| * | ||
| * Fills in resolved results for calls that are indexable (name, addr, text, contenthash, pubkey, | ||
| * zonehash, recordVersions). Calls that aren't indexable (ABI, interfaceImplementer) remain | ||
| * unresolved and flow to the terminal RPC pass. | ||
| */ | ||
| export async function accelerateKnownOnchainStaticResolver({ | ||
| operations, | ||
| resolver, | ||
| node, | ||
| selection, | ||
| }: { | ||
| operations: Operation[]; | ||
| resolver: AccountId; | ||
| node: Node; | ||
| selection: ResolverRecordsSelection; | ||
| }): Promise<Operation[]> { | ||
| const records = await getRecordsFromIndex({ resolver, node, selection }); | ||
|
|
||
| return operations.map((op) => { | ||
| if (isOperationResolved(op)) return op; | ||
| return resolveOperationWithIndex(op, records); | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Attempts to resolve an Operation from indexed records. | ||
| * | ||
| * For indexable calls returns a new Operation with a resolved `result`. For calls that aren't | ||
| * indexable (ABI, interfaceImplementer) returns the input Operation unchanged — so its | ||
| * `result: undefined` flows on to the RPC tail. | ||
| * | ||
| * Pass `null` `records` when there is no indexed row for (resolver, node) — indexable calls still | ||
| * have well-defined "no record" results in that case. | ||
| */ | ||
| function resolveOperationWithIndex(op: Operation, records: IndexedRecords): Operation { | ||
| switch (op.functionName) { | ||
| case "name": | ||
| return { ...op, result: records?.name ?? null }; | ||
| case "addr": { | ||
| const coinType = op.args[1]; | ||
| const found = records?.addressRecords.find((r) => r.coinType === coinType); | ||
| return { ...op, result: found?.value ?? null }; | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| case "text": { | ||
| const key = op.args[1]; | ||
| const found = records?.textRecords.find((r) => r.key === key); | ||
| return { ...op, result: found?.value ?? null }; | ||
| } | ||
| case "contenthash": | ||
| return { ...op, result: records?.contenthash ?? null }; | ||
| case "pubkey": | ||
| return { | ||
| ...op, | ||
| result: | ||
| records?.pubkeyX && records?.pubkeyY ? { x: records.pubkeyX, y: records.pubkeyY } : null, | ||
| }; | ||
| case "zonehash": | ||
| return { ...op, result: records?.dnszonehash ?? null }; | ||
| case "recordVersions": | ||
| // null when no `VersionChanged` event has been seen for this node | ||
| return { ...op, result: records?.version ?? null }; | ||
| /** | ||
| * The following return the Operation as-is, instructing forward-resolution to resolve them via RPC. | ||
| */ | ||
| case "ABI": | ||
| case "interfaceImplementer": | ||
| return op; | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.