Skip to main content

Upgrading from 0.5

@fluent.xyz/connect 0.6.0 publishes only the API it keeps. This file lists everything 0.5.3 exported that 0.6.0 does not, every member of a kept type that 0.6.0 removes or renames, and the behaviour that changes under code that still compiles. It is the one document of the package that names the removed exports; every other guide uses the 0.6.0 names only. The kept API is in the API reference.

How to read this file​

Every row of the tables below is exactly one of three kinds:

KindMeaningWhat the row gives
renameEvery use of the old name works after replacing it with the new one: the same inputs, the same result, the same effect; for a type, assignable both ways.The new name.
recipeThe kept API reaches the same result another way.A link to a short checked example using kept names only, with the condition under which the result is not always the same.
noneThere is no public way.The reason, in one line.

A name that is not a rename is never a drop-in replacement, even when a kept name looks alike. A removed export your code still imports is a compile error in TypeScript. The package is ESM only, so in JavaScript a named import of it fails when the module is linked, before any of its code runs. Code that compiles against 0.6.0 but behaves differently is listed under Behaviour changes, not in a row.

Behaviour changes​

  • network is required and has no default. 0.5 fell back to the VITE_FLUENT_WIDGET_NETWORK or FLUENT_NETWORK environment variable (with the aliases dev, development, prod and production), then to "testnet". 0.6.0 reads no environment variable: a JavaScript host that omits network or passes null gets a FluentWidgetConfigError with missing_option when <FluentWidget> renders, and any other value than "testnet" and "mainnet" gets invalid_option. A host that set only the environment variable reads it itself and passes the Network.
  • confirmation fails closed. A confirmation that is passed is Silent mode only when it is exactly "silent"; every other value, null and the 0.5 values "always" and "session" included, is Prompt mode. A 0.5 host that passed "session" to skip the Review gets the Review on a Fluent ID's Batch operations; it passes "silent" instead. An omitted confirmation follows Quick sign: see Prompt mode and Silent mode.
  • FluentExecuteResult.sponsored can be null. It is null when a Fluent ID operation in ETH made a sponsored submission and the receipt names no paymaster; 0.5 reported the send's guess. It is false for a Gas token payment, for a Fluent ID operation in ETH that made no sponsored submission and whose receipt names no paymaster, such as the fallback, and for every External wallet operation.
  • The Widget session is a projection. onSessionChange, the render context's session and useFluentWidget().session hand out { account: { address, type }, issuedAt } and nothing else; a JavaScript host reading session.user, session.idToken or session.wallet gets undefined. A session stored by 0.5 is still restored, unless its address or issuedAt is malformed: the widget then discards it when it loads.
  • Config errors are FluentWidgetConfigError with a code. Outside execution, a config the widget refused threw a plain Error in 0.5; 0.6.0 throws a FluentWidgetConfigError (still an Error) with missing_option, invalid_option or removed_option, its message naming the option. A host that compared a message switches on code.
  • Error codes change at runtime. A FluentAuthError carries invalid_login_credential, login_credential_missing, no_signer, challenge_unknown, challenge_used and challenge_expired where 0.5 carried invalid_privy_token, privy_token_missing, no_embedded_wallet, nonce_unknown, nonce_used and nonce_expired, and a service refusal whose code the SDK does not name arrives as service_refused, where 0.5 passed the service's code through. FluentReviewRejectedError and FluentSponsorshipFallbackError gain a code.
  • FluentSponsorshipFallbackError carries summaries, not the vendor errors. In 0.5, cause and fallbackError were the errors the sponsored and own-gas submissions threw, with their request URLs, request bodies and addresses. In 0.6.0 each is a plain { name, message, status? } object whose message has those identifiers replaced by placeholders, and the error's own message is redacted the same way; see errors.md. A host that read details, shortMessage, url, walk() or instanceof on either reads message and status instead.
  • Debug logs carry no Privy DID nor Signer address. With debugLogging on, the console no longer shows either value.
  • Removed options and members in JavaScript. A config.scopes, a showDebugPayload prop or an AccountAvatar userLogoUrl that a JavaScript host still passes has no effect, so an Account avatar given only userLogoUrl shows its defaultLogoUrl or the Fluent mark; an executor passed to execute() is read as options, none of which it sets, so the widget sends the Batch operation itself; and a call with functionName but no method makes widget.createBatchOp throw, where 0.5 encoded functionName.
  • The debug panel follows debugLogging. In mode="home", 0.5 showed the debug panel unless showDebugPayload was false; 0.6.0 shows it only while debugLogging is on.

Removed exports​

UI primitives​

RemovedKindUse instead
Button, buttonVariants, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Icon, IconName, Label, Separator, Switch, WIDGET_STYLE_SCOPE, FluentPortalContainerProvidernoneInternal UI: the widget's own building blocks and styling scope are not public.

Widget components​

RemovedKindUse instead
FluentAccountDrawer, WalletMenuActionCardnoneInternal UI; openAccount opens the widget's own account drawer.
FluentWidgetConnectButton, FluentWidgetConnectButtonPropsnoneInternal UI; renderConnectButton replaces the connect button, and its DefaultButton draws the widget's own.
useWidgetrecipeRecipe: useWidget

Recipe: useWidget​

0.5's useWidget() returned useFluentWidget().widget, and so does this hook, throwing in the same way outside <FluentWidget>; the Widget API it returns has 0.6.0's members, listed under Removed or renamed members.

import { useFluentWidget } from "@fluent.xyz/connect";

export function useWidgetApi() {
return useFluentWidget().widget;
}

Batch operations and signing​

RemovedKindUse instead
createFluentBatchOp, FluentBatchOperationExecutornoneThe feature is removed: a Batch operation with an executor the App builds. A Batch operation is built by widget.createBatchOp and sent by the widget.
FluentBatchConfirmationModerecipeRecipe: confirmation values
FluentBatchOperationReview, FluentSignatureReviewnoneInternal UI: the Review is the widget's own screen.
FluentTypedDataRequestrecipeRecipe: FluentTypedDataRequest

Recipe: FluentTypedDataRequest​

The parameter of widget.signTypedData, with its generics at their constraints, is the same type as 0.5's FluentTypedDataRequest, assignable both ways.

import type { FluentSignApi } from "@fluent.xyz/connect";

export type TypedDataRequest = Parameters<FluentSignApi["signTypedData"]>[0];

Permission sessions​

RemovedKindUse instead
CallType, ParamCondition, createFluentPermissionApi, createFluentPermissionClient, createFluentPermissionPolicyBuilders, createFluentPermissionSession, createFluentZeroDevPermissionSession, FluentCallPermission, FluentPermissionApi, FluentPermissionArgConstraint, FluentPermissionArgs, FluentPermissionBatchPolicy, FluentPermissionBatchPolicyInput, FluentPermissionCallInput, FluentPermissionCallPolicy, FluentPermissionClient, FluentPermissionClientConfig, FluentPermissionGrant, FluentPermissionGrantRequest, FluentPermissionPolicy, FluentPermissionPolicyBuilders, FluentPermissionPreview, FluentPermissionSession, FluentPermissionSessionExecutor, FluentPermissionSessionInput, FluentPermissionStatus, FluentSpendPeriod, FluentSpendPermission, FluentZeroDevPermissionCall, FluentZeroDevPermissionSessionnoneThe feature is removed: permission sessions and their policies.

ZeroDev and paymaster plumbing​

RemovedKindUse instead
FLUENT_ZERODEV_ERC20_PAYMASTER_QUERY, FLUENT_ZERODEV_PAYMASTER_DEMO_RECIPIENT, createFluentSponsorshipRpcUrl, createFluentZeroDevErc20Paymaster, createFluentZeroDevErc20PaymasterApprovalCall, createFluentZeroDevErc20PaymasterClient, createFluentZeroDevErc20PaymasterRpcUrl, createFluentZeroDevRpcUrl, createFluentZeroDevSponsoredPaymaster, fluentIntegrations, fluentZeroDevChainIds, getFluentZeroDevErc20PaymasterTokens, getZeroDevRpcUrl, getZerodevIntegration, isFluentZeroDevChain, resolveFluentZeroDevErc20PaymasterToken, sendFluentZeroDevErc20PaymasterDemo, useFluentZeroDevAccount, FluentZeroDevErc20PaymasterToken, FluentZeroDevErc20PaymasterTokenInfo, FluentZeroDevKernel, FluentZeroDevPaymasterDemoResult, FluentZeroDevPaymasterKernel, FluentZeroDevSignerMode, FluentZeroDevSponsorshipTokenSource, ZerodevIntegrationnoneThe widget does this itself: it prepares the Fluent ID's account and pays gas through execute(), with gasPayment choosing how.

Chains and registry​

RemovedKindUse instead
fluentChainrecipeRecipe: fluentChain
fluentChainsrecipeRecipe: fluentChains
getFluentChainrecipeRecipe: getFluentChain
getFluentExplorerBaseUrlrecipeRecipe: getFluentExplorerBaseUrl
fluentDefinitionToViemChainnone0.6.0 converts no chain definition to a viem chain.
fluentL1Chains, getL1Chain, getL1ForFluentChain, l1DefinitionToViemChain, resolveL1Definition, L1ChainDefinitionnoneThe registry's L1 chains are not public.
fluentApps, getApp, AppDefinition, registryVersionnoneThe registry's app entries and version are not public.
fluentBridgeAbi, BridgeAddresses, resolveBridgeAddresses, getContractAddressFromChainnoneThe bridge contracts' ABI and address helpers are not public.

Recipe: fluentChain​

0.5's fluentChain was the object { testnet: fluentTestnet, mainnet: fluentMainnet }; this one holds the same two viem chains.

import { fluentMainnet, fluentTestnet } from "@fluent.xyz/connect";

export const chainsByNetwork = { testnet: fluentTestnet, mainnet: fluentMainnet } as const;

Recipe: fluentChains​

0.5's fluentChains held the registry's two chain definitions by Network; this record holds the same definitions, found by the chain ids of fluentTestnet and fluentMainnet. Each value is typed FluentChainDefinition | undefined, though both ids are always found.

import { fluentMainnet, fluentTestnet, getFluentChainByChainId } from "@fluent.xyz/connect";

export const chainDefinitions = {
testnet: getFluentChainByChainId(fluentTestnet.id),
mainnet: getFluentChainByChainId(fluentMainnet.id),
};

Recipe: getFluentChain​

0.5's getFluentChain(network) returned the registry's definition of "testnet" or "mainnet"; this function returns the same definition. Its result is typed FluentChainDefinition | undefined: it is defined for "testnet" and "mainnet", and undefined for any other value a JavaScript caller passes, as 0.5's was.

import {
fluentMainnet,
fluentTestnet,
getFluentChainByChainId,
type FluentWidgetNetwork,
} from "@fluent.xyz/connect";

const chainIds = { testnet: fluentTestnet.id, mainnet: fluentMainnet.id } as const;

export function chainDefinitionOf(network: FluentWidgetNetwork) {
return getFluentChainByChainId(chainIds[network]);
}

Recipe: getFluentExplorerBaseUrl​

0.5's getFluentExplorerBaseUrl(network) was this expression. Like it, it returns testnet's explorer for any value other than "mainnet".

import { getFluentChainForNetwork, type FluentWidgetNetwork } from "@fluent.xyz/connect";

export function explorerBaseUrlOf(network: FluentWidgetNetwork): string | undefined {
return getFluentChainForNetwork(network).blockExplorers?.default.url;
}

Network and config​

RemovedKindUse instead
normalizeFluentWidgetNetworknoneThe widget takes only "testnet" or "mainnet"; the App maps its own value and passes it as network.
resolveFluentWidgetNetworkFromEnvnoneThe widget reads no environment variable; the App passes network.
FluentWidgetNetworkProvider, useFluentWidgetNetwork, isFaucetNetworknoneInternal: the App passes network itself, so it already knows it.
ResolvedFluentWidgetConfig, ResolvedFluentWidgetExecutionnoneThere is no public resolved config.
FLUENT_CONNECT_DEFAULT_ASSETSnoneThe widget's default images are internal.

Storage keys and session​

RemovedKindUse instead
FLUENT_WIDGET_SESSION_STORAGE_KEYnoneThe widget's storage is internal. Read the render context's session, which holds a restored session, and onSessionChange for later Direct-login changes.
FLUENT_WIDGET_USER_TOKENS_STORAGE_KEY, FLUENT_WIDGET_USER_TOKENS_IMPORT_MARKER_KEYnoneThe widget's storage is internal.
FluentSessionnoneThe 0.5 session shape is not public; the Widget session is FluentWidgetSession, a different shape.
clearPrivyRecentLoginMethodnoneThe widget does this itself.

Fluent client and families​

RemovedKindUse instead
fluent, createFluentClient, FluentClient, FluentClientConfig, createFluentFamiliesClient, FluentFamilies, FluentFamiliesClient, FluentFamiliesClientConfig, FluentFamily, FluentFamilyTier, FluentFamilyTypenoneThe feature is removed: the standalone client and the families lookup.

Tokens and balances​

RemovedKindUse instead
fluentMainnetTokenDefaults, fluentTestnetTokenDefaults, getFluentTokenDefaults, getFluentTokenDefaultsForNetwork, getFluentDefaultWidgetDisplayTokens, getFluentDefaultWidgetGasTokens, isFluentDefaultToken, isFluentNativeToken, fluentTokenIdentity, mergeFluentDisplayTokens, findFluentSymbolCollisionsnoneThe widget does this itself: it lists its Default tokens beside the App's tokens.
readFluentTokenBalances, readFluentTokenMetadata, FluentTokenBalancenoneThe widget reads balances itself; refreshBalances refetches them.
FLUENT_USER_TOKEN_LIMIT, createFluentUserTokenStore, createFluentBackendUserTokenStore, useFluentUserTokens, UserTokenStore, BackendUserTokenStore, FluentUserTokenAddResultnoneThe widget keeps the person's User tokens itself.

Gas payment​

RemovedKindUse instead
FLUENT_WIDGET_DEFAULT_GAS_TOKEN, resolveDefaultGasTokennoneThe widget does this itself; config.gasPayment.defaultToken sets the Gas token it starts with.
FLUENT_GAS_PAYMENT_DEFAULT_ETH_RATES, deriveFluentGasEthRates, getFluentGasPaymentEthValue, getFluentGasPaymentTokens, getFluentGasPaymentValueTier, getFluentGasTokenAddress, selectFluentGasPaymentToken, sortFluentGasTokens, FluentGasPaymentSelection, FluentGasPaymentValueTiernoneThe widget does this itself: widget.gasPayment is the Gas payment chosen in the widget.

Token transfer​

RemovedKindUse instead
buildFluentTransferCall, checkFluentTransferFee, fluentTransferAbi, parseFluentTransferAmount, parseFluentTransferRecipient, FluentTokenTransferOutcome, FluentTokenTransferRequest, FluentTokenTransferSender, FluentTransferAmount, FluentTransferFee, FluentTransferRecipientnoneInternal to the widget's Send form.

User settings​

RemovedKindUse instead
createFluentSettingsClient, FluentSettingsClient, FluentSettingsError, FluentSettingsErrorCode, FluentUserSettings, FluentUserSettingsPatch, FluentProfilenoneThe widget keeps User settings itself.

Iframe​

RemovedKindUse instead
createFluentIframeBridge, createFluentIframeRpcHandler, FluentIframeBridge, FluentIframeBridgeOptions, FluentIframeRpcExecutor, FluentIframeRpcHandler, FluentIframeRpcRequestnoneThe feature is removed: a bridge with an executor the App builds. useFluentIframeBridge bridges an iframe to the Widget account.
FluentIframeRpcErrornoneNumeric RPC errors are internal; a dismissed Review reaches the iframe as 4001.

Removed or renamed members​

AccountAvatarProps​

MemberKindUse instead
AccountAvatarProps.userLogoUrlrenameAccountAvatarProps.userAvatarUrl

FluentBatchApi​

MemberKindUse instead
FluentBatchApi.confirmationModerecipeRecipe: FluentBatchApi.confirmationMode
FluentBatchApi.createPermissionSession, FluentBatchApi.policiesnoneThe feature is removed: permission sessions and their policies.

Recipe: FluentBatchApi.confirmationMode​

0.5's widget.confirmationMode was "session" while the person's Quick sign was on and "always" otherwise; 0.6.0's widget.signingMode is "silent" and "prompt" in the same states, and this hook gives back the 0.5 value.

import { useFluentWidget } from "@fluent.xyz/connect";

export function useConfirmationMode(): "always" | "session" {
return useFluentWidget().widget.signingMode === "silent" ? "session" : "always";
}

FluentBatchCallInput​

MemberKindUse instead
FluentBatchCallInput.functionNamerenameFluentBatchCallInput.method

FluentBatchOperation​

MemberKindUse instead
FluentBatchOperation.executenoneIts executor argument is removed: execute(options) takes the options only and sends through the widget.

FluentBatchOperationExecuteOptions​

MemberKindUse instead
FluentBatchOperationExecuteOptions.confirmationrecipeRecipe: confirmation values
FluentSigningMode "always"recipeRecipe: confirmation values
FluentSigningMode "session"recipeRecipe: confirmation values

Recipe: confirmation values​

confirmation is kept, and its values changed: 0.5's "session" signed as Silent mode and "always" as Prompt mode. This function gives the 0.6.0 value with the same effect for every 0.5 value. A 0.5 value passed unchanged is read as Behaviour changes says.

import type { FluentSigningMode } from "@fluent.xyz/connect";

export function signingModeOf(confirmation: "always" | "session"): FluentSigningMode {
return confirmation === "session" ? "silent" : "prompt";
}

FluentTokenDefinition​

MemberKindUse instead
FluentTokenDefinition.gasPriority, FluentTokenDefinition.nativenoneThe widget already ignored both on a token the App passed: only a Default token can be a Gas token or the chain's own currency.

FluentWidgetAccount​

MemberKindUse instead
FluentWidgetAccount.signerAddressnoneThe Signer's address is not part of the Widget API.

FluentWidgetConfig​

MemberKindUse instead
FluentWidgetConfig.scopesnoneThe option is removed; it only filled the 0.5 session's scopes.

FluentWidgetProps​

MemberKindUse instead
FluentWidgetProps.showDebugPayloadnoneThe prop is removed; the debug panel follows debugLogging.

FluentWidgetRenderContext​

MemberKindUse instead
FluentWidgetRenderContext.connectingrecipeRecipe: FluentWidgetRenderContext.connecting
FluentWidgetRenderContext.connectedAddressnoneNo member holds the same value in every state: connectedAddress preferred a Fluent ID's address, and widget.account.address is a connected External wallet's until the Fluent ID's account is ready.

Recipe: FluentWidgetRenderContext.connecting​

0.5's connecting was true exactly when status was "connecting", in every state; this hook reads the same.

import { useFluentWidget } from "@fluent.xyz/connect";

export function useConnecting(): boolean {
return useFluentWidget().status === "connecting";
}

FluentWidgetSession​

MemberKindUse instead
FluentWidgetSession.walletrecipeRecipe: FluentWidgetSession.wallet
FluentWidgetSession.app, FluentWidgetSession.appId, FluentWidgetSession.expiresAt, FluentWidgetSession.idToken, FluentWidgetSession.metadata, FluentWidgetSession.scopes, FluentWidgetSession.usernoneThe Widget session is { account, issuedAt } only; an App proves who the person is with an Auth token from getAuthToken().

Recipe: FluentWidgetSession.wallet​

0.5's session.wallet.smartAccountAddress is session.account.address, the same address copied from the same stored session. Only that field has a replacement: wallet.signerAddress and wallet.authorizationSession have none.

import { useFluentWidget } from "@fluent.xyz/connect";

export function useSessionAddress() {
return useFluentWidget().session?.account.address;
}

FluentAuthErrorCode​

Each 0.6.0 code is raised exactly where 0.5 raised the old one.

MemberKindUse instead
FluentAuthErrorCode "invalid_privy_token"rename"invalid_login_credential"
FluentAuthErrorCode "privy_token_missing"rename"login_credential_missing"
FluentAuthErrorCode "no_embedded_wallet"rename"no_signer"
FluentAuthErrorCode "nonce_unknown"rename"challenge_unknown"
FluentAuthErrorCode "nonce_used"rename"challenge_used"
FluentAuthErrorCode "nonce_expired"rename"challenge_expired"