-
Notifications
You must be signed in to change notification settings - Fork 49
fix(keychain): float→BigInt crash in token send + HMR provider exports #2623
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
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 |
|---|---|---|
| @@ -1,8 +1,8 @@ | ||
| import { useCallback, useEffect, useMemo, useRef, useState } from "react"; | ||
| import { STABLE_CONTROLLER } from "@/components/provider/upgrade"; | ||
| import { STABLE_CONTROLLER } from "@/components/provider/upgrade-context"; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| import { DEFAULT_SESSION_DURATION, now } from "@/constants"; | ||
| import { useConnection } from "@/hooks/connection"; | ||
| import { useWallets } from "@/hooks/wallets"; | ||
| import { useWallets } from "@/hooks/use-wallets"; | ||
| import Controller from "@/utils/controller"; | ||
| import { TurnkeyWallet } from "@/wallets/social/turnkey"; | ||
| import { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ import { Link, useSearchParams } from "react-router-dom"; | |
| import { SendRecipient } from "@/components/modules/recipient"; | ||
| import { SendAmount } from "./amount"; | ||
| import { Disclosure } from "@cartridge/controller-ui"; | ||
| import { parseTokenAmount } from "@/utils/token-amount"; | ||
|
|
||
| export function SendTokenDrawer({ | ||
| disclosure, | ||
|
|
@@ -35,6 +36,7 @@ export function SendTokenDrawer({ | |
|
|
||
| const [to, setTo] = useState(""); | ||
| const [amount, setAmount] = useState<number | undefined>(); | ||
| const [amountInput, setAmountInput] = useState<string | undefined>(); | ||
| const [amountError, setAmountError] = useState<Error | undefined>(); | ||
| const [toError, setToError] = useState<Error | undefined>(); | ||
| const [selectedToken, setSelectedToken] = useState<Token | undefined>(token); | ||
|
|
@@ -52,13 +54,18 @@ export function SendTokenDrawer({ | |
| ) { | ||
| return ""; | ||
| } else { | ||
| const baseUnitAmount = parseTokenAmount( | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| amountInput, | ||
| selectedToken.metadata.decimals, | ||
| ); | ||
| if (baseUnitAmount === undefined) { | ||
| return ""; | ||
| } | ||
|
|
||
| const sendParams = new URLSearchParams(searchParams); | ||
| sendParams.set("tokenAddress", tokenAddress); | ||
| sendParams.set("recipient", to); | ||
| sendParams.set( | ||
| "amount", | ||
| BigInt(amount * 10 ** selectedToken.metadata.decimals).toString(), | ||
| ); | ||
| sendParams.set("amount", baseUnitAmount.toString()); | ||
| return `send?${sendParams.toString()}`; | ||
| } | ||
| }, [ | ||
|
|
@@ -68,6 +75,7 @@ export function SendTokenDrawer({ | |
| toError, | ||
| recipientLoading, | ||
| amount, | ||
| amountInput, | ||
| to, | ||
| searchParams, | ||
| tokenAddress, | ||
|
|
@@ -88,9 +96,10 @@ export function SendTokenDrawer({ | |
| (token: Token) => { | ||
| setSelectedToken(token); | ||
| setAmount(undefined); | ||
| setAmountInput(undefined); | ||
| userSelectedToken.current = true; | ||
| }, | ||
| [setSelectedToken, setAmount], | ||
| [setSelectedToken, setAmount, setAmountInput], | ||
| ); | ||
|
|
||
| if (!token) { | ||
|
|
@@ -133,6 +142,7 @@ export function SendTokenDrawer({ | |
| amount={amount} | ||
| submitted={false} | ||
| setAmount={setAmount} | ||
| setAmountInput={setAmountInput} | ||
| setError={setAmountError} | ||
| /> | ||
| )} | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| import { createContext, ReactNode } from "react"; | ||
| import { addAddressPadding, Call } from "starknet"; | ||
| import type { Chain } from "@cartridge/controller"; | ||
| import { ControllerError } from "@/utils/connection"; | ||
| import Controller from "@/utils/controller"; | ||
|
|
||
| export enum OutsideExecutionVersion { | ||
| V2, | ||
| V3, | ||
| } | ||
|
|
||
| export type ControllerVersionInfo = { | ||
| version: string; | ||
| hash: string; | ||
| outsideExecutionVersion: OutsideExecutionVersion; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| changes: string[]; | ||
| }; | ||
|
|
||
| export const CONTROLLER_VERSIONS: ControllerVersionInfo[] = [ | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| { | ||
| version: "1.0.4", | ||
| hash: "0x24a9edbfa7082accfceabf6a92d7160086f346d622f28741bf1c651c412c9ab", | ||
| outsideExecutionVersion: OutsideExecutionVersion.V2, | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| changes: [], | ||
| }, | ||
| { | ||
| version: "1.0.5", | ||
| hash: "0x32e17891b6cc89e0c3595a3df7cee760b5993744dc8dfef2bd4d443e65c0f40", | ||
| outsideExecutionVersion: OutsideExecutionVersion.V2, | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| changes: ["Improved session token implementation"], | ||
| }, | ||
| { | ||
| version: "1.0.6", | ||
| hash: "0x59e4405accdf565112fe5bf9058b51ab0b0e63665d280b816f9fe4119554b77", | ||
| outsideExecutionVersion: OutsideExecutionVersion.V3, | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| changes: [ | ||
| "Support session key message signing", | ||
| "Support session guardians", | ||
| "Improve paymaster nonce management", | ||
| ], | ||
| }, | ||
| { | ||
| version: "1.0.7", | ||
| hash: "0x3e0a04bab386eaa51a41abe93d8035dccc96bd9d216d44201266fe0b8ea1115", | ||
| outsideExecutionVersion: OutsideExecutionVersion.V3, | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| changes: ["Unified message signature verification"], | ||
| }, | ||
| { | ||
| version: "1.0.8", | ||
| hash: "0x511dd75da368f5311134dee2356356ac4da1538d2ad18aa66d57c47e3757d59", | ||
| outsideExecutionVersion: OutsideExecutionVersion.V3, | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| changes: ["Improved session message signature"], | ||
| }, | ||
| { | ||
| version: "1.0.9", | ||
| hash: "0x743c83c41ce99ad470aa308823f417b2141e02e04571f5c0004e743556e7faf", | ||
| outsideExecutionVersion: OutsideExecutionVersion.V3, | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| changes: ["Wildcard session support"], | ||
| }, | ||
| ]; | ||
|
|
||
| export const STABLE_CONTROLLER = CONTROLLER_VERSIONS[5]; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| export const BETA_CONTROLLER = CONTROLLER_VERSIONS[5]; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
|
|
||
| export const findVersion = ( | ||
| classHash: string, | ||
| ): ControllerVersionInfo | undefined => | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| CONTROLLER_VERSIONS.find( | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| (v) => addAddressPadding(v.hash) === addAddressPadding(classHash), | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| ); | ||
|
|
||
| /** | ||
| * Determines if an upgrade is available and returns the appropriate controller version | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| * @param currentVersion The current controller version | ||
| * @param isBeta Whether beta features are enabled | ||
| * @returns An object containing whether an upgrade is available and the target controller version | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| */ | ||
| export function determineUpgradePath( | ||
| currentVersion: ControllerVersionInfo | undefined, | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| isBeta: boolean, | ||
| ): { available: boolean; targetVersion: ControllerVersionInfo } { | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| const targetVersion = isBeta ? BETA_CONTROLLER : STABLE_CONTROLLER; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
|
|
||
| if (!currentVersion) { | ||
| return { available: false, targetVersion }; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| } | ||
|
|
||
| // Find the indices of the current and target versions in the CONTROLLER_VERSIONS array | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| const currentIndex = CONTROLLER_VERSIONS.findIndex( | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| (v) => v === currentVersion, | ||
| ); | ||
| const targetIndex = CONTROLLER_VERSIONS.findIndex((v) => v === targetVersion); | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
|
|
||
| // Only set available to true if the target controller is newer than the current one | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| const available = currentIndex !== -1 && targetIndex > currentIndex; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
|
|
||
| return { available, targetVersion }; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| } | ||
|
|
||
| export interface UpgradeInterface { | ||
| available: boolean; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| current?: ControllerVersionInfo; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| latest: ControllerVersionInfo; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| calls: Call[]; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| isSynced: boolean; | ||
| isUpgrading: boolean; | ||
| error?: ControllerError; | ||
| onUpgrade: () => Promise<void>; | ||
| isBeta: boolean; | ||
| } | ||
|
|
||
| export const UpgradeContext = createContext<UpgradeInterface | undefined>( | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| undefined, | ||
| ); | ||
|
|
||
| export interface UpgradeProviderProps { | ||
| controller?: Controller; | ||
| /** Chains the dapp explicitly configured (see | ||
| * `ConnectionContextValue.configuredChains`). The account's class is checked on | ||
| * each of them - not just the controller's active chain - so an upgrade is offered | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| * for e.g. an appchain still on a pre-wildcard class while the account is already | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| * up to date on the settlement chain. */ | ||
| chains?: Chain[]; | ||
| children: ReactNode; | ||
| } | ||
|
|
||
| /** A chain whose account is behind the target version. */ | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| export type OutdatedChain = { rpcUrl: string; version: ControllerVersionInfo }; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,10 +8,10 @@ import { | |
| ControllerVersionInfo, | ||
| OutsideExecutionVersion, | ||
| STABLE_CONTROLLER, | ||
| UpgradeProvider, | ||
| determineUpgradePath, | ||
| useUpgrade, | ||
| } from "./upgrade"; | ||
| } from "./upgrade-context"; | ||
|
Contributor
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. Blocking:
Contributor
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. Blocking: |
||
| import { UpgradeProvider } from "./upgrade"; | ||
| import { useUpgrade } from "./use-upgrade"; | ||
| import { ReactNode } from "react"; | ||
| import { PostHogContext, PostHogWrapper } from "@cartridge/controller-ui/utils"; | ||
| import Controller from "@/utils/controller"; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blocking:
contextis still referenced here, but this diff removes its definition/export.