Conversation
hotbox port
new reg contract, opt
vendor eik, api urls
|
@0xthrpw is attempting to deploy a commit to the EthID Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThis PR replaces provider-specific RPC ID plumbing (Alchemy/QuickNode) with full env-driven RPC URLs, moves transports into a new server-safe
Confidence Score: 4/5Safe to merge with minor follow-ups; the RPC transport refactor is clean and the Docker plumbing is well-considered. The RPC transport extraction is straightforward and the server/client boundary reasoning is sound. The
Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant Server as Server (OG routes / API)
participant RPC as src/lib/rpc.ts
participant Wagmi as src/lib/wagmi.ts
participant Client as Browser Client
Note over RPC: Reads NEXT_PUBLIC_*_RPC_URL<br/>(build-time inlined)
Server->>RPC: "import { transports }"
RPC-->>Server: fallback([envUrl?, publicUrl])
Server->>Server: "createPublicClient({ transport: transports[mainnet.id] })"
Server->>Server: getEtherPrice() via Chainlink
Wagmi->>RPC: "import { transports }"
RPC-->>Wagmi: same transport map
Wagmi->>Wagmi: "createConfig({ transports })"
Wagmi-->>Client: WagmiProvider (SSR + hydration)
Client->>Client: providers.tsx module init
Client->>Client: setIdentityKitApiUrls(efpApiUrl, grailsApiUrl, ensMetadataUrl)
Client->>Client: setIdentityKitUtilsApiUrls(...)
Client->>RPC: use-list-settings, getEfpProfileRoles, ens.ts
RPC-->>Client: transports[mainnet/base/optimism]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant Server as Server (OG routes / API)
participant RPC as src/lib/rpc.ts
participant Wagmi as src/lib/wagmi.ts
participant Client as Browser Client
Note over RPC: Reads NEXT_PUBLIC_*_RPC_URL<br/>(build-time inlined)
Server->>RPC: "import { transports }"
RPC-->>Server: fallback([envUrl?, publicUrl])
Server->>Server: "createPublicClient({ transport: transports[mainnet.id] })"
Server->>Server: getEtherPrice() via Chainlink
Wagmi->>RPC: "import { transports }"
RPC-->>Wagmi: same transport map
Wagmi->>Wagmi: "createConfig({ transports })"
Wagmi-->>Client: WagmiProvider (SSR + hydration)
Client->>Client: providers.tsx module init
Client->>Client: setIdentityKitApiUrls(efpApiUrl, grailsApiUrl, ensMetadataUrl)
Client->>Client: setIdentityKitUtilsApiUrls(...)
Client->>RPC: use-list-settings, getEfpProfileRoles, ens.ts
RPC-->>Client: transports[mainnet/base/optimism]
|
| NEXT_PUBLIC_OPTIMISM_ALCHEMY_ID= | ||
| NEXT_PUBLIC_OP_SEPOLIA_ALCHEMY_ID= | ||
| # Full RPC URLs (key/token embedded), e.g. https://<rpc-host>/hbx_rpc_... | ||
| # Unset chains fall back to free public endpoints (see src/lib/wagmi.ts). |
| const rpc = (envUrl: string | undefined, publicUrl: string) => | ||
| fallback((envUrl ? [envUrl, publicUrl] : [publicUrl]).map((url) => http(url, { batch: true }))) |
There was a problem hiding this comment.
fallback with a single transport is a no-op
When envUrl is undefined, fallback([http(publicUrl, { batch: true })]) wraps a single transport in a fallback list. fallback only adds value with ≥ 2 transports; with one entry it behaves identically to a bare http() call but adds unnecessary overhead. Consider returning http(url, { batch: true }) directly when there is only one URL.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| dispatch(setRegistrationError(`Failed to get price for batch ${batchIndex + 1}`)) | ||
| return | ||
| } | ||
|
|
||
| const batchPrices = await getBulkRentPrices(batchLabels, batchDurations) | ||
| if (!batchPrices) { | ||
| dispatch(setRegistrationError(`Failed to get per-name prices for batch ${batchIndex + 1}`)) | ||
| return | ||
| } | ||
|
|
||
| const valueWithBuffer = (batchPrice * BigInt(105)) / BigInt(100) | ||
|
|
||
| const tx = await submitMultiRegister( | ||
| batchLabels, | ||
| owner, | ||
| batchDurations, | ||
| batchPrices, |
There was a problem hiding this comment.
Two sequential RPC calls for pricing with no reconciliation
getBulkTotalPrice is called first to compute batchPrice (used for the ETH value buffer), then getBulkRentPrices is called separately to obtain the per-name prices array passed to multiRegister. These are two independent on-chain reads; if a price oracle update lands between them, the ETH value ceiling derived from the total could be lower than the sum the contract actually requires, causing the transaction to revert.
A simpler approach: derive the total from the already-fetched batchPrices array (batchPrices.reduce((a, b) => a + b, 0n)), eliminating the second RPC call and removing the timing window.
env-driven full RPC URLs, drop alchemy/quicknode plumbing