-
Notifications
You must be signed in to change notification settings - Fork 16
Move the encoded referrer library module to @namehash/ens-referrals
#1972
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
base: main
Are you sure you want to change the base?
Changes from all commits
6aca12e
26749bb
38e1aa8
bc06274
24f2c1d
a4caa18
5fdd5aa
ee44283
d6938aa
faa685d
4b24d78
425d2b3
1daafba
1c645e4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| "@namehash/ens-referrals": minor | ||
| "@ensnode/ensnode-sdk": minor | ||
| "enssdk": minor | ||
| --- | ||
|
|
||
| Added `Referrer` type to `enssdk` (raw 32-byte onchain referrer bytes). Runtime helpers (`buildEncodedReferrer`, `decodeReferrer` — renamed from `decodeEncodedReferrer`, `ZERO_ENCODED_REFERRER`, and related constants) moved from `@ensnode/ensnode-sdk` to `@namehash/ens-referrals`, which now owns a branded `EncodedReferrer` type returned by `buildEncodedReferrer`. `buildEncodedReferrer` now accepts `Address` (previously `NormalizedAddress`) and normalizes internally. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,9 +7,10 @@ import { | |
| labelhashLiteralLabel, | ||
| makeENSv1DomainId, | ||
| makeSubdomainNode, | ||
| type Referrer, | ||
| } from "enssdk"; | ||
|
|
||
| import { type EncodedReferrer, PluginName } from "@ensnode/ensnode-sdk"; | ||
| import { PluginName } from "@ensnode/ensnode-sdk"; | ||
|
|
||
| import { ensureDomainEvent } from "@/lib/ensv2/event-db-helpers"; | ||
| import { ensureLabel, ensureUnknownLabel } from "@/lib/ensv2/label-db-helpers"; | ||
|
|
@@ -38,7 +39,7 @@ export default function () { | |
| labelHash: LabelHash; | ||
| baseCost?: bigint; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe we can make use of the |
||
| premium?: bigint; | ||
| referrer?: EncodedReferrer; | ||
| referrer?: Referrer; | ||
| }>; | ||
| }) { | ||
| const { labelHash, baseCost: base, premium, referrer } = event.args; | ||
|
|
@@ -91,7 +92,7 @@ export default function () { | |
| labelHash: LabelHash; | ||
| baseCost?: bigint; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe we can make use of the |
||
| premium?: bigint; | ||
| referrer?: EncodedReferrer; | ||
| referrer?: Referrer; | ||
| }>; | ||
| }) { | ||
| const { labelHash, baseCost: base, premium, referrer } = event.args; | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -154,7 +154,9 @@ Check out [`production-editions.json`](https://ensawards.org/production-editions | |||||||||
|
|
||||||||||
| ## Other Utilities | ||||||||||
|
|
||||||||||
| The package also includes helpers for building referral links. | ||||||||||
| The package also includes helpers. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| ### Building referral links | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| ```typescript | ||||||||||
| import { buildEnsReferralUrl } from "@namehash/ens-referrals"; | ||||||||||
|
|
@@ -166,3 +168,16 @@ const referrerAddress: Address = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; | |||||||||
| const referrerUrl = buildEnsReferralUrl(referrerAddress).toString(); | ||||||||||
| // https://app.ens.domains/?referrer=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| ### Building encoded referrer | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| ```typescript | ||||||||||
| import { buildEncodedReferrer } from "@namehash/ens-referrals"; | ||||||||||
| import type { Address } from "enssdk"; | ||||||||||
|
|
||||||||||
| const referrerAddress: Address = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"; | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| // Build an encoded referrer value | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| const encodedReferrer = buildEncodedReferrer(referrerAddress); | ||||||||||
| // 0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045 | ||||||||||
| ``` | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,17 +1,18 @@ | ||||||
| import { type Hex, isNormalizedAddress, type NormalizedAddress, toNormalizedAddress } from "enssdk"; | ||||||
| import type { Address, Referrer } from "enssdk"; | ||||||
| import { type Hex, type NormalizedAddress, toNormalizedAddress } from "enssdk"; | ||||||
| import { pad, size, slice, zeroAddress } from "viem"; | ||||||
|
|
||||||
| /** | ||||||
| * Encoded Referrer | ||||||
| * | ||||||
| * Represents a "raw" ENS referrer value. | ||||||
| * Represents "a Referrer that is guaranteed to be validly encoded" | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| * | ||||||
| * Registrar controllers emit referrer data as bytes32 values. This type represents | ||||||
| * that raw 32-byte hex string. | ||||||
| * Guaranteed to be a 32-byte hex with 12 bytes of zero padding followed by | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| * a 20-byte lowercase address. | ||||||
| * | ||||||
| * @invariant Guaranteed to be a hex string representation of a 32-byte value. | ||||||
| * Constructible only through {@link buildEncodedReferrer} (and {@link ZERO_ENCODED_REFERRER}). | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| */ | ||||||
| export type EncodedReferrer = Hex; | ||||||
| export type EncodedReferrer = Referrer & { readonly __brand: "EncodedReferrer" }; | ||||||
|
|
||||||
| /** | ||||||
| * Encoded Referrer byte offset | ||||||
|
|
@@ -28,7 +29,7 @@ export const ENCODED_REFERRER_BYTE_OFFSET = 12; | |||||
| export const ENCODED_REFERRER_BYTE_LENGTH = 32; | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A few ideas:
|
||||||
|
|
||||||
| /** | ||||||
| * Expected padding for a valid encoded referrer | ||||||
| * Expected padding for a valid {@link EncodedReferrer} | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| * | ||||||
| * Properly encoded referrers must have exactly 12 zero bytes of left padding | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| * before the 20-byte Ethereum address. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
@@ -43,46 +44,51 @@ export const EXPECTED_ENCODED_REFERRER_PADDING: Hex = pad("0x", { | |||||
| * | ||||||
| * Guaranteed to be a hex string representation of a 32-byte zero value. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| */ | ||||||
| export const ZERO_ENCODED_REFERRER: EncodedReferrer = pad("0x", { | ||||||
| export const ZERO_ENCODED_REFERRER = pad("0x", { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To build this, maybe we just call
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe the idea of The |
||||||
| size: ENCODED_REFERRER_BYTE_LENGTH, | ||||||
| dir: "left", | ||||||
| }); | ||||||
| }) as EncodedReferrer; | ||||||
|
|
||||||
| /** | ||||||
| * Build an {@link EncodedReferrer} value for the given {@link NormalizedAddress} | ||||||
| * Build an {@link EncodedReferrer} value for the given {@link Address} | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| * according to the referrer encoding with left-zero-padding. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| * | ||||||
| * @throws if `address` does not represent an EVM Address | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| */ | ||||||
| export function buildEncodedReferrer(address: NormalizedAddress): EncodedReferrer { | ||||||
| if (!isNormalizedAddress(address)) throw new Error(`Address '${address}' is not normalized.`); | ||||||
| export function buildEncodedReferrer(address: Address): EncodedReferrer { | ||||||
| const normalizedAddress = toNormalizedAddress(address); | ||||||
|
|
||||||
| return pad(address, { size: ENCODED_REFERRER_BYTE_LENGTH, dir: "left" }); | ||||||
| return pad(normalizedAddress, { | ||||||
| size: ENCODED_REFERRER_BYTE_LENGTH, | ||||||
| dir: "left", | ||||||
| }) as EncodedReferrer; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Decode an {@link EncodedReferrer} value into a {@link NormalizedAddress} | ||||||
| * Decode a {@link Referrer} value into a {@link NormalizedAddress} | ||||||
| * according to the referrer encoding with left-zero-padding. | ||||||
| * | ||||||
| * @param encodedReferrer - The "raw" {@link EncodedReferrer} value to decode. | ||||||
| * @param referrer - The "raw" {@link Referrer} value to decode. | ||||||
| * @returns The decoded referrer address. | ||||||
| * @throws when encodedReferrer value is not represented by | ||||||
| * @throws when referrer value is not represented by | ||||||
| * {@link ENCODED_REFERRER_BYTE_LENGTH} bytes. | ||||||
| * @throws when decodedReferrer is not a valid EVM address. | ||||||
| */ | ||||||
|
shrugs marked this conversation as resolved.
|
||||||
| export function decodeEncodedReferrer(encodedReferrer: EncodedReferrer): NormalizedAddress { | ||||||
| export function decodeReferrer(referrer: Referrer): NormalizedAddress { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I note how currently this PR is proposing to change: into It feels like there's a better way. What if we had the following functions instead?
Places in the ENSNode monorepo that call into these functions can then be updated to make use of this new decomposition of logic. |
||||||
| // Invariant: encoded referrer must be of expected size | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| if (size(encodedReferrer) !== ENCODED_REFERRER_BYTE_LENGTH) { | ||||||
| if (size(referrer) !== ENCODED_REFERRER_BYTE_LENGTH) { | ||||||
| throw new Error( | ||||||
| `Encoded referrer value must be represented by ${ENCODED_REFERRER_BYTE_LENGTH} bytes.`, | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| const padding = slice(encodedReferrer, 0, ENCODED_REFERRER_BYTE_OFFSET); | ||||||
| const padding = slice(referrer, 0, ENCODED_REFERRER_BYTE_OFFSET); | ||||||
|
|
||||||
| // strict validation: padding must be all zeros | ||||||
| // if any byte in the padding is non-zero, treat as Zero Encoded Referrer | ||||||
| if (padding !== EXPECTED_ENCODED_REFERRER_PADDING) return zeroAddress; | ||||||
|
|
||||||
| const decodedReferrer = slice(encodedReferrer, ENCODED_REFERRER_BYTE_OFFSET); | ||||||
| const decodedReferrer = slice(referrer, ENCODED_REFERRER_BYTE_OFFSET); | ||||||
|
|
||||||
| try { | ||||||
| // return normalized address | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.